网站地图    收藏   

主页 > 后端 > 网站安全 >

浅谈新形势下在线Web投票系统的攻防(2) - 网站安

来源:自学PHP网    时间:2015-04-17 13:03 作者: 阅读:

[导读] 接上文浅谈新形势下在线Web投票系统的攻防(1),本文主要讨论一种验证码绕过的情况和利用Http请求头字段X-Forwarded-For的IP绕过。一种验证码绕过的情况上文用两种很不优雅的方式实现了...

接上文浅谈新形势下在线Web投票系统的攻防(1),本文主要讨论一种验证码绕过的情况和利用Http请求头字段X-Forwarded-For的IP绕过。

 

一种验证码绕过的情况

上文用两种很不优雅的方式实现了案例二的刷票。当LZ同同伴准备把验证码识别和POST操作整合的时候,伙伴发现验证码原来可以不输入的,坑爹了,92%识别率的验证码破解工具派不上用场了。在仔细分析前端代码后我发现这个投票系统的验证码是js加载的:




刷票过程中模拟http post操作时直接把response的响应流读取出来进行处理,没有对html进行解析,这句<body onload=”getcode();”> 中的js函数压根就没有被执行,而这个getcode()的作用是加载并显示验证码文件/getcode.php。这样验证码就没有被读取,服务器那头用来校验验证码也是没有被更新过的(还是最近一次的值或者是初始化的值),看到这里如果你不懂怎么回事儿,建议仔细思考下验证码机制的工作原理。这也不能算是个bug,因为要是有意这样的效果也是不能避免的。在浏览器要产生这样的效果,有一种方法是不让浏览器加载/getcode.php这个页面,方法可以是Firefox的Autoproxy中对这个验证码图片页面url设置一个根本不存在的代理,这样这个图片就加载不了了。

但是!

但是这个漏洞是件郎有情,妾有意的事情,服务器为什么没有检测到验证码被禁用了没有被加载呢?后来拿到了那个系统的代码后我终于知道为什么了:
在处理投票post请求的代码中发现了这么个有bug的判断

if (strcmp($code, $_SESSION['code']) != 0)

 

{
$_SESSION['code'] = '';
echo '<script language="javascript">
alert("验证码错误,请重新输入!");
location = "javascript:history.go(-1)";
</script>';
exit();
}

上述$code是post过来的,是一个空的字符串,就是说$code==”";而$_SESSION['code']是不存在,空值,为$_SESSION['code']==null;而在php中null==”",两者是等价的!八阿哥就这么来了!


受该怎么办:
$_SESSION['code']初始化为一个非法的值,判断的时候再判断一下$_SESSION['code']的值是否合法。

 

利用X-Forwarded-For的IP绕过

终于讲到本文的正经内容了,写这篇文章初衷其实就是讨论下IP绕过,但是又觉得讲IP绕过不讲刷票有点欠缺了,纠结了很久。

IP绕过的核心是HTTP协议头X-Forwarded-For的伪造,前几天我闲着蛋疼,就把Wiki上的X-Forwarded-For词条英文版照抄全部翻译了一遍,在此,我想尽量表达完整英文版的意思,所以语言非常的生硬。关于这个协议字段头的官方文档在此

从HTTP层上简单地讲:如果你的IP是10.23.231.23,通过一台透明的代理服务器上网,比如代理地址是10.23.231.1:8080,你请求一个web页面,这个HTTP请求被发到代理服务器后,服务器对该请求报头至少做了如下处理:

  • HTTP请求头上添加了X-Forwarded-For:10.23.231.23这么一行
  • 如果特殊必要,HTTP请求头上添加了CLIENT_IP:10.23.231.1这么一行

对于服务端,限制IP用的IP获取代码大多类似:

 

 

//传说这段代码是Discuz!中的,非常完整地表述了正常情况下访客的真实IP
function getip() {
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$onlineip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
$onlineip = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
$onlineip = $_SERVER['REMOTE_ADDR'];
}
return $onlineip;
}

上面总共有三个字段HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR、REMOTE_ADDR 我在这里找到了解释并验证通过!验证过程如下:

感谢同学借美国主机给我做测试:

测试代码:

 

 

<?php
echo '<p>getevn(\'HTTP_CLIENT_IP\')='.getenv('HTTP_CLIENT_IP').';';
echo '<p>getevn(\'HTTP_X_FORWARDED_FOR\')='.getenv('HTTP_X_FORWARDED_FOR').';';
echo '<p>getevn(\'REMOTE_ADDR\')='.getenv('REMOTE_ADDR').';';
echo '<p>$_SERVER[\'REMOTE_ADDR\']='.$_SERVER['REMOTE_ADDR'].';';
?>


通过一台普通非文艺非二逼的透明代理服务器访问页面,结果(三四行的结果一样,我隐藏了):


getevn(‘HTTP_CLIENT_IP’)=;
getevn(‘HTTP_X_FORWARDED_FOR’)=172.23.60.145;
getevn(‘REMOTE_ADDR’)=###.##.171.119;
$_SERVER['REMOTE_ADDR']=###.##.171.119;

这种情况下getip()的值就是172.23.60.145,合法并且正确。

ADSL联网后直接访问页面:

getevn(‘HTTP_CLIENT_IP’)=;
getevn(‘HTTP_X_FORWARDED_FOR’)=;
getevn(‘REMOTE_ADDR’)=###.200.51.#9;
$_SERVER['REMOTE_ADDR']=##.200.51.#9;

这种情况下getip()的值就是###.200.51.#9,合法并且正确。

ADSL联网后直接联网的状态下伪造http头(使用Firefox的Poster Addon,请求头Headers中加入一行X_FORWARDED_FOR=foo,如下图):\

结果:

getevn(‘HTTP_CLIENT_IP’)=;
getevn(‘HTTP_X_FORWARDED_FOR’)=foo;
getevn(‘REMOTE_ADDR’)=###.200.51.#9;
$_SERVER['REMOTE_ADDR']=###.200.51.#9;

伪造得非常好,这里我没有用一个合法的IPv4地址而是一个字符串,但是数据报还是顺利到达Web服务器并被识别。之后的测试中,我尝试在headers中加了CLIENT_IP,效果和XFF一样。随便网上找了一个在线代理,其中getevn(‘HTTP_X_FORWARDED_FOR’)显示空的,这应该就是传说中的匿名代理了吧!

 

受该怎么办:

XFF的中文wiki中提到:

完整起见,Web服务器应该记录请求来源的IP地址以及X-Forwarded-For 字段信息。

因此,请求来源的IP地址(也就是REMOTE_ADDR)和 X-Forwarded-For 都应该被记录下来。通常的刷票行为往往都是短时间内伪造大量投票请求的。虽然X-Forwarded-For是不一样的,但是REMOTE_ADDR往往是不变的。短时间内检测到含X-Forwarded-For信息的投票请求的REMOTE_ADDR的请求地址相同,就应该检查该代理服务器是否是合法的。就投票来说,另外一点要值得注意的是,X-Forwarded-For信息如果有的话,应该是一个内网地址,如果是一个外网地址,那这家伙也是企图刷票吧,虽然手段不文艺不普通。

全文完毕


作者 McKelvin's Blog

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论