赞
踩
结构化查询语言(Structured Query Language,缩写︰SQL),是一种特殊的编程语言,用于数据库中的标准数据查询语言。
1986年10月,美国国家标准学会对SQL进行规范后,以此作为关系式数据库管理系统的标准语言(ANSI X3.135-1986) , 1987年得到国际标准组织的支持下成为国际标准。不过各种通行的数据库系统在其实践过程中都对SQL规范作了某些编改和扩充。所以,实际上不同数据库系统之间的SQL不能完全相互通用。
SQL注入(SQL Injection)是一种常见的web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。
针对SQL注入的攻击行为可描述为通过用户可控参数中注入SQL语法,破坏原有SQL结构,达到编写程序时意料之外结果的攻击行为。其成因可以归结为一下两个原因叠加造成的:
1、程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句。
2、未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中。
根据SQL注入漏洞的原理,在用户“可控参数”中注入SQL语法,也就是说Web应用在获取用户数据的地方,只要带入数据库查询,都有存在SQL注入的可能,这些地方通常包括:
1、GET 数据
2、POST 数据
3、HTTP 头部(HTTP请求报文其他字段)
4、Cookie 数据
…
攻击者利用SQL注入漏洞,可以获取数据库中的多种信息(例如:管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取webshell或者服务器系统权限。
SQL注入漏洞根据不同的标准,有不同的分类。
但是从数据类型分类来看,SQL注入分为:
数字型注入 就是说注入点的数据,拼接到SQL语句中是以数字型出现的,即数据两边没有被单引号、双引号包括。
字符型注入 正好相反。
根据注入手法分类,大致可分为以下几个类别:
UNION query SQL injection (可联合查询注入)联合查询
Error-based SQL injection(报错型注入)报错注入
Boolean-based blind SQL injection (布尔型注入)布尔盲注
Time-based blind SQL injection(基于时间延迟的注入)延时注入
Stacked queries SQL injection (可多语句查询注入:主要是增删改)堆叠查询
根据提交数据的位置分为GET\POST\COOKIE(GPC)注入
SQLi-Labs是一个专业的SQL注入练习平台,适用于GET和POST场景,包含了以下注入:
1、基于错误的注入(Union Select)
字符串
整数
2、基于误差的注入(双查询注入)
3、盲注入(01、基于Boolian数据类型注入, 02、基于时间注入)
4、更新查询注入(update )
5、插入查询注入(insert )
6、Header头部注入(01、基于Referer注入, 02、基于UserAgent注入,03、基于cookie注入)
7、二阶注入,也可叫二次注入
8、绕过WAF
绕过黑名单\过滤器\剥离\注释剥离 OR&AND 剥离空格和注释剥离 UNION和SELECT
隐瞒不匹配
9、绕过addslashes()函数
10、绕过mysql_real_escape_string()函数(在特殊条件下)
11、堆叠注入(堆查询注入)
12、二级通道提取
下载地址:https://github.com/Audi-1/sqli-labs
需要php+mysql的环境搭建,下载phpstudy即可,以前的文章有说到过。
然后只需要将它解压到phpstudy的web根目录下,然后更改db-creds.inc里面的数据库密码就可以了
然后访问网页,创建数据库
接下来就可以正常使用了
由于关系型数据库系统,具有明显的库/表/列/内容结构层次,所以我们通过SQL注入漏洞获取数据库中信息时候,也依据这样的顺序:
首先获取数据库名,其次获取表名,然后获取列名,最后获取数据。
这里是我自己写的一个小网站和SQLi-Labs 当作靶场,刚好可以用来模拟sql注入
我们会在疑似注入点的连接或参数后面尝试提交以下数据:GET方式的注入发现
[?id=2 +1/-1] 看页面是否有变化,有变化则考虑联合查询
当我们变换id 参数的时候,发现同一个页面展现出来的内容是不同的,也就是说,数据库中的内容会回显到网页中来。
初步判定,id 参数会带入数据库查询,根据不同的id 查询到不同的内容。
猜测后台的sql 语句大致结构是:select * from tbName where id=2
[?id=2’] 判断是字符型还是数字型(根据报错信息),有报错则考虑报错注入
执行的sql 主语句则变为:select * from tbName where id=2'
页面报错,根据报错信息:
提示单引号位置出现错误,说明,sql语句的从头到2之间都是正确的。也就是说,我们添加的单引号是多余的。因此可以判定参数2之前没有引号。为数字型。
判断为字符型,单引号
有括号
双引号
判断是否有布尔类型的状态(根据页面返回的状态是否相同),有布尔类型状态考虑布尔盲注(基于布尔的盲注)
[?id=2 and 1=1]:页面正常
[?id=2 and 1=2]:页面没有显示内容数据库也没有报错。由于1=2 是恒假式,也就是查询条件[where id=2 and 1=2 --+]恒假,这样的SQL语句在数据库中执行后,没有返回结果,没有新闻内容。
反过来看,页面没有新闻内容,也就是SQL语句查询条件为假。也就是说,我们写的语句[and 1=2–+],起到了将查询条件置为假的作用。
那么,可以通过构造语句来控制SQL语句的查询结果,并且SQL语句查询条件真假性,在页面回显中有体现。
[?id=2 and sleep(5)] 判断是否有延时,有则考虑延时查询(基于时间的盲注)。
注入sleep(5)语句,可以通过网络时间线看到延时。说明sleep(5)语句起到了作用。
综上(除了第一个),此连接存在sql 注入漏洞。
可以实现跨库跨表查询
由于数据库中的内容会回显到页面中来,所以我们可以采用联合查询进行注入。
联合查询就是SQL语法中的union select语句。该语句会同时执行两条select语句,生成两张虚拟表,然后把查询到的结果进行拼接。
select ~~~~ union select ~~~~
由于虚拟表是二维结构,联合查询会"纵向"拼接,两张虚拟的表。
必要条件:
判断字段的个数:
可以使用 [order by] 语句来判断当前select语句所查询的虚拟表的列数。[order by]语句本意是按照某一列进行排序,在mysql中可以使用数字来代替具体的列名,比如[order by 1]就是按照第一列进行排序,如果mysql没有找到对应的列,就会报错[Unknown column]。我们可以依次增加数字,直到数据库报错。
[order by 1 --+]
[order by 2 --+]
…
[order bv 4 --+]
知道了数据库字段个数之后,我们就可以使用联合查询(数字可以转换成字符类型)
由于select 查询不用指定表名,所以我们的sql 语句可以是这样的
发现没有报错,由于前面SQL语句的查询为真,后面的语句就不执行,我们只需要让前面的语句为假,就会执行我们自己写的sql语句了
这时候,我们发现输出了几个数字,那么这些数字是什么呢?我们来查看一下数据库
发现字段和对应的值是相同的,这时候我们就有想法了,可以将显示出来的几个字段替换成函数,就可以获取数据库信息了!
这样,我们就可以看到数据库名和登陆的用户以及数据库版本了!
库名get!接下来就到表名了
思路:我们可以从元数据数据库information_schema中的tables表中查询表名!
这样我们就得到了表名!但是我们发现只显示了一个数据库表,这时候我们可以用group_concat()函数来将所有的表名进行拼接
表名get!之后我们可以通过类似的方法获得表中的字段名
字段名get!
这时候我们就可以查找到它的用户名和密码
我们发现它的密码是进行加密了的,初步判断是MD5加密,我们进入cmd5网站,进行暴力破解密码,得到明文
使用得到的账号密码进行登录
登陆成功
在注入点的判断过程中,发现数据库中SQL语句的报错信息,会显示在页面中,因此可以进行报错注入。
报错注入的原理,就是在错误信息中执行SQL语句。触发报错的方式很多,具体细节也不尽相同。此处建议直接背公式即可。
group by 重复键冲突(是Mysql的一个bug 编号为#8652。当使用rand ()函数进行分组聚合时,会产生重复键的错误。)
?id=2 and (select 1 from (select count(*), concat('^',(select table_name from information_schema.tables where table_schema=database() limit 3, 1),'^' ,floor(rand()*2)) x from information_schema.tables group by x) a) --+
XPATH 报错(利用函数的语法错误)
?id=2 and extractvalue(1,concat( '^' , (select version() ), '^' )) --+
updatexml(xml_document,xpath_string,new_value):
第一个参数:XML文档对象名称。
第二个参数:XPath字符串
第三个参数:替换查找到的符合条件的数据。
?id=2 and updatexml(1,concat('^' , (select database()),'^'),1) --+
Blind SQL(盲注)是注入攻击的其中一种,向数据库发送true或 false这样的问题,并根据应用程序返回的信息判断结果。这种攻击的出现是因为应用程序配置为只显示常规错误,但并没有解决SQL注入存在的代码问题。
演示盲注问题。当攻击者利用SQL注入漏洞进行攻击时,有时候web应用程序会显示,后端数据库执行SQL查询返回的错误信息.。Blind SQL(盲注)与常规注入很接近,不同的是数据库返回数据的检索方式。若数据库没有输出数据到web页面,攻击者会询问一些列的 true或 false问题,强制从数据库获取数据。
盲注常分为:基于布尔型的盲注、基于时间的盲注
判断是否有注入点?
true:
false:
对比发现页面产生变化,但是没有报错信息,则判断可以进行布尔盲注:
多试几次(这里就不再一一演示了),我们发现数据库的长度等于8
然后我们可以根据数据库的长度来一一猜测它的字母组成:根据ASCII码对照表
我们将它的8位字母都整出来后,就可以知道它的数据库名是什么了,这里不再一一演示,最终测试出数据库名为:security
缺陷:受网络因素影响比较大,例如:网不好一直加载不出来
延时注入:根据sleep()函数的反馈来判断是否有注入点
发现沉睡了10s,则说明sleep()函数起作用了
所以我们就可以根据判断的正确与否来实施是否进行sleep(),例如:判断正确就沉睡5s,判断错误则不沉睡,这样我们就可以知道是否错误了
说明我们猜测正确,就这样我们就可以一步步猜测出数据库名了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。