Bugku Web Write up

Bugku平台的Web题的Write up,差不多刷了一遍,总结一下。

前言

进度稍微延迟了这么一点,本来是想着前天刷完,昨天写Blog。结果碰上最后几个注入题,有点自闭,多搞了一点时间,导致进度一拖再拖,昨天又玩了一下午游戏无所作为。想着不能再拖了,必须今天写掉,不然过几天忘干净了再写就没意义了。所以稍微少几个题,以后再写吧


直接从题目开写吧,遇到相应知识再拓展。

基础题

0x01 Web2

点进去一堆滑稽js脚本

结合题目描述:“听说聪明的人都能找到答案” ,直接按F12。ctrl+F搜索flag,找到。

0x02 计算器

点进题目,发现标题是随机数字运算验证码。本来还以为是要利用Session,写python脚本提交。最后居然只是前端输入框长度被限制。
所以打开F12,找到输入框前端代码,更改输入框最大长度,再输入表达式计算值,弹出flag

0x03 web基础$_GET

点进去看到题目给了源码。

只需构造get请求传入what=flag即可。payload:http://123.206.87.240:8002/get/?what=flag

0x04 web基础$_POST

点进去发现题目源码。

与上题类似,不过是GET请求变成了POST,使用火狐插件hackbar或者其他类似插件构造post请求即可。

这里注意,不要直接用burp将GET改POST,亲测无效。如下图示

  1. 不用hackbar正常的GET请求
  2. 将GET直接修改成POST提交数据无效

    这里据我个人分析,是因为直接改成POST后,服务器不知道接受的数据是什么类型。所以得不到flag,于是在文件头中加上Content-Type,得出了flag,证明猜测是对的
  3. 文件头加上Content-Type

    小小总结

    以后需要改POST的还是直接用hackbar吧,233~

0x05 矛盾

点击题目后,看到源码

分析可知,需要GET传入num为数字1才能输出flag,但是如果输入纯数字的话,直接不满足if条件,进不去if语句里面,就输出不了flag。
但是这里判断num等于1,用的是==,而不是===,就用到了php弱类型比较,即 1 == 1miracle是为true的。弱类型比较自行参照搜索引擎。
于是可以构造payload:http://123.206.87.240:8002/get/index1.php?num=1miracle778

0x06 web3

题目描述为: flag就在这里快来找找吧
点击题目去,弹了一个框说flag就在这里,来找找吧

一开始还没想到flag藏的具体位置,于是只能F12,看一下源码及http文件头。结果发现弹框的那段js代码,如下图,原来”在这里”的意思是说在js代码里。

直接找到flag:
<!--&#75;&#69;&#89;&#123;&#74;&#50;&#115;&#97;&#52;&#50;&#97;&#104;&#74;&#75;&#45;&#72;&#83;&#49;&#49;&#73;&#73;&#73;&#125;-->

实体解码即可得flag:KEY{J2sa42ahJK-HS11III}

0x07 你必须让他停下

点击题目去,如下图,页面一直在刷新,图片也是不停更换

按照图中页面所述,本来以为要停在弹出一个熊猫的图片的地方,结果在页面出等了几秒,发现有些图片根本不存在,只有这一张2333~
于是打开burp,看到访问历史里,jpg的名字随机更换,而且页面响应的地方有一个flag is here,如下图划线处。

所以可以使用repeat一直按Go重放,直到出现flag为止。

0x08 文件包含

好像题目链接挂了。。。

0x09 变量1

点击题目,看到源码

分析一下,可以看到var_dump那里出现$$,存在变量覆盖,前面正则对args进行了过滤,只能输入[a-z][0-9][A-Z]。
因为存在变量覆盖,所以我们传入args=GLOBALS,即可达到输出$GLOBALS数组的目的,GLOBALS为php的超全局变量,一个包含了全部变量的全局组合数组。

0x10 web5

题目描述:JSPFUCK??????答案格式CTF{**}
点进题目并查看源码,发现一堆js混淆过的jsfuck。

复制下来直接输入F12控制台即可得到flag,再将ctf改为大写即可

0x11 头等舱

点进题目如图,源代码里也找不到啥东西

结合题目:头等舱 猜测flag藏在http头里
于是直接在响应的Headers里面找到

初级题

0x12 网站被黑

点进题目去,是一个如下图示界面,源代码、HTTP头都没找到什么东西

结合题目意思,网站被黑,说不定留下了什么后门。
于是用御剑(或者其他工具)扫一下后台,发现shell.php

访问一下,看到一个登录框,随便输个密码,出现如图所警告

到这一步的话,没有其他提示,只能先通过万能密码看看能不能绕过登录,不能的话再暴力破解
用万能密码绕过失败,尝试Burp暴力破解,Burp暴力破解具体操作自行百度,或者参考我之前发的Dvwa暴力破解
暴力破解选择simple list里的password字典进行爆破

