代码改变世界

PJBlog恶意广告POST漏洞之测试与修复

2007-08-30 00:45  Timothy Ye  阅读(307)  评论(0编辑  收藏  举报
    今天在网上找了一个Vista的皮肤,赶紧给我的BLOG换上,漂亮了许多,呵呵。
    最近BLOG上,广告多得吓人,特别是在文章的评论和留言本里面,真是无孔不入的广告。由于偶比较痛恨这些广告,手动删除也不是办法,整页整页的广告评论和留言,多则上百条。而且手动在管理界面删除,也只是一个治标不治本的办法。
   据寡人分析 ,可能是评论和留言的post环节不够强悍,导致垃圾广告有孔而入。不过这个BLOG的评论和留言都是有验证码的,评论的POST对应于blogcomm.asp文件,评论的页面,通过指向GetCode.asp,获取验证码图片,并在Session中保存该验证码,用以和用户输入的验证码比对。
   那么如果要达到用程序,自动提交垃圾广告,可以想到的方法有两种:
   1.用程序识别图片验证码,获取其内容,然后模拟POST。不过这个比较高难,要程序识别图片中的数字,需要图形识别的知识。
   2.绕过验证码的过程,直接POST。这个要根据具体的漏洞而定。

   于是随手在google上搜索了一下,PJBlog还真有这个漏洞。

   具体的漏洞描述如下:
   blogcomm.asp文件对验证码判断不严格。
   如果用户没有请求过GetCode.asp文件,那么服务器端Session里面的GetCode值为空,而用户提交的数据里面验证码也为空,这样刚好空等于空,反而通过了验证码验证。

   查看blogcomm.asp源码,在Line 94行有这样的情况。
  
   为了验证这个漏洞是否存在,我们可以自己动手测试一下,用程序模拟POST一次。就拿偶的BLOG做实验吧。首先,随便打开一个文章,启动网络抓包工具,(这里我用的是WSE--WinSocketExpert),随便敲入几个字,查看捕获下来的网络包。我们会发现,POST的数据格式是这样的:
  
username=Timothy&password=&Message=PostData&logID=171&action=post&submit2=%E5%8F%91%E8%A1%A8%E8%AF%84%E8%AE%BA

     username 是评论者名称
   password 是密码(游客不需要密码)
   logID 就是文章编号
   Message 就是评论内容了,垃圾广告最关注的就是这个……
   action 是一个隐藏的field,值为post,这个可以在页面上通过查看源码看到
   submit2 后面的码,转换成中文,其实就是“发表评论”,同样参考评论页面源码

   POST的结构知道了,下面我们用程序来模拟POST一下,看漏洞是否存在,测试代码如下:
   (请慎用此部分代码,不要用于垃圾广告软件,谢谢 )

      
private void PostFunc()
        {

            WebClient wc = new WebClient();

            string postData = "username=Timothy&password=&Message=PostData&logID=171&action=post&submit2=%E5%8F%91%E8%A1%A8%E8%AF%84%E8%AE%BA";
            try
            {
                wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                wc.UploadData("http://www.xiaozhou.net/cooldog/blogcomm.asp", "POST", Encoding.Default.GetBytes(postData));
            }
            catch
            {
                wc.Dispose();
                return;
            }

            wc.Dispose();
        }


          运行此程序,可以在我的blog的编号171的文章评论中,看到下图:


      看来漏洞真的存在……
    这里,我们可以看到POST数据结构中,logID是可以人为改变的,也就是文章编号。如果把logID作为变量自增,测试代码外面,再套一个for循环,这个程序就成了制造垃圾广告的机器了……

    找到了漏洞,得赶紧补上才行。其实我们需要修改的地方,就是在blogcomm.asp。找到94行,这里的判断,由于没有对Session进行判断才导致了此漏洞的产生。
    修改方法如下:
    blogcomm.asp Line:94
      原代码:
    
IF (memName=empty or blog_validate=true) and cstr(lcase(Session("GetCode")))<>cstr(lcase(validate)) then

      替换后的代码,增加对Session的判断:
    
IF (memName=empty or blog_validate=true) and (cstr(lcase(Session("GetCode")))<>cstr(lcase(validate)) or IsEmpty(Session("GetCode"))) then


      大功告成了…… 睡觉去……