漏洞描述:XFF,是X-Forwarded-for的缩写,XFF注入是SQL注入的一种,该注入原理是通过修改X-Forwarded-for头对带入系统的dns进行sql注入,从而得到网站的数据库内容。
检测条件:HTTP Header中存在X-Forwarded-for参数的调用
检测方法:
1、检测方法,通过火狐的插件X-Forwarded-for header 1.0.1.1进行对本地IP地址进行修改,为其带入的IP地址加入敏感字符。
2、修改后,找到网站登录页面或者其它功能交互页面,提交数据后,查看是否会报错,如果会报错,则说明存在该漏洞。
漏洞成因:PHP中的getenv()函数用于获取一个环境变量的值,类似于$_SERVER或$_ENV,返回环境变量对于应的值,如果环境变量不存在则返回false。
使用以下代码即可获取客户端IP地址,程序先判断是否存在HTTP头部参数HTTP_CLIENT_IP,如果存在,则赋给$ip,如果不存在,则判断是否存在HTTP头部参数HTTP_X_FORWARDED_FOR,如果存在,则赋给$ip,如果不存在,则将在HTTP头部参数REMOTE_ADDR赋给$ip。
<?php $localhost="localhost"; $db_user="root"; $db_pass="root"; $db_name="xff"; $username=$_POST['username']; $password=$_POST['pwd']; $conn=mysqli_connect($localhost,$db_user,$db_pass,$db_name); if(!$conn) { die("数据库连接失败".mysqli_connect_error()); } else { $sql="insert into user (username,pwd,ip) values ('$username','$password','127.0.0.1')"; $result=mysqli_query($conn,$sql); if(getenv('HTTP_CLIENT_IP')) { $ip = getenv('HTTP_CLIENT_IP'); } elseif(getenv('HTTP_X_FORWARDED_FOR')) { $ip = getenv('HTTP_X_FORWARDED_FOR'); } elseif(getenv('REMOTE_ADDR')) { $ip = getenv('REMOTE_ADDR'); } else { $ip = $HTTP_SERVER_VARS['REMOTE_ADDR']; } $sql1="select * from user where ip='$ip'"; $result1=mysqli_query($conn,$sql1); if($result1) { echo "<td>用户名:",$username,"</td>"; echo "<br>"; echo "<td>密码:",$password,"</td>"; }else{ echo "<script>alert('您正在新机器上登录账号,请确定是否为本人操作!')</script>"; } echo "<br>"; echo "查询的语句是:$sql1"; } ?>
接下来,将$ip拼接到select语句,然后查询结果输出到界面上。
由于HTTP头部参数是可以伪造的,所以可以添加一个头部参数CLIENT_IP或X_FORWARDED_FOR。当设置X_FORWARDED_FOR=1′ union select 1,2,3%23时,执行SQL语句为:
select * from user where ‘ip’=’1′ union select 1,2,3#’
此时SQL语句可以分为select * from user where ‘ip’=’1’ 和union select 1,2,3两条,利用第二个语句(union查询)就可以获取数据库中的数据.
漏洞复现:
在本地搭建的环境进行测试
随意输入一个账户后点击抓包
此时的返回包,显示账号密码
放到repeater进行测试
在x-forward-for:127.0.0.1后面加上’,发生弹窗提醒
在加上127.0.0.1′ and 1=1#,回显正常
后续注入过程不在演示。
修复方案:1、过滤http头中的X-Forwarded-for header中的内容,不允许其插入敏感字符,过滤字符参考sql注入修复方案。
.2、过滤以下敏感字符。需要过滤的特殊字符及字符串有:
net user xp_cmdshell add exec master.dbo.xp_cmdshell net localgroup administrators select count Asc char mid ' : " insert delete from drop table update truncate from %