得到密码为hack

输入密码即可得flag

0x13 管理员系统

点进题目如图示,使用万能密码测试登录,提示说IP不允许访问,联系本地管理员登录

于是添加XXF(X-Forwarded-For)=127.0.0.1进行登录尝试,提示说密码不对

从上面尝试知道,万能密码不管用,所以密码可能藏在某个地方(也是凑巧发现233~)
查看源代码,发现有一行诡异的base64注释,解码可得内容为test123

于是用admin&test123进行登录,同时添加XXF头,得到flag

0x14 web4

题目如图示

按提示查看源代码,如图发现一段被url编码的js脚本

将这段代码进行解码,如图示

通过阅读源码分析,只要在输入框输入67d709b2b54aa2aa648cf6e87a7114f1即可得到flag

0x15 flag在index里

题目如图示

点击链接后跳转到如图示地址

很明显存在文件包含,结合题目标题 flag在index里,构造payload:http://123.206.87.240:8005/post/index.php?file=php://filter/read/convert.base64-encode/resource=index.php获取index.php源码
将获取到的base64解码后得到网页源码,找到flag

0x16 输入密码查看flag

题目如图

很明显,用Burp暴力破解,得到密码为13579

输入得flag:flag{bugku-baopo-hah}

0x17 点击一百万次

题目hints为:JavaScript
题目如图,每点击这个图片一次,数量加1,当数量为100万的时候出来flag

显然,不可能为了一个flag浪费一个鼠标233~
结合题目给的hints,于是查看前端关于点击的js代码

分析可知,点击一次clicks加1,当clicks大于100万的时候,提交一个表单,value等于clicks的值,所以我们直接POST提交clicks即可。

0x18 备份是个好习惯

点击题目如图示,出现一段hash编码

乍一看还以为是md5,算了下长度,发现是64位,但是前32位跟后32位是相同的。感觉有点奇怪,于是把前32位md5解密一下,发现是个空密码。所以这段编码估计是没有什么用了。那应该怎么做呢?
题目描述是备份是个好习惯猜测可能是备份文件泄露漏洞。于是访问index.php.bak,可以下载。于是打开备份文件查看源码

分析一下,这里代码意思是,第11行获取url ?及?后的字符串,第12行去除?,第13行剩下字符串中的key替代成’’,第14行解析字符串,即将 key1=234&key2=123解析成$key1=234、$key2=123。
到了这里就应该明白了,主要考察两个点,第一是13行处,绕过str_replace。绕过之后,来到第二处,md5弱类型比较。
对于第一个点,可以使用双写绕过,第二个点的话,可以利用两个字符串md5都是0e开头绕过,或者将key1 key2赋为两个不同数组进行绕过(md5不能对数组进行操作,会返回null=null)

payload1: http://123.206.87.240:8002/web16/index.php?kekeyy1=QNKCDZO&kekeyy2=aabg7XSs

payload2: http://123.206.87.240:8002/web16/index.php?kekeyy1[]=1&kekeyy2[]=12

0x19 成绩单

打开题目链接后,题目如图示

简单的输入 1’、1’#测试后,发现存在sql注入漏洞,于是开始进行注入

  1. 用order by测试出有4个字段
  2. union查看一下哪些字段可显示
  3. 爆表
  4. 爆fl4g表的列
  5. 爆flag值

入门题

0x20 秋名山老司机

点进链接,题目如图示

请在两秒内计算车速,很明显要用到python脚本。但计算出车速来应该怎么提交呢?于是多刷新几遍,发现题目偶尔会变成下图示,里面讲到了通过post提交参数value

于是写一个python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python3
# coding=UTF-8
'''
@Author: Miracle778
@LastEditors: Miracle778
@Description: file content
@Date: 2019-04-01 10:24:57
@LastEditTime: 2019-04-01 12:59:49
'''
import requests
from bs4 import BeautifulSoup

s = requests.Session()
r = s.get('http://123.206.87.240:8002/qiumingshan/')
soup = BeautifulSoup(r.text,'html.parser')
exp = soup.find_all('div')[0].string[:-3]
# print(exp)
value = {'value':eval(exp)}
r = s.post('http://123.206.87.240:8002/qiumingshan/',data=value)
print(r.text)

利用bs4提取表达式并计算。然后使用POST提交
运行脚本即可得flag

0x21 速度要快

题目点进去如图示

没找到别的信息。
用burp看一下http头部跟页面源码,发现下图示信息。

上图注释信息说明需要POST提交参数margin的值,margin的值估计就是头部中的flag。
将头部中的flag base64解密一下得到如下信息

于是进行POST提交 margin=NDk4MDQ2,用火狐hackbar提交后,提示说不够快

