SQL注入:web程序对用户输入数据的合法性没有判断,前端传入后端的参数可控的,并且参数带入数据库查询,攻击者可通过构造SQL语句来实现对数据库的任意操作。
1.sql注入原理
满足条件:
参数用户可控:前端传入后端的内容用户可以控制
参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询。
原因:用户输入的数据被SQL解释器执行
2.注入漏洞分类
1)数字型注入
当输入的参数为整型时,如:ID、年龄、页码,若存在注入漏洞,则可认为是数字型
测试:单引号 and语句 (1 and 1=1 , 1 and 1=2),若以上三个步骤全部满足,则可能存在SQL注入漏洞
数字型注入常出现在ASP、PHP等弱类型语言。强类型语言,若试图把一个字符串转换为int类型,会抛出异常,无法继续执行。
2)字符型注入
当输入参数为字符串时,称为字符型。
数字型与字符型注入最大的区别:数字型不需要单引号闭合,而字符型一般使用单引号来闭合。
字符型注入最关键的是如何闭合SQL语句以及注释多余的代码。
注:数据库不同,字符串连接符不同, SQL server的连接符为“+”,Oracle连接符为“||”,MySQL连接符为空格
3)SQL注入分类
SQL只分为两类数字型和字符型。其余注入都是在其两大类的不同展示形式,或者不同的展现位置。
由于数据库进行数据查询时,输入数据一般有两种:一种数字型,一种字符串型. 严格来说:数字也算字符串
post注入:注入字段在post数据中(post请求中username字段存在注入漏洞)
get注入:注入字段在get数据中
cookie注入:注入字段在cookie数据中
延时注入:使用数据库延时特性注入(sleep函数)
搜索注入:注入处为搜索的地点
base64注入:注入字符串需要经过base64加密
3.常见的数据库注入
数据库注入的利用方式:查询数据、读写文件、执行文件
mysql
mysql数据库 5.0之后,默认在数据库存放 information_schema 的数据库,在该库中存在三个表名
schemata 表示存储用户创建的所有数据库的库名
tables 。。。。。。。库名和表名 table_schema数据库库名 table_name 表名的字段名
columns 。。。。。。。。库名、表名、字段名 table_schema数据库库名 table_name 表名的字段名 columns_name 字段名的字段名
注释符:
#或 --空格 或 /**/
内联注释 /*! 内容 */
(1)MySQL中的注释
#:注释从#字符到行尾
--:注释从--序列到行尾(使用该注释,在其后需要跟上一个或多个空格)
(2)获取元数据
A查询数据库名称
B查询当前数据库表
C查询指定表的所有字段
(3)union查询
用于把多个select语句的结果组合到一个结果集合中,且每列的数据类型必须相同
在Oracle和SQL server中,列的数据不确定时,最好不要用null关键字匹配
(4)MySQL函数利用
需要记住的函数:database():当前网站的数据库 version():当前MySQL版本 user()用户
A load_file()函数读取文件操作
但文件的位置必须在服务器上,文件必须为绝对路径,而且用户必须有file权限,文件容量必须小于max_allowed_packet字节(默认16m,最大1gb)
B into outfile写文件操作
MySQL提供向磁盘写入文件的操作,与load_file一样,必须持有file权限,且文件有绝对路径
C 连接字符 concat() concat_ws()
(5)mysql显错式注入
A 通过updatexml函数,执行SQL
B 通过extractvalue函数,执行SQL语句
C 通过floor函数,执行SQL语句
(6)宽字节注入
该注入是由编码不统一所造成的,一般出现在PHP+MySQL中
PHP配置文件php.ini存在magic_quotes_gpc选项,被称为魔术引号,当此选项打开时,使用get、post、cookie所接收的单引号、双引号、反斜线\和null字符都会被自动加上一个反斜线转义
(7)MySQL长字符截断
在 MySQL 中的一个设置里有一个sql_mode选项,当sql_mode设置为default时,即没有开启STRICT_ALL_TABLES选项时(MySQL sql_mode默认即default),MySQL对插入超长的值只会提示warning,而不是error,这样就可能会导致一些截断问题。
通过length取的长度,判断值的长度
select length(username) from users where id=1
在默认下,如果数据超过列默认长度,MySQL会将其截断
(8)延时注入
根据页面差异来判断URL是否存在SQL注入漏洞
盲注:页面无差异的注入
延时注入时盲注的一种,是基于时间差异的注入技术。
select * from users where id=1 and sleep(3); /* 3秒后执行SQL语句 */
延时注入的操作:
4.注入工具
1)SQLmap
是一个开源渗透测试工具,自动检测和利用SQL注入漏洞。基于Python编写,跨平台。
具有强大的检测引擎。若URL存在注入漏洞,就可以在数据库中提取数据。若权限够大,可以在其操作系统上执行命令,读写文件。
特点:
(1)判断注入点
第一步:判断是否是注入点
sqlmap.py -u "ip"
第二步:获取数据库
sqlmap.py -u "ip" --dbs 使用-dbs参数读取数据库
第三步:查看当前应用程序所用数据库
sqlmap.py -u "ip" --current-db
第四步:列出指定数据库的所有表
sqlmap.py -u "ip" --table -D "数据库名"
第五步:读取指定表中字段名称
sqlmap.py -u "ip" --columns -T "表名" -D "数据库名"
第六步:读取指定字段内容
sqlmap.py -u "ip" --dump -C "username,password" -T "表名" -D "数据库名"
--dump参数意为转存数据,-C参数指定字段名称,-T指定表名,-D指定数据库名 -U用户
在读取数据后,会把数据转存在SQLMap/output/目录下,文件以Table.cvs 保存
2)SQLmap工具详解
更新升级 sqlmap -update
帮助:sqlmap -h
sqlmap.py -u "ip" --cookie "COOKIE_VALUE" cookie注入
sqlmap.py -u "http://url?id=1" --data "id=3" post注入
sqlmap.py -u "http://url?id=1" -v 1 -f 指纹判别数据库类型
sqlmap.py -u "http://url?id=1" --proxy "http://127.0.0.1:8181" 代理注入
sqlmap.py -u "http://url?id=1" --sql -shell 执行指定SQL命令
sqlmap.py -u "http://url?id=1" --os-cmd=whoami 执行系统命令
sqlmap.py -u "http://url?id=1" --os-pwn 反弹shell
--technique 测试指定注入类型\使用的技术
不加参数默认测试所有注入技术
B: 基于布尔的 SQL 盲注
E: 基于显错 sql 注入
U: 基于 UNION 注入
S: 叠层 sql 注入
T: 基于时间盲注
--tamper 通过编码绕过web防火墙(waf)
5.防止SQL注入
SQL注入攻击就是 用户可以控制输入
防御主要分:数据类型判断和特殊字符转义
1)严格的数据类型
java,c等强类型语言可完全忽略数字型注入
严格判断数据类型 可解决数字型SQL注入
2)特殊字符转义
针对字符型注入
在数据库字符串查询时,任何字符串都必须加上单引号
3)使用预编译语句
预编译语句在创建的时候已将指定的SQL语句发送给DBMS,完成了解析、检查、编译等工作,我们需要的仅仅是将变量传给SQL语句。
4)框架技术
与数据库相关的框架:持久层框架
5)存储过程
存储过程:在大型数据库系统中,一组为了完成特定功能或经常使用的SQL语句集,经编译后存储在数据库中。
存储过程具有较高的安全性,可以防止SQL注入。
过滤危险字符:正则表达式过滤传入参数(若匹配到,则退出程序)像select "" from 等
6)不要把机密信息直接存放,加密或hash掉密码和敏感信息