Use InlineFlowTest for local and remote flow tests

This commit is contained in:
Tony Torralba
2021-10-08 11:48:35 +02:00
parent 446c738f20
commit 2df30dc107
9 changed files with 124 additions and 153 deletions

View File

@@ -14,36 +14,39 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class A {
private static void sink(Object o) {}
public static void main(String[] args) {
String[] a = args; // user input
String s = args[0]; // user input
sink(args); // $hasLocalValueFlow
sink(args[0]); // $hasLocalTaintFlow
}
public static void userInput() throws SQLException, IOException, MalformedURLException {
System.getenv("test"); // user input
sink(System.getenv("test")); // $hasLocalValueFlow
class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.getParameter("test"); // remote user input
req.getHeader("test"); // remote user input
req.getQueryString(); // remote user input
req.getCookies()[0].getValue(); // remote user input
throws ServletException, IOException {
sink(req.getParameter("test")); // $hasRemoteValueFlow
sink(req.getHeader("test")); // $hasRemoteValueFlow
sink(req.getQueryString()); // $hasRemoteValueFlow
sink(req.getCookies()[0].getValue()); // $hasRemoteValueFlow
}
}
new Properties().getProperty("test"); // user input
System.getProperty("test"); // user input
sink(new Properties().getProperty("test")); // $hasLocalValueFlow
sink(System.getProperty("test")); // $hasLocalValueFlow
new Object() {
public void test(ResultSet rs) throws SQLException {
rs.getString(0); // user input
sink(rs.getString(0)); // $hasLocalValueFlow
}
};
new URL("test").openConnection().getInputStream(); // remote user input
new Socket("test", 1234).getInputStream(); // remote user input
InetAddress.getByName("test").getHostName(); // remote user input
sink(new URL("test").openConnection().getInputStream()); // $hasRemoteValueFlow
sink(new Socket("test", 1234).getInputStream()); // $hasRemoteValueFlow
sink(InetAddress.getByName("test").getHostName()); // $hasRemoteValueFlow
System.in.read(); // user input
new FileInputStream("test").read(); // user input
sink(System.in); // $hasLocalValueFlow
sink(new FileInputStream("test")); // $hasLocalValueFlow
}
}

View File

@@ -4,34 +4,39 @@ import android.app.Activity;
public class IntentSources extends Activity {
private static void sink(Object o) {}
public void test() throws java.io.IOException {
String trouble = this.getIntent().getStringExtra("key");
Runtime.getRuntime().exec(trouble);
sink(trouble); // $hasRemoteTaintFlow
}
public void test2() throws java.io.IOException {
String trouble = getIntent().getStringExtra("key");
Runtime.getRuntime().exec(trouble);
sink(trouble); // $hasRemoteTaintFlow
}
public void test3() throws java.io.IOException {
String trouble = getIntent().getExtras().getString("key");
Runtime.getRuntime().exec(trouble);
sink(trouble); // $hasRemoteTaintFlow
}
}
class OtherClass {
private static void sink(Object o) {}
public void test(IntentSources is) throws java.io.IOException {
String trouble = is.getIntent().getStringExtra("key");
Runtime.getRuntime().exec(trouble);
sink(trouble); // $hasRemoteTaintFlow
}
}

View File

@@ -1,15 +1,18 @@
package security.library.dataflow;
public class RmiFlowImpl implements RmiFlow {
private static void sink(Object o) {}
public String listDirectory(String path) throws java.io.IOException {
String command = "ls " + path;
Runtime.getRuntime().exec(command);
sink(command); // $hasRemoteTaintFlow
return "pretend there are some results here";
}
public String notRemotable(String path) throws java.io.IOException {
String command = "ls " + path;
Runtime.getRuntime().exec(command);
sink(command); // Safe
return "pretend there are some results here";
}
}

View File

