当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-084948

漏洞标题:某通用网站管理系统任意用户登陆/SQL注入/GetShell漏洞源码分析

相关厂商:力拓科技

漏洞作者: xfkxfk

提交时间:2014-11-27 20:31

修复时间:2015-02-25 20:32

公开时间:2015-02-25 20:32

漏洞类型:设计缺陷/逻辑错误

危害等级:高

自评Rank:20

漏洞状态:已交由第三方合作机构(cncert国家互联网应急中心)处理

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-11-27: 细节已通知厂商并且等待厂商处理中
2014-12-01: 厂商已经确认,细节仅向厂商公开
2014-12-04: 细节向第三方安全合作伙伴开放
2015-01-25: 细节向核心白帽子及相关领域专家公开
2015-02-04: 细节向普通白帽子公开
2015-02-14: 细节向实习白帽子公开
2015-02-25: 细节向公众公开

简要描述:

此系统非开源,大部分是高校在用,把源码脱下来看了下

详细说明:

0x00 通用案例:

厂商:力拓科技
官网:http://www.ltpower.net/
主要是做教育产品的厂商
搜了一下用户大部分都是高校使用的门户网站
技术支持:广东省东莞市力拓科技有限公司
案例如下:
http://zybj.jnu.edu.cn/
http://jpkc.gmc.edu.cn/gwsy/index.asp
http://210.36.18.31/slstx/
http://glz.dgpt.edu.cn/
http://xxgcxy.gdut.edu.cn/user/reg.asp
http://qghgxy.gdut.edu.cn/user/reg.asp
http://tmjtxy.gdut.edu.cn/user/login.asp
http://gsgc.gzhu.edu.cn/szgc/user/reg.asp
http://nhsjd.gzhu.edu.cn/user/reg.asp
http://eeit.hut.edu.cn/user/reg.asp
http://glsxjd.dgpt.edu.cn/user/reg.asp
http://glz.dgpt.edu.cn/user/reg.asp
http://jdsxjd.dgpt.edu.cn/user/reg.asp
http://etc.xmut.edu.cn/user/reg.asp
http://www.zjyy.com.cn/mnwk/
http://sps.sysu.edu.cn/zsyx/
http://202.116.65.190/xhyxt/index.asp
......


0x01 漏洞分析:
任意用户登陆漏洞:
首先看一下前台注册用户过程文件user/reg.asp

<%
dim action,UserID
action=Trim(Request("action"))
if action="savereg" then
dim usr,pwd,code,cname,AuditState
dim strSql,objRs
usr=RSQL(Request.Form("usr"))
pwd=MD5(Request.Form("pwd1"))
cname=RSQL(Request.Form("cname"))
code = Request.Form("Code")

' if arrSite(23)="0" then
' AuditState=0
' else
' AuditState=1
' end if

If CStr(code) <>CStr(Session(Const_Cache&"_Code")) then
Response.Write("<script>alert('验证码有误,重新输入!');history.back();</script>")
Response.End
End If

strSql="select * from base_user where UserName='"&usr&"'"
set objRs=conn.execute(strSql)
if not objRs.eof and not objRs.bof then
Response.Write("<script>alert('用户已存在,请更换用户!');history.back();</script>")
Response.End
else
strSql="insert into base_user (RoleID,UserName,[PassWord],Cname,IsEnable) values(6,'"&usr&"','"&pwd&"','"&cname&"',0)"
conn.execute(strSql)
Response.Write("<script>alert('用户注册成功!');location.href='../index.asp';</script>")

end if
end if
%>


用户注册成功后,将用户信息插入表“base_user”表
这里用户角色roleid被写死了,这里是6,有些是5
接下来看看后台登陆文件\Admin\login.asp

