Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Every C99.php shell is backdoored (thehackerblog.com)
130 points by chewxy on June 24, 2014 | hide | past | favorite | 91 comments


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.

[1] https://blog.avast.com/2014/06/09/are-hackers-passwords-stro...

[2] https://github.com/kijin/qade


What about putting it behind https and use basic http auth? If it's only for you you can always have a self signed certificate.


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.


Why would anyone who's not completely insane install anything like C99 in the first place?

Not only is the idea completely nuts, but all Google produces for C99shell is how it's used in backdoor tools.

Surprises: Zero.


Apparently it's mostly used by script kiddies who compromise someone else's server and install it.


Well, I hope someone tells them their backdoor has been compromised.


This is exactly what it's used for.


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.


It's also useful when your PITA sys admin won't give you SSH but also hasn't taken any precautions against exec.

Of course, the better solution is to leave ASAP...


What should people use?

C99shell is easy to use and common.

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.


I've used it in the past so I could run commands on a server, when the administrator only gave me FTP access.

Uploading PHP files with system() calls works too, but C99 is much easier to use.

But yes, I only came to know it when I was a stupid defacer teen. Shame on me.


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.


Maybe I live in a place where technology (and security practices, specifically) goes forward later than Silicon Valley?

(Answer: yes)


Why would anyone who's not completely insane use anything like php in the first place?

There are always reasons, sometimes valid reasons, to do insane things.


In all my years of writing PHP code I have yet to find a legitimate use case for extract() - PHP should have gotten rid of it generations ago.


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."

Oh, Bog....


> This is the anti-Scheme.

Since when is Scheme the arbiter of what is good or bad?

PHP lets you do this, or not do this, your choice. Like C, PHP doesn't tell you what to do, it's up to you.

That's why people actually use it.


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.


If this is the quality of the argument then I have nothing to concern myself with.

Your post might be [slightly] humorous, but as an argument against PHP language constructs it fails miserably.


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.


Yup, then you see people building sine wave roads for the square wheels they build last week.

Or making critical parts of infrastructure work by a cron job that calls wget.

For some reason PHP needs extract, because a dictionary just won't do.

  foo["var_x"]

  // for some reason needs to be:

  $var_x


I think you mean catenaries, not sine waves.


> "Let's make a function that has the side effect of introducing variables into scope. That's a great idea."

And ``let'' is? ;-)

Doing a (let [request] (check-auth ...)) would be equally dumb. Let's not blame the tools.


That's not not how 'let' works, you can't do that with 'let'. You most definitely should blame the tools here.


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 is when unexpected variables are overwritten. It would be better to have a mandatory list of allowed variables that can be extracted.

    $login = '1234';
    extract(array('login'=>true, 'messsage'=>'hacker'), 'message');
    var_dump($login_, $message);
    // => $login='1234', $message='hacker'
(pardon my rusty PHP)


> variables are overwritten. It would be better to have a mandatory list of allowed variables that can be extracted.

You can set the EXTR_SKIP flag to do something like that. There are a bunch of other flags as well to control how it works.


Or you could do this:

    function qux() { return [$foo, $bar, $baz]; }

    list($foo, $bar, $baz) = qux();


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:

    qux = () -> {blah: "a", blorp: "b", zoop: "c"}
    {blah, blorp, zoop} = quz()


Yah, I do that when it's just a few variables, but it gets unmanageable when the number starts increasing.

It's also error prone if you have several feeder/user functions since you have to change them in multiple places.

Or if you have two code paths that end up with two different sets of variables (probably controlled by a semaphore variable) then this won't work.


This smells like an antipattern. I can't imagine a reason for wanting to do this that isn't a result of some very poor architectural choices.


I've found exactly two:

Ghetto templating (using a PHP file as a template). Extract an object from the database into local vars to echo in the "template".

Parsing fixed width files, zip the columns with their names, then extract in the processing function.

In both cases you know exactly which vars are being replaced. The real WTF is extract on $_{REQUEST,GET,POST,SERVER,...}.


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.


I think it is a useful construct for specifically the scenario it is mis-used in here. Overriding default values, or a kwargs polyfill

    function foo($option1=1, $option2=2, $option3=3, $option4=4) {
        //do stuff with params
    }