@@ -4,22 +4,24 @@ import org.springframework.web.multipart.MultipartRequest;
public class SpringMultiPart {
MultipartFile file;
private static void sink(Object o) {}
public void test() throws Exception {
file.getBytes();
file.isEmpty();
file.getInputStream();
file.getResource();
file.getName();
file.getContentType();
file.getOriginalFilename();
sink(file.getBytes()); // $hasRemoteValueFlow
sink(file.isEmpty()); // Safe
sink(file.getInputStream()); // $hasRemoteValueFlow
sink(file.getResource()); // $hasRemoteValueFlow
sink(file.getName()); // $hasRemoteValueFlow
sink(file.getContentType()); // $hasRemoteValueFlow
sink(file.getOriginalFilename()); // $hasRemoteValueFlow
}
public void test(MultipartRequest request) {
request.getFile("name");
request.getFileMap();
request.getFileNames();
request.getFiles("name");
request.getMultiFileMap();
request.getMultipartContentType("name");
sink(request.getFile("name"));// $hasRemoteValueFlow
sink(request.getFileMap());// $hasRemoteValueFlow
sink(request.getFileNames());// $hasRemoteValueFlow
sink(request.getFiles("name"));// $hasRemoteValueFlow
sink(request.getMultiFileMap());// $hasRemoteValueFlow
sink(request.getMultipartContentType("name")); // $hasRemoteValueFlow
}
}

View File

@@ -4,23 +4,25 @@ import org.springframework.security.web.savedrequest.SimpleSavedRequest;
public class SpringSavedRequest {
SavedRequest sr;
private static void sink(Object o) {}
public void test() {
sr.getRedirectUrl();
sr.getCookies();
sr.getHeaderValues("name");
sr.getHeaderNames();
sr.getParameterValues("name");
sr.getParameterMap();
sink(sr.getRedirectUrl()); // $hasRemoteValueFlow
sink(sr.getCookies()); // $hasRemoteValueFlow
sink(sr.getHeaderValues("name")); // $hasRemoteValueFlow
sink(sr.getHeaderNames()); // $hasRemoteValueFlow
sink(sr.getParameterValues("name")); // $hasRemoteValueFlow
sink(sr.getParameterMap()); // $hasRemoteValueFlow
}
SimpleSavedRequest ssr;
public void test2() {
ssr.getRedirectUrl();
ssr.getCookies();
ssr.getHeaderValues("name");
ssr.getHeaderNames();
ssr.getParameterValues("name");
ssr.getParameterMap();
sink(ssr.getRedirectUrl()); // $hasRemoteValueFlow
sink(ssr.getCookies()); // $hasRemoteValueFlow
sink(ssr.getHeaderValues("name")); // $hasRemoteValueFlow
sink(ssr.getHeaderNames()); // $hasRemoteValueFlow
sink(ssr.getParameterValues("name")); // $hasRemoteValueFlow
sink(ssr.getParameterMap()); // $hasRemoteValueFlow
}
}

View File

@@ -1,10 +0,0 @@
| A.java:17:27:17:39 | args | A.java:17:27:17:39 | args |
| A.java:17:27:17:39 | args | A.java:18:18:18:21 | args |
| A.java:17:27:17:39 | args | A.java:19:16:19:19 | args |
| A.java:17:27:17:39 | args | A.java:19:16:19:22 | ...[...] |
| A.java:23:5:23:25 | getenv(...) | A.java:23:5:23:25 | getenv(...) |
| A.java:34:5:34:40 | getProperty(...) | A.java:34:5:34:40 | getProperty(...) |
| A.java:35:5:35:30 | getProperty(...) | A.java:35:5:35:30 | getProperty(...) |
| A.java:38:9:38:23 | getString(...) | A.java:38:9:38:23 | getString(...) |
| A.java:45:5:45:13 | System.in | A.java:45:5:45:13 | System.in |
| A.java:46:5:46:31 | new FileInputStream(...) | A.java:46:5:46:31 | new FileInputStream(...) |

View File

