Skip to content

Java: add SSRF sink model for the third parameter of RestTemplate.getForObject #18153

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 11, 2024

Conversation

owen-mc
Copy link
Contributor

@owen-mc owen-mc commented Nov 28, 2024

I ran MRVA for the ssrf query restricted to only this new sink (before I had added the commit to reduce FPs) and got no alerts. So I don't think this is a commonly used sink.

Note to reviewers: currently I have had to make HostSanitizingPrefix public to make this work, and I have introduced a bidirectional import between Spring and RequestForgery. I am very open to suggestions for how to do this better.

@owen-mc owen-mc force-pushed the java/resttemplate-getforobject branch from 9f884b4 to 2c061b0 Compare November 29, 2024 09:47
i <=
max(int occurrenceIndex, int occurrenceOffset |
exists(
hsp.getStringValue().regexpFind("\\{[^}]*\\}", occurrenceIndex, occurrenceOffset)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not immediately familiar, but is there an escaping for literal { in these strings that ought to be checked and disregarded?

Copy link
Contributor Author

@owen-mc owen-mc Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The strings will be something like "http://{domain}.com/users/{userid}". Depending on which overload of getForObject you are calling the placeholders are then replaced with either (a) the arguments corresponding to the varargs parameter, in order (ignoring the string in the placeholder), or (b) the value in the provided map, where the key is the string in the placeholder.

In this particular part of the code we're trying to find how many placeholders there are before the first character which lets us know that the hostname is over("?", "#", unescaped "/"). I guess it would be possible that someone would put an escaped "{" in there. I'm not sure how it would be interpreted. I guess we could first replaceall "{" and "}" with some other string with the same number of characters, say " ". I'll do that.

i <=
max(int occurrenceIndex, int occurrenceOffset |
exists(
hsp.getStringValue().regexpFind("\\{[^}]*\\}", occurrenceIndex, occurrenceOffset)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull this out as something like

class GetForObjectTemplateStringConstant extends CompileTimeConstantExpr {
  GetForObjectTemplateStringConstant() { this = any(Method m | ... is a getForObject method ... ).getACall().getArgument(0) }

  predicate hasPlaceholderAtOffset(int idx, int offset) { ... }
}

@owen-mc
Copy link
Contributor Author

owen-mc commented Dec 5, 2024

@smowton I've addressed the review comments. What about the cyclic imports I've created? Is it okay because I've added a private import?

@egregius313
Copy link
Contributor

egregius313 commented Dec 11, 2024

What about the cyclic imports I've created? Is it okay because I've added a private import?

@owen-mc that is a normal pattern, and in this case SpringWebClient is indirectly imported by RequestForgery. Cf this ql4ql query: https://github.com/github/codeql/blob/main/ql/ql/src/queries/performance/AbstractClassImport.ql

RequestForgery.qll <- Spring.qll <- SpringController.qll <- SpringWebClient.qll

Ideally RequestForgery would privately import the Spring library instead, but I don't know if that's too much of a breaking change since it changes the API surface of RequestForgery.qll

Copy link
Contributor

@egregius313 egregius313 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@owen-mc owen-mc merged commit 066db76 into github:main Dec 11, 2024
15 checks passed
@owen-mc owen-mc deleted the java/resttemplate-getforobject branch December 11, 2024 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants