mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02:00
Merge branch 'main' into atorralba/promote-unsafe-android-webview-fetch
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
| BusyWaits.java:4:4:4:19 | stmt | Prefer wait/notify or java.util.concurrent to communicate between threads. |
|
||||
| BusyWaits.java:10:5:10:39 | stmt | Prefer wait/notify or java.util.concurrent to communicate between threads. |
|
||||
| BusyWaits.java:4:4:4:19 | <Expr>; | Prefer wait/notify or java.util.concurrent to communicate between threads. |
|
||||
| BusyWaits.java:10:5:10:39 | <Expr>; | Prefer wait/notify or java.util.concurrent to communicate between threads. |
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
| CloseReader.java:11:42:11:71 | new FileReader(...) | This FileReader is not always closed on method exit. |
|
||||
| CloseReader.java:44:6:44:40 | new FileInputStream(...) | This FileInputStream is not always closed on method exit. |
|
||||
| CloseReader.java:18:42:18:71 | new FileReader(...) | This FileReader is not always closed on method exit. |
|
||||
| CloseReader.java:23:20:23:50 | new FileInputStream(...) | This FileInputStream is not always closed on method exit. |
|
||||
| CloseReader.java:33:6:33:40 | new FileInputStream(...) | This FileInputStream is not always closed on method exit. |
|
||||
| CloseReader.java:43:21:43:43 | new ZipFile(...) | This ZipFile is not always closed on method exit. |
|
||||
|
||||
@@ -1,41 +1,30 @@
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.CharArrayReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
class CloseReader {
|
||||
|
||||
public static void test1() throws IOException {
|
||||
void test1() throws IOException {
|
||||
BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"));
|
||||
System.out.println(br.readLine());
|
||||
}
|
||||
|
||||
public static void test2() throws FileNotFoundException, IOException {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("C:\\test.txt"));
|
||||
System.out.println(br.readLine());
|
||||
}
|
||||
finally {
|
||||
if(br != null)
|
||||
br.close(); // 'br' is closed
|
||||
}
|
||||
void test2() throws IOException {
|
||||
InputStream in = new FileInputStream("file.bin");
|
||||
in.read();
|
||||
}
|
||||
|
||||
public static void test3() throws IOException {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("C:\\test.txt"));
|
||||
System.out.println(br.readLine());
|
||||
}
|
||||
finally {
|
||||
cleanup(br); // 'br' is closed within a helper method
|
||||
}
|
||||
}
|
||||
|
||||
public static void test4() throws IOException {
|
||||
void test3() throws IOException {
|
||||
InputStreamReader reader = null;
|
||||
try {
|
||||
// InputStreamReader may throw an exception, in which case the ...
|
||||
@@ -50,7 +39,35 @@ class CloseReader {
|
||||
}
|
||||
}
|
||||
|
||||
public static void test5() throws IOException {
|
||||
void test4() throws IOException {
|
||||
ZipFile zipFile = new ZipFile("file.zip");
|
||||
System.out.println(zipFile.getComment());
|
||||
}
|
||||
|
||||
void testCorrect1() throws IOException {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("C:\\test.txt"));
|
||||
System.out.println(br.readLine());
|
||||
}
|
||||
finally {
|
||||
if(br != null)
|
||||
br.close(); // 'br' is closed
|
||||
}
|
||||
}
|
||||
|
||||
void testCorrect2() throws IOException {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("C:\\test.txt"));
|
||||
System.out.println(br.readLine());
|
||||
}
|
||||
finally {
|
||||
cleanup(br); // 'br' is closed within a helper method
|
||||
}
|
||||
}
|
||||
|
||||
void testCorrect3() throws IOException {
|
||||
FileInputStream fis = null;
|
||||
InputStreamReader reader = null;
|
||||
try {
|
||||
@@ -66,7 +83,7 @@ class CloseReader {
|
||||
}
|
||||
}
|
||||
|
||||
public static void test6() throws IOException {
|
||||
void testCorrect4() throws IOException {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader("C:\\test.txt"));
|
||||
@@ -77,15 +94,15 @@ class CloseReader {
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanup(java.io.Closeable... closeables) throws IOException {
|
||||
for (java.io.Closeable c : closeables) {
|
||||
void cleanup(Closeable... closeables) throws IOException {
|
||||
for (Closeable c : closeables) {
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LogFile {
|
||||
static class LogFile {
|
||||
private BufferedReader fileRd;
|
||||
LogFile(String path) {
|
||||
FileReader fr = null;
|
||||
@@ -100,9 +117,21 @@ class CloseReader {
|
||||
private void init(InputStreamReader reader) {
|
||||
fileRd = new BufferedReader(reader);
|
||||
}
|
||||
public void readStuff() throws java.io.IOException {
|
||||
public void readStuff() throws IOException {
|
||||
System.out.println(fileRd.readLine());
|
||||
fileRd.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Classes which should be ignored
|
||||
void testIgnore() throws IOException {
|
||||
Reader r1 = new CharArrayReader(new char[] {'a'});
|
||||
r1.read();
|
||||
|
||||
Reader r2 = new StringReader("a");
|
||||
r2.read();
|
||||
|
||||
InputStream i1 = new ByteArrayInputStream(new byte[] {1});
|
||||
i1.read();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Likely Bugs/Resource Leaks/CloseReader.ql
|
||||
Likely Bugs/Resource Leaks/CloseReader.ql
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
| CloseWriter.java:17:42:17:71 | new FileWriter(...) | This FileWriter is not always closed on method exit. |
|
||||
| CloseWriter.java:22:22:22:53 | new FileOutputStream(...) | This FileOutputStream is not always closed on method exit. |
|
||||
| CloseWriter.java:32:6:32:41 | new FileOutputStream(...) | This FileOutputStream is not always closed on method exit. |
|
||||
@@ -0,0 +1,131 @@
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.Closeable;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
class CloseWriter {
|
||||
|
||||
void test1() throws IOException {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\test.txt"));
|
||||
bw.write("test");
|
||||
}
|
||||
|
||||
void test2() throws IOException {
|
||||
OutputStream out = new FileOutputStream("test.bin");
|
||||
out.write(1);
|
||||
}
|
||||
|
||||
void test3() throws IOException {
|
||||
OutputStreamWriter writer = null;
|
||||
try {
|
||||
// OutputStreamWriter may throw an exception, in which case the ...
|
||||
writer = new OutputStreamWriter(
|
||||
// ... FileOutputStream is not closed by the finally block
|
||||
new FileOutputStream("C:\\test.txt"), "UTF-8");
|
||||
writer.write("test");
|
||||
}
|
||||
finally {
|
||||
if (writer != null)
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
void testCorrect1() throws IOException {
|
||||
BufferedWriter bw = null;
|
||||
try {
|
||||
bw = new BufferedWriter(new FileWriter("C:\\test.txt"));
|
||||
bw.write("test");
|
||||
}
|
||||
finally {
|
||||
if(bw != null)
|
||||
bw.close(); // 'bw' is closed
|
||||
}
|
||||
}
|
||||
|
||||
void testCorrect2() throws IOException {
|
||||
BufferedWriter bw = null;
|
||||
try {
|
||||
bw = new BufferedWriter(new FileWriter("C:\\test.txt"));
|
||||
bw.write("test");
|
||||
}
|
||||
finally {
|
||||
cleanup(bw); // 'bw' is closed within a helper method
|
||||
}
|
||||
}
|
||||
|
||||
void testCorrect3() throws IOException {
|
||||
FileOutputStream fos = null;
|
||||
OutputStreamWriter writer = null;
|
||||
try {
|
||||
fos = new FileOutputStream("C:\\test.txt");
|
||||
writer = new OutputStreamWriter(fos);
|
||||
writer.write("test");
|
||||
}
|
||||
finally {
|
||||
if (fos != null)
|
||||
fos.close(); // 'fos' is closed
|
||||
if (writer != null)
|
||||
writer.close(); // 'writer' is closed
|
||||
}
|
||||
}
|
||||
|
||||
void testCorrect4() throws IOException {
|
||||
BufferedWriter bw = null;
|
||||
try {
|
||||
bw = new BufferedWriter(new FileWriter("C:\\test.txt"));
|
||||
bw.write("test");
|
||||
}
|
||||
finally {
|
||||
cleanup(null, bw); // 'bw' is closed within a varargs helper method, invoked with multiple args
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup(Closeable... closeables) throws IOException {
|
||||
for (Closeable c : closeables) {
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class LogFile {
|
||||
private BufferedWriter fileWr;
|
||||
LogFile(String path) {
|
||||
FileWriter fw = null;
|
||||
try {
|
||||
fw = new FileWriter(path);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error: File not readable: " + path);
|
||||
System.exit(1);
|
||||
}
|
||||
init(fw);
|
||||
}
|
||||
private void init(OutputStreamWriter writer) {
|
||||
fileWr = new BufferedWriter(writer);
|
||||
}
|
||||
public void writeStuff() throws IOException {
|
||||
fileWr.write("test");
|
||||
fileWr.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Classes which should be ignored
|
||||
void testIgnore() throws IOException {
|
||||
Writer w1 = new CharArrayWriter();
|
||||
w1.write("test");
|
||||
|
||||
Writer w2 = new StringWriter();
|
||||
w2.write("test");
|
||||
|
||||
OutputStream o1 = new ByteArrayOutputStream();
|
||||
o1.write(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Likely Bugs/Resource Leaks/CloseWriter.ql
|
||||
@@ -1,4 +1,4 @@
|
||||
| A.java:8:11:8:15 | !... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:8:5:8:16 | stmt | Loop |
|
||||
| A.java:15:11:15:15 | ... > ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:14:5:14:19 | stmt | Loop |
|
||||
| A.java:29:20:29:32 | ... < ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:29:5:29:38 | stmt | Loop |
|
||||
| A.java:36:12:36:15 | cond | $@ might not terminate, as this loop condition is constant within the loop. | A.java:36:5:36:16 | stmt | Loop |
|
||||
| A.java:8:11:8:15 | !... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:8:5:8:16 | while (...) | Loop |
|
||||
| A.java:15:11:15:15 | ... > ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:14:5:14:19 | for (...;...;...) | Loop |
|
||||
| A.java:29:20:29:32 | ... < ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:29:5:29:38 | for (...;...;...) | Loop |
|
||||
| A.java:36:12:36:15 | cond | $@ might not terminate, as this loop condition is constant within the loop. | A.java:36:5:36:16 | while (...) | Loop |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| A.java:14:9:14:17 | stmt | This 'continue' never re-runs the loop - the $@ is always false. | A.java:17:14:17:18 | false | loop condition |
|
||||
| A.java:54:11:54:19 | stmt | This 'continue' never re-runs the loop - the $@ is always false. | A.java:57:16:57:20 | false | loop condition |
|
||||
| A.java:79:9:79:17 | stmt | This 'continue' never re-runs the loop - the $@ is always false. | A.java:82:14:82:18 | false | loop condition |
|
||||
| A.java:14:9:14:17 | continue | This 'continue' never re-runs the loop - the $@ is always false. | A.java:17:14:17:18 | false | loop condition |
|
||||
| A.java:54:11:54:19 | continue | This 'continue' never re-runs the loop - the $@ is always false. | A.java:57:16:57:20 | false | loop condition |
|
||||
| A.java:79:9:79:17 | continue | This 'continue' never re-runs the loop - the $@ is always false. | A.java:82:14:82:18 | false | loop condition |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Test.java:14:4:14:10 | stmt | Switch case may fall through to the next case. Use a break or return to terminate this case. |
|
||||
| Test.java:20:4:20:10 | stmt | Switch case may fall through to the next case. Use a break or return to terminate this case. |
|
||||
| Test.java:14:4:14:10 | case ... | Switch case may fall through to the next case. Use a break or return to terminate this case. |
|
||||
| Test.java:20:4:20:10 | case ... | Switch case may fall through to the next case. Use a break or return to terminate this case. |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| A.java:12:7:16:7 | stmt | Double-checked locking on the non-volatile field $@ is not thread-safe. | A.java:9:18:9:19 | s1 | s1 |
|
||||
| A.java:40:7:45:7 | stmt | Double-checked locking on the non-volatile field $@ is not thread-safe. | A.java:36:13:36:14 | b1 | b1 |
|
||||
| A.java:101:7:106:7 | stmt | Double-checked locking on the non-volatile field $@ is not thread-safe. | A.java:98:26:98:27 | b5 | b5 |
|
||||
| A.java:12:7:16:7 | synchronized (...) | Double-checked locking on the non-volatile field $@ is not thread-safe. | A.java:9:18:9:19 | s1 | s1 |
|
||||
| A.java:40:7:45:7 | synchronized (...) | Double-checked locking on the non-volatile field $@ is not thread-safe. | A.java:36:13:36:14 | b1 | b1 |
|
||||
| A.java:101:7:106:7 | synchronized (...) | Double-checked locking on the non-volatile field $@ is not thread-safe. | A.java:98:26:98:27 | b5 | b5 |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| Finally.java:6:4:6:10 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:17:5:17:13 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:30:5:30:40 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:63:6:63:11 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:77:7:77:12 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:111:6:111:14 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:125:7:125:15 | stmt | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:6:4:6:10 | return ... | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:17:5:17:13 | return ... | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:30:5:30:40 | throw ... | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:63:6:63:11 | break | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:77:7:77:12 | break | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:111:6:111:14 | continue | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
| Finally.java:125:7:125:15 | continue | Leaving a finally-block with this statement can cause exceptions to silently disappear. |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| MissedTernaryOpportunityTest.java:6:3:6:13 | stmt | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:32:3:32:13 | stmt | Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:74:9:74:19 | stmt | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:133:9:133:18 | stmt | Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:145:13:145:23 | stmt | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:155:13:155:23 | stmt | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:6:3:6:13 | if (...) | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:32:3:32:13 | if (...) | Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:74:9:74:19 | if (...) | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:133:9:133:18 | if (...) | Both branches of this 'if' statement write to the same variable - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:145:13:145:23 | if (...) | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
| MissedTernaryOpportunityTest.java:155:13:155:23 | if (...) | Both branches of this 'if' statement return - consider using '?' to express intent better. |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| PartiallyMaskedCatchTest.java:16:5:16:25 | stmt | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:12:5:12:24 | stmt | here for exceptions of type 'ExceptionB' |
|
||||
| PartiallyMaskedCatchTest.java:16:5:16:25 | stmt | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:14:5:14:24 | stmt | here for exceptions of type 'ExceptionA' |
|
||||
| PartiallyMaskedCatchTest.java:26:5:26:25 | stmt | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:22:5:22:47 | stmt | here for exceptions of type 'ExceptionB' |
|
||||
| PartiallyMaskedCatchTest.java:26:5:26:25 | stmt | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:24:5:24:43 | stmt | here for exceptions of type 'ExceptionA' |
|
||||
| PartiallyMaskedCatchTest.java:36:5:36:44 | stmt | This catch-clause is unreachable for type IOException; it is masked $@. | PartiallyMaskedCatchTest.java:32:5:32:47 | stmt | here for exceptions of type 'ExceptionB' |
|
||||
| PartiallyMaskedCatchTest.java:36:5:36:44 | stmt | This catch-clause is unreachable for type IOException; it is masked $@. | PartiallyMaskedCatchTest.java:34:5:34:51 | stmt | here for exceptions of type 'ExceptionA' |
|
||||
| PartiallyMaskedCatchTest.java:16:5:16:25 | catch (...) | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:12:5:12:24 | catch (...) | here for exceptions of type 'ExceptionB' |
|
||||
| PartiallyMaskedCatchTest.java:16:5:16:25 | catch (...) | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:14:5:14:24 | catch (...) | here for exceptions of type 'ExceptionA' |
|
||||
| PartiallyMaskedCatchTest.java:26:5:26:25 | catch (...) | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:22:5:22:47 | catch (...) | here for exceptions of type 'ExceptionB' |
|
||||
| PartiallyMaskedCatchTest.java:26:5:26:25 | catch (...) | This catch-clause is unreachable; it is masked $@. | PartiallyMaskedCatchTest.java:24:5:24:43 | catch (...) | here for exceptions of type 'ExceptionA' |
|
||||
| PartiallyMaskedCatchTest.java:36:5:36:44 | catch (...) | This catch-clause is unreachable for type IOException; it is masked $@. | PartiallyMaskedCatchTest.java:32:5:32:47 | catch (...) | here for exceptions of type 'ExceptionB' |
|
||||
| PartiallyMaskedCatchTest.java:36:5:36:44 | catch (...) | This catch-clause is unreachable for type IOException; it is masked $@. | PartiallyMaskedCatchTest.java:34:5:34:51 | catch (...) | here for exceptions of type 'ExceptionA' |
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
| UseBraces.java:28:4:28:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:29:4:29:7 | stmt | the next statement | UseBraces.java:27:3:27:10 | stmt | the control structure |
|
||||
| UseBraces.java:32:4:32:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:32:9:32:12 | stmt | the next statement | UseBraces.java:31:3:31:10 | stmt | the control structure |
|
||||
| UseBraces.java:58:4:58:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:59:4:59:7 | stmt | the next statement | UseBraces.java:53:3:53:10 | stmt | the control structure |
|
||||
| UseBraces.java:66:4:66:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:66:10:66:13 | stmt | the next statement | UseBraces.java:61:3:61:10 | stmt | the control structure |
|
||||
| UseBraces.java:82:4:82:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:83:4:83:7 | stmt | the next statement | UseBraces.java:81:3:81:14 | stmt | the control structure |
|
||||
| UseBraces.java:87:4:87:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:87:9:87:12 | stmt | the next statement | UseBraces.java:86:3:86:14 | stmt | the control structure |
|
||||
| UseBraces.java:112:4:112:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:113:4:113:7 | stmt | the next statement | UseBraces.java:111:3:111:25 | stmt | the control structure |
|
||||
| UseBraces.java:116:4:116:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:116:9:116:12 | stmt | the next statement | UseBraces.java:115:3:115:25 | stmt | the control structure |
|
||||
| UseBraces.java:132:4:132:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:133:4:133:7 | stmt | the next statement | UseBraces.java:131:3:131:24 | stmt | the control structure |
|
||||
| UseBraces.java:136:4:136:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:136:9:136:12 | stmt | the next statement | UseBraces.java:135:3:135:24 | stmt | the control structure |
|
||||
| UseBraces.java:145:4:145:12 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:147:4:147:7 | stmt | the next statement | UseBraces.java:144:3:144:12 | stmt | the control structure |
|
||||
| UseBraces.java:166:4:166:7 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:167:4:167:7 | stmt | the next statement | UseBraces.java:165:8:165:17 | stmt | the control structure |
|
||||
| UseBraces.java:176:4:176:15 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:178:4:178:7 | stmt | the next statement | UseBraces.java:175:3:175:11 | stmt | the control structure |
|
||||
| UseBraces.java:186:4:186:12 | stmt | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:188:4:188:7 | stmt | the next statement | UseBraces.java:185:3:185:14 | stmt | the control structure |
|
||||
| UseBraces.java:28:4:28:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:29:4:29:7 | <Expr>; | the next statement | UseBraces.java:27:3:27:10 | if (...) | the control structure |
|
||||
| UseBraces.java:32:4:32:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:32:9:32:12 | <Expr>; | the next statement | UseBraces.java:31:3:31:10 | if (...) | the control structure |
|
||||
| UseBraces.java:58:4:58:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:59:4:59:7 | <Expr>; | the next statement | UseBraces.java:53:3:53:10 | if (...) | the control structure |
|
||||
| UseBraces.java:66:4:66:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:66:10:66:13 | <Expr>; | the next statement | UseBraces.java:61:3:61:10 | if (...) | the control structure |
|
||||
| UseBraces.java:82:4:82:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:83:4:83:7 | <Expr>; | the next statement | UseBraces.java:81:3:81:14 | while (...) | the control structure |
|
||||
| UseBraces.java:87:4:87:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:87:9:87:12 | <Expr>; | the next statement | UseBraces.java:86:3:86:14 | while (...) | the control structure |
|
||||
| UseBraces.java:112:4:112:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:113:4:113:7 | <Expr>; | the next statement | UseBraces.java:111:3:111:25 | for (...;...;...) | the control structure |
|
||||
| UseBraces.java:116:4:116:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:116:9:116:12 | <Expr>; | the next statement | UseBraces.java:115:3:115:25 | for (...;...;...) | the control structure |
|
||||
| UseBraces.java:132:4:132:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:133:4:133:7 | <Expr>; | the next statement | UseBraces.java:131:3:131:24 | for (... : ...) | the control structure |
|
||||
| UseBraces.java:136:4:136:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:136:9:136:12 | <Expr>; | the next statement | UseBraces.java:135:3:135:24 | for (... : ...) | the control structure |
|
||||
| UseBraces.java:145:4:145:12 | if (...) | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:147:4:147:7 | <Expr>; | the next statement | UseBraces.java:144:3:144:12 | if (...) | the control structure |
|
||||
| UseBraces.java:166:4:166:7 | <Expr>; | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:167:4:167:7 | <Expr>; | the next statement | UseBraces.java:165:8:165:17 | if (...) | the control structure |
|
||||
| UseBraces.java:176:4:176:15 | while (...) | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:178:4:178:7 | <Expr>; | the next statement | UseBraces.java:175:3:175:11 | if (...) | the control structure |
|
||||
| UseBraces.java:186:4:186:12 | if (...) | Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation. | UseBraces.java:188:4:188:7 | <Expr>; | the next statement | UseBraces.java:185:3:185:14 | while (...) | the control structure |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| Test.java:15:3:15:14 | stmt |
|
||||
| Test.java:15:3:15:14 | return ... |
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
edges
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:7:44:7:69 | ... + ... |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:10:29:10:74 | new String[] |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:18:29:18:31 | cmd |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:16:13:16:25 | ... + ... : String |
|
||||
| Test.java:6:35:6:44 | arg : String | Test.java:24:29:24:32 | cmd1 |
|
||||
| Test.java:16:5:16:7 | cmd [post update] : List | Test.java:18:29:18:31 | cmd |
|
||||
| Test.java:16:13:16:25 | ... + ... : String | Test.java:16:5:16:7 | cmd [post update] : List |
|
||||
| Test.java:28:38:28:47 | arg : String | Test.java:29:44:29:64 | ... + ... |
|
||||
| Test.java:57:27:57:39 | args : String[] | Test.java:60:20:60:22 | arg : String |
|
||||
| Test.java:57:27:57:39 | args : String[] | Test.java:61:23:61:25 | arg : String |
|
||||
@@ -12,6 +14,8 @@ nodes
|
||||
| Test.java:6:35:6:44 | arg : String | semmle.label | arg : String |
|
||||
| Test.java:7:44:7:69 | ... + ... | semmle.label | ... + ... |
|
||||
| Test.java:10:29:10:74 | new String[] | semmle.label | new String[] |
|
||||
| Test.java:16:5:16:7 | cmd [post update] : List | semmle.label | cmd [post update] : List |
|
||||
| Test.java:16:13:16:25 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| Test.java:18:29:18:31 | cmd | semmle.label | cmd |
|
||||
| Test.java:24:29:24:32 | cmd1 | semmle.label | cmd1 |
|
||||
| Test.java:28:38:28:47 | arg : String | semmle.label | arg : String |
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
edges
|
||||
| XSS.java:23:21:23:48 | getParameter(...) : String | XSS.java:23:5:23:70 | ... + ... |
|
||||
| XSS.java:27:21:27:48 | getParameter(...) : String | XSS.java:27:5:27:70 | ... + ... |
|
||||
| XSS.java:38:67:38:87 | getPathInfo(...) : String | XSS.java:38:30:38:87 | ... + ... |
|
||||
| XSS.java:41:36:41:56 | getPathInfo(...) : String | XSS.java:41:36:41:67 | getBytes(...) |
|
||||
nodes
|
||||
| XSS.java:23:5:23:70 | ... + ... | semmle.label | ... + ... |
|
||||
| XSS.java:23:21:23:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| XSS.java:27:5:27:70 | ... + ... | semmle.label | ... + ... |
|
||||
| XSS.java:27:21:27:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| XSS.java:38:30:38:87 | ... + ... | semmle.label | ... + ... |
|
||||
| XSS.java:38:67:38:87 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| XSS.java:41:36:41:56 | getPathInfo(...) : String | semmle.label | getPathInfo(...) : String |
|
||||
| XSS.java:41:36:41:67 | getBytes(...) | semmle.label | getBytes(...) |
|
||||
#select
|
||||
| XSS.java:23:5:23:70 | ... + ... | XSS.java:23:21:23:48 | getParameter(...) : String | XSS.java:23:5:23:70 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:23:21:23:48 | getParameter(...) | user-provided value |
|
||||
| XSS.java:27:5:27:70 | ... + ... | XSS.java:27:21:27:48 | getParameter(...) : String | XSS.java:27:5:27:70 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:27:21:27:48 | getParameter(...) | user-provided value |
|
||||
| XSS.java:38:30:38:87 | ... + ... | XSS.java:38:67:38:87 | getPathInfo(...) : String | XSS.java:38:30:38:87 | ... + ... | Cross-site scripting vulnerability due to $@. | XSS.java:38:67:38:87 | getPathInfo(...) | user-provided value |
|
||||
| XSS.java:41:36:41:67 | getBytes(...) | XSS.java:41:36:41:56 | getPathInfo(...) : String | XSS.java:41:36:41:67 | getBytes(...) | Cross-site scripting vulnerability due to $@. | XSS.java:41:36:41:56 | getPathInfo(...) | user-provided value |
|
||||
|
||||
@@ -22,7 +22,7 @@ public class XSS extends HttpServlet {
|
||||
response.getWriter().print(
|
||||
"The page \"" + request.getParameter("page") + "\" was not found.");
|
||||
|
||||
// BAD: a request parameter is written directly to an error response page
|
||||
// GOOD: servlet API encodes the error message HTML for the HTML context
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND,
|
||||
"The page \"" + request.getParameter("page") + "\" was not found.");
|
||||
|
||||
@@ -30,7 +30,7 @@ public class XSS extends HttpServlet {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND,
|
||||
"The page \"" + encodeForHtml(request.getParameter("page")) + "\" was not found.");
|
||||
|
||||
// FALSE NEGATIVE: passed through function that is not a secure check
|
||||
// GOOD: servlet API encodes the error message HTML for the HTML context
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND,
|
||||
"The page \"" + capitalizeName(request.getParameter("page")) + "\" was not found.");
|
||||
|
||||
|
||||
119
java/ql/test/query-tests/security/CWE-094/Jexl2Injection.java
Normal file
119
java/ql/test/query-tests/security/CWE-094/Jexl2Injection.java
Normal file
@@ -0,0 +1,119 @@
|
||||
import org.apache.commons.jexl2.*;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Jexl2Injection {
|
||||
|
||||
private static void runJexlExpression(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
Expression e = jexl.createExpression(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionWithJexlInfo(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
Expression e = jexl.createExpression(jexlExpr, new DebugInfo("unknown", 0, 0));
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlScript(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
Script script = jexl.createScript(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
script.execute(jc); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlScriptViaCallable(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
Script script = jexl.createScript(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
|
||||
try {
|
||||
script.callable(jc).call(); // $hasJexlInjection
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaGetProperty(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
jexl.getProperty(new Object(), jexlExpr); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaSetProperty(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
jexl.setProperty(new Object(), jexlExpr, new Object()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaUnifiedJEXLParseAndEvaluate(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
UnifiedJEXL unifiedJEXL = new UnifiedJEXL(jexl);
|
||||
unifiedJEXL.parse(jexlExpr).evaluate(new MapContext()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaUnifiedJEXLParseAndPrepare(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
UnifiedJEXL unifiedJEXL = new UnifiedJEXL(jexl);
|
||||
unifiedJEXL.parse(jexlExpr).prepare(new MapContext()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaUnifiedJEXLTemplateEvaluate(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlEngine();
|
||||
UnifiedJEXL unifiedJEXL = new UnifiedJEXL(jexl);
|
||||
unifiedJEXL.createTemplate(jexlExpr).evaluate(new MapContext(), new StringWriter()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void testWithSocket(Consumer<String> action) throws Exception {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
try (Socket socket = serverSocket.accept()) {
|
||||
byte[] bytes = new byte[1024];
|
||||
int n = socket.getInputStream().read(bytes);
|
||||
String jexlExpr = new String(bytes, 0, n);
|
||||
action.accept(jexlExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// below are tests for the query
|
||||
|
||||
public static void testWithJexlExpressionEvaluate() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpression);
|
||||
}
|
||||
|
||||
public static void testWithJexlExpressionEvaluateWithInfo() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpressionWithJexlInfo);
|
||||
}
|
||||
|
||||
public static void testWithJexlScriptExecute() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlScript);
|
||||
}
|
||||
|
||||
public static void testWithJexlScriptCallable() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlScriptViaCallable);
|
||||
}
|
||||
|
||||
public static void testWithJexlEngineGetProperty() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpressionViaGetProperty);
|
||||
}
|
||||
|
||||
public static void testWithJexlEngineSetProperty() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpressionViaSetProperty);
|
||||
}
|
||||
|
||||
public static void testWithUnifiedJEXLParseAndEvaluate() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpressionViaUnifiedJEXLParseAndEvaluate);
|
||||
}
|
||||
|
||||
public static void testWithUnifiedJEXLParseAndPrepare() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpressionViaUnifiedJEXLParseAndPrepare);
|
||||
}
|
||||
|
||||
public static void testWithUnifiedJEXLTemplateEvaluate() throws Exception {
|
||||
testWithSocket(Jexl2Injection::runJexlExpressionViaUnifiedJEXLTemplateEvaluate);
|
||||
}
|
||||
}
|
||||
194
java/ql/test/query-tests/security/CWE-094/Jexl3Injection.java
Normal file
194
java/ql/test/query-tests/security/CWE-094/Jexl3Injection.java
Normal file
@@ -0,0 +1,194 @@
|
||||
import java.io.StringWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.jexl3.*;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@Controller
|
||||
public class Jexl3Injection {
|
||||
|
||||
private static void runJexlExpression(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JexlExpression e = jexl.createExpression(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionWithJexlInfo(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JexlExpression e = jexl.createExpression(new JexlInfo("unknown", 0, 0), jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlScript(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JexlScript script = jexl.createScript(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
script.execute(jc); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlScriptViaCallable(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JexlScript script = jexl.createScript(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
|
||||
try {
|
||||
script.callable(jc).call(); // $hasJexlInjection
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaGetProperty(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
jexl.getProperty(new Object(), jexlExpr); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaSetProperty(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
jexl.setProperty(new Object(), jexlExpr, new Object()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaJxltEngineExpressionEvaluate(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JxltEngine jxlt = jexl.createJxltEngine();
|
||||
jxlt.createExpression(jexlExpr).evaluate(new MapContext()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaJxltEngineExpressionPrepare(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JxltEngine jxlt = jexl.createJxltEngine();
|
||||
jxlt.createExpression(jexlExpr).prepare(new MapContext()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaJxltEngineTemplateEvaluate(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JxltEngine jxlt = jexl.createJxltEngine();
|
||||
jxlt.createTemplate(jexlExpr).evaluate(new MapContext(), new StringWriter()); // $hasJexlInjection
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaCallable(String jexlExpr) {
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JexlExpression e = jexl.createExpression(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
|
||||
try {
|
||||
e.callable(jc).call(); // $hasJexlInjection
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testWithSocket(Consumer<String> action) throws Exception {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
try (Socket socket = serverSocket.accept()) {
|
||||
byte[] bytes = new byte[1024];
|
||||
int n = socket.getInputStream().read(bytes);
|
||||
String jexlExpr = new String(bytes, 0, n);
|
||||
action.accept(jexlExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// below are tests for the query
|
||||
|
||||
public static void testWithJexlExpressionEvaluate() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpression);
|
||||
}
|
||||
|
||||
public static void testWithJexlExpressionEvaluateWithInfo() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionWithJexlInfo);
|
||||
}
|
||||
|
||||
public static void testWithJexlScriptExecute() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlScript);
|
||||
}
|
||||
|
||||
public static void testWithJexlScriptCallable() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlScriptViaCallable);
|
||||
}
|
||||
|
||||
public static void testWithJexlEngineGetProperty() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionViaGetProperty);
|
||||
}
|
||||
|
||||
public static void testWithJexlEngineSetProperty() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionViaSetProperty);
|
||||
}
|
||||
|
||||
public static void testWithJxltEngineExpressionEvaluate() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionViaJxltEngineExpressionEvaluate);
|
||||
}
|
||||
|
||||
public static void testWithJxltEngineExpressionPrepare() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionViaJxltEngineExpressionPrepare);
|
||||
}
|
||||
|
||||
public static void testWithJxltEngineTemplateEvaluate() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionViaJxltEngineTemplateEvaluate);
|
||||
}
|
||||
|
||||
public static void testWithJexlExpressionCallable() throws Exception {
|
||||
testWithSocket(Jexl3Injection::runJexlExpressionViaCallable);
|
||||
}
|
||||
|
||||
@PostMapping("/request")
|
||||
public ResponseEntity testWithSpringControllerThatEvaluatesJexlFromPathVariable(@PathVariable String expr) {
|
||||
|
||||
runJexlExpression(expr);
|
||||
return ResponseEntity.ok(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/request")
|
||||
public ResponseEntity testWithSpringControllerThatEvaluatesJexlFromRequestBody(@RequestBody Data data) {
|
||||
|
||||
String expr = data.getExpr();
|
||||
runJexlExpression(expr);
|
||||
|
||||
return ResponseEntity.ok(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/request")
|
||||
public ResponseEntity testWithSpringControllerThatEvaluatesJexlFromRequestBodyWithNestedObjects(
|
||||
@RequestBody CustomRequest customRequest) {
|
||||
|
||||
String expr = customRequest.getData().getExpr();
|
||||
runJexlExpression(expr);
|
||||
|
||||
return ResponseEntity.ok(HttpStatus.OK);
|
||||
}
|
||||
|
||||
public static class CustomRequest {
|
||||
|
||||
private Data data;
|
||||
|
||||
CustomRequest(Data data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Data getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Data {
|
||||
|
||||
private String expr;
|
||||
|
||||
Data(String expr) {
|
||||
this.expr = expr;
|
||||
}
|
||||
|
||||
public String getExpr() {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.FlowSteps
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.JexlInjection
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class Conf extends TaintTracking::Configuration {
|
||||
Conf() { this = "qltest:cwe:jexl-injection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(JexlInjectionAdditionalTaintStep c).step(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
class JexlInjectionTest extends InlineExpectationsTest {
|
||||
JexlInjectionTest() { this = "HasJexlInjectionTest" }
|
||||
|
||||
override string getARelevantTag() { result = "hasJexlInjection" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasJexlInjection" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, Conf conf | conf.hasFlow(src, sink) |
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import org.apache.commons.jexl2.*;
|
||||
import org.apache.commons.jexl2.introspection.*;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SandboxedJexl2 {
|
||||
|
||||
private static void runJexlExpressionWithSandbox(String jexlExpr) {
|
||||
Sandbox sandbox = new Sandbox();
|
||||
sandbox.white(SandboxedJexl2.class.getCanonicalName());
|
||||
Uberspect uberspect = new SandboxUberspectImpl(null, sandbox);
|
||||
JexlEngine jexl = new JexlEngine(uberspect, null, null, null);
|
||||
Expression e = jexl.createExpression(jexlExpr);
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // Safe
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaSandboxedUnifiedJexl(String jexlExpr) {
|
||||
Sandbox sandbox = new Sandbox();
|
||||
sandbox.white(SandboxedJexl2.class.getCanonicalName());
|
||||
Uberspect uberspect = new SandboxUberspectImpl(null, sandbox);
|
||||
JexlEngine jexl = new JexlEngine(uberspect, null, null, null);
|
||||
UnifiedJEXL unifiedJEXL = new UnifiedJEXL(jexl);
|
||||
unifiedJEXL.parse(jexlExpr).evaluate(new MapContext()); // Safe
|
||||
}
|
||||
|
||||
private static void simpleServer(Consumer<String> action) throws Exception {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
try (Socket socket = serverSocket.accept()) {
|
||||
byte[] bytes = new byte[1024];
|
||||
int n = socket.getInputStream().read(bytes);
|
||||
String jexlExpr = new String(bytes, 0, n);
|
||||
action.accept(jexlExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void saferJexlExpressionEvaluate() throws Exception {
|
||||
simpleServer(SandboxedJexl2::runJexlExpressionWithSandbox);
|
||||
}
|
||||
|
||||
public static void saferJexlExpressionEvaluateViaUnifiedJexl() throws Exception {
|
||||
simpleServer(SandboxedJexl2::runJexlExpressionViaSandboxedUnifiedJexl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.jexl3.*;
|
||||
import org.apache.commons.jexl3.introspection.*;
|
||||
|
||||
public class SandboxedJexl3 {
|
||||
|
||||
private static void runJexlExpressionWithSandbox(String jexlExpr) {
|
||||
JexlSandbox sandbox = new JexlSandbox(false);
|
||||
sandbox.white(SandboxedJexl3.class.getCanonicalName());
|
||||
JexlEngine jexl = new JexlBuilder().sandbox(sandbox).create();
|
||||
JexlExpression e = jexl.createExpression(jexlExpr); // Safe
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // Safe
|
||||
}
|
||||
|
||||
private static void runJexlExpressionWithUberspectSandbox(String jexlExpr) {
|
||||
JexlUberspect sandbox = new JexlUberspectSandbox();
|
||||
JexlEngine jexl = new JexlBuilder().uberspect(sandbox).create();
|
||||
JexlExpression e = jexl.createExpression(jexlExpr); // Safe
|
||||
JexlContext jc = new MapContext();
|
||||
e.evaluate(jc); // Safe
|
||||
}
|
||||
|
||||
private static JexlBuilder STATIC_JEXL_BUILDER;
|
||||
|
||||
static {
|
||||
JexlSandbox sandbox = new JexlSandbox(false);
|
||||
sandbox.white(SandboxedJexl3.class.getCanonicalName());
|
||||
STATIC_JEXL_BUILDER = new JexlBuilder().sandbox(sandbox);
|
||||
}
|
||||
|
||||
private static void runJexlExpressionViaJxltEngineWithSandbox(String jexlExpr) {
|
||||
JexlEngine jexl = STATIC_JEXL_BUILDER.create();
|
||||
JxltEngine jxlt = jexl.createJxltEngine();
|
||||
jxlt.createExpression(jexlExpr).evaluate(new MapContext()); // Safe
|
||||
}
|
||||
|
||||
private static class JexlUberspectSandbox implements JexlUberspect {
|
||||
|
||||
}
|
||||
|
||||
private static void withSocket(Consumer<String> action) throws Exception {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
try (Socket socket = serverSocket.accept()) {
|
||||
byte[] bytes = new byte[1024];
|
||||
int n = socket.getInputStream().read(bytes);
|
||||
String jexlExpr = new String(bytes, 0, n);
|
||||
action.accept(jexlExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// below are examples of safer Jexl usage
|
||||
|
||||
// with JexlSandbox
|
||||
public static void saferJexlExpressionInSandbox() throws Exception {
|
||||
withSocket(SandboxedJexl3::runJexlExpressionWithSandbox);
|
||||
}
|
||||
|
||||
// with a custom sandbox implemented with JexlUberspect
|
||||
public static void saferJexlExpressionInUberspectSandbox() throws Exception {
|
||||
withSocket(SandboxedJexl3::runJexlExpressionWithUberspectSandbox);
|
||||
}
|
||||
|
||||
// with JexlSandbox and JxltEngine
|
||||
public static void saferJxltExpressionInSandbox() throws Exception {
|
||||
withSocket(SandboxedJexl3::runJexlExpressionViaJxltEngineWithSandbox);
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
edges
|
||||
| HttpsUrlsTest.java:23:23:23:31 | "http://" : String | HttpsUrlsTest.java:28:50:28:50 | u |
|
||||
| HttpsUrlsTest.java:36:23:36:28 | "http" : String | HttpsUrlsTest.java:41:50:41:50 | u |
|
||||
| HttpsUrlsTest.java:49:23:49:31 | "http://" : String | HttpsUrlsTest.java:55:50:55:50 | u |
|
||||
| HttpsUrlsTest.java:87:23:87:28 | "http" : String | HttpsUrlsTest.java:92:50:92:50 | u |
|
||||
nodes
|
||||
| HttpsUrlsTest.java:23:23:23:31 | "http://" : String | semmle.label | "http://" : String |
|
||||
| HttpsUrlsTest.java:28:50:28:50 | u | semmle.label | u |
|
||||
| HttpsUrlsTest.java:36:23:36:28 | "http" : String | semmle.label | "http" : String |
|
||||
| HttpsUrlsTest.java:41:50:41:50 | u | semmle.label | u |
|
||||
| HttpsUrlsTest.java:49:23:49:31 | "http://" : String | semmle.label | "http://" : String |
|
||||
| HttpsUrlsTest.java:55:50:55:50 | u | semmle.label | u |
|
||||
| HttpsUrlsTest.java:87:23:87:28 | "http" : String | semmle.label | "http" : String |
|
||||
| HttpsUrlsTest.java:92:50:92:50 | u | semmle.label | u |
|
||||
#select
|
||||
| HttpsUrlsTest.java:28:50:28:67 | openConnection(...) | HttpsUrlsTest.java:23:23:23:31 | "http://" : String | HttpsUrlsTest.java:28:50:28:50 | u | URL may have been constructed with HTTP protocol, using $@. | HttpsUrlsTest.java:23:23:23:31 | "http://" | this source |
|
||||
| HttpsUrlsTest.java:41:50:41:67 | openConnection(...) | HttpsUrlsTest.java:36:23:36:28 | "http" : String | HttpsUrlsTest.java:41:50:41:50 | u | URL may have been constructed with HTTP protocol, using $@. | HttpsUrlsTest.java:36:23:36:28 | "http" | this source |
|
||||
| HttpsUrlsTest.java:55:50:55:67 | openConnection(...) | HttpsUrlsTest.java:49:23:49:31 | "http://" : String | HttpsUrlsTest.java:55:50:55:50 | u | URL may have been constructed with HTTP protocol, using $@. | HttpsUrlsTest.java:49:23:49:31 | "http://" | this source |
|
||||
| HttpsUrlsTest.java:92:50:92:67 | openConnection(...) | HttpsUrlsTest.java:87:23:87:28 | "http" : String | HttpsUrlsTest.java:92:50:92:50 | u | URL may have been constructed with HTTP protocol, using $@. | HttpsUrlsTest.java:87:23:87:28 | "http" | this source |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-319/HttpsUrls.ql
|
||||
@@ -0,0 +1,119 @@
|
||||
// Semmle test case for CWE-319: Cleartext Transmission of Sensitive Data
|
||||
// http://cwe.mitre.org/data/definitions/319.html
|
||||
package test.cwe319.cwe.examples;
|
||||
|
||||
import java.net.URL;
|
||||
import java.io.*;
|
||||
import java.rmi.*;
|
||||
import java.rmi.server.*;
|
||||
import java.rmi.registry.*;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.rmi.ssl.*;
|
||||
|
||||
interface Hello extends java.rmi.Remote {
|
||||
String sayHello() throws java.rmi.RemoteException;
|
||||
}
|
||||
|
||||
class HelloImpl implements Hello {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// HttpsUrls
|
||||
{
|
||||
String protocol = "http://";
|
||||
URL u = new URL(protocol + "www.secret.example.org/");
|
||||
// using HttpsURLConnections to enforce SSL is desirable
|
||||
// BAD: this will give a ClassCastException at runtime, as the
|
||||
// http URL cannot be used to make an HttpsURLConnection
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
String protocol = "http";
|
||||
URL u = new URL(protocol, "www.secret.example.org", "foo");
|
||||
// using HttpsURLConnections to enforce SSL is desirable
|
||||
// BAD: this will give a ClassCastException at runtime, as the
|
||||
// http URL cannot be used to make an HttpsURLConnection
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
String protocol = "http://";
|
||||
// the second URL overwrites the first, as it has a protocol
|
||||
URL u = new URL(new URL("https://www.secret.example.org"), protocol + "www.secret.example.org");
|
||||
// using HttpsURLConnections to enforce SSL is desirable
|
||||
// BAD: this will give a ClassCastException at runtime, as the
|
||||
// http URL cannot be used to make an HttpsURLConnection
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
String protocol = "https://";
|
||||
URL u = new URL(protocol + "www.secret.example.org/");
|
||||
// using HttpsURLConnections to enforce SSL is desirable
|
||||
// GOOD: open connection to URL using HTTPS
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
String protocol = "https";
|
||||
URL u = new URL(protocol, "www.secret.example.org", "foo");
|
||||
// using HttpsURLConnections to enforce SSL is desirable
|
||||
// GOOD: open connection to URL using HTTPS
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
String protocol = "http";
|
||||
URL u = new URL(protocol, "internal-url", "foo");
|
||||
// FALSE POSITIVE: the query has no way of knowing whether the url will
|
||||
// resolve to somewhere outside the internal network, where there
|
||||
// are unlikely to be interception attempts
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
String input = "URL is: http://www.secret-example.org";
|
||||
String url = input.substring(8);
|
||||
URL u = new URL(url);
|
||||
// FALSE NEGATIVE: we cannot tell that the substring results in a url
|
||||
// string
|
||||
HttpsURLConnection hu = (HttpsURLConnection) u.openConnection();
|
||||
hu.setRequestMethod("PUT");
|
||||
hu.connect();
|
||||
OutputStream os = hu.getOutputStream();
|
||||
hu.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// fail
|
||||
}
|
||||
}
|
||||
|
||||
public String sayHello() {
|
||||
return "Hello";
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
| Test.java:11:15:11:41 | getInputStream(...) | Stream using vulnerable non-SSL connection. |
|
||||
| UseSSLTest.java:11:15:11:41 | getInputStream(...) | Stream using vulnerable non-SSL connection. |
|
||||
|
||||
@@ -2,7 +2,7 @@ import java.net.HttpURLConnection;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.*;
|
||||
|
||||
class Test {
|
||||
class UseSSLTest {
|
||||
public void m1(HttpURLConnection connection) throws java.io.IOException {
|
||||
InputStream input;
|
||||
if (connection instanceof HttpsURLConnection) {
|
||||
114
java/ql/test/query-tests/security/CWE-502/C.java
Normal file
114
java/ql/test/query-tests/security/CWE-502/C.java
Normal file
@@ -0,0 +1,114 @@
|
||||
import java.util.HashMap;
|
||||
import java.io.StringReader;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import com.cedarsoftware.util.io.JsonReader;
|
||||
import com.esotericsoftware.yamlbeans.YamlReader;
|
||||
import org.ho.yaml.Yaml;
|
||||
import org.ho.yaml.YamlConfig;
|
||||
import org.exolab.castor.xml.Unmarshaller;
|
||||
import com.caucho.hessian.io.Hessian2Input;
|
||||
import com.caucho.hessian.io.HessianInput;
|
||||
import com.caucho.burlap.io.BurlapInput;
|
||||
import com.caucho.hessian.io.Hessian2Input;
|
||||
import com.caucho.hessian.io.HessianInput;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
@Controller
|
||||
public class C {
|
||||
|
||||
@GetMapping(value = "jyaml")
|
||||
public void bad1(HttpServletRequest request) throws Exception {
|
||||
String data = request.getParameter("data");
|
||||
Yaml.load(data); //bad
|
||||
Yaml.loadStream(data); //bad
|
||||
Yaml.loadStreamOfType(data, Object.class); //bad
|
||||
Yaml.loadType(data, Object.class); //bad
|
||||
|
||||
org.ho.yaml.YamlConfig yamlConfig = new YamlConfig();
|
||||
yamlConfig.load(data); //bad
|
||||
yamlConfig.loadStream(data); //bad
|
||||
yamlConfig.loadStreamOfType(data, Object.class); //bad
|
||||
yamlConfig.loadType(data, Object.class); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "jsonio")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String data = request.getParameter("data");
|
||||
|
||||
HashMap hashMap = new HashMap();
|
||||
hashMap.put("USE_MAPS", true);
|
||||
|
||||
JsonReader.jsonToJava(data); //bad
|
||||
|
||||
JsonReader jr = new JsonReader(data, null); //bad
|
||||
jr.readObject();
|
||||
}
|
||||
|
||||
@GetMapping(value = "yamlbeans")
|
||||
public void bad3(HttpServletRequest request) throws Exception {
|
||||
String data = request.getParameter("data");
|
||||
YamlReader r = new YamlReader(data);
|
||||
r.read(); //bad
|
||||
r.read(Object.class); //bad
|
||||
r.read(Object.class, Object.class); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "hessian")
|
||||
public void bad4(HttpServletRequest request) throws Exception {
|
||||
byte[] bytes = request.getParameter("data").getBytes();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
HessianInput hessianInput = new HessianInput(bis);
|
||||
hessianInput.readObject(); //bad
|
||||
hessianInput.readObject(Object.class); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "hessian2")
|
||||
public void bad5(HttpServletRequest request) throws Exception {
|
||||
byte[] bytes = request.getParameter("data").getBytes();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
Hessian2Input hessianInput = new Hessian2Input(bis);
|
||||
hessianInput.readObject(); //bad
|
||||
hessianInput.readObject(Object.class); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "castor")
|
||||
public void bad6(HttpServletRequest request) throws Exception {
|
||||
Unmarshaller unmarshaller = new Unmarshaller();
|
||||
unmarshaller.unmarshal(new StringReader(request.getParameter("data"))); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "burlap")
|
||||
public void bad7(HttpServletRequest request) throws Exception {
|
||||
byte[] serializedData = request.getParameter("data").getBytes();
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(serializedData);
|
||||
BurlapInput burlapInput = new BurlapInput(is);
|
||||
burlapInput.readObject(); //bad
|
||||
|
||||
BurlapInput burlapInput1 = new BurlapInput();
|
||||
burlapInput1.init(is);
|
||||
burlapInput1.readObject(); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "jsonio1")
|
||||
public void good1(HttpServletRequest request) {
|
||||
String data = request.getParameter("data");
|
||||
|
||||
HashMap hashMap = new HashMap();
|
||||
hashMap.put("USE_MAPS", true);
|
||||
|
||||
JsonReader.jsonToJava(data, hashMap); //good
|
||||
}
|
||||
|
||||
@GetMapping(value = "jsonio2")
|
||||
public void good2(HttpServletRequest request) {
|
||||
String data = request.getParameter("data");
|
||||
|
||||
HashMap hashMap = new HashMap();
|
||||
hashMap.put("USE_MAPS", true);
|
||||
|
||||
JsonReader jr1 = new JsonReader(data, hashMap); //good
|
||||
jr1.readObject();
|
||||
}
|
||||
}
|
||||
34
java/ql/test/query-tests/security/CWE-502/KryoTest.java
Normal file
34
java/ql/test/query-tests/security/CWE-502/KryoTest.java
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.pool.KryoPool;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
|
||||
public class KryoTest {
|
||||
|
||||
private Kryo getSafeKryo() {
|
||||
Kryo kryo = new Kryo();
|
||||
kryo.setRegistrationRequired(true);
|
||||
// ... kryo.register(A.class) ...
|
||||
return kryo;
|
||||
}
|
||||
|
||||
public void kryoDeserialize(Socket sock) throws java.io.IOException {
|
||||
KryoPool kryoPool = new KryoPool.Builder(this::getSafeKryo).softReferences().build();
|
||||
Input input = new Input(sock.getInputStream());
|
||||
Object o = kryoPool.run(kryo -> kryo.readClassAndObject(input)); // OK
|
||||
}
|
||||
|
||||
public void kryoDeserialize2(Socket sock) throws java.io.IOException {
|
||||
KryoPool kryoPool = new KryoPool.Builder(this::getSafeKryo).softReferences().build();
|
||||
Input input = new Input(sock.getInputStream());
|
||||
Kryo k = kryoPool.borrow();
|
||||
try {
|
||||
Object o = k.readClassAndObject(input); // OK
|
||||
} finally {
|
||||
kryoPool.release(k);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,6 +48,38 @@ edges
|
||||
| B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:29:5:29:15 | inputStream : InputStream |
|
||||
| B.java:29:5:29:15 | inputStream : InputStream | B.java:29:22:29:26 | bytes [post update] : byte[] |
|
||||
| B.java:29:22:29:26 | bytes [post update] : byte[] | B.java:31:23:31:23 | s |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:27:17:27:20 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:30:19:30:22 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:31:25:31:28 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:32:31:32:34 | data |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | C.java:33:23:33:26 | data |
|
||||
| C.java:38:17:38:44 | getParameter(...) : String | C.java:43:25:43:28 | data |
|
||||
| C.java:38:17:38:44 | getParameter(...) : String | C.java:46:3:46:4 | jr |
|
||||
| C.java:51:17:51:44 | getParameter(...) : String | C.java:53:3:53:3 | r |
|
||||
| C.java:51:17:51:44 | getParameter(...) : String | C.java:54:3:54:3 | r |
|
||||
| C.java:51:17:51:44 | getParameter(...) : String | C.java:55:3:55:3 | r |
|
||||
| C.java:60:18:60:45 | getParameter(...) : String | C.java:61:55:61:59 | bytes : byte[] |
|
||||
| C.java:60:18:60:45 | getParameter(...) : String | C.java:63:3:63:14 | hessianInput |
|
||||
| C.java:60:18:60:45 | getParameter(...) : String | C.java:64:3:64:14 | hessianInput |
|
||||
| C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:63:3:63:14 | hessianInput |
|
||||
| C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:64:3:64:14 | hessianInput |
|
||||
| C.java:61:55:61:59 | bytes : byte[] | C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream |
|
||||
| C.java:69:18:69:45 | getParameter(...) : String | C.java:70:55:70:59 | bytes : byte[] |
|
||||
| C.java:69:18:69:45 | getParameter(...) : String | C.java:72:3:72:14 | hessianInput |
|
||||
| C.java:69:18:69:45 | getParameter(...) : String | C.java:73:3:73:14 | hessianInput |
|
||||
| C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:72:3:72:14 | hessianInput |
|
||||
| C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:73:3:73:14 | hessianInput |
|
||||
| C.java:70:55:70:59 | bytes : byte[] | C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream |
|
||||
| C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) |
|
||||
| C.java:84:27:84:54 | getParameter(...) : String | C.java:85:54:85:67 | serializedData : byte[] |
|
||||
| C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput |
|
||||
| C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 |
|
||||
| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:87:3:87:13 | burlapInput |
|
||||
| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | C.java:91:3:91:14 | burlapInput1 |
|
||||
| C.java:85:54:85:67 | serializedData : byte[] | C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream |
|
||||
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
|
||||
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream |
|
||||
| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) |
|
||||
@@ -111,6 +143,39 @@ nodes
|
||||
| B.java:29:5:29:15 | inputStream : InputStream | semmle.label | inputStream : InputStream |
|
||||
| B.java:29:22:29:26 | bytes [post update] : byte[] | semmle.label | bytes [post update] : byte[] |
|
||||
| B.java:31:23:31:23 | s | semmle.label | s |
|
||||
| C.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:24:13:24:16 | data | semmle.label | data |
|
||||
| C.java:25:19:25:22 | data | semmle.label | data |
|
||||
| C.java:26:25:26:28 | data | semmle.label | data |
|
||||
| C.java:27:17:27:20 | data | semmle.label | data |
|
||||
| C.java:30:19:30:22 | data | semmle.label | data |
|
||||
| C.java:31:25:31:28 | data | semmle.label | data |
|
||||
| C.java:32:31:32:34 | data | semmle.label | data |
|
||||
| C.java:33:23:33:26 | data | semmle.label | data |
|
||||
| C.java:38:17:38:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:43:25:43:28 | data | semmle.label | data |
|
||||
| C.java:46:3:46:4 | jr | semmle.label | jr |
|
||||
| C.java:51:17:51:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:53:3:53:3 | r | semmle.label | r |
|
||||
| C.java:54:3:54:3 | r | semmle.label | r |
|
||||
| C.java:55:3:55:3 | r | semmle.label | r |
|
||||
| C.java:60:18:60:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:61:30:61:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | semmle.label | new ByteArrayInputStream(...) : ByteArrayInputStream |
|
||||
| C.java:61:55:61:59 | bytes : byte[] | semmle.label | bytes : byte[] |
|
||||
| C.java:63:3:63:14 | hessianInput | semmle.label | hessianInput |
|
||||
| C.java:64:3:64:14 | hessianInput | semmle.label | hessianInput |
|
||||
| C.java:69:18:69:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:70:30:70:60 | new ByteArrayInputStream(...) : ByteArrayInputStream | semmle.label | new ByteArrayInputStream(...) : ByteArrayInputStream |
|
||||
| C.java:70:55:70:59 | bytes : byte[] | semmle.label | bytes : byte[] |
|
||||
| C.java:72:3:72:14 | hessianInput | semmle.label | hessianInput |
|
||||
| C.java:73:3:73:14 | hessianInput | semmle.label | hessianInput |
|
||||
| C.java:79:26:79:71 | new StringReader(...) | semmle.label | new StringReader(...) |
|
||||
| C.java:79:43:79:70 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:84:27:84:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
|
||||
| C.java:85:29:85:68 | new ByteArrayInputStream(...) : ByteArrayInputStream | semmle.label | new ByteArrayInputStream(...) : ByteArrayInputStream |
|
||||
| C.java:85:54:85:67 | serializedData : byte[] | semmle.label | serializedData : byte[] |
|
||||
| C.java:87:3:87:13 | burlapInput | semmle.label | burlapInput |
|
||||
| C.java:91:3:91:14 | burlapInput1 | semmle.label | burlapInput1 |
|
||||
| TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | semmle.label | entityStream : InputStream |
|
||||
| TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | semmle.label | new ObjectInputStream(...) |
|
||||
| TestMessageBodyReader.java:22:40:22:51 | entityStream : InputStream | semmle.label | entityStream : InputStream |
|
||||
@@ -141,4 +206,24 @@ nodes
|
||||
| B.java:15:12:15:28 | parse(...) | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes | Unsafe deserialization of $@. | B.java:12:31:12:51 | getInputStream(...) | user input |
|
||||
| B.java:23:12:23:30 | parseObject(...) | B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s | Unsafe deserialization of $@. | B.java:19:31:19:51 | getInputStream(...) | user input |
|
||||
| B.java:31:12:31:24 | parse(...) | B.java:27:31:27:51 | getInputStream(...) : InputStream | B.java:31:23:31:23 | s | Unsafe deserialization of $@. | B.java:27:31:27:51 | getInputStream(...) | user input |
|
||||
| C.java:24:3:24:17 | load(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:24:13:24:16 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:25:3:25:23 | loadStream(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:25:19:25:22 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:26:3:26:43 | loadStreamOfType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:26:25:26:28 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:27:3:27:35 | loadType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:27:17:27:20 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:30:3:30:23 | load(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:30:19:30:22 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:31:3:31:29 | loadStream(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:31:25:31:28 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:32:3:32:49 | loadStreamOfType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:32:31:32:34 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:33:3:33:41 | loadType(...) | C.java:23:17:23:44 | getParameter(...) : String | C.java:33:23:33:26 | data | Unsafe deserialization of $@. | C.java:23:17:23:44 | getParameter(...) | user input |
|
||||
| C.java:43:3:43:29 | jsonToJava(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:43:25:43:28 | data | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
|
||||
| C.java:46:3:46:17 | readObject(...) | C.java:38:17:38:44 | getParameter(...) : String | C.java:46:3:46:4 | jr | Unsafe deserialization of $@. | C.java:38:17:38:44 | getParameter(...) | user input |
|
||||
| C.java:53:3:53:10 | read(...) | C.java:51:17:51:44 | getParameter(...) : String | C.java:53:3:53:3 | r | Unsafe deserialization of $@. | C.java:51:17:51:44 | getParameter(...) | user input |
|
||||
| C.java:54:3:54:22 | read(...) | C.java:51:17:51:44 | getParameter(...) : String | C.java:54:3:54:3 | r | Unsafe deserialization of $@. | C.java:51:17:51:44 | getParameter(...) | user input |
|
||||
| C.java:55:3:55:36 | read(...) | C.java:51:17:51:44 | getParameter(...) : String | C.java:55:3:55:3 | r | Unsafe deserialization of $@. | C.java:51:17:51:44 | getParameter(...) | user input |
|
||||
| C.java:63:3:63:27 | readObject(...) | C.java:60:18:60:45 | getParameter(...) : String | C.java:63:3:63:14 | hessianInput | Unsafe deserialization of $@. | C.java:60:18:60:45 | getParameter(...) | user input |
|
||||
| C.java:64:3:64:39 | readObject(...) | C.java:60:18:60:45 | getParameter(...) : String | C.java:64:3:64:14 | hessianInput | Unsafe deserialization of $@. | C.java:60:18:60:45 | getParameter(...) | user input |
|
||||
| C.java:72:3:72:27 | readObject(...) | C.java:69:18:69:45 | getParameter(...) : String | C.java:72:3:72:14 | hessianInput | Unsafe deserialization of $@. | C.java:69:18:69:45 | getParameter(...) | user input |
|
||||
| C.java:73:3:73:39 | readObject(...) | C.java:69:18:69:45 | getParameter(...) : String | C.java:73:3:73:14 | hessianInput | Unsafe deserialization of $@. | C.java:69:18:69:45 | getParameter(...) | user input |
|
||||
| C.java:79:3:79:72 | unmarshal(...) | C.java:79:43:79:70 | getParameter(...) : String | C.java:79:26:79:71 | new StringReader(...) | Unsafe deserialization of $@. | C.java:79:43:79:70 | getParameter(...) | user input |
|
||||
| C.java:87:3:87:26 | readObject(...) | C.java:84:27:84:54 | getParameter(...) : String | C.java:87:3:87:13 | burlapInput | Unsafe deserialization of $@. | C.java:84:27:84:54 | getParameter(...) | user input |
|
||||
| C.java:91:3:91:27 | readObject(...) | C.java:84:27:84:54 | getParameter(...) : String | C.java:91:3:91:14 | burlapInput1 | Unsafe deserialization of $@. | C.java:84:27:84:54 | getParameter(...) | user input |
|
||||
| TestMessageBodyReader.java:22:18:22:65 | readObject(...) | TestMessageBodyReader.java:20:55:20:78 | entityStream : InputStream | TestMessageBodyReader.java:22:18:22:52 | new ObjectInputStream(...) | Unsafe deserialization of $@. | TestMessageBodyReader.java:20:55:20:78 | entityStream | user input |
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1
|
||||
|
||||
@@ -1 +1 @@
|
||||
| InfiniteLoop.java:4:13:4:36 | stmt | Loop might not terminate, as termination depends in part on $@ being false but it is always true. | InfiniteLoop.java:4:27:4:30 | ... < ... | this test |
|
||||
| InfiniteLoop.java:4:13:4:36 | for (...;...;...) | Loop might not terminate, as termination depends in part on $@ being false but it is always true. | InfiniteLoop.java:4:27:4:30 | ... < ... | this test |
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.client.methods.HttpOptions;
|
||||
import org.apache.http.client.methods.HttpTrace;
|
||||
import org.apache.http.client.methods.HttpPatch;
|
||||
import org.apache.http.client.methods.RequestBuilder;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
||||
import org.apache.http.message.BasicRequestLine;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ApacheHttpSSRF extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
|
||||
String sink = request.getParameter("uri");
|
||||
URI uri = new URI(sink);
|
||||
|
||||
HttpGet httpGet = new HttpGet(uri); // $ SSRF
|
||||
HttpGet httpGet2 = new HttpGet();
|
||||
httpGet2.setURI(uri); // $ SSRF
|
||||
|
||||
new HttpHead(uri); // $ SSRF
|
||||
new HttpPost(uri); // $ SSRF
|
||||
new HttpPut(uri); // $ SSRF
|
||||
new HttpDelete(uri); // $ SSRF
|
||||
new HttpOptions(uri); // $ SSRF
|
||||
new HttpTrace(uri); // $ SSRF
|
||||
new HttpPatch(uri); // $ SSRF
|
||||
|
||||
new BasicHttpRequest(new BasicRequestLine("GET", uri.toString(), null)); // $ SSRF
|
||||
new BasicHttpRequest("GET", uri.toString()); // $ SSRF
|
||||
new BasicHttpRequest("GET", uri.toString(), null); // $ SSRF
|
||||
|
||||
new BasicHttpEntityEnclosingRequest(new BasicRequestLine("GET", uri.toString(), null)); // $ SSRF
|
||||
new BasicHttpEntityEnclosingRequest("GET", uri.toString()); // $ SSRF
|
||||
new BasicHttpEntityEnclosingRequest("GET", uri.toString(), null); // $ SSRF
|
||||
|
||||
RequestBuilder.get(uri); // $ SSRF
|
||||
RequestBuilder.post(uri); // $ SSRF
|
||||
RequestBuilder.put(uri); // $ SSRF
|
||||
RequestBuilder.delete(uri); // $ SSRF
|
||||
RequestBuilder.options(uri); // $ SSRF
|
||||
RequestBuilder.head(uri); // $ SSRF
|
||||
RequestBuilder.trace(uri); // $ SSRF
|
||||
RequestBuilder.patch(uri); // $ SSRF
|
||||
RequestBuilder.get("").setUri(uri); // $ SSRF
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
}
|
||||
}
|
||||
}
|
||||
18
java/ql/test/query-tests/security/CWE-918/JakartaWsSSRF.java
Normal file
18
java/ql/test/query-tests/security/CWE-918/JakartaWsSSRF.java
Normal file
@@ -0,0 +1,18 @@
|
||||
import jakarta.ws.rs.client.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class JakartaWsSSRF extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
Client client = ClientBuilder.newClient();
|
||||
String url = request.getParameter("url");
|
||||
client.target(url); // $ SSRF
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.Proxy.Type;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class JavaNetHttpSSRF extends HttpServlet {
|
||||
private static final String VALID_URI = "http://lgtm.com";
|
||||
private HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
|
||||
String sink = request.getParameter("uri");
|
||||
URI uri = new URI(sink);
|
||||
URI uri2 = new URI("http", sink, "fragement");
|
||||
URL url1 = new URL(sink);
|
||||
|
||||
URLConnection c1 = url1.openConnection(); // $ SSRF
|
||||
SocketAddress sa = new SocketAddress() {
|
||||
};
|
||||
URLConnection c2 = url1.openConnection(new Proxy(Type.HTTP, sa)); // $ SSRF
|
||||
InputStream c3 = url1.openStream(); // $ SSRF
|
||||
|
||||
// java.net.http
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request2 = HttpRequest.newBuilder().uri(uri2).build(); // $ SSRF
|
||||
HttpRequest request3 = HttpRequest.newBuilder(uri).build(); // $ SSRF
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
}
|
||||
}
|
||||
}
|
||||
18
java/ql/test/query-tests/security/CWE-918/JaxWsSSRF.java
Normal file
18
java/ql/test/query-tests/security/CWE-918/JaxWsSSRF.java
Normal file
@@ -0,0 +1,18 @@
|
||||
import javax.ws.rs.client.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class JaxWsSSRF extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
Client client = ClientBuilder.newClient();
|
||||
String url = request.getParameter("url");
|
||||
client.target(url); // $ SSRF
|
||||
}
|
||||
|
||||
}
|
||||
18
java/ql/test/query-tests/security/CWE-918/RequestForgery.ql
Normal file
18
java/ql/test/query-tests/security/CWE-918/RequestForgery.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
import java
|
||||
import semmle.code.java.security.RequestForgeryConfig
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class HasFlowTest extends InlineExpectationsTest {
|
||||
HasFlowTest() { this = "HasFlowTest" }
|
||||
|
||||
override string getARelevantTag() { result = "SSRF" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "SSRF" and
|
||||
exists(RequestForgeryConfiguration conf, DataFlow::Node sink | conf.hasFlowTo(sink) |
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
123
java/ql/test/query-tests/security/CWE-918/SanitizationTests.java
Normal file
123
java/ql/test/query-tests/security/CWE-918/SanitizationTests.java
Normal file
@@ -0,0 +1,123 @@
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class SanitizationTests extends HttpServlet {
|
||||
private static final String VALID_URI = "http://lgtm.com";
|
||||
private HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
|
||||
URI uri = new URI(request.getParameter("uri"));
|
||||
// BAD: a request parameter is incorporated without validation into a Http
|
||||
// request
|
||||
HttpRequest r = HttpRequest.newBuilder(uri).build(); // $ SSRF
|
||||
client.send(r, null);
|
||||
|
||||
// GOOD: sanitisation by concatenation with a prefix that prevents targeting an arbitrary host.
|
||||
// We test a few different ways of sanitisation: via string conctentation (perhaps nested),
|
||||
// via a stringbuilder (for which we consider appends done in the constructor, chained onto
|
||||
// the constructor and applied in subsequent statements) and via String.format.
|
||||
String safeUri3 = "https://example.com/" + request.getParameter("uri3");
|
||||
HttpRequest r3 = HttpRequest.newBuilder(new URI(safeUri3)).build();
|
||||
client.send(r3, null);
|
||||
|
||||
String safeUri4 = "https://example.com/" + ("someprefix" + request.getParameter("uri4"));
|
||||
HttpRequest r4 = HttpRequest.newBuilder(new URI(safeUri4)).build();
|
||||
client.send(r4, null);
|
||||
|
||||
StringBuilder safeUri5 = new StringBuilder();
|
||||
safeUri5.append("https://example.com/").append(request.getParameter("uri5"));
|
||||
HttpRequest r5 = HttpRequest.newBuilder(new URI(safeUri5.toString())).build();
|
||||
client.send(r5, null);
|
||||
|
||||
StringBuilder safeUri5a = new StringBuilder("https://example.com/");
|
||||
safeUri5a.append(request.getParameter("uri5a"));
|
||||
HttpRequest r5a = HttpRequest.newBuilder(new URI(safeUri5a.toString())).build();
|
||||
client.send(r5a, null);
|
||||
|
||||
StringBuilder safeUri5b = (new StringBuilder("https://example.com/")).append("dir/");
|
||||
safeUri5b.append(request.getParameter("uri5b"));
|
||||
HttpRequest r5b = HttpRequest.newBuilder(new URI(safeUri5b.toString())).build();
|
||||
client.send(r5b, null);
|
||||
|
||||
StringBuilder safeUri5c = (new StringBuilder("prefix")).append("https://example.com/dir/");
|
||||
safeUri5c.append(request.getParameter("uri5c"));
|
||||
HttpRequest r5c = HttpRequest.newBuilder(new URI(safeUri5c.toString())).build();
|
||||
client.send(r5c, null);
|
||||
|
||||
String safeUri6 = String.format("https://example.com/%s", request.getParameter("uri6"));
|
||||
HttpRequest r6 = HttpRequest.newBuilder(new URI(safeUri6)).build();
|
||||
client.send(r6, null);
|
||||
|
||||
String safeUri7 = String.format("%s/%s", "https://example.com", request.getParameter("uri7"));
|
||||
HttpRequest r7 = HttpRequest.newBuilder(new URI(safeUri7)).build();
|
||||
client.send(r7, null);
|
||||
|
||||
String safeUri8 = String.format("%s%s", "https://example.com/", request.getParameter("uri8"));
|
||||
HttpRequest r8 = HttpRequest.newBuilder(new URI(safeUri8)).build();
|
||||
client.send(r8, null);
|
||||
|
||||
String safeUri9 = String.format("http://%s", "myserver.com") + "/" + request.getParameter("uri9");
|
||||
HttpRequest r9 = HttpRequest.newBuilder(new URI(safeUri9)).build();
|
||||
client.send(r9, null);
|
||||
|
||||
// BAD: cases where a string that would sanitise is used, but occurs in the wrong
|
||||
// place to sanitise user input:
|
||||
String unsafeUri3 = request.getParameter("baduri3") + "https://example.com/";
|
||||
HttpRequest unsafer3 = HttpRequest.newBuilder(new URI(unsafeUri3)).build(); // $ SSRF
|
||||
client.send(unsafer3, null);
|
||||
|
||||
String unsafeUri4 = ("someprefix" + request.getParameter("baduri4")) + "https://example.com/";
|
||||
HttpRequest unsafer4 = HttpRequest.newBuilder(new URI(unsafeUri4)).build(); // $ SSRF
|
||||
client.send(unsafer4, null);
|
||||
|
||||
StringBuilder unsafeUri5 = new StringBuilder();
|
||||
unsafeUri5.append(request.getParameter("baduri5")).append("https://example.com/");
|
||||
HttpRequest unsafer5 = HttpRequest.newBuilder(new URI(unsafeUri5.toString())).build(); // $ SSRF
|
||||
client.send(unsafer5, null);
|
||||
|
||||
StringBuilder unafeUri5a = new StringBuilder(request.getParameter("uri5a"));
|
||||
unafeUri5a.append("https://example.com/");
|
||||
HttpRequest unsafer5a = HttpRequest.newBuilder(new URI(unafeUri5a.toString())).build(); // $ SSRF
|
||||
client.send(unsafer5a, null);
|
||||
|
||||
StringBuilder unsafeUri5b = (new StringBuilder(request.getParameter("uri5b"))).append("dir/");
|
||||
unsafeUri5b.append("https://example.com/");
|
||||
HttpRequest unsafer5b = HttpRequest.newBuilder(new URI(unsafeUri5b.toString())).build(); // $ SSRF
|
||||
client.send(unsafer5b, null);
|
||||
|
||||
StringBuilder unsafeUri5c = (new StringBuilder("https")).append(request.getParameter("uri5c"));
|
||||
unsafeUri5c.append("://example.com/dir/");
|
||||
HttpRequest unsafer5c = HttpRequest.newBuilder(new URI(unsafeUri5c.toString())).build(); // $ SSRF
|
||||
client.send(unsafer5c, null);
|
||||
|
||||
String unsafeUri6 = String.format("%shttps://example.com/", request.getParameter("baduri6"));
|
||||
HttpRequest unsafer6 = HttpRequest.newBuilder(new URI(unsafeUri6)).build(); // $ SSRF
|
||||
client.send(unsafer6, null);
|
||||
|
||||
String unsafeUri7 = String.format("%s/%s", request.getParameter("baduri7"), "https://example.com");
|
||||
HttpRequest unsafer7 = HttpRequest.newBuilder(new URI(unsafeUri7)).build(); // $ SSRF
|
||||
client.send(unsafer7, null);
|
||||
|
||||
String unsafeUri8 = String.format("%s%s", request.getParameter("baduri8"), "https://example.com/");
|
||||
HttpRequest unsafer8 = HttpRequest.newBuilder(new URI(unsafeUri8)).build(); // $ SSRF
|
||||
client.send(unsafer8, null);
|
||||
|
||||
String unsafeUri9 = request.getParameter("baduri9") + "/" + String.format("http://%s", "myserver.com");
|
||||
HttpRequest unsafer9 = HttpRequest.newBuilder(new URI(unsafeUri9)).build(); // $ SSRF
|
||||
client.send(unsafer9, null);
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
}
|
||||
}
|
||||
}
|
||||
70
java/ql/test/query-tests/security/CWE-918/SpringSSRF.java
Normal file
70
java/ql/test/query-tests/security/CWE-918/SpringSSRF.java
Normal file
@@ -0,0 +1,70 @@
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import java.net.URI;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.*;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.Proxy.Type;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class SpringSSRF extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request2, HttpServletResponse response2)
|
||||
throws ServletException, IOException {
|
||||
String fooResourceUrl = request2.getParameter("uri");;
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
HttpEntity<String> request = new HttpEntity<>(new String("bar"));
|
||||
try {
|
||||
restTemplate.getForEntity(fooResourceUrl + "/1", String.class); // $ SSRF
|
||||
restTemplate.exchange(fooResourceUrl, HttpMethod.POST, request, String.class); // $ SSRF
|
||||
restTemplate.execute(fooResourceUrl, HttpMethod.POST, null, null, "test"); // $ SSRF
|
||||
restTemplate.getForObject(fooResourceUrl, String.class, "test"); // $ SSRF
|
||||
restTemplate.patchForObject(fooResourceUrl, new String("object"), String.class, "hi"); // $ SSRF
|
||||
restTemplate.postForEntity(new URI(fooResourceUrl), new String("object"), String.class); // $ SSRF
|
||||
restTemplate.postForLocation(fooResourceUrl, new String("object")); // $ SSRF
|
||||
restTemplate.postForObject(fooResourceUrl, new String("object"), String.class); // $ SSRF
|
||||
restTemplate.put(fooResourceUrl, new String("object")); // $ SSRF
|
||||
restTemplate.delete(fooResourceUrl); // $ SSRF
|
||||
restTemplate.headForHeaders(fooResourceUrl); // $ SSRF
|
||||
restTemplate.optionsForAllow(fooResourceUrl); // $ SSRF
|
||||
{
|
||||
String body = new String("body");
|
||||
URI uri = new URI(fooResourceUrl);
|
||||
RequestEntity<String> requestEntity =
|
||||
RequestEntity.post(uri).body(body); // $ SSRF
|
||||
ResponseEntity<String> response = restTemplate.exchange(requestEntity, String.class);
|
||||
RequestEntity.get(uri); // $ SSRF
|
||||
RequestEntity.put(uri); // $ SSRF
|
||||
RequestEntity.delete(uri); // $ SSRF
|
||||
RequestEntity.options(uri); // $ SSRF
|
||||
RequestEntity.patch(uri); // $ SSRF
|
||||
RequestEntity.head(uri); // $ SSRF
|
||||
RequestEntity.method(null, uri); // $ SSRF
|
||||
}
|
||||
{
|
||||
URI uri = new URI(fooResourceUrl);
|
||||
MultiValueMap<String, String> headers = null;
|
||||
java.lang.reflect.Type type = null;
|
||||
new RequestEntity<String>(null, uri); // $ SSRF
|
||||
new RequestEntity<String>(headers, null, uri); // $ SSRF
|
||||
new RequestEntity<String>("body", null, uri); // $ SSRF
|
||||
new RequestEntity<String>("body", headers, null, uri); // $ SSRF
|
||||
new RequestEntity<String>("body", null, uri, type); // $ SSRF
|
||||
new RequestEntity<String>("body", headers, null, uri, type); // $ SSRF
|
||||
}
|
||||
} catch (org.springframework.web.client.RestClientException | java.net.URISyntaxException e) {}
|
||||
}
|
||||
}
|
||||
1
java/ql/test/query-tests/security/CWE-918/options
Normal file
1
java/ql/test/query-tests/security/CWE-918/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.2.3:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/servlet-api-2.4/
|
||||
Reference in New Issue
Block a user