@@ -1,18 +1,40 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineFlowTest
class Conf extends TaintTracking::Configuration {
Conf() { this = "remote taint conf" }
override predicate isSource(DataFlow::Node n) {
n instanceof UserInput and
not n instanceof RemoteFlowSource
class LocalSource extends DataFlow::Node {
LocalSource() {
this instanceof UserInput and
not this instanceof RemoteFlowSource
}
override predicate isSink(DataFlow::Node n) { any() }
}
from DataFlow::Node src, DataFlow::Node sink, Conf conf
where conf.hasFlow(src, sink)
select src, sink
class LocalValueConf extends DefaultValueFlowConf {
override predicate isSource(DataFlow::Node n) { n instanceof LocalSource }
}
class LocalTaintConf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node n) { n instanceof LocalSource }
}
class LocalFlowTest extends InlineFlowTest {
override string getARelevantTag() { result = ["hasLocalValueFlow", "hasLocalTaintFlow"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasLocalValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
or
tag = "hasLocalTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}

View File

@@ -1,74 +0,0 @@
| A.java:28:9:28:32 | getParameter(...) | A.java:28:9:28:32 | getParameter(...) |
| A.java:29:9:29:29 | getHeader(...) | A.java:29:9:29:29 | getHeader(...) |
| A.java:30:9:30:28 | getQueryString(...) | A.java:30:9:30:28 | getQueryString(...) |
| A.java:31:9:31:38 | getValue(...) | A.java:31:9:31:38 | getValue(...) |
| A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) |
| A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) |
| A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) |
| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra |
| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra |
| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra |
| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this |
| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) |
| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) |
| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble |
| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra |
| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra |
| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra |
| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this |
| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) |
| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) |
| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] read: android.content.Intent.extras of argument -1 in getExtras |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | [summary] to write: return (return) in getExtras |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1863:19:1863:27 | parameter this |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] read: <map.value> of argument -1 in getString |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | [summary] to write: return (return) in getString |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:30 | getIntent(...) |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble |
| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: <map.value> of android.content.Intent.extras of argument -1 in getStringExtra |
| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] read: android.content.Intent.extras of argument -1 in getStringExtra |
| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | [summary] to write: return (return) in getStringExtra |
| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1564:19:1564:32 | parameter this |
| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) |
| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) |
| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:34:29:34:35 | trouble |
| PlayResource.java:19:37:19:46 | uri | PlayResource.java:19:37:19:46 | uri |
| PlayResource.java:20:18:20:48 | getQueryString(...) | ../../../stubs/playframework-2.6.x/play/mvc/Results.java:634:33:634:42 | url |
| PlayResource.java:20:18:20:48 | getQueryString(...) | PlayResource.java:20:18:20:48 | getQueryString(...) |
| PlayResource.java:20:18:20:48 | getQueryString(...) | PlayResource.java:21:21:21:23 | url |
| PlayResource.java:24:42:24:53 | token | ../../../stubs/playframework-2.6.x/play/mvc/Results.java:94:27:94:40 | content |
| PlayResource.java:24:42:24:53 | token | PlayResource.java:24:42:24:53 | token |
| PlayResource.java:24:42:24:53 | token | PlayResource.java:25:30:25:34 | token |
| PlayResource.java:28:56:28:65 | uri | PlayResource.java:28:56:28:65 | uri |
| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:4:30:4:40 | path |
| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:5:20:5:31 | ... + ... |
| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:5:28:5:31 | path |
| RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:6:29:6:35 | command |
| SpringMultiPart.java:8:3:8:17 | getBytes(...) | SpringMultiPart.java:8:3:8:17 | getBytes(...) |
| SpringMultiPart.java:10:3:10:23 | getInputStream(...) | SpringMultiPart.java:10:3:10:23 | getInputStream(...) |
| SpringMultiPart.java:11:3:11:20 | getResource(...) | SpringMultiPart.java:11:3:11:20 | getResource(...) |
| SpringMultiPart.java:12:3:12:16 | getName(...) | SpringMultiPart.java:12:3:12:16 | getName(...) |
| SpringMultiPart.java:13:3:13:23 | getContentType(...) | SpringMultiPart.java:13:3:13:23 | getContentType(...) |
| SpringMultiPart.java:14:3:14:28 | getOriginalFilename(...) | SpringMultiPart.java:14:3:14:28 | getOriginalFilename(...) |
| SpringMultiPart.java:18:3:18:25 | getFile(...) | SpringMultiPart.java:18:3:18:25 | getFile(...) |
| SpringMultiPart.java:19:3:19:22 | getFileMap(...) | SpringMultiPart.java:19:3:19:22 | getFileMap(...) |
| SpringMultiPart.java:20:3:20:24 | getFileNames(...) | SpringMultiPart.java:20:3:20:24 | getFileNames(...) |
| SpringMultiPart.java:21:3:21:26 | getFiles(...) | SpringMultiPart.java:21:3:21:26 | getFiles(...) |
| SpringMultiPart.java:22:3:22:27 | getMultiFileMap(...) | SpringMultiPart.java:22:3:22:27 | getMultiFileMap(...) |
| SpringMultiPart.java:23:3:23:41 | getMultipartContentType(...) | SpringMultiPart.java:23:3:23:41 | getMultipartContentType(...) |
| SpringSavedRequest.java:8:3:8:21 | getRedirectUrl(...) | SpringSavedRequest.java:8:3:8:21 | getRedirectUrl(...) |
| SpringSavedRequest.java:9:3:9:17 | getCookies(...) | SpringSavedRequest.java:9:3:9:17 | getCookies(...) |
| SpringSavedRequest.java:10:3:10:28 | getHeaderValues(...) | SpringSavedRequest.java:10:3:10:28 | getHeaderValues(...) |
| SpringSavedRequest.java:11:3:11:21 | getHeaderNames(...) | SpringSavedRequest.java:11:3:11:21 | getHeaderNames(...) |
| SpringSavedRequest.java:12:3:12:31 | getParameterValues(...) | SpringSavedRequest.java:12:3:12:31 | getParameterValues(...) |
| SpringSavedRequest.java:13:3:13:22 | getParameterMap(...) | SpringSavedRequest.java:13:3:13:22 | getParameterMap(...) |
| SpringSavedRequest.java:19:3:19:22 | getRedirectUrl(...) | SpringSavedRequest.java:19:3:19:22 | getRedirectUrl(...) |
| SpringSavedRequest.java:20:3:20:18 | getCookies(...) | SpringSavedRequest.java:20:3:20:18 | getCookies(...) |
| SpringSavedRequest.java:21:3:21:29 | getHeaderValues(...) | SpringSavedRequest.java:21:3:21:29 | getHeaderValues(...) |
| SpringSavedRequest.java:22:3:22:22 | getHeaderNames(...) | SpringSavedRequest.java:22:3:22:22 | getHeaderNames(...) |
| SpringSavedRequest.java:23:3:23:32 | getParameterValues(...) | SpringSavedRequest.java:23:3:23:32 | getParameterValues(...) |
| SpringSavedRequest.java:24:3:24:23 | getParameterMap(...) | SpringSavedRequest.java:24:3:24:23 | getParameterMap(...) |

View File

@@ -1,15 +1,33 @@
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import TestUtilities.InlineFlowTest
class Conf extends TaintTracking::Configuration {
Conf() { this = "remote taint conf" }
class RemoteValueConf extends DefaultValueFlowConf {
override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node n) { any() }
}
from DataFlow::Node src, DataFlow::Node sink, Conf conf
where conf.hasFlow(src, sink)
select src, sink
class RemoteTaintConf extends DefaultTaintFlowConf {
override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
}
class RemoteFlowTest extends InlineFlowTest {
override string getARelevantTag() { result = ["hasRemoteValueFlow", "hasRemoteTaintFlow"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasRemoteValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
or
tag = "hasRemoteTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}