|
! b$ n5 u. c( c5 ~& ` Web-SQL注入漏洞介绍:SQL注入漏洞(SQL injection)是Web层面最高危的漏洞之一在2008年至2010年期间,SQL注入漏洞连续3年在OWASP年度十大漏洞排行中排名第一漏洞原理:SQL注入是因为后台SQL语句拼接了用户的输入,而且Web应用程序对用户输入数据的合法性没有判断和过滤,前端传入后端的参数是攻击者可控的,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。 6 O n7 y8 i- Y0 f6 D9 F
比如查询、删除,增加,修改数据等等,如果数据库的用户权限足够大,还可以对操作系统执行操作漏洞危害:可以造成信息泄露,上传Webshell、获取或者修改信息MySQLMySQL是一种开放源代码的关系型数据库管理系统,使用最常见的数据库管理语言--结构化查询语言(SQL)进行数据库管理
" {) [) y( g7 N7 e! n9 r+ ]% q5 m 端口号:3306MySQL支持三种注释风格:#:注释从 “#” 字符到行尾--:注释从“--”序列到行尾需要注意的是,使用此注释时,后面需要跟上一个或者多个空格/*/:注释从/序列到后面的*/序列中间的字符。
# D* |% N( E+ G2 p% k v- }2 T" u; t% v MySQL 5.0及其以上版本提供了information_schema,information_schema是信息数据库 information_schema数据库中三个很重要的表: information_schema.schemata: 该数据表存储了mysql数据库中的所有数据库的库名
; L L: N7 e+ x7 h% P information_schema.tables: 该数据表存储了mysql数据库中的所有数据表的表名 information_schema.columns: 该数据表存储了mysql数据库中的所有列的列名 $ i% n/ H+ L! f5 U- N
关于这几个表的语法:通过这条语句可以得到所有的数据库名select schema_name from information_schema.schemata limit 0,1通过这条语句可以得到所有的数据表名
2 H. {5 i: h$ `3 j& v/ Z- p select table_name from information_schema.tables limit 0,1通过这条语句可以得到指定security数据库中的所有表名select table_name from information_schema.tables where table_schema=securitylimit 0,1 + k( f4 `: h6 `1 \1 Q6 @
通过这条语句可以得到所有的列名select column_name from information_schema.columns limit 0,1通过这条语句可以得到指定数据库security中的数据表users的所有列名 9 E) B. W6 H) H+ p- n0 {
select column_name from information_schema.columns where table_schema=security and table_name=users limit 0,1 ! ^+ S) ?- u1 Z, S( t6 U0 M* P! f7 L+ I
MySQL中比较常用的函数: version(): 查询数据库的版本 user():查询数据库的使用者 database():数据库 system_user():系统用户名 session_user():连接数据库的用户名 ( M8 ]* n6 ^9 h! K3 u# ]+ s
current_user:当前用户名 load_file():读取本地文件 into outfile:写文件操作 @@datadir:读取数据库路径 @@basedir:mysql安装路径 @@version_complie_os:查看操作系统 , H) Z+ J# {8 F. Q% W- r
SQL注入的分类:数字型和字符型数字型数字型注入是最简单的一种,假设URL为http://www.xxxx.com/test.php?id=8我们可以猜测一下SQL语句为:select * from table where id=8 2 O4 E$ }; I( c: s
判断是不是数字型,这时候我们可以在URL后面加一个引号,比如http://www.xxxx.com/test.php?id=8‘此时的SQL语句为:select * from table where id=8‘
) Y1 c! z& z+ m# N; { 如果我们SQL语句猜测是正确的话,这样会使原来的页面报错然后我们在原来的URL后面加and 1=1 、and 1=2测试页面http://www.xxxx.com/test.php?id=8 and 1=1页面返回正常(SQL语句为:select * from table where id=8 and 1=1 永远为真)。
3 r4 H) |" G' l! d/ C http://www.xxxx.com/test.php?id=8 and 1=2页面返回不正常(SQL语句为:select * from table where id=8 and 1=2 永远为假)如果满足上述的条件可能就存在SQL注入 8 \" }: F# e+ |* n/ p2 d
字符型当我们输入的参数是字符串时,我们称为字符型数字型和字符型存在最大的区别是:数字型不需要单引号来闭合,而字符型一般都是要用单引号来闭合字符型的SQL语句为:select * from table where username=’admin‘
0 q( Q |, T! r9 } 字符型注入的关键是闭合单引号和注释多于代码 然后我们也要在原来的URL后面加and 1=1 、and 1=2测试页面,但此时要注意单引号和它们的位置关系正常的SQL语句应该是:select * from table where username=admin and 1=1 # (单引号闭合前面的单引号,#注释后面多于的代码 ) ]1 t$ x! v8 _" \: n
select * from table where username=admin and 1=2 #如果满足上述的条件可能就存在SQL注入报错注入主要利用数据库的报错信息来判断是否存在注入,当我们输入不符合数据库规范的字符时,数据库就会产生报错 # _' S7 B6 W4 l7 v
常用的字符:’ / ; ) #(盲注盲注主要分为:基于时间的注入、布尔类型、无报错信息的注入基于时间的注入我们没有办法从其他方面判断我们的SQL语句是否执行,只能通过页面的回显时间来判断常用的语句是:
4 A9 Y; w8 z- V& x if(length(database())>1,sleep(5),1)如果数据库名称的长度大于1,那么让页面延迟5秒响应,以此来判断我们的语句是否正确之前遇到过基于时间的注入但是把逗号过滤的情况,这里再给大家介绍一种语句就是:select case when 7 t/ a7 r- K3 |+ G5 J) a) f# N
SQL CASE表达式是一种通用表达式,类似于if/elseselectcasewhenusername=adminthen(sleep(3))elsexxxxendfromuser;布尔类型的注入如果我们成功注入会显示正确信息,如果失败则不会显示正常信息
! e) @3 ]" i' B6 L( [: P7 Y. x 无报错信息的注入没有任何报错显示,但是能根据页面是否正确显示来进行判断常用到的函数:1.length()函数判读数据库的长度lengh(database())=92.substr()函数截取字符串截取数据库名称的第一个字母是不是p i0 ]9 J& R& I% ]1 ]
selectsubstr(database(),1,1)=psubstr()和substring()功能是一样的,都是截取字符串3.left()函数从字符表达式最左边一个字符开始返回指定数目的字符获取数据库名字最左边的字符是不是p , C1 m1 S/ n" k6 q' P2 u# H2 u
selectleft(database(),1)=p4.MID()函数用于从文本字段中提取字符提取第一个字符判断是不是pselectmid(database(),1)=p5.ord()函数把字符转成ASCII 8 c1 |+ ` Z- n, E1 E
判断第一个字符的ascii是不是97,也就是第一个字符是不是aselectord(mid(database(),1))=97很多时候我们需要利用这些函数结合脚本去跑,根据实际情况写脚本堆叠注入SQL语句默认是以分号结束,我们可以在参数后面加上分号,然后加上我们的语句 + D# w0 P: R) @. f5 W. ?8 R
id=1;select mid(database(),1)=p %23二次注入在存入数据库的时候做了过滤检测,但在取出来的时候没有检测,就可能造成二次注入比如:我们在注册账号时可以注册一个admin -- ‘
6 G: m+ C& O% {0 w+ ~& { w# l 然后我们修改这个账号的密码,当这个用户名从数据库里面获取的时候,可能就只获取到了admin,因为我们后面注释了,所以这样就能改admin用户的密码宽字节注入宽字节注入是因为客户端的字符集和接收端的字符集设置不一样,造成单引号逃逸,大部分是因为数据库的字符集设置为GBK编码,一般出现在PHP+MySQL中
9 ~& D9 s2 a% H0 x 在单引号前面加%df,GBK编码默认两个字节是一个汉字Cookie注入有些时候在Cookie中也会存在注入XFF注入在头部信息的X-Forwarded-for字段也可能存在注入XFF主要作用是伪造客户端IP - k' Z X- v& @
注入工具SQLMapSQLMap是一个开放源码的渗透测试工具,它可以自动检测和利用SQL注入漏洞,并且它在http://SecTools.org注入工具分类里位列第一名SQLMap配置了一个功能强大的检测引擎,如果URL存在注入漏洞,它就可以从数据库中提取数据,如果权限较大,甚至可以在操作系统上执行命令、读写文件
3 S) @2 o# f$ E9 I+ x7 t9 U) i 我们实际操作一下,用SQLMap对靶场存在SQL注入的题目进行操作一下首先判断一下是否存在注入点-u 参数指定URL
4 O5 b. v# J# @( Z6 Y$ X2 r g 用SQLMap跑一会就提示,id参数是可注入的,问是否还检测其它,我们这里默认否就行
7 S, V# w4 a1 J0 d3 p2 a 使用--current-db参数列出当前应用程序所使用的数据库,可以看到当前数据库是maoshe’ " d# X. n! R \; t/ G1 l
再使用--table参数获取数据库表,-D参数指定数据库,可以看到有4个表,我们肯定首先是跑admin表
% V" u: }; |4 G& a 使用--columns参数列字段名 -T参数指定表明,有三个字段id、username、password
: q3 R- B L q. W/ l2 l7 ~. n 使用--dump参数列数据 -C参数指定字段名称,爆出了用户名和密码
& A: s' B# l0 s# W( }! Z- n 其实这类注入的工具有很多,比如:Pangolin、明小子、Havij、啊D,根据自己的喜好选择修补建议:1.严格数据类型2.特殊字符转义3.使用预编译语句4.框架技术总结如今SQL注入工具已经比较完善了,如果工具注入无法完成,再进行手工注入,总之,SQL注入时,一般是工具为主,手工为辅,虽然SQL注入危害很大,但是只要程序开发团队的程序员有一定的安全意识的话,完全是可以杜绝的 2 }8 Y+ l& V5 V
# c) ^* g) |9 B2 g& T: Q0 P# Z; D) A% o. a( R) o# I
$ [, Q0 l9 M l+ h4 [! p1 c; _# L7 q% j; x) M) `* X
|