-
Notifications
You must be signed in to change notification settings - Fork 2
Improve CQL Injection Query #200
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
base: main
Are you sure you want to change the base?
Conversation
Will fix later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
Co-authored-by: Luke Cartey <[email protected]>
The locations were shifted due to the module-level docstring attached at the beginning of the file. The counts of the rows remain the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some more requested changes related to property writes to object literals used as arguments to entries
calls - I don't believe they are vulnerable, and I think we should remove them as sinks.
It also looks like the expected SARIF results need to be updated.
It is unclear at the time being if a string concatenation written to a property of its argument is a possible injection vector or not. Therefore, remove them from the test suite until the answer to the above question becomes clear.
This is also related to the controversial `entries` call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two final changes - otherwise I think we will still flag some of the entity
cases.
I think we should also resurrect the entity
tests to show that we don't currently flag them.
chainedMethodCall = this.getAChainedMethodCall(_) | ||
| | ||
result = chainedMethodCall.getAnArgument() or | ||
result = chainedMethodCall.getAnArgument().(SourceNode).getAPropertyWrite().getRhs() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to remove this case, otherwise it will still be a sink via StringConcatParameterOfCqlShortcutMethodCall
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the below case in 3b073eb.
chainedMethodCall = this.getAChainedMethodCall(_) | ||
| | ||
result = chainedMethodCall.getAnArgument() or | ||
result = chainedMethodCall.getAnArgument().(SourceNode).getAPropertyWrite().getRhs() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to remove this case, otherwise it will still be a sink via StringConcatParameterOfCqlShortcutMethodCall
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the below case in 3b073eb.
chainedMethodCall = this.getAChainedMethodCall(_) | ||
| | ||
result = chainedMethodCall.getAnArgument() or | ||
result = chainedMethodCall.getAnArgument().(SourceNode).getAPropertyWrite().getRhs() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to remove this case, otherwise it will still be a sink via StringConcatParameterOfCqlShortcutMethodCall
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the below case in 3b073eb.
Even for INSERT, UPSERT, or CREATE calls, keep the tracking granularity low to prevent the CQL injection query making an alert on those cases with calls to `entries`.
1. These are now deemed safe (for now), so flip the labels. 2. Some cases are impossible: `entries` call only accepts only objects (as varargs or an array of them). So, if it can be fixed, then fix it; otherwise, remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, other than the unit test failure.
…s tainted For example, this example was not alerted on: ``` javascript this.on("send00234", async (req) => { const { id } = req.data; const { Service1Entity } = this.entities; await UPDATE.entity(Service1Entity).set("col1 = col1 + " + id).where`ID = ${id}`; // UNSAFE: direct concatenation with `+` }); ```
For cases of `.run(...)`, the comment location was made on where the CQL was assembled. Shift the label to be where the actual sink, the call to `run`, is.
The previous query marked only the base shortcut call (srv.read, srv.update, ...) as the primary location. This is a bit misleading since the "this query" part would mean the entire chained method call. Therefore, make the chained method call at the very end as the primary location, thereby making the entire chained call including the base shortcut call as the primary location.
The actual "string concatenation" location is found in the path information.
Changes since last review:
|
What this PR contributes
Improve CQL Injection Query.
CqlQueryRunnerCall
now expands and replacesTaintedCqlClause
, now coveringcds.run
,cds.db.run
,srv.run
, andtx.run
..run
and property readentities
:EntityEntry
is "absorbed" intoEntityReference
. Plus,EntityReference
now covers more examples, namely,cds
as a shortcut tocds.db
.Add robust test cases (This is the gist of this PR, please take a look for the behavioral summary description of what this PR aims to implement).
cds.run
and friends.await
-ing the query.this.run
and friends.Service2.run
and friends.cds.ql
.cds.parse.cql
.CQL
.Service2.tx( tx => tx.run(...) )
and friends.this.tx( tx => tx.run(...) )
and friends.cds.tx( tx => tx.run(...) )
and friends.cds.db.tx( tx => tx.run(...) )
and friends.Future works
cds.read(...).from(...)
, only thecds.read(...)
part is alerted on, where the entire chained method call is more desirable as a alert location.SensitiveExposure.ql
seems to be quite brittle, it needs a rewrite. This PR only updates the query's reference to old definitions that are no longer available.