代码执行&命令执行
代码执行
基础
-
用户可以通过请求将代码注入到应用中最终到WebServer中执行
-
当应用在调用一些能将字符转化为代码的函数(如PHP中的eval)时,
没有考虑用户是否能控制这个字符串,这就会造成代码执行漏洞。 -
引起的函数,过滤不严导致
php: eval() assert() 大多是因为载入缓存或者模板一级对变量的处理不严导致的,如直接把一个外部可控的参数拼接到模板里,然后调用这两个函数去当成PHP代码执行 preg_replace() 执行需要存在/e参数,参数是用来处理字符串的,多存在于URL,HTML标签一级文章内容等过滤功能 call_user_func() call_user_func_array() 多用在框架里动态调用函数 array_map() 调用并且除第一个参数外其他参数为数组 Python: exec asp: <%=CreateObject(“wscript.shell”).exec(“cmd.exe /c ipconfig”).StdOut.ReadAll()%> Java: 没有类似函数,但采用的反射机制和各种基于反射机制的表达式引擎(OGNL、SpEL、MVEL等)有类似功能测试代码
测试代码
-
eval&assert函数
-
把字符串按照 PHP 代码来计算。
-
动态执行代码,参数是php代码
<?php $data = $_GET['data']; eval("\$ret = $data;"); echo $ret; ?>
-
-
preg_replace()
-
执行一个正则表达式的搜索和替换。
-
语法
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) $pattern: 要搜索的模式,可以是字符串或一个字符串数组。 e: 设置了这个被弃用的修饰符, preg_replace() 在进行了对替换字符串的 后向引用替换之后, 将替换后的字符串作为php 代码评估执行(eval 函数方式),并使用执行结果 作为实际参与替换的字符串。单引号、双引号、反斜线(\)和 NULL 字符在 后向引用替换时会被用反斜线转义. $replacement: 用于替换的字符串或字符串数组。 replacement中可以包含后向引用\\n 或$n,语法上首选后者。 每个这样的引用将被匹配到的第n个捕获子组捕获到的文本替换。 n 可以是0-99,\\0和$0代表完整的模式匹配文本。 捕获子组的序号计数方式为:代表捕获子组的左括号从左到右, 从1开始数。如果要在replacement 中使用反斜线,必须使用4个("\\\\",译注:因为这首先是php的字符串,经过转义后,是两个,再经过 正则表达式引擎后才被认为是一个原文反斜线)。 当在替换模式下工作并且后向引用后面紧跟着需要是另外一个数字(比如:在一个匹配模式后紧接着增加一个原文数字), 不能使用\\1这样的语法来描述后向引用。比如, \\11将会使preg_replace() 不能理解你希望的是一个\\1后向引用紧跟一个原文1,还是 一个\\11后向引用后面不跟任何东西。 这种情况下解决方案是使用${1}1。 这创建了一个独立的$1后向引用, 一个独立的原文1。 $subject: 要搜索替换的目标字符串或字符串数组。 $limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)。 $count: 可选,为替换执行的次数。 搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换,当pattern处即第一个参数存在e修饰符时,replacement的值会被当成PHP代码执行
-
例子
<?php echo preg_replace("/test/e",$_GET["h"],"jutst test"); ?>
<?php preg_replace("/\[(.*)\]/e",'\\1',$_GET['str']); ?> 意思是 正则是从$_GET['str']中搜索[]中的内容作为第一次结果,preg_replace()函数第二个为\\1代表这里用第一次结果填充 这里是直接执行代码
-
-
call_user_func()&array_map()等数十个函数有调用其他函数的功能
其中一个参数作为要调用的函数名,若传入的参数名可控,则可以调用意外的函数来执行
mixed call_user_func(callable $callback [,mixed $parameter [,mixed $...]])
-
第一个参数为回调函数,后面的参数为回调函数的参数
-
测试代码
<?php $b="phpinfo()" call_user_func($_GET['a'],$b) ?>
-
-
同类型
-
动态函数执行
-
php函数可以直接由字符串拼接成
-
写法
-
利用
<?php $_GET['a']($_GET['b']); ?> 意思是 接受GET请求的a参数,作为参数,b参数作为函数的参数。当请求参数为assert是,b的参数为phpinfo()
-
防范
- 白名单过滤
命令执行
-
可以执行CMD或者bash命令
-
可引起的函数
system() exec() shell_exec() passthru() pcntl_exec() popen() popen_open() (`)反引号
-
pcntl_exec()
- 函数说明
void pcntl_exec(string $path [,array $args[,arry $envs]])
KaTeX parse error: Expected 'EOF', got '#' at position 35: …ash脚本,则需要在文件头加上#̲!/bin/bash来标识路径…args标识传递给 p a t h 程 序 的 参 数 , path程序的参数, path程序的参数,envs则是执行这个程序的环境变量
- 函数说明
-
popen(),popen_open()
-
不会执行一个结果而是返回一个文件指针,但是命令已经执行了
-
测试代码
<?php popen('whoiam >>D:/1.txt','r'); ?>
执行完后在1.txt文件里就能看到用户名
-
-
反引号命令
- 实际上是调用的shell_exec()函数
-
防御
-
防注入函数
- escapeshellcmd()过滤一整条命令
- escapshellarg()保障参数是以字符串参数形式存在,不能被注入
-
白名单