<!--#include file="Conn.asp"-->
<!--#include file="Config.asp"-->
<!--#include file="../Inc/MD5.asp"-->
<!--#include file="Function.asp"-->
<%
Select Case Request("Action")
Case "LoginCheck"
Call LoginCheck()
Case "LoginOut"
Call LoginOut()
Case Else
Call Lt_login_Main()
End Select
Sub LoginCheck()
Dim A_PWD,PassWord,UserName,Lt_Code,SqlStr,RS
Lt_Code = trim(Request.Form(Const_Cache&"Code"))
If CStr(Lt_Code)<>CStr(Session(Const_Cache&"_Code")) then
Response.Write("<script>alert('验证码有误,重新输入!');history.back();</script>")
Response.End
End If

A_PWD = MD5(Request.Form("PassWord"))
UserName = RSQL(Request.Form("UserName"))
PassWord = RSQL(Request.Form("PassWord"))
Set RS = Server.CreateObject("ADODB.RecordSet")
SqlStr = "select * from base_user where UserName='" & UserName & "'"
RS.Open SqlStr,Conn,1,3
IF Rs.eof And Rs.bof Then
exe("INSERT INTO Base_log(Logtype,LogUser,Logcontent,LogIP,LogTime) VALUES('登陆日志','"&UserName&"','后台登陆失败,错误的管理帐号!','"&getip()&"','"&now&"')")
Response.Write("<script>alert('登录失败:\n\n您输入了错误的管理帐号,请再次输入!');history.back();</script>")
Response.End
Else
IF Rs("PassWord") = A_PWD Then
IF Rs("IsEnable") = 1 Then
exe("INSERT INTO Base_log(Logtype,LogUser,Logcontent,LogIP,LogTime) VALUES('登陆日志','"&UserName&"','后台登陆失败,账号已被管理员锁定!','"&getip()&"','"&now&"')")
Response.Write("<script>alert('登录失败:\n\n您的账号已被管理员锁定,请与您的系统管理员联系!');history.back();</script>")
Response.End
Else
exe("UPDATE Base_User SET Lastlogin='"&now&"',Loginip='"&GetIP()&"',LoginNum=LoginNum+1 where username='"&UserName&"'")
exe("INSERT INTO Base_log(Logtype,LogUser,Logcontent,LogIP,LogTime) VALUES('登陆日志','"&rs("UserName")&"','后台登陆成功','"&getip()&"','"&now&"')")
Response.Cookies(Const_Cache)("AdminID") = Rs("UserID")
Session.Timeout = 30
End IF
Else
exe("INSERT INTO Base_log(Logtype,LogUser,Logcontent,LogIP,LogTime) VALUES('登陆日志','"&UserName&"','后台登陆失败,密码错误','"&getip()&"','"&now&"')")
Response.Write("<script>alert('登录失败:\n\n您输入了错误的口令,请再次输入!');history.back();</script>")
Response.End
End IF
Rs.Close:Set Rs = Nothing
Response.Redirect("index.asp")
End IF
End Sub


这里后台登陆也是直接从base_user表里面取出用户信息进行对比的
这样的话我们注册的前台普通用户也能登陆后台admin了
但是这里有roleid的限制,虽然普通用户登陆了后台,但是是没权限使用功能的,没有功能模块,空白页面
后台操作的权限控制是通过文件admin/checkuserpopedom.asp控制的

<!--#include file="conn.asp"-->
<!--#include file="Config.asp"-->
<!--#include file="Function.asp"-->
<!--#include file="../Inc/Lt_Main.Cls.asp"-->
<%
Dim AdminUserID,AdminRoleID,objRs,AdminUser,Lt
set Lt=new Lt_Main
AdminUserID=request.Cookies(Const_Cache)("AdminID")
if AdminUserID<>"" then
set objRs=conn.execute("SELECT * FROM Base_User WHERE Userid="&AdminUserID)
if not objRs.eof and not objRs.bof then
AdminUser=objRs("UserName")
AdminRoleID=objRs("RoleID")
else
response.Redirect "login.asp"
response.end
end if
else
response.Redirect "login.asp"
response.end
end if


从这里可以看到,根据AdminUserID从base_user表中取出用户信息AdminRoleID
主要是这里的AdminRoleID就是后台功能模块的判断标准
通过此AdminRoleID判断此用户是否有权限操作后台响应功能模块
但是这里我们看到

AdminUserID=request.Cookies(Const_Cache)("AdminID")


