Skip to content
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

C++: New query for SSL certificates not checked #7243

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

@geoffw0
Copy link
Contributor

@geoffw0 geoffw0 commented Nov 25, 2021

This is the second of two new queries for CWE-295: Improper Certificate Validation.

Results:

  • on 132 LGTM projects; there are quite a few results.
  • there's one obvious FP where the code is simply wrapping SSL_get_peer_certificate.
  • the other results look like plausible TPs to me, but I may need to improve my familiarity with the library and figure out if some of these are in fact OK / safe?

Precision:

  • provisionally set to @medium, for review after looking at the LGTM results in more depth.

Performance:

  • tested locally on kamailio_kamailio and chakra-core (performance is great with a warmed up cache).
  • no timeouts on the above LGTM run.
@geoffw0 geoffw0 added the C++ label Nov 25, 2021
@geoffw0 geoffw0 requested a review from as a code owner Nov 25, 2021
Copy link
Contributor

@MathiasVP MathiasVP left a comment

I haven't looked at any of the LGTM results yet. But I have a couple of code comments.

Loading

cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.qhelp Outdated Show resolved Hide resolved
Loading
cpp/ql/src/Security/CWE/CWE-295/SSLResultNotCheckedBad.cpp Outdated Show resolved Hide resolved
Loading
Loading
* `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
* `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
*/
predicate certNotChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
Copy link
Contributor

@MathiasVP MathiasVP Nov 26, 2021

Choose a reason for hiding this comment

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

Intead of rolling our own control-flow analysis here, could we instead use StackVariableReachability? Then isSource could be the call to SSL_get_peer_certificate, isSink could be the exit of the function, and isBarrier could be a call to SSL_get_verify_result.

Would that work?

It may be difficult to fit the certIsZero barrier into SSL_get_peer_certificate, but I think it's doable by having one StackVariableReachability for each call to SSL_get_peer_certificate.

Loading

Copy link
Contributor Author

@geoffw0 geoffw0 Nov 29, 2021

Choose a reason for hiding this comment

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

I tried a couple of libraries that didn't quite fit the problem, I may have overlooked StackVariableReachability.. Trying it now...

Loading

Copy link
Contributor Author

@geoffw0 geoffw0 Nov 29, 2021

Choose a reason for hiding this comment

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

It may be difficult to fit the certIsZero barrier into SSL_get_peer_certificate, but I think it's doable by having one StackVariableReachability for each call to SSL_get_peer_certificate.

This turns out not to be a major issue, the existing GVN logic finds appropriate guards on certificates returned by SSL_get_peer_certificate, and I've never seen more than one certificate being used at once (in which case we'd have to worry about which certificate it is).

What is an issue is that the certIsZero barrier needs to be a barrier edge, not a barrier node. StackVariableReachability does not appear to support barrier edges and I haven't found a sufficient workaround for this yet. I suppose I could add it as a new feature, but that will then require a lot of testing.

Loading

// if (cert) { }
guard = cert and
node1 = guard and
node2 = guard.getAFalseSuccessor()
or
// if (!cert) {
node1 = guard.getParent() and
node2 = guard.getParent().(NotExpr).getATrueSuccessor()
Copy link
Contributor

@MathiasVP MathiasVP Nov 26, 2021

Choose a reason for hiding this comment

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

Could these cases not be covered by using guard.controls? That might be able to solve the FP in test2_11 (and in principle the one in test2_9 as well, but IIRC the GuardConditions class specifically doesn't handle this case very well).

Loading

geoffw0 and others added 2 commits Nov 29, 2021
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

2 participants