既然手工不够快,那就用python跑一下吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
# coding=UTF-8
'''
@Author: Miracle778
@LastEditors: Miracle778
@Description: file content
@Date: 2019-04-01 13:06:09
@LastEditTime: 2019-04-04 20:48:35
'''
import requests
import base64

s = requests.Session()
r = s.get('http://123.206.87.240:8002/web6/')
flag_header = r.headers['flag'].encode('utf-8')
flag_message = base64.b64decode(flag_header).decode('utf-8')
tmp_list = flag_message.split(': ')
margin = base64.b64decode(tmp_list[-1].encode('utf-8')).decode()
data = {'margin':margin}

r = s.post("http://123.206.87.240:8002/web6/",data=data)
print(r.text)

跑一下,出来结果

0x22 cookies欺骗

打开题目链接页面如下

页面一段字符,看上去也不像什么编码。于是找http头部看看有没有啥提示。但找了一圈并没有发现。
但是看到访问url时,发现有的猫腻,url两个参数,一个line、另一个filename,filename的值还用base64加密了一手。
于是将filename的值解密一下看看,解密结果为keys.txt。
直接访问keys.txt看一下。与前面内容一样

所以可以得出结论,前面index.php的两个参数line和filename可以用来读取网页源文件,于是将index.php用base64加密,line从0开始,将index.php一行行读出来。避免繁琐,可以写个python脚本。

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
#!/usr/bin/env python
# coding=UTF-8
'''
@Author: Miracle778
@LastEditors: Miracle778
@Description: 导出生成index.php
@Date: 2019-04-01 13:37:02
@LastEditTime: 2019-04-01 14:01:33
'''
import requests

url = 'http://123.206.87.240:8002/web11/index.php'

# url.format(2)
data = {'filename':'aW5kZXgucGhw'}
res = ''
# r = requests.get(url+'?line=100',params=data)
for i in range(100):
data['line'] = i
r = requests.get(url,params=data)
if r.text == '':
break
res += r.text

f = open('./Bugku/Web/cookies欺骗/index.php','w')
f.write(res)
f.close

得到index.php源码

由index.php源码可知,只能通过filename读取file_list数组里的文件,而如果想读取keys.php的话,就需要构造cookie使得$_COOKIE[‘margin’]==’margin’成立。
于是再写一个python脚本,添加上Cookie值,将keys.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
#!/usr/bin/env python
# coding=UTF-8
'''
@Author: Miracle778
@LastEditors: Miracle778
@Description: 导出keys.php
@Date: 2019-04-01 14:01:56
@LastEditTime: 2019-04-01 14:11:45
'''
import requests

url = 'http://123.206.87.240:8002/web11/index.php'
# 设置cookie不通过header
# header = {'Cookie':{"margin":"margin"}}
cookie = {'margin':'margin'}
data = {'filename':'a2V5cy5waHA='}
res = ''
for i in range(100):
data['line'] = i
r = requests.get(url,params=data,cookies=cookie)
if r.text == '':
break
res += r.text
# print(res)
f = open('./Bugku/Web/cookies欺骗/keys.php','w')
f.write(res)
f.close

keys.php的源码如下图

得到flag

0x23 never give up

点进题目去,如图示

流程走一遍,查看源码及http头,在源码处发现提示:1p.html

访问一下,发现直接被重定向了。
于是只好查看1p.html的源代码,发现一段编码

解密后得到下面代码

1
2
3
4
5
6
7
8
9
var Words ="<script>window.location.href='http://www.bugku.com';</script> 
<!--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==-->"
function OutWord()
{
var NewWords;
NewWords = unescape(Words);
document.write(NewWords);
}
OutWord();

其余代码无关紧要,作用就是进行重定向。真正有用的是<!–里这段base64编码,将这段编码先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
24
25
";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 !!!";
}


?>

到这里就很明显了,传入a,b,id三个参数,分别满足if条件即可
在这里,a利用的是文件包含,用php://input协议传入数据;b利用ereg函数的%00截断以同时满足eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4这两个矛盾点;还有一个id == 0容易被忽略,本来我以为直接id=0就能绕过,这个条件是不是太简单了。后面发现id = 0的话,!$_GET[‘id’]就满足了,直接退出,根本就到不了后面,所以id还要利用一手php弱类型比较
所以最终payload为:
url: http://123.206.87.240:8006/test/hello.php?id=0miracle778&a=php://input&b=%001234566
post:bugku is a nice plateform!

当然也可以直接访问f4l2a3g.txt,233

0x24 welcome to bugkuctf

点进题目去,F12审查一下元素

发现代码,简单审计后,发现可以文件包含。构造payload
url: http://123.206.87.240:8006/test1//test1/?txt=php://input&file=php://filter/read/convert.base64-encode/resource=hint.php
post: welcome to the bugkuctf
得到hint.php源码

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php  

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

