Skip to content

Conversation

artem-smotrakov
Copy link
Contributor

@artem-smotrakov artem-smotrakov commented Apr 18, 2020

Here is a list of main updates:

  • Added experimental/Security/CWE/CWE-094/SpelInjection.ql and a couple of libraries.
  • Added a qhelp file with a few examples.
  • Added tests and stubs for Spring Framework.

The query finds CVE-2018-1273 that is an RCE with Spring Data Commons 1.13.10 due to a SpEL injection. To catch the issue, a database should contain both Spring Framework 4.3.14 and Spring Data Commons 1.13.10 because tainted data travels for a while inside the framework before it reaches a sink in MapDataBinder. It also looks like the CodeQL CLI doesn't recognize Lombok. Therefore, Spring Data Commons needs to be built with this hack.

@artem-smotrakov artem-smotrakov requested review from felicitymay and a team as code owners April 18, 2020 17:37
@artem-smotrakov artem-smotrakov changed the title Java: Add a query for SPeL injections Java: Add a query for SpEL injections Apr 18, 2020
}
}

class NativeWebRequest extends RefType {
Copy link
Contributor

Choose a reason for hiding this comment

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

This one seems to not be used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're absolutely right. At first, I thought that NativeWebRequest may be used as an additional source but then it turned out that it doesn't bring much value. I've removed the class. Thanks!

Copy link
Contributor

@aschackmull aschackmull left a comment

Choose a reason for hiding this comment

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

The QL code is generally looking very good, but I've made some inline comments.

/**
* A configuration for safe evaluation context that may be used in expression evaluation.
*/
class SafeEvaluationContextFlowConfig extends TaintTracking2::Configuration {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest changing TaintTracking2::Configuration to DataFlow2::Configuration, as data flow seems more appropriate for this check than taint flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, makes sense.

import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
import SpringFrameworkLib
import DataFlow
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit cleaner if this import is removed - most things appear to be referenced with their qualified names anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this import is redundant.

ExpressionEvaluationSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m instanceof ExpressionEvaluationMethod and
(getExpr() = ma or getExpr() = ma.getQualifier()) and
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this just be

Suggested change
(getExpr() = ma or getExpr() = ma.getQualifier()) and
getExpr() = ma.getQualifier() and

m.getDeclaringType().getAnAncestor*() instanceof ExpressionParser and
m.hasName("parseExpression") and
ma.getAnArgument() = node1.asExpr() and
(node2.asExpr() = ma.getQualifier() or node2.asExpr() = ma)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is a call to parseExpression supposed to taint the qualifier? Shouldn't this just be

Suggested change
(node2.asExpr() = ma.getQualifier() or node2.asExpr() = ma)
node2.asExpr() = ma

predicate isSimpleEvaluationContextConstructorCall(Expr expr) {
exists(ConstructorCall cc |
cc.getConstructedType() instanceof SimpleEvaluationContext and
(cc = expr or cc.getQualifier() = expr)
Copy link
Contributor

Choose a reason for hiding this comment

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

The qualifier of the constructor call? Surely this should just be

Suggested change
(cc = expr or cc.getQualifier() = expr)
cc = expr

exists(MethodAccess ma, Method m | ma.getMethod() = m |
m.getDeclaringType() instanceof SimpleEvaluationContextBuilder and
m.hasName("build") and
(ma = expr or ma.getQualifier() = expr)
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 less certain here, but including the qualifier looks superfluous to me?

Suggested change
(ma = expr or ma.getQualifier() = expr)
ma = expr

m.hasName("getParameterNames") or
m.hasName("getParameterMap")
) and
(ma = asExpr() or ma.getQualifier() = asExpr())
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason to include the qualifier as the source instead of just the method result?

Suggested change
(ma = asExpr() or ma.getQualifier() = asExpr())
ma = asExpr()

predicate createMutablePropertyValuesStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(ConstructorCall cc | cc.getConstructedType() instanceof MutablePropertyValues |
node1.asExpr() = cc.getAnArgument() and
(node2.asExpr() = cc or node2.asExpr() = cc.getQualifier())
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
(node2.asExpr() = cc or node2.asExpr() = cc.getQualifier())
node2.asExpr() = cc

@aibaars
Copy link
Contributor

aibaars commented May 27, 2020

@artem-smotrakov
Copy link
Contributor Author

@aschackmull Thanks for the review and suggestions for the qualifiers. Let me have a closer look.

- Added experimental/Security/CWE/CWE-094/SpelInjection.ql
  and a couple of libraries
- Added a qhelp file with a few examples
- Added tests and stubs for Spring
@artem-smotrakov artem-smotrakov requested a review from a team as a code owner May 31, 2020 17:53
@artem-smotrakov
Copy link
Contributor Author

@aschackmull There was a bit of mess with qualifiers - thanks for your suggestions! I've addressed the comments.

@artem-smotrakov artem-smotrakov requested review from aschackmull and removed request for a team May 31, 2020 17:55
@aschackmull
Copy link
Contributor

@aschackmull There was a bit of mess with qualifiers - thanks for your suggestions! I've addressed the comments.

I'm about to look at your latest changes, but this is made a bit more difficult than it ought to be due to the commits being squashed together. Please don't squash commits in the future once review has started.

@aschackmull aschackmull merged commit e4e51b5 into github:master Jun 5, 2020
@artem-smotrakov artem-smotrakov deleted the spel-injection branch June 5, 2020 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants