I am confused. Is this saying that if you don't have access to `cat`, instead of `cat /path/to/input-file` you can use `base64 /path/to/input-file | base64 --decode`?

Or is it saying that `base64 /path/to/input-file | base64 --decode` can bypass read file permission flags?

The first thing. Invoked processes inherit the permissions of the user who invoked them (unless they have the setuid bit). It's just in case you land access to a computer which has all the standard Unix tools disabled to stop attackers from lateral movement.

Why would you bother even doing that?

If someone has the power to execute commands, they are already on the other side of the airtight hatch.

https://devblogs.microsoft.com/oldnewthing/20240102-00/?p=10...

Put your meagre and limited resources on keeping them outside the hatch.

If they get through the hatch, that is where you fucked up, not that you didn't remove every conceiveable command from yourself should they get through. If they can remotely get some program to execute a shell, they can quite conceivably get the same program to just read them the files directly by writing different shellcode. Running a shell is just a convenience for them.

The number of setups that are insecure enough to allow remote shells by arbitrary attackers, but are secure because you disabled /bin/cat once they get in, is zero.

Security is done in layers. Yes, we do our best to keep the adversaries outside the proverbial hatch. But even inside the hatch, the principal of least privilege is important in reducing the damage of attacks.

Typically you do things like this to either work in restricted envs (distroless) or to evade detection logic. It's not about bypassing a boundary, it's about getting things done in the env you have available.

It's the principle of 'Defence in Depth'. Do both, as one control may fail.

But you wouldn't, or shouldn't, take a patchwork approach to it.

If the software you're trying to secure actually depends on a full, working, intertwined unix system... you leave that as it is. You can certainly try reducing a process's access to the system it's running on (whether that be by containers, jail(8), SELinux, AppArmor, etc.), but you don't go around deleting 7-zip or your scripting languages or compilers, on the off-chance that'll thwart a hacker.

Sure, you can say, "defense in depth", but if you have one layer that's actually holding up the security guarantees, and a second layer that is largely ineffectual (haha! I removed /bin/cat, now they can't read files! oh and base64 too... and yyencode... and... and... and...), I wouldn't waste much time on the second layer.

I think you have the wrong end of the stick. The OP link is a resource for when you do get access to the processes environment which has already been reduced via containers, jails, or what have you.

If the environment is already restricted, but the process has, for example, access to the base64 tool, here's how you can use that to do something you otherwise aren't able to.

This is saying that restricting privileges by blacklisting commands do not work (and never worked).

Cool, so it is what I imagined, thanks!

It's the former. Not bypassing permissions but in shells that might be highly restricted to just a couple commands. Like others have said, very very common in CTFs.

If there's a file your user does not have read access to, but you have the ability to run the `base64` binary as root, you can run `base64` as root, (thus encoding the file contents as base64), then pipe the output to another base64 process to decode the file contents.

So yes, the end result is just `cat` with extra steps.

Wouldn't a tar pipe be even lighter?

I just grabbed one of the examples there which was readable and didn't require the reader to know all the extra flags passed. One that would illustrate the purpose of the website. One that Linux newbies who read the question and further answers here could follow along with. Not one that tried to be optimal.

Depends on what you have access to / what's misconfigured.