The whole thing is a backdoor. Backdoor in a backdoor? Surprise! Of course it's backdoors all the way down ;)
But of course, script kiddies aren't particularly good at securing the servers they pwned, are they? [1]
A couple of months ago, I wrote QADE [2] for fun, a "quick and dirty" PHP-based text editor and webshell for editing files and running commands remotely. I deliberately failed to implement any authentication-related feature, because I didn't want to give an illusion of security. A secure webshell is an oxymoron.
That's exactly what I do with my own installation of QADE on my dev box. The README on GitHub recommends others to do the same, since it's pretty much the only way to make QADE secure.
Indeed, in years of writing PHP I only know of C99 because I found endless copies of it squirreled away, obfuscated, appended to other files, base64 encoded, and/or masquerading as jpg files after one of our servers was compromised.
Why is it nuts?? You're using it for quick and easy defacements and compromises.
This is a numbers game often from people with low skill levels. I see no issues here at all. If your defacements were getting quickly taken back by another crew it might be an issue, but I've seen no evidence of this happening.
Just because there's a security issue it's not the end of the world. Risk management still comes into it.
Easy to use = more defacements. Might have a hole, well is there evidence we are losing enough defacements to justify the retraining of the crew and added costs?
And more importantly, be agile. Defacements getting retaken over at unacceptable levels, just move to a different product.
If the only tool you have is FTP then either you're an attacker with a single set of compromised credentials, or a legitimate user forced to act like one.
Frameworks tend to use it, to create variables in a view that were sent from a controller. For similar usecases it also makes sense (you want a bunch of variables created from an associative array).
It's not terribly bad if you use it inside a function or method. Creating global variables is what causes all the issues, but then again, if you're handling global variables, you're asking for trouble anyway.
What's really bad about extract() is that the default behavior is to overwrite existing variables. This is just a recipe for disaster, no less than the infamous register_globals.
I once wrote a framework where the controller would pass variables to the view as $view->currentUser and the template would access it as $currentUser instead of the more verbose $this->currentUser. This was implemented with extract(), but I went to great lengths to make sure that the scope was clean.
PHP probably ain't gonna get rid of extract() any time soon, but at least they should change the default to EXTR_SKIP.
You can use it to pass a bunch of variables between functions, without having to constantly get them from an array.
function qux() {
return compact('foo', 'bar', 'baz');
}
And in the other function:
extract(qux());
You can have one "preparer" function that works on the data and sets up the variables, then several others that work on it, and all call the same preparer. Or the reverse.
Obviously you can do the same thing by just passing arrays but sometimes a simple variable is easier and less cumbersome.
... and to think that my contempt for PHP couldn't be increased.
Wow. This is the anti-Scheme. It's like they took everything good in language design and decided to do the exact opposite. "Let's make a function that has the side effect of introducing variables into scope. That's a great idea."
Just because something is being used widely does not make it right, nor should it be held up as a fine example of design.
Language hacks like the one we're discussing are fine IF:
- You work with people who avoid bad features.
- You can avoid using code that uses bad features (less of a problem, until you have to debug things and then you're in a world of hurt).
- The features are not short-sighted hacks that prevent the language from moving forward (e.g., eliminate the opportunity to make things faster through dynamic compilation or whatever).
Scheme is a great language that is not useful in the real world, while PHP is a terrible language that happens to be in wide use. Neither of these positions are unique, and honestly I'd much rather use a bad language with good tooling than a great language with poor support. But I will continue to point out PHP's flaws, which are many and just howling bad, and work towards improving the alternatives.
Exactly, what's wrong with a double clawed hammer?
Use it or not, if you don't like it you can smash stuff with the triblade screw driver. Or the 7 point socket wrench.
PHP provides a wealth of very useful tools that you can choose to use or not. I don't know why people think my 7 point socket wrench is dumb, it works quite well to round the edges of 6 sided bolts and saves a lot of money on buying those special bolts that can't be removed once tightened.
It really doesn't. Especially when you see people pulling out the double claw hammers at your company.
Features that have limited real benefits with lots of risk get abused all the time. They are the retarded tools of the world creating technical debt for everybody else and they should be retired.
Extract is one of the stupidist language feature conceived precisely because it puts something so ripe for abuse into the hands of idiots. It even has a simple name that practically encourages its abuse.
You're right, let is a macro so you can't pass binding forms from a variable, my mistake. But surely Scheme has some function for binding variables to the local scope...
My point is that trusting user input is the error, not having the ability to play with the scope.
Scheme has forms that add bindings to the local scope -- local defines -- but they're similar in spirit to let. There aren't any such functions in standard Scheme, and I don't know of any major implementation that has any. It's not clear how they would interact with macros or macro hygiene, and they would do unpleasant things to lexical scope which is Scheme's original schtick.
The problem with this is that it leaves things without any obvious, canonical, name. You have to read a bunch of code to figure out what's going on and a change in the values returned may result in subtle errors.
Coffeescript has a really neat destructuring operator for this kind of thing:
I wouldn't use the word "exactly" (high chance?): f.ex. where did the fixed width files come from? If it's from some (external) other system you're already have an attack vector.
> f.ex. where did the fixed width files come from?
Encrypted and signed files sent over the wire from a company we do business with. Additionally I was just pairing the values up with local names that I chose (the fixed width file had no column names itself, they sent us a word doc (ugh)). And the function that called extract had exactly one local, the array I built representing a row from the file (unused after the initial call to extract).
Extract also lets you prefix the extracted vars, avoid overwriting name collisions, etc. http://php.net/extract
The code from this article is unsafe because it directly operates on user input, was not explicit about what values were required (you can filter an array by key easily enough...) and doesn't isolate the environment it's extracting in. That's the unsafe behavior.
obviously its a preference thing, but I think it is a somewhat harmless use case. If there are any params which you do not want to be overriden you move them beneath the call to extract.
Yep, totally valid, and like I said basically a preference thing.
I personally like to work with explicit variables within the function rather then array indices. With your system I could easily call extract on your resulting array, but I also like defining the variables I want overridden explicitly in code so I my IDE doesn't think they are undefined (though JetBrains does a pretty good job of determining which variables are being created by extract in most scenarios anyway).
Drupal uses it to implement templates. I always got the feeling that it's one of those language features where you want to take a deep breath before using it; sort of like when you type `rm -rf *` and haven't pressed enter yet.
It makes perfect sense when PHP is actually being used as a backend-isolated, controlled-environment templating language.
Imagine this setup:
1. you have Nginx at $DOMAIN, with your well-oiled API service (with no HTML rendering logic to be found within it) mounted to /, and a PHP FCGI instance sitting on /views.
2. Nginx is configured such that /views is only accessible from localhost.
3. Your webapp on / mostly sees requests with "Accept: application/json" or some such. It responds to these directly.
4. If your webapp sees "Accept: text/html", it does the same stuff it would to render a text/json response... but then takes that response body, and sends it in an HTTP subrequest back to Nginx, to, say, /views/accounts.php.
5. PHP does this:
extract(json_decode($_POST['response']));
...and then does whatever it does, simply and elegantly, to render your template.
6. Your webapp catches the response from Nginx, and sends it back without modification to the client.
The way PHP allows fluid, dynamic interaction with the symbol table is pretty nifty, I think, and even if there were no extract() function built into the language, you could implement it yourself out of other primitives. I'm not one that believes that any feature of a language that can be used in dangerous ways should be eliminated (anything can be dangerous). I just think extract() is one that you ought to think carefully about before using. This example ought to reinforce that.
Agreed. The sane alternative is to extract specific, expected inputs to scope once they have been filtered and escaped. Any API I've written has this sort of validation built-in.
I have only every seen the c99.php shell used by script kiddies which utilizes some well known php vulnerability and uploads this as the control point.
It would be cool if somebody wrote an automated script which would seek out these c99 and try to identify those which are used on hacked sites. It could then use this to get access and remove this script and fix the original exploit.
Using exploits to help people is of course a can or worms but I like the idea of good hackers helping everyone.
Please don't do this. Max Butler did that to DNS in 1998 with patching bind (plus a backdoor). He went to prison 18 months. Then coming back out, he ended up doing carding and back to prison.
Fixing a broken BIND and then installing a backdoor is a much different kettle of fish than just writing a worm that fixes the bug and then walks away.
That said, I would agree completely that it's very legally dangerous. If it's not yours, don't mess with it!
As an academic matter, I think such a worm could end up being socially useful, if there are enough compromised machines and the people running them are sufficiently incompetent and those machines are being used against other people and you can be sure that your fix doesn't break something else and the machines just won't get re-compromised again next week. That's too many conditional clauses for me, but maybe someone else feels like taking one for the team.
I'm actually disgusted to see how many people use extract in bad ways! As some others here have mentioned, I've never found a legitamate reason to use extract - and the php documentation clearly mentioned not to use it on input data.
This is due to insane usage of the extract() function. Not a vulnerability with the function itself.
You can pass user-supplied input directly to plenty of other functions which have equally idiotic outcomes, it doesn't mean that they have vulnerabilities, it means the author is a liability.
It is easier to use in strings, `$blah = "hi $gVar_hello"` rather than $blah = "hi {$_GET['hello']}";`.
Not that it is a massive deal... I guess I just got in the habit when I was younger. Like I said, I always used import_request_variables (with various prefixes).
----
But back to my question - is it bad to use like I have?
Like you said, I wouldn't use it without first cleaning the input.
I guess I use it more out of habit and preferring a straight variable to an array... just feels neater.
Good point on the memory, but I wouldn't think thats a big issue.
I haven't tested right now, but I dont remember ever having issues using the $_GET variable after exporting?
Not sure if thats what you meant.
Well, like most coding bad practices, plenty of which I'm guilty of too, it's fine until it's not -- and then it's really bad.
I can't immediately think of a practical way to make a problem out of that. But, you're making a couple of bets here: you're betting that there never will be a problem with it, and you're betting that the rules in PHP won't change in the future. All those folks that relied on magic_quotes already got boned by that second bet.
So, no, I wouldn't do it that way, but I wouldn't criticize you for it either.
Yes this is poor form. Prefixing, you don't have to deal with serious security issues, but this is just a step you really don't have to take--if this is part of your normal "bootstrap" you're likely doing it wrong.
I think the trouble is now, if this was just released, is that you can easily google for c99.php and find vulnerable servers with this file hosted on it, from pre-existing backdoors/phishing hosts, or what have you, and this allows anyone and everyone to use it, not just the original person who placed the backdoor. Which, I suppose, kind of enhances the problem exponentially.
As far as I'm concerned though, Google and Firefox's malware checker engines should blacklist any domain that has the c99.php file located on it and block their webbrowsers from connecting to it in the first place.
The only reason you have C99 on your server is because you've already been hacked. Its' one of the oldest shells used for backdooring a hacked site - you rarely see it anymore because there are much better shells now.
There are thousands of variations of C99 used by various 'hackers'. Many of which are obfuscated (base64, gzip, other more obscure encodings). Generally, searching for a combination of 'base64_decode', 'gzdecode', and 'eval' will find a great deal of them. Others may require more manual inspection. Just searching for 'eval' alone tends to find a lot.
There are a few tools floating about that try to use a more signature-based approach to searching, and clamav has some signatures for the shells, but they can be hit-and-miss, as the obfuscation often changes.
Is the C99.php shell any popular? This is such a classic exploit of `extract()` that it seems like very amateurish job. If they even use this function at all I imagine the rest of the script is not that secure either.
Founder of https://commando.io. It is utterly frightening that anybody would consider using c99. If you're interested in a parallel SSH web-based interface, check us out. Commando.io does not provide an interactive shell, but instead operates through pre-defined scripts we called recipes (written in shell, bash, perl, python, ruby, go, or node.js). Recipes are fully versioned, and we keep a full audit trail of all executions run on your infrastructure.
People are messing with you because C99 is used almost exclusively by script kiddies as a web shell into servers they compromise. Almost no one has ever used it as an actual administration shell for their own servers.
Or we could, you know, use SSH (and sudo if we were so inclined). I don't think anyone uses a PHP shell willingly unless they're trying to do something they shouldn't.
But of course, script kiddies aren't particularly good at securing the servers they pwned, are they? [1]
A couple of months ago, I wrote QADE [2] for fun, a "quick and dirty" PHP-based text editor and webshell for editing files and running commands remotely. I deliberately failed to implement any authentication-related feature, because I didn't want to give an illusion of security. A secure webshell is an oxymoron.
[1] https://blog.avast.com/2014/06/09/are-hackers-passwords-stro...
[2] https://github.com/kijin/qade