Archive for January, 2007

My Sniffer

最近写的一个Sniffer小程序,可以捕获当前用户上了哪些网。
(设置混杂模式部分参考网络文章,SocketInfo来自codeproject.com)

下载:http://www.mpfive.com/m/myapps/MySniffer.rar

使用方法:
1:拷贝下面的文件到你的工程下

HttpParser.cpp
SocketInfo.cpp
SocketInfo.h
define.h
SnifferManager.h
Sniffer.cpp
Sniffer.h
HttpParser.h
SnifferManager.cpp

2:在程序中 include SnifferManager.h
3:在你的程序中开启Sniffer的地方加入:

CSnifferManager *pSM = CSnifferManager::GetInstance();
pSM->StartSniffers();

4:程序关闭的地方加入:

this->ShowWindow(SW_HIDE);if(CSnifferManager::DestroyThreads())

       CSnifferManager::FreeInstance();

else

{

       PostMessage(WM_CLOSE);

       TRACE("// %s:%dn", __FILE__, __LINE__);

       return;

}

比如在OnClose中加入

void CMySnifferDlg::OnClose()

{

       this->ShowWindow(SW_HIDE);       if(CSnifferManager::DestroyThreads())

              CSnifferManager::FreeInstance();

       else

       {

              PostMessage(WM_CLOSE);

              TRACE("//%s:%dn", __FILE__, __LINE__);

              return;

       }

CDialog::OnClose();

}

Single Sign-On

单点登录,即Single Sign-On使得用户只需在一个Entry Point登录便可以在多个应用之间来回的切换,而无须再次登录,这样大大的增强的用户体验,最为著名的SSO的例子就是MS的Passport,想必大家已经体会到了SSO的便捷功能。

如果你Google SSO,得到的大都是WEB站点和WEB站点之间的SSO技术,对于Windows应用程序和WEB站点之间共享验证信息的技术几乎没有,目前IM软件中通常采用这样的技术,比如MS的Windows Live Messenger以及Tencent的QQ等。在这样软件中,用户只要在IM中登录,通过程序界面打开浏览器浏览WEB站点,就不需要再次登录了。

下面是我的一种解决方案:

比如用户要访问:http://www.googlestop.com/user/cp,这里假设用户名为:charry,密码为:123456,该密码MD5后为:e10adc3949ba59abbe56e057f20f883e。如果不考虑安全问题,我们可以把所有的信息都追加在URL中,比如:

http://www.googlestop.com/usre/cp/?uid=charry&passwd=e10adc3949ba59abbe56e057f20f883e

这样服务器端只要验证该用户名和密码是否都正确就可以判断来访者是否是个有效用户。但是这样做有很多缺点,比如:将用户名和密码的Hash值都以明文的方式呈现出来是个安全隐患,如果Cracker收集了这些信息将导致安全问题,还有,用户完全可以把这个URL复制出来,发给另一个用户,当另一个用户访问该URL时,他也被认为是一个合法用户。并且这个URL可以被保存下来,任何时候都可以再次使用,这么一来,Sign-In模块就形同虚设了。

如果我们把用户名和密码再次加密一次,是不是就不会导致安全性的问题了呢?回答是肯定的。针对上述的URL,我们可以把

http://www.googlestop.com/usre/cp/?uid=charry&passwd=e10adc3949ba59abbe56e057f20f883e

加密后再放到URL中。这里一定要保证的是此次加密是可逆的,否则发给服务器后,将毫无用处。注意,这里的加密算法是可逆的,我们假定选择AES算法。首先使用一个KEY将上述的URL加密,假设得到的密文是:

#$DKJFSDFSDFK(不可能这么短,只是假设)

这样我们把加密后URL,提交给 http://www.googlestop.com/redir/?q=#$DKJFSDFSDFK。服务器端通过把#$DKJFSDFSDFK解密后,就得到了

http://www.googlestop.com/usre/cp/?uid=charry&passwd=e10adc3949ba59abbe56e057f20f883e

这样它就知道用户要访问的URL、用户的ID、用户的密码等信息。

问题是,那个用于加密和解密的KEY该如何生成并告知服务器端?我们可以让程序在用户打开浏览器前,随机生成一个KEY,比如”sdfk7879#@”,然后用这个KEY加密上述的URL,然后马上在程序内部使用HTTPS协议把这个KEY发给服务器端,并保存到表中。当服务器端接到一个请求时,它首先去表中查询,是不是在短时间内(比如30秒)有一个KEY被发过来,如果有,就取得该KEY,并用KEY解密URL中得密文。接下来得事情就好办了。

上面的解决方法中存在一个隐患,如果在一个短时间内有大量的这样的请求,将导致大量的KEY被发到服务器的表中,那么服务器端如何分辨每个用户呢?解决起来也容易,在每次用户请求前,除了随机生成一个KEY外,我们再多生成一个GUID,我们把KEY和GUID一起发给服务器(HTTPS方式),作为两个字段,GUID为主键,同时明文的URL中,我们也加上这个GUID(假设为:19270efa-a213-4733-b117-bdeb4b4528a2)

http://www.googlestop.com/redir/?q=#$DKJFSDFSDFK&GUID=19270efa-a213-4733-b117-bdeb4b4528a2

这样服务器端就可以通过GUID来查找KEY了。

上面使用的是GET的方法提交,有可能会超过GET的长度限制,我们也可以用POST的方法,只是需要借助一个临时html文件来中转,好像QQ就是这么做的。

To be continued…

Switch to our mobile site