0x00 HEAD注入

head注入的注入点在数据包的请求头部分。与之相对的有Cookie注入等。

很多网站会获取访问者的IP地址、浏览器标识等信息,并将其记录在数据库中,便于用户下次访问时进行某些提醒(如异地登录等)。而访问者的这些信息通常包含在发出请求数据包的请求头(HEAD部分)中。因此在普通传参做了防护措施时,可以在HEAD部分构造语句进行注入。

0x01 产生原因

在PHP中,超全局变量 $_SERVER 通常会获取请求头中的一些信息。如:

$_SERVER['HTTP_USER_AGENT'] 获取当前请求数据包的User-Agent内容

$_SERVER['REMOTE_ADDR'] 获取当前请求包的IP地址

$_SERVER['REQUEST_URI'] 获取当前URL

等。$_SERVER功能强大,但不当使用会造成SQL注入。

0x02 产生条件

1、使用了$_SERVER获取数据并进行数据库操作

2、对数据过滤不严格

0x03 代码审计

head注入1.png

第15-28行定义了一个form表单用来提交用户的登录数据,数据提交给自身。

head注入2.png

第66行定义了两个变量,$uagent和$ip,分别用$_SERVER 获取了User-Agent和IP地址。

head注入3.png

第76、77行调用了 check_input() 函数对输入的数据进行检查,这个函数定义在第37行

head注入4.png

第39行,如果传入的值不为空,则取这个值的前20个字符。

第46行,调用 get_magic_quotes_gpc() 函数对其进行转义

第52行调用了ctype_digit()函数对值进行判断:

ctype_digit():主要功能是检测字符串中的字符是否都是数字,负数和小数会检测不通过,且检测内容必须是字符串。

如果检测不通过,则会执行if()语句中的内容:调用mysql_real_escape_string()函数对其进行处理:

mysql_real_escape_string:转义SQL语句中使用的某些特殊字符。

并且在首位分别添加一个单引号。

回到第79行,将处理后的变量uname和passwd拼接进SQL语句执行,如果返回结果(登陆成功),会进入第82行的if()语句,否则提示错误。

第85行,将变量uagent、IP、uname拼接进SQL语句,插入到数据库中。而uagent、IP两个变量是直接用$_SERVER获取的,中间没有任何过滤。

因此判断在head部分存在SQL注入。前提是必须要输入正确的账号密码。

0x04 靶场复现

正常登录会返回IP地址和User-Agent信息

head注入5.png

输入admin/admin,点击登录并抓包,发到Repeater

正常返回包长度为1793

head注入6.png

修改User-Agent,添加一个单引号,发现返回SQL语法错误

head注入7.png

根据返回,构造语句

获取数据库名

head注入8.png