来源:自学PHP网 时间:2015-04-17 13:03 作者: 阅读:次
[导读] 接上文浅谈新形势下在线Web投票系统的攻防(1),本文主要讨论一种验证码绕过的情况和利用Http请求头字段X-Forwarded-For的IP绕过。一种验证码绕过的情况上文用两种很不优雅的方式实现了...
接上文浅谈新形势下在线Web投票系统的攻防(1),本文主要讨论一种验证码绕过的情况和利用Http请求头字段X-Forwarded-For的IP绕过。 一种验证码绕过的情况上文用两种很不优雅的方式实现了案例二的刷票。当LZ同同伴准备把验证码识别和POST操作整合的时候,伙伴发现验证码原来可以不输入的,坑爹了,92%识别率的验证码破解工具派不上用场了。在仔细分析前端代码后我发现这个投票系统的验证码是js加载的:
但是! 但是这个漏洞是件郎有情,妾有意的事情,服务器为什么没有检测到验证码被禁用了没有被加载呢?后来拿到了那个系统的代码后我终于知道为什么了:
{ $_SESSION [ 'code' ] = '' ; echo '<script language= "javascript" > alert( "验证码错误,请重新输入!" ); location = "javascript:history.go(-1)" ; </script>'; exit (); } 上述$code是post过来的,是一个空的字符串,就是说$code==”";而$_SESSION['code']是不存在,空值,为$_SESSION['code']==null;而在php中null==”",两者是等价的!八阿哥就这么来了! 受该怎么办: 利用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请求被发到代理服务器后,服务器对该请求报头至少做了如下处理:
对于服务端,限制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' ]. ';' ; ?> 通过一台普通非文艺非二逼的透明代理服务器访问页面,结果(三四行的结果一样,我隐藏了):
这种情况下getip()的值就是172.23.60.145,合法并且正确。 ADSL联网后直接访问页面:
这种情况下getip()的值就是###.200.51.#9,合法并且正确。 ADSL联网后直接联网的状态下伪造http头(使用Firefox的Poster Addon,请求头Headers中加入一行X_FORWARDED_FOR=foo,如下图): 结果:
伪造得非常好,这里我没有用一个合法的IPv4地址而是一个字符串,但是数据报还是顺利到达Web服务器并被识别。之后的测试中,我尝试在headers中加了CLIENT_IP,效果和XFF一样。随便网上找了一个在线代理,其中getevn(‘HTTP_X_FORWARDED_FOR’)显示空的,这应该就是传说中的匿名代理了吧!
受该怎么办: XFF的中文wiki中提到:
因此,请求来源的IP地址(也就是REMOTE_ADDR)和 X-Forwarded-For 都应该被记录下来。通常的刷票行为往往都是短时间内伪造大量投票请求的。虽然X-Forwarded-For是不一样的,但是REMOTE_ADDR往往是不变的。短时间内检测到含X-Forwarded-For信息的投票请求的REMOTE_ADDR的请求地址相同,就应该检查该代理服务器是否是合法的。就投票来说,另外一点要值得注意的是,X-Forwarded-For信息如果有的话,应该是一个内网地址,如果是一个外网地址,那这家伙也是企图刷票吧,虽然手段不文艺不普通。 全文完毕 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com