觉得问题值得探讨,就尝试回答了该问题,并分享到公众号上一起交流
免责声明
本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。
回答原文
我猜题主想问的是,从一句话木马到读取目标机器上的文件之间,到底发生了什么。
我们可以从经典的一句话木马入手,别的答主已经贴出来了:
php @
eval
($_REQUEST[
'shell'
]);
这是php的一句话木马,所以是php代码(废话)。而php代码,由php解释器去解释执行,比如ngnix或者Apache就自带php代码解释执行的能力。
然后再看这个一句话木马的逻辑:
- 1. `$_REQUEST['shell']:获取参数名为"shell"的参数内容;
- 2. eval():解释执行php代码;
合在一起看,就是这个木马会获取参数"shell"所携带的命令,然后调用php函数eval去执行它。但是eval()只会执行php的命令,而不能执行操作系统的命令。但是php同样提供了一些函数来实现操作系统命令的执行,比如system()。
所以我们需要对一句话木马做进一层的分解,变成这样:
<?
php
@
eval
(
system
($
_REQUEST
['
shell
'])); ?>
通过eval()去调用system(),再通过system()去执行系统命令。
为什么system()能执行操作系统命令呢?php是依赖一个叫做Zend的引擎,这个引擎由C语言实现,而Zend里实现了system()的功能,就是通过调用操作系统内核提供的系统调用,实现对操作系统和硬件的一系列操作。
那么,system()具体执行了哪些命令,实现对目标机器其他资源的访问?执行的命令组合可以很多,我们挑最常见的两个命令看:
- 1. ls命令:列出目录下的所有文件
- 2. cat命令:读取文件内容并输出
所以,我们只需要传送类似/?shell="ls",?/?shell="cat /etc/passwd"。之类的命令,就能访问文件了。当然,这里面涉及到可读权限之类的限制,这里暂且不讲。
最后,执行的这些命令,具体调用了哪些系统调用?这个我们可以实战跟踪以下整个执行过程来分析:
1. 我的环境是php 8.1.27:
2. 准备一个php文件,写入我们要跟踪的命令,先看ls命令:
3. 执行"php xxx.php",成功打印了当前目录所有文件名:
4. 然后我们使用strace来追踪程序,看具体干了什么:
strace -f php
eval
.php
5. 输出很多,我们挑关键的地方看。进程会从环境变量找名为ls的程序,找到后将调用vfort()拉起一个子进程,然后子进程通过execve()调用我们主进程找到的ls程序,也就是"/usr/bin/ls",这就类似于我们在shell里输入ls
6. 然后子进程获得的ls的输出,就是当前目录的所有文件名,通过pipe2()建立一个子进程到主进程的管道,通过read()和write()完成ls输出的传送和打印:
7. cat命令也是类似的操作,先修改一下eval.php:
8. 然后strace一下,可以看到,也是找cat,创建子进程,获得输出,管道传输输出并打印几个步骤:
总结
最后我们回到问题:
一句话木马为什么能通过上传到网站的目录下,去访问服务端的其它资源?
它大概的步骤是:
携带payload请求 -> php解释执行 -> eval()函数 -> system()函数 -> Zend引擎 -> 系统调用
原文始发于微信公众号(赛博安全狗):【安全杂谈】聊聊一句话木马是如何读取服务器上的文件的
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论