Its mean to show all the projects on Github that are vulnerable to injection attacks. An attack can maliciously create a GET request that escapes out the current command and then execute arbitrary commands.
It is executing shell commands based on what you pass in through a request parameter. Since there is no filtering going on, you could, I suppose, pass in an entire bash script and have a good ol' time.
Which points out that the context has to considered as well. E.g., if it's a personal intranet or password protected page, this may not be vulnerability.
What if a hacker would have access to a user of said personal intranet, or would find a way to bypass the password protected page. Then he'd be able to execute anything on the server, even stuff the user he hacked shouldn't be able to access. So no, this is always a vulnerability.
Maybe not unintended, but definitely full access, and the world is almost certainly full of outdated/non whitelist access/weakly passworded panels.
Also, on a a sufficiently misconfigured server, you could always use \! (mysql's shell_exec, etc.) with phpmyadmin etc. to open a remote shell somewhere, then work from there.
It would still be vulnerable to a CSRF attack. The attacker can just get a logged-in user to launch their exploit, through a vulnerable site they frequent or even a link or image in an email.
Theoretically, building CSRF protection in isn't mutually exclusive with passing unsanitised variables to a shell. Although sure, most people who do the latter won't do the former.
It would actually be a nice to build an optional warning feature into `git` itself. You could download some known common issues and the script would generate warnings if you checked in corresponding code. E.g.
git add id_rsa
WARNING: You may have just staged a private key.
or better
echo '{"password": "mypassword"}' > config.json
git add config.json
WARNING: You may have just staged a password.
I thought about doing the exact same thing. But I wonder about the: limiting of the issue creation API on github and false positives. [The variable has been sanitized prior to being executed]
I remember reading about something like this and Github their response was that the guy should stop according to their ToS. Their ToS blocks stuff like this to prevent spamming.
I don't like Issue bots, but it could actually be a huge value-add for GitHub to integrate these kinds of checks (as well as hardcoded credentials, etc) for their users.
After looking at the search result i can see that most of the results have legit reasons.
Instead of half-assing the problem, please dedicate 10 minute of your life to look in, analyze & report one or two of the problems you find.
Also explain why you think this is an security issue.
You will:
* help someone out by pointing out an issue
* hopefully educate the person how to write better code
* educate yourself in reading and understanding others spaghetti code
As a theoretical aside, I wonder if it'd be possible to have a typesystem based solution to these kinds of problems - where variables coming from the user (or from another program) are considered 'unsafe' and the compiler refuses to let exec() or whatever use them until they've been through a cleaner/tester of some kind... (OK, I know PHP doesn't have a compiler as such - but a static checker of some kind could work the same...)
But of course we just laugh about Perl and pat ourself on our backs with our safe new languages because we clearly know much more than those anachronistic neckbeards.
But of course we just laugh about Perl and pat ourself on our backs with our safe new languages
And there is some justification for that: if those "safe new languages" are doing the type checking at compile time, that is better than only finding out you have a safety issue when you fail at run time.
Ah, "Taint" was the missing magic word I couldn't figure out to aid my google-fu (well, duckduckgofu...). Thanks for that - there is a lot of interesting stuff out there. :-)
On the practical side, Ruby (MRI specifically) has such a system ($SAFE), that taints certain objects (e.g. those gained by IO) and only allows you to use them in certain fashions (e.g. only after explicit handling).
It's leaky as hell, because all components have to get the marking right. Also, not all Objects have equal trust levels. Objects created due to a HTTP request (GET-Parameters) should certainly be tainted, but how about Object read through IO - do we trust out filesystem? Do we trust the database? Thats more of an architectural decision.
In the end, the problem comes down to this: you have to whitelist the world and everything you miss is an error.
There is Argos[0] which is a research project at my university, it's a qemu-based emulator that tracks tainted data coming from the network and other compromised sources and makes sure it doesn't tamper with memory or filesystem locations than it shouldn't. It's a bit overkill,especially for this, but it's interesting to check out :)
Then people notice that exec($_GET['foo']) doesn't work, but some smart cookie figures out that exec(untaint($_GET['foo'])) (or whatever the syntax is for removing the taint from an input variable) does, posts it online, and everyone copies that instead without thinking about the consequences.
Different languages (SQL, JS, HTML, Shell, Plaintext, etc.) are treated as different types. Language-specific functions only accept arguments of the relevant type (eg. shell_exec takes Shell, db_query takes SQL, etc.). User input is Plaintext (usually; sometimes it might be something more specific like BASE64).
Different languages can't be combined (eg. SQL can't be concatenated with Plaintext), but they can be converted down to Plaintext and Plaintext can be converted to any language via escaping functions. This avoids injection attacks, since the only way to please the type-checker is by escaping properly.
Directly passing user data to the command line is highly dangerous.It allows an attacker to execute arbitrary commands on the command line [0].
escapehellarg [1] has to be used to Escape a string to be used as a shell argument
Directly doing anything with attacker supplied data is generally a no-no.
Everything that may come from a user must be filtered, escaped or generally treated as hostile.
As an example on an IRC channel someone once made their chan bot log the channel to the web, all it took was pasting javascript into an IRC window, and typing "LOL look at this! http://stupidbot.com/ircweblog". Channel pwned.
True, but there is a lot of software out there where people don't do that. Might be interesting to find vulnerabilities that are slightly less obvious.
Sadly, there's cases where exec() is impossible to avoid - for example, every kind of tool that doesn't have a proper library and language bindings. See git and the grit library for an example.
As a side note, this is how many SQL injection attacks happen too. You almost never want unfiltered user input to directly interact with your system. A while back, I did an episode on how SQL injection can lead to code execution by using unfiltered user input on a LAMP stack. See it @ http://sysadmincasts.com/episodes/21-anatomy-of-a-sql-inject...
I think you're giving him too much credit. The input was not sanitized. Now its no one programmers fault. It was a long living bug many had a chance to see it and correct it for a long time. It was rooted in the same carelessness as exec(GET)
I think the problem here is the fact that tainted variables (user input) are used to execute shell commands. it doesn't matter if that's $_POST or $_GET, both of these are user input and therefore these are huge vulnerabilities.
It depends by the command, echo is idempotent for example. There should be some checking like
$cmdname = split(' ', $_GET['command']);
if(!in_array(IDEMPOTENT_COMMANDS, $cmdname))
echo '<h1>Your request is not guaranteed to be idempotent. Please use a POST.</h1>';
else
exec($_GET['command'] ...
As a simple call, yes. But there are many shell tricks (redirection, command substitution, process substitution) that can make an echo call have significant side effects - so if you were daft enough to be considering this you'd need to do much more checking before submitting the provided instruction to your shell, and those checks would need to know which shell you were targeting (in fact you'd probably want to force the issue by exec()ing a specific shell instead of just using the default for the user the code is running as).
Thats not the point. Of course "rm -rf /" won't work, but what about downloading and installing a backdoor? Or modifying the website scripts itself? Or dumping a database? Or...
Removing all the files from a filesystem is something only a script kiddy would do, and it's probably a "best case scenario" for the owner of the server, because the impact of that is relatively small (just re-install the server and restore the backups). But once the attacker starts injecting mallware, stealing customer information (credit card numbers anyone?) or anything else nasty they can think of that they would benefit from, then you are in a whole lot more trouble...
True, but once you have <foo; $any_command_with_user_privilege> you can start executing any user commands. So you do a </dev/null; mkdir ~/www/nefarious; cp ~/www/AdminSettings.php ~/www/nefarious/settingns.txt;> (without the index file you can just view the file as plain text, which probably contains the database username and password. Then you can go on and download a database dump. The attacker probably does not give a damn about root in this scenario.
Paul's Security Weekly (a security podcast) had their blog owned after inadvertently removing the .htaccess (the password protection in your example) from their admin directory.
I really, really, really want to post on their issue tracker, but maybe I shouldn't. There's no guarantee the person grading the project will care, either.
Fortunately?? More often than we all care to admit, these things are exposed to the internet. (because it's so cool when I can turn on the coffee machine from my smartphone halfway home from work)
I already have a thing called "all seeing eye" that picks up on things like this on a pre-commit script in SVN and tells people to go away if they do something stupid. It's done some wonderful work so far.
130 comments
[ 2.9 ms ] story [ 207 ms ] threadhttp://www.php.net/manual/en/function.exec.php
http://www.php.net/manual/en/reserved.variables.get.php
They don't give untintended full access to the web server.
That said, they are a little insecure.
https://en.wikipedia.org/wiki/Webmin
Maybe not unintended, but definitely full access, and the world is almost certainly full of outdated/non whitelist access/weakly passworded panels.
Also, on a a sufficiently misconfigured server, you could always use \! (mysql's shell_exec, etc.) with phpmyadmin etc. to open a remote shell somewhere, then work from there.
Someone should write a script that automatically raises an issues for each line and each project, it's probably possible, but I'm chronically lazy.
And to be clear, I'm talking about providing at least one legit use for passing user input directly to exec without any kind of filtering...
He deliberately wrote vulnerable code to test his auditing script. There are more repos like this.
[1] https://news.ycombinator.com/item?id=7665232
Instead of half-assing the problem, please dedicate 10 minute of your life to look in, analyze & report one or two of the problems you find.
Also explain why you think this is an security issue.
You will:
But of course we just laugh about Perl and pat ourself on our backs with our safe new languages because we clearly know much more than those anachronistic neckbeards.
And there is some justification for that: if those "safe new languages" are doing the type checking at compile time, that is better than only finding out you have a safety issue when you fail at run time.
It's not explicit enough and it's easy enough to find legitimate code with accidental untainting of dangerous data.
Ruby requires an explicit untaint call, and IMHO it's the right way to go.
And yes, this can be encoded in the type system and you can also make it so the sanitization is context dependent, i.e. http://www.comp.nus.edu.sg/~prateeks/papers/csas-ccs11.pdf
It's leaky as hell, because all components have to get the marking right. Also, not all Objects have equal trust levels. Objects created due to a HTTP request (GET-Parameters) should certainly be tainted, but how about Object read through IO - do we trust out filesystem? Do we trust the database? Thats more of an architectural decision.
In the end, the problem comes down to this: you have to whitelist the world and everything you miss is an error.
[0] http://www.few.vu.nl/argos/?page=1
Different languages (SQL, JS, HTML, Shell, Plaintext, etc.) are treated as different types. Language-specific functions only accept arguments of the relevant type (eg. shell_exec takes Shell, db_query takes SQL, etc.). User input is Plaintext (usually; sometimes it might be something more specific like BASE64).
Different languages can't be combined (eg. SQL can't be concatenated with Plaintext), but they can be converted down to Plaintext and Plaintext can be converted to any language via escaping functions. This avoids injection attacks, since the only way to please the type-checker is by escaping properly.
[0] http://gcattani.co.vu/2013/03/a-tale-of-a-php-shell/ [1] http://php.net/manual/en/function.escapeshellarg.php
Everything that may come from a user must be filtered, escaped or generally treated as hostile.
As an example on an IRC channel someone once made their chan bot log the channel to the web, all it took was pasting javascript into an IRC window, and typing "LOL look at this! http://stupidbot.com/ircweblog". Channel pwned.
It should be easily doable to write a tool that finds an exec() of a variable that was assigned a $GET etc
PHP with its argument ordering strikes again :)
Edit: ah, most of those are Metasploit scripts.
Removing all the files from a filesystem is something only a script kiddy would do, and it's probably a "best case scenario" for the owner of the server, because the impact of that is relatively small (just re-install the server and restore the backups). But once the attacker starts injecting mallware, stealing customer information (credit card numbers anyone?) or anything else nasty they can think of that they would benefit from, then you are in a whole lot more trouble...
$device = $_GET['device']; $state = $_GET['state'];
exec( "sudo ./send " . $device . " " . $state );
EDIT: it is for home automation, but also appears to be a CS class group project.
https://github.com/search?q=exec+sudo+%24_GET&type=Code&ref=...
https://github.com/search?q=%22exec%28%24_GET%22&type=Code&r...
Otherwise there are way too many false positives. Still, 188 results is pretty awful.
$_GET['a']($_GET['b']);