在一个偶然的机会下,一位美女黑客向我询问有关php验证码的问题,我才知道一个叫三叶草的安全组织正在举行信息安全技术大赛。
于是我看了一下题目,难度还是挺高的,由于比赛期间不能泄漏答案,于是等到今天才写出一些题目的攻略。
打开 http://code1.myclover.org/Default.aspx ,可以看到以下界面:
这道题要求在60秒内提交60次验证码,我看了一下,发现还是有点难度的,最后用了一个比较特殊的方法完成。
打开firebug,点击go按钮,跳转到提交验证码的页面:
这时看一下firebug捕获的请求:
可以看到点击按钮后向Default.aspx提交(POST)了一次数据,还有获取(GET)了Match.aspx和Code.aspx页面的数据。
1、首先看一下Default.aspx提交的参数。
提交的参数用php可以写成:
$post = array( 'Button1' => 'Go!', '__EVENTVALIDATION' => '/wEWAgLyjPLGBgKM54rGBmPDqObMucxXxtsHOLHUVmjnku17WnTdivWFADL9ShD4', '__VIEWSTATE' => '/wEPDwUKMjA0OTM4MTAwNGRkkuXw0Thu//c7r9Pfb1F+JxSPHeM6sKURi786gPIAgNE=' );
其中'Button1'的值是固定的'Go!',那么'__EVENTVALIDATION'和'__VIEWSTATE'是从哪里获取的呢? 查看Default.aspx的网页源码,可以发现源码里有两个隐藏域:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEWAgLyjPLGBgKM54rGBmPDqObMucxXxtsHOLHUVmjnku17WnTdivWFADL9ShD4" /> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEPDwUKMjA0OTM4MTAwNGRkkuXw0Thu//c7r9Pfb1F+JxSPHeM6sKURi786gPIAgNE=" />
所以提交数据之前要先获取Default.aspx的源码,匹配出这两个隐藏域,再提交数据。
2、查看Default.aspx提交数据后服务器的响应头信息。
我们感兴趣的是Set-Cookie信息:
Set-Cookie ASP.NET_SessionId=ynb5mevekohm00ow0wszmrfo; path=/; HttpOnly Star=1HrpUk4vFyGyGBLmqVg1BNWvnTsr/N8A8NB6ih4u/fI=; path=/
其中ASP.NET_SessionId值是用户与页面会话的标识。
Star值相当于标识了用户点击Go!按钮的时间。
用户点击了Go!按钮,服务器会记录点击的时间,正确提交60个验证码后,服务器会判断开始时间和最后提交的时间差,如果时间差小于60秒,就会显示过关的key。
3、获取Match.aspx页面的源码。
网页源码中也有同意的隐藏域,提交验证码时要用到:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMjYxMjUwMDUwZGS8D8v8uuSQ6rLtNG29gJP//sHvMScyfWHzWAIAiuZDlQ==" /> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwKK29znBwLs0bLrBgKM54rGBu8AlJPAD4CBCYKKKwuQqrQBlSp5MkeP+9MlpGQSykvw" />
4、获取Code.aspx的信息。
可以看到页面返回一张验证码图片,而且响应头信息中有Set-Cookie,CheckCode是该验证码图片的唯一标识:
Set-Cookie CheckCode=E033FDB11F1FAAD86C9A492D4696EC31; path=/
5、填写验证码后点击SUBMIT按钮,发现是向Match.aspx提交数据,查看提交的参数:
提交的参数用php可以写成:
$post = array( 'Button1' => 'SUBMIT', 'TextBox1' => '5191', '__EVENTVALIDATION' => '/wEWAwKK29znBwLs0bLrBgKM54rGBu8AlJPAD4CBCYKKKwuQqrQBlSp5MkeP+9MlpGQSykvw', '__VIEWSTATE' => '/wEPDwUJMjYxMjUwMDUwZGS8D8v8uuSQ6rLtNG29gJP//sHvMScyfWHzWAIAiuZDlQ==' );
其中'Button1'的值是固定的'SUBMIT','TextBox1'是验证码,隐藏域的值是在第3步中获取的。
综上所述,要完成验证码提交,需要完成以下步骤:
1、获取首页Default.aspx的源码,匹配出隐藏域的值。
2、模拟点击Go!按钮提交数据。
3、获取Match.aspx网页源码的隐藏域的值。
4、访问Code.aspx,获得验证码图片,自动识别成验证码数字。
识别验证码可以参考这篇文章:php实现验证码的识别(初级篇)。
5、模拟点击SUBMIT按钮提交验证码。
6、重复步骤456,一共重复60次。
7、注意每次请求都要发送和保存cookie。
但是由于我的网速和代码执行速度比较慢,所以每次都要执行60秒以上:
由于代码是php写的,但php又没有多线程,所以时间总是超过60秒,最后用了一种方法来模拟多线程。方法就是开两个页面来跑php代码,把代码分成3个文件:
submit.php :用来模拟提交验证码,验证码图片保存到valid.gif,cookie保存到cookie.txt。
submit2.php :和submit.php差不多,验证码图片保存到valid2.gif,cookie保存到cookie2.txt。
go.php :用来模拟点击Go!按钮,然后把cookie保存到cookie.txt,然后复制一份为cookie2.txt。
这样执行go.php后,cookie.txt和cookie2.txt有相同的ASP.NET_SessionId值和star值。
再同时执行submit.php和submit2.php,这两个脚本获取的验证码图片和验证码cookie都会保存在不同的文件里,所以不会互相干扰。
每个页面执行了40多秒,于是成功地获取了过关的key:
源码下载
好吧,活动结束后,出题者的话:“我的code.aspx在OnLoad时间里面会生成验证码并md5存cookie。只要你们通过发包的形式。只请求一次code.aspx。后面都同样的验证码即可。”看来以后做题前还是要多分析分析。
2014/05/31 18:45:13
好牛啊,,,大神,学习中
2013/10/17 19:02:28
firebug 太爽了
用curl模拟post提交 得到了360云盘的外链
2013/10/17 19:27:48
现在发现用python的话一下子就搞定了,python也可以用curl
2013/09/05 15:21:06
2013/06/04 06:40:36
想到了当年那个666666游戏和去年的光棍节程序员闯关秀。题目没有这个这么难和正规,属于游戏性质,胜在解题思路很奇葩。特别是那个666666游戏,着实火了一阵,也一定程度上普及了一些网络安全知识。
2013/06/02 19:12:44
..这种题按题目走肯定是错的…比如有题问 鸟叔在 江南style里摇了多少次手…结果是用删掉cookie,不断暴力提交就可以了
2013/06/03 21:14:19
是的,不过在不能作弊的题目里,就只能这样分析了,所以我才把这些步骤写出来。
2013/05/24 15:45:20
2013/05/24 21:20:48
因为研究这些东西没什么用,所以很少人研究。