BUUCTF-Web-[GXYCTF2019]禁止套娃
本文为记录个人信安小白的刷题路程,大佬勿喷,也同时希望文章能对您有所帮助
打开靶机,
F12查看,Burp抓包都没有获得什么信息,
使用dirsear扫描网站,
可以看到有flag.php文件,但是没有文件可以通过URL下载,
但是可以看到几乎全是/.git/目录下的文件,推测为git泄露,
使用GitHack工具,
我的是kali虚拟机root模式下下载的,
1 | git clone https://github.com/lijiejie/GitHack |
这个支持python3环境,


获得index.php源码文件,下面进行代码审计,
1 |
|
重点理解第二层检查,这个检查会有字符串直接输入的限制,
1 | if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) |
[a-z,_]+
匹配 1个或多个小写字母或下划线(即函数名,如 a, get_flag, readfile)。
例如:abc, my_func 都符合。
( 和 )
匹配 左括号(和右括号),表示函数调用。
(?R)?
(?R) 表示递归匹配整个正则表达式(即可以嵌套函数())。
? 表示递归部分是可选的(即允许 a() 或 a(b()) 或 a(b(c()))等)。
实例:
1 | a(b(c())) // 匹配成功 |
分解:
a( → 匹配 [a-z,_]+\(
b( → 递归 (?R) 匹配 [a-z,_]+\(
c() → 递归 (?R) 匹配 [a-z,_]+\(\)
最终 a(b(c())) 被替换为空,只剩 ;(如果输入是 a(b(c()));)。
解法一:
构造payload:
1 | ?exp=highlight_file(next(array_reverse(scandir(current(localeconv()))))); |
(1)localeconv()
作用:返回本地化数字和货币格式信息(关联数组)。
关键点:它的返回值是一个数组,且第一个元素是 ‘.’(当前目录)。这个函数默认返回的结果第一个数组元素就是’.’
(2)current(localeconv())
作用:获取数组的第一个元素(即 ‘.’)。
结果:返回 ‘.’(当前目录)。
(3)scandir(current(localeconv()))
作用:扫描当前目录(’.’)并返回文件列表,如:
1 | [0 => ".", 1 => "..", 2 => "flag.php", 3 => "index.php"] |
(4)array_reverse(scandir(…))
作用:反转数组,使flag.php更容易被next()获取:
1 | [0 => "index.php", 1 => "flag.php", 2 => "..", 3 => "."] |
(5)next(array_reverse(…))
作用:移动数组指针,返回第二个元素(即 “flag.php”)。
结果:返回 “flag.php”。
(6)highlight_file(next(…))
作用:高亮显示 flag.php 的源代码,直接输出 flag。
获得flag
解法二:
发现其中并没有过滤session_id函数
构造payload:
1 | ?exp=highlight_file(session_id(session_start())); |
并且传入Cookie:PHPSESSID=flag.php(HackBar和Burp都可以)
(1)session_start()
作用:启动PHP Session,如果请求中包含PHPSESSID Cookie,则使用该值作为Session ID。
返回值:始终返回 true(但这里不重要,重点是它初始化了 Session)。
(2)session_id()
无参数调用时:返回当前Session ID。
session_id() 返回当前 Session ID,即 “flag.php”。
(3)highlight_file()
作用:高亮显示指定文件的源代码(这里用于读取flag.php)。
获得flag
