Skip to content

Commit b357274

Browse files
committed
Simplify test case and minor update to the query
1 parent 311c9e4 commit b357274

File tree

2 files changed

+5
-122
lines changed

2 files changed

+5
-122
lines changed

java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ private class LoadSpringResourceFlowStep extends SummaryModelCsv {
200200
[
201201
"org.springframework.core.io;ClassPathResource;false;ClassPathResource;;;Argument[0];Argument[-1];taint",
202202
"org.springframework.core.io;ClassPathResource;true;" +
203-
["getFilename", "getPath", "getURL", "resolveURL"] + ";;;Argument[-1];ReturnValue;value",
203+
["getFilename", "getPath", "getURL", "resolveURL"] + ";;;Argument[-1];ReturnValue;taint",
204204
"org.springframework.core.io;ResourceLoader;true;getResource;;;Argument[0];ReturnValue;taint",
205205
"org.springframework.core.io;Resource;true;createRelative;;;Argument[0];ReturnValue;taint"
206206
]

java/ql/test/experimental/query-tests/security/CWE-552/UnsafeLoadSpringResource.java

Lines changed: 4 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public String getFileContent1(@RequestParam(name="fileName") String fileName) {
4545
//GOOD: Get resource from ClassPathResource with input path validation
4646
public String getFileContent1a(@RequestParam(name="fileName") String fileName) {
4747
String result = null;
48-
if (!isInvalidPath(fileName) && !isInvalidEncodedPath(fileName)) {
48+
if (fileName.startsWith("/safe_dir") && !fileName.contains("..")) {
4949
ClassPathResource clr = new ClassPathResource(fileName);
5050
char[] buffer = new char[4096];
5151
StringBuilder out = new StringBuilder();
@@ -86,9 +86,9 @@ public String getFileContent2(@RequestParam(name="fileName") String fileName) {
8686
public String getFileContent2a(@RequestParam(name="fileName") String fileName) {
8787
String content = null;
8888

89-
if (!isInvalidPath(fileName) && !isInvalidEncodedPath(fileName)) {
89+
if (fileName.startsWith("/safe_dir") && !fileName.contains("..")) {
9090
try {
91-
File file = ResourceUtils.getFile(fileName);
91+
File file = ResourceUtils.getFile(fileName);
9292
//Read File Content
9393
content = new String(Files.readAllBytes(file.toPath()));
9494
} catch (IOException ie) {
@@ -132,7 +132,7 @@ public String getFileContent3(@RequestParam(name="fileName") String fileName) {
132132
public String getFileContent3a(@RequestParam(name="fileName") String fileName) {
133133
String content = null;
134134

135-
if (!isInvalidPath(fileName) && !isInvalidEncodedPath(fileName)) {
135+
if (fileName.startsWith("/safe_dir") && !fileName.contains("..")) {
136136
try {
137137
Resource resource = resourceLoader.getResource(fileName);
138138

@@ -150,121 +150,4 @@ public String getFileContent3a(@RequestParam(name="fileName") String fileName) {
150150
}
151151
return content;
152152
}
153-
154-
/**
155-
* Check whether the given path contains invalid escape sequences.
156-
* @param path the path to validate
157-
* @return {@code true} if the path is invalid, {@code false} otherwise
158-
* @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799
159-
*/
160-
private boolean isInvalidEncodedPath(String path) {
161-
if (path.contains("%")) {
162-
try {
163-
// Use URLDecoder (vs UriUtils) to preserve potentially decoded UTF-8 chars
164-
String decodedPath = URLDecoder.decode(path, "UTF-8");
165-
if (isInvalidPath(decodedPath)) {
166-
return true;
167-
}
168-
decodedPath = processPath(decodedPath);
169-
if (isInvalidPath(decodedPath)) {
170-
return true;
171-
}
172-
} catch (IllegalArgumentException | UnsupportedEncodingException ex) {
173-
// Should never happen...
174-
}
175-
}
176-
return false;
177-
}
178-
179-
/**
180-
* Process the given resource path.
181-
* <p>The default implementation replaces:
182-
* <ul>
183-
* <li>Backslash with forward slash.
184-
* <li>Duplicate occurrences of slash with a single slash.
185-
* <li>Any combination of leading slash and control characters (00-1F and 7F)
186-
* with a single "/" or "". For example {@code " / // foo/bar"}
187-
* becomes {@code "/foo/bar"}.
188-
* </ul>
189-
* @since 3.2.12
190-
* @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799
191-
*/
192-
protected String processPath(String path) {
193-
path = StringUtils.replace(path, "\\", "/");
194-
path = cleanDuplicateSlashes(path);
195-
return cleanLeadingSlash(path);
196-
}
197-
198-
/** @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799 **/
199-
private String cleanDuplicateSlashes(String path) {
200-
StringBuilder sb = null;
201-
char prev = 0;
202-
for (int i = 0; i < path.length(); i++) {
203-
char curr = path.charAt(i);
204-
try {
205-
if ((curr == '/') && (prev == '/')) {
206-
if (sb == null) {
207-
sb = new StringBuilder(path.substring(0, i));
208-
}
209-
continue;
210-
}
211-
if (sb != null) {
212-
sb.append(path.charAt(i));
213-
}
214-
} finally {
215-
prev = curr;
216-
}
217-
}
218-
return sb != null ? sb.toString() : path;
219-
}
220-
221-
/** @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799 **/
222-
private String cleanLeadingSlash(String path) {
223-
boolean slash = false;
224-
for (int i = 0; i < path.length(); i++) {
225-
if (path.charAt(i) == '/') {
226-
slash = true;
227-
}
228-
else if (path.charAt(i) > ' ' && path.charAt(i) != 127) {
229-
if (i == 0 || (i == 1 && slash)) {
230-
return path;
231-
}
232-
return (slash ? "/" + path.substring(i) : path.substring(i));
233-
}
234-
}
235-
return (slash ? "/" : "");
236-
}
237-
238-
/**
239-
* Identifies invalid resource paths. By default rejects:
240-
* <ul>
241-
* <li>Paths that contain "WEB-INF" or "META-INF"
242-
* <li>Paths that contain "../" after a call to
243-
* {@link org.springframework.util.StringUtils#cleanPath}.
244-
* <li>Paths that represent a {@link org.springframework.util.ResourceUtils#isUrl
245-
* valid URL} or would represent one after the leading slash is removed.
246-
* </ul>
247-
* <p><strong>Note:</strong> this method assumes that leading, duplicate '/'
248-
* or control characters (e.g. white space) have been trimmed so that the
249-
* path starts predictably with a single '/' or does not have one.
250-
* @param path the path to validate
251-
* @return {@code true} if the path is invalid, {@code false} otherwise
252-
* @since 3.0.6
253-
* @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799
254-
*/
255-
protected boolean isInvalidPath(String path) {
256-
if (path.contains("WEB-INF") || path.contains("META-INF")) {
257-
return true;
258-
}
259-
if (path.contains(":/")) {
260-
String relativePath = (path.charAt(0) == '/' ? path.substring(1) : path);
261-
if (ResourceUtils.isUrl(relativePath) || relativePath.startsWith("url:")) {
262-
return true;
263-
}
264-
}
265-
if (path.contains("..") && StringUtils.cleanPath(path).contains("../")) {
266-
return true;
267-
}
268-
return false;
269-
}
270153
}

0 commit comments

Comments
 (0)