AdminUserID直接从cookie中取得,用户完全可控了
所以我们前台注册的用户,通过登陆后台后,在修改COOKIE中的AdminID为管理员ID,0或者1即可登陆管理员账户了,导致了任意用户登陆漏洞
0x02 SQL注入漏洞
而且这里的AdminUserID没有通过处理,导致SQL注入漏洞
0x03 GetShell
这里的GetShell需在IIS环境下进行
文件admin/templetedit.asp,这里可以添加模板也可以修改原先模版

Function save()
Dim Content,FileFSO
Content=request("content")
Path=request("Path")
If lcase(Right(Path,4))<>"html" And lcase(Right(Path,3))<>"htm" Then Call Lt.Alert("文件名的扩展名必须是html或htm","")
Set FileFSO = Server.CreateObject("ADODB.Stream")
With FileFSO
.Type = 2
.Mode = 3
.Open
.Charset = "utf-8"
.Position = FileFSO.Size
.WriteText Content
.SaveToFile Server.MapPath(Path),2
.Close
End With
Set FileFSO = Nothing
Response.Write ("<script>parent.frame.cols=""180,*"";</script>")
Call Lt.Alert("模板修改成功!","TempLate.asp"):Exit Function
End Function
Function Addsave()
Dim Content,FileFSO,File,PhysicalPath,fs
Content=request("content")
File=request("File")
Path=request("Path")
If lcase(Right(File,4))<>"html" And lcase(Right(File,3))<>"htm" Then Call Lt.Alert("文件名的扩展名必须是html或htm","")
Set fs = Server.CreateObject("scripting.filesystemobject")
PhysicalPath=Server.Mappath(Path&File)
if fs.FileExists(PhysicalPath) = False Then
Set FileFSO = Server.CreateObject("ADODB.Stream")
With FileFSO
.Type = 2
.Mode = 3
.Open
.Charset = "utf-8"
.Position = FileFSO.Size
.WriteText Content
.SaveToFile Server.MapPath(Path&File),2
.Close
End With
Set FileFSO = Nothing
Response.Write ("<script>parent.frame.cols=""180,*"";</script>")
Call Lt.Alert("模板增加成功!","TempLate.asp"):Exit Function
Else
Call Lt.Alert("文件名已经存在,请另取一个名称!","")
End If
End Function


从代码可以看到,在保存文件时,主要后四位为html,或者后三位为htm即可,没有处理文件内容
所以当在IIS情况下,我们可以修改保存文件名为111111.asp;.html,或者111111.asp;.htm即可
文件内容为一句话木马,或者webshell内容

漏洞证明:

拿暨南大学为例证明:
1、前台注册用户地址:http://zybj.jnu.edu.cn/user/reg.asp
2、用注册的用户后台登陆地址:http://zybj.jnu.edu.cn/admin/login.asp
3、后台登陆后为空白:

1.png


4、修改cookie中的adminid即可登陆管理

2.png


5、修改模板拿shell:

3.png


6、成功拿到shell,这个站已经有黑阔来过了,pr都上了,看了已经沦陷:

4.png


其他案例也是这样同样的漏洞和同样的证明方法
此系统肯定还有很多漏洞,既然拿到shell,拿到源码了就没什么说的了

修复方案:

版权声明:转载请注明来源 xfkxfk@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:18

确认时间:2014-12-01 17:16

厂商回复:

最新状态:

2015-05-12:已经查明此问题在少部分网站中存在,目前绝大多数有此隐患的网站已经完成紧急修复!


漏洞评价:

评论

  1. 2014-11-28 09:16 | 光刃 ( 普通白帽子 | Rank:200 漏洞数:24 | 萝卜白菜保平安)

    大牛逼

  2. 2014-11-28 09:19 | covertops ( 普通白帽子 | Rank:112 漏洞数:23 | wooyun)

    把源码脱下来看了下

  3. 2015-04-04 17:39 | dgdg ( 路人 | Rank:9 漏洞数:5 | 乌云币:10000)

    http://wooyun.org/bugs/wooyun-2010-081636