this is unwieldy and difficult to reason about when you see it used, especially if you are trying to use some of the initial default values. ie.

    foo(null, null, null, 10)
vs.

    function foo($options) {
        $option1 = 1;
        $option2 = 2;
        $option3 = 3;
        $option4 = 4;

        extract($options);

        //do stuff with params
    }
With this, you can just do

    foo(array('option4'=>10));
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.


We typically handle that by having a $defaults array, then array_merge($defaults, $options) in the function.


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).


Wordpress shortcodes, to extract variables from an array into local scope. Works great and even lets you set default values easily.


I agree with you, but here the problem is not the extract() call as everyone here seems to imply.

The security problem lies in the fact that the authentication code is conditionally called depending on user input.

    if ($login) { … }
is not less safe than

    if ($_POST['c99shcook']['login']) { … }
would have been.


I'm pretty sure $login can be set to true/false somewhere on top of the file as 'configuration'. Only it gets overwritten by the call to extract().

It was not meant to be user input


I feel stupid. Of course, you are right.


Don't feel stupid. This is difficult to reason about, hence the existence of the bug and the inadvisability of PHP's `extract` function.


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.


You are setting yourself up for a reflected request forgery attack.


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.


Exactly, I'm all for getting rid of black magics such as extract() and compact().


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.

http://www.securityfocus.com/news/203 http://en.wikipedia.org/wiki/Max_Butler#FBI_investigation.2C...


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.

Legally: again, don't do it. It's not yours.


>> "a can or worms"

There's a typo ...

and I'm afraid "bad hackers" react even more quickly,

so I'm hoping "good hackers" can hurry ...

but watch out! Don't mess things up and cause a disaster :O


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.

Example: https://github.com/search?l=PHP&p=1&q=extract%28%24_GET%29%3...

Yuck...



Got confused for a minute. Why the hell call your shell after a C language standard? Also, the term "shell" is terribly overloaded nowadays.


> due to a vulnerability in the extract() command

No.

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.


Right, didn't mean that in the original post - obviously this is how the function is designed to work. Fixed up the wording to clarify.


After reading these comments I am intrigued. Whenever I have used PHP I pretty much always run extract three times:

    extract($_GET, EXTR_PREFIX_ALL|EXTR_REFS, 'gVar');
    extract($_POST, EXTR_PREFIX_ALL|EXTR_REFS, 'pVar');
    extract($_COOKIE, EXTR_PREFIX_ALL|EXTR_REFS, 'cVar');
It makes working with get/post/cookies much easier. All variables are extracted with a prefix... so:

http://www.yyy.com/script.php?hello=world Results with: $gVar_hello being the variables holding 'world'.

Is this poor form?

I previously used: `import_request_variables` - but thats been sidelined.


Why is using $gVar_hello easier than $_GET['hello']? Also $_GET and friends have the benefit of being super global.


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?


First: this could result in:

  echo $blah; // hi <script>alert('foo');</script>
But maybe it's just because you posted an example...

Second: it will double the memory used.

Third: you can't use the variables global anymore


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.


If I am not mistaken, PHP is copy-on-write, so if extract just copy value then memory usage wouldn't be doubling.


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.


haha yeah that is true, when they said import_request_variables was being removed I was so close to just forgetting the idea of doing what I am doing.


You missed out the sanitizing of the input just for this example, right!?


of course!


  $blah = "hi $_GET[hello]";


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.


A tool that's pretty much only useful for hacking is backdoored? Heaven forbid!

How is this even news?


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.

Of course - correct me if I'm wrong here.


actually, google is pretty far ahead of this. trying searching allinurl:c99.php, most of the returns are actually about the script.



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.


So... what's the best way to tell if C99 is "installed" on your server(s)?

    grep -Ri c99 /path/to/htdocs 
would be my guess


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.


I just deployed a lot of these for fun on Heroku. Really interesting stuff. http://php-c99.herokuapp.com/


I thought everyone knew this already ~10 years ago...


Is this a joke?


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.


Are you recommending us to use your software on servers that we compromise?


Absolutely not, recommending Commando.io for anybody looking for a web-based SSH interface for servers they rightfully manage.


;)


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: