- A+
标 题: 【原创】大学的那点事~XX高校数字登录系统浅析
作 者: 習生
时 间: 2014-03-22,23:47:10
链 接: http://bbs.pediy.com/showthread.php?t=185874
关于XX高校数字登录系统,我的几点看法
正如孔子所说,“逝者如斯夫,不舍昼夜!”时间如流水落花般逝去,二十二的年龄,毕业的季节。大四下,我会好好欣赏XX高校的各式风景。
*************************************************************
好了,感慨不多发了,我们进入正题。写这篇文章的主要目的是分析一下数字XX高校的不足之处,好让这个系统能够更加完美。当然,有则改之,无则加勉。
其实,在刚发这个校园卡上网的时候,见着6位数字的默认密码,我就曾大胆的猜测过,用穷举法不就能登录别人的帐号吗?对,就是一个一个试,当然不是靠我们人来手工操作,
6位数字的密码,共100万个,人工输入尝试当然是不可取的。但是写程序呢?那又会怎么样呢?
************************************************************
一、暴力密码拆解程序的实现。
这是登录界面,校内网的同学就能看到,地址:http://61.137.86.87:8080/portalNat444/index.jsp
我们平常登录是输入帐号密码,点击登陆按钮进行登录,这就是说明我们给服务端发送了一个数据,服务端接收到我们的数据然后判断帐号密码的正确性,最后给我们正确的响应。
我们要用的是:
网页封包抓取---->即我们要知道计算机向服务端到底发送了什么样的数据包,便能依瓢画葫芦,直接实现数据包尝试登录。
抓包的工具很多,如果你还在用Httpwatch的话,我可以告诉你,你没有跟上潮流。Httpwatch固然老牌,但是貌似在64位系统下不兼容。这里我用的是Wireshark,一款相当nice的抓包工具,当然如果你是Firefox浏览器的话,可以直接用自带的debug。
具体操作可以百度Wireshark的user manual,我这里不多加阐述。
根据Wireshark抓包,可以知道抓到的包是POST 类型的,当然在网页的源码里也能找到:
当然,后面的便是date.resultCode为0时,就登录成功,如果你能成功控制服务器,把resultCode设置成0,则会永远登录成功,显然这是不明智的。
回归正题,我们需要发送的post数据包为:
网址:http://61.137.86.87:8080/portalNat444/AccessServices/login
方式:POST
数据内容:
accountID=010103100527%40zndx.inter //这里的%40 代表的是@
&password=56aad664fa33bffb42b2c0be23ebc5efce17d7f82c0d75ade387941c690063382fef34369b1d7c929945fdbd4ba28bc77db7b028d022464646165acedf2b5deb2ce1fb3d4dc074c55888e299d384af306572a368f468d88fdafdaefebfa39bf84fad0530775d37f35dc79594ba62be4fc5189544397ed97054f4fc375903b6
&brasAddress=59df7586
&userIntranetAddress=10.96.85.80
我们可以看到,一共发送给了服务器4个参数:
第一个参数accountID:(学号加上@zndx.inter)
第二个参数password:顾名思义,这是密码。不过并不是我们所期待的6位数字,这是因为他经过了处理,加密了,加密算法为RSA1024bit,这个算法后面会讲到。
第三个参数brasAddress:我这里是59df7586,应该是本机的物理特征,多抓取了几个封包,发现这个不变,就不必管它了,不影响我们工作。
第四个参数userIntranetAddress:这是本机内网IP,我们可以在cmd中输入ipconfig/all或者ipconfig进行查看:
也可以写一个小程序遍历本机的ip地址。
这是我写的一个小程序:
也可以用C++:
程序C++源码如下:
*****************************************************************************
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int doit(int, char **)
{
char host_name[255];
//获取本地主机名称
if (gethostname(host_name, sizeof(host_name)) == SOCKET_ERROR) {
printf("Error %d when getting local host name.\n", WSAGetLastError());
return 1;
}
printf("Host name is: %s\n", host_name);
//从主机名数据库中得到对应的“主机”
struct hostent *phe = gethostbyname(host_name);
if (phe == 0) {
printf("Yow! Bad host lookup.");
return 1;
}
//循环得出本地机器所有IP地址
for (int i = 0; phe->h_addr_list[i] != 0; ++i) {
struct in_addr addr;
memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
printf("IPAddress %d : %s\n" , i, inet_ntoa(addr));
}
printf("如果有10.96的IP address,则说明此Ip为本机Ipv4地址****************** \n" );
printf("如果无10.96的IP address,则说明计算机未连通校园网****************** \n" );
return 0;
}
int main(int argc, char *argv[])
{
WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
return 255;
}
int retval = doit(argc, argv);
WSACleanup();
return retval;
}
****************************************************************************
好了,一共4个参数,我们解决了3个,头痛的是第二个被加密的密码是如何由6位数字转换成256位的加密后的字符串的。
256位的加密字符串很容易让人联想到RSA1024加密,这是一种单向加密,多用于商业用途,强度取决于对大数的因式分解。具体可以到维基百科看。
这种过高的加密强度使得我望而却步。
正要放弃,却发现了一个致命的弱点,有一个security.js的文件又再给人一线希望。将源文件下载到本地,分析后就知道了由6位数字如何魔术般成为了256位字符。
一共有这么几个文件:
我们打开security.js,可以发现,我们的猜测并没有错:
一共700行代码,不一一贴出
***************************************************************************
无论是注解还是函数名称,都证明了是RSA1024无疑。可笑的是,这个代码是05年写的,10年经过修改。并且在调试过程中,我发现了供应商是华为,无疑。
既然有了源码,我们也能发现这和我们抓包所得到的数据一致,只是密码用了一个函数encodeURIComponent()函数进行编码后再用security.js里写好的RSA加密算法进行加密。
搞定了POST的四个参数,用一个循环和100万个密码进行暴力破解,也就能实现用别人的一个已知的学号(默认密码)进行登录。
二、暴力破解的效率
百度网盘曾经有段时间是4位数字密码,即1万个数字,即使算最后一次才尝试成功,也在10分钟以内。我们就按这个概率算,当然,你可以计算时间的期望值如果你的概率论学得不错。就算10分钟,1000分钟也能尝试出一个密码,约16个小时。是不是很nice,按期望的话,平均9小时就差不多能得到一个帐号的密码。
当然官方不是吃素的,他当然会考虑到这个可能性。
三、官方限制
可能考虑到有人会尝试穷举所有密码,或是因为代码的严谨性,这个文件里的内容就是来限制大家的次数,我大概尝试了下,1个帐号连续输错10次密码后会提示错误信息“无法获取”,大约停止3分钟。如果按照这个官方设计好的方式来算,10次密码耗时3分钟,100万次耗时30万分钟,约208天的时间,当然,就不存在穷举来窃取他人帐号,因为没有人愿意发大半年时间就破解一个密码,可能还不够交电费。那我们就放弃吗?
Of course not!尽管它是限制了次数,我们可以用一种巧妙的方法躲过,方法很简单:我们可以尝试010103100101的密码10次,一直到无法获取,开始尝试2号学号的10次,这样我们电脑的效率能实现最大化,概率当然不变,还是9小时左右能拿到一个号。
我还发现,代码里存在一个登录标志,这使得多线程无法得以实现。不过不怕,每个寝室不是你一个人在战斗,跟他们说清情况,结果可想而知,你懂的。
四、优化
100万次的次数太多,为了使得尝试次数减少,我向同学要了大概10个左右的密码,基本可以剔除6位数字里全相同的,5个数字相同的以及4个数字相同的密码。
这样的密码可以不用尝试:
11111;22222;11115;344445;863888;
用排列组合,我们可以算出,剔除了以上几种可能后,密码的尝试次数将减少到746640次,这样的话,时间又能缩短了。当然,你还可以去除一些123456;765432;这样的密码,具体可以参考双色球的一些软件的算法。这里不做赘述。
五、其他
除了温柔的暴力拆解密码以外,当然可以采取直接的入侵手段,那样便会方便很多,当然完成后记得删除telnet 和http等日志。
总的来说,数字XX高校还是设计得不够完善。
提出几点建议如下:
大家不要嫌麻烦,建议改下密码,6位数字并不安全。
数字XX高校应把源码藏好,不能让外面轻易得到,这点是很值得改善的。
源代码里的验证码都被注释了起来:
图一:jsp中的
Js中的validateCode 也全部不再使用,尽管提高了学生上网的方便,同时也使得帐号的安全性下降了。
其他的就是网络攻防了,这就看管理员的水平了。
--------------------------------------------------------------------------------
声明:本人水平有限,若有不正确之处,还望各位大侠指正。
-----------------------------------------------------------------------------------
Xiaoyu
2014年03月22日
附录一:公钥定义处
- 我的微信
- 这是我的微信扫一扫
- 我的微信公众号
- 我的微信公众号扫一扫