lighttpd无效HTTP请求与重写规则绕过技术分析

本文详细分析了lighttpd服务器在处理无效HTTP请求时的异常行为,揭示了如何通过精心构造的请求绕过URL重写规则,访问受限资源的技术细节,并提供了多种防御方案。

无效HTTP请求与绕过lighttpd重写规则

在最近一次针对lighttpd服务器的Web应用测试中,我遇到了一个令人困惑的情况。本文将讲述如何通过两种技术手段发现lighttpd的一个有趣漏洞,最终导致意外漏洞的整个过程。

问题发现

测试过程中,客户端提供了文档根目录的列表。当我通过Burp Repeater请求secret.html时,成功获取了秘密内容:

1
2
3
4
HTTP/1.1 200 OK
Content-Type: text/html
...
This is top secret stuff you shouldn't see

但通过浏览器访问相同URL时却收到"无权查看"的提示。更奇怪的是:

  • Burp能获取秘密内容
  • 使用Burp提供的URL时curl无法获取
  • Burp生成的curl命令也失败
  • netcat尝试直接挂起

技术分析

通过Wireshark抓包对比发现关键差异:

  1. 行尾符号:Burp使用DOS格式(\r\n),而netcat使用Unix格式(\n)
  2. 路径格式:Burp请求"secret.html",而curl请求"/secret.html"

实验证明:

  • 请求"secret.html"可获取机密内容
  • 请求"/secret.html"被拒绝

根本原因

检查lighttpd配置发现重写规则:

1
2
3
url.rewrite-once = (
    "^/secret.html" => "/not_permitted.html"
)

由于规则只匹配以"/secret.html"开头的请求,因此"secret.html"请求未被重写。

绕过技术

通过URL规范化特性发现有效载荷:

1
http://example.com//secret.html

双斜线使请求变为"//secret.html",绕过正则匹配。

其他Web服务器测试

对比测试结果:

  • Apache/NGINX/IIS:均拒绝无前导斜线的请求(400错误)
  • 所有服务器都接受DOS/Unix行尾格式

防御方案

  1. 最佳实践:将敏感文件存放在文档根目录外
  2. 访问控制:使用mod_access模块
1
2
3
$HTTP["url"] =~ "^/(secret.html)$" {
    url.access-deny = ("")
}
  1. 改进重写规则
1
"^[/]*secret.html" => "/not_permitted.html"

关键发现总结

  1. lighttpd要求HTTP请求使用DOS(\r\n)行尾
  2. lighttpd接受无前导斜线的请求(其他主流服务器拒绝)
  3. url.rewrite获取原始请求路径,$HTTP[“url”]获取规范化路径
  4. 计算机行为具有确定性,看似异常的行为背后都有其规则
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计