这里得到信息还是不够完善,于是将上面payload中的file更改一下,将index.php源码读出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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 ! ";
}

?>

由index.php代码分析来看,flag应该藏在flag.php里,但是通过文件包含应该是出不来,因为include前进行了一步正则匹配,file参数值不能含flag,双写flag也没能绕过去。

所以文件包含是得不到flag的,往下看,发现$password = unserialize($password);终于第三个参数用到了。这里存在反序列化漏洞。具体参考:php反序列化漏洞
于是可以构造payload
url: http://123.206.87.240:8006/test1/?txt=php://input&file=hint.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
post: welcome to the bugkuctf

0x25 过狗一句话

题目描述:

1
2
3
4
5
6
<?php 
$poc="a#s#s#e#r#t";
$poc_1=explode("#",$poc);
$poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];
$poc_2($_GET['s'])
?>

实际就是 assert($_GET['s']) 一句话木马
所以可以传入 s=cmd 进行命令执行
于是构造 s=print_r(scandir(‘./‘)) 进行文件扫描。

看到一个flag_xx.txt
直接访问即可

或者构造 s=print_r(readfile(‘./flag_sm1skla1.txt’))读取


2019/4/8 更

0x26 字符?正则?

题目链接进去,发现给了代码,这就好办了,把代码看懂就好了。

这里的意思是GET传入id的值进行一个正则匹配,匹配的话就能得到flag。直接给个链接学一波PHP正则
构造符合条件的payload: keyAAkeyAAAAkey:/A/AAkeya@得到flag

0x27 login1(SKCTF)

题目hint说是 SQL约束攻击
点进去看到是一个管理系统登录框

试了下万能密码,发现绕不过去,然后发现有注册功能,随便注册一个账号,用注册的账号进行登录,发现提示说不是管理员不能看flag

然后理所当然的去注册admin账号,不出意外的果然提示说admin已存在

我做的时候是没有看到hint的,于是自然而然想是不是可以通过sql注入,注入update语句修改admin密码,从而达到目的。后面自然是失败了。后面实在没办法,只能去看看别人的WP了,结果才发现有hint,2333~,以后一定要仔细看题目。
那提示是说SQL约束攻击,于是百度一下。基于约束的SQL攻击
使用’admin ‘做用户名进行注册登录即可。

0x28 你从哪里来

题目进去是一句话 :are you from google?

很容易就联想到更改http头部,增加Referer

0x29 md5 collision(NUPT_CTF)

这个题目之前在南邮网络攻防平台上做过,不过那边给了代码,这里代码提示什么都没给,只有一个please input a,有点尴尬,这里虽然知道怎么做,但是还是不写好了。

0x30 程序员本地网站

题目进去说请从本地访问···

感觉有点瓜皮,这题目做着做着又回到前面几题简单题一样了。
直接修改XXF头为127.0.0.1即可。图都懒得截了。

0x31 各种绕过

题目进去又给代码。

分析一下,id 可以url双重编码绕过,uname和passwd只能用sha1对数组操作返回Null来绕过了。
这里注意passwd使用post提交的,之前0x04的时候说过,post请求还是用hackbar提交吧。
这里也是,用burp直接提交是得不到flag的。

还是要用hackbar提交一手

小小总结

新版火狐的hackbar也有个小缺点,就是post提交数据的时候,一定要有参数名,也就是说遇上php://input这种的话,Execute不动,post不了数据。
所以做个小总结,遇见php://input用burp,遇见post name=value这种用hackbar,遇见两者皆有,那就用burp改GET为POST,手动加Content-Type。

0x32 web8

题目描述:txt????
题目进去又有代码看

很明显了,看到file_get_contents就要想到php://input
最后payload
url:http://123.206.87.240:8002/web8/?ac=Miracle778&fn=php://input
post:Miracle778

0x33 细心

题目描述:想办法变成admin
题目进去如下图

网页源代码及http头找了一遍没找到啥信息或提示
于是直接扫后台吧。不过扫之前可以先试试robots.txt存不存在
这里是存在的,访问一下看看,发现存在一个resusl.php

访问一下,得到下图页面

看到 管理员、IP这两个字,都顾不得别的,弄得我直接改XXF头为127.0.0.1,然并卵,并无任何作用。后面仔细分析,看到那句代码 if($_GET(x)==$password),感觉有点奇怪,这password鬼知道是谁。。后面回看一下题目,题目叫细心,描述说想办法变成admin,么得办法,把admin当password提交一手,还真就爆出来flag了。


分界线 今天就到这~~
择日再更

ヾノ≧∀≦)o 来呀!快活呀!~
-------- 本文结束 --------