Shopxp网上购物系统 v7.4存在SQL注入漏洞

来源:岁月联盟 编辑:zhuzhu 时间:2009-11-08
Shopxp网上购物系统 v7.4存在SQL注入漏洞

问题文件:xpCatalog_xpDesc.asp,xpCatalog_xpsmall_Desc.asp
问题代码:

<%

dim shopxpbe_id, anclassname, shopxpse_id, nclassname
dim totalPut
dim CurrentPage, TotalPages

if request("shopxpbe_id")<>"" then
shopxpbe_id=request("shopxpbe_id")
else
shopxpbe_id=0
end if
if request("shopxpbe_id")="" then
shopxpbe_id=1
end if
if not isempty(request("page")) then
currentPage=cint(request("page"))
else
currentPage=1
end if

set rs=server.createobject("adodb.recordset")
rs.open "select * from shopxp_btype where shopxpbe_id="&amp;shopxpbe_id,conn,1,1
anclassname=rs("shopxpbe_name")
rs.close
%>


并没有对shopxpbe_id进行整形判断。下面在说说他的防注入系统。好像是网上的枫叶防注入。看代码吧:Dim Fy_Url,Fy_a,Fy_x,Fy_Cs(),Fy_Cl,Fy_Ts,Fy_Zx
Fy_Cl = 2 &apos;处理方式:1=提示信息,2=转向页面,3=先提示再转向
Fy_Zx = "../" &apos;出错时转向的页面
On Error Resume Next
Fy_Url=Request.ServerVariables("QUERY_STRING")
Fy_a=split(Fy_Url,"&amp;")
redim Fy_Cs(ubound(Fy_a))
On Error Resume Next
for Fy_x=0 to ubound(Fy_a)
Fy_Cs(Fy_x) = left(Fy_a(Fy_x),instr(Fy_a(Fy_x),"=")-1)
Next
For Fy_x=0 to ubound(Fy_Cs)
If Fy_Cs(Fy_x)<>"" Then
If Instr(LCase(Request(Fy_Cs(Fy_x))),"&apos;")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"and")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"select")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"update")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"chr")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"delete%20from")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),";")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"insert")<>0 or Instr(LCase(Request(Fy_Cs(Fy_x))),"mid")<>0 Or Instr(LCase(Request(Fy_Cs(Fy_x))),"master.")<>0 Then
Select Case Fy_Cl
省略部分代码

这个防注入系统在网上貌似很火,但是他防的是有问题的。关键是这句,Fy_Url=Request.ServerVariables("QUERY_STRING"),Request.ServerVariables得到的数据是原样的,并不会进行URL解码。这也就导致可以进行URL编码绕过这个防注入。以下是lake2对这段代码的分析:

 

“它的思路就是先获得提交的数据,以“&amp;”为分界获得并处理name/value组,然后判断value里是否含有定义的关键字(这里为求简便,我只留下了“and”),有之,则为注射。

 

乍一看去,value被检查了,似乎没有问题。呵呵,是的,value不会有问题,可是,name呢?

它的name/value组值来自于Request.ServerVariables("QUERY_STRING"),呵呵,不好意思,这里出问题了。Request.ServerVariables("QUERY_STRING")是得到客户端提交的字符串,这里并不会自动转换url编码,哈哈,如果我们把name进行url编码再提交的话,呵呵,那就可以绕过检查了。比如参数是ph4nt0m=lake2 and lis0,此时程序能够检测到;如果提交%50h4nt0m=lake2 and lis0(对p进行url编码),程序就会去判断%50h4nt0m的值,而%50h4nt0m会被转换为ph4nt0m,所以%50h4nt0m值为空,于是就绕过了检测。

 

等等,为什么既然name不解码可以绕过检查而value就不能绕过呢?因为value的值取自Request(Fy_Cs(Fy_x)),这个服务器就会解码的。

 

程序怎么改进呢?只要能够得到客户端提交的数据是解码后的就可以了,把得到name的语句改为For Each SubmitName In Request.QueryString就可以了。”

 

下面说下利用:
Google:inurl:xpCatalog_xpDesc.asp?action_key_order=big
inurl:Catalog_Desc.asp?action_key_order=big (这个貌似是商业版的)


构造如下地址:
http://www.xxx.com/xpCatalog_xpDesc.asp?action_key_order=big&amp;shopxpbe_%69d=79 (对i进行URL编码),交给工具 手动添加表名:shopxp_admin 和shop_admin(商业版的)
默认后台是 admin_shopxp 或者admin