Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/** Definitions for the RSA without OAEP query */

import java
import Encryption
import semmle.code.java.dataflow.DataFlow

/** A configuration for finding RSA ciphers initialized without using OAEP padding. */
class RsaWithoutOaepConfig extends DataFlow::Configuration {
RsaWithoutOaepConfig() { this = "RsaWithoutOaepConfig" }

override predicate isSource(DataFlow::Node src) {
exists(CompileTimeConstantExpr specExpr, string spec |
specExpr.getStringValue() = spec and
specExpr = src.asExpr() and
spec.matches("RSA/%") and
not spec.matches("%OAEP%")
)
}

override predicate isSink(DataFlow::Node sink) {
exists(CryptoAlgoSpec cr | sink.asExpr() = cr.getAlgoSpec())
}
}
7 changes: 7 additions & 0 deletions java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// BAD: No padding scheme is used
Cipher rsa = Cipher.getInstance("RSA/ECB/NoPadding");
...

//GOOD: OAEP padding is used
Cipher rsa = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
...
27 changes: 27 additions & 0 deletions java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.qhelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>

<overview>
<p>Cryptographic algorithms often use padding schemes to make the plaintext less predictable. The OAEP (Optimal Asymmetric Encryption Padding) scheme should be used with RSA encryption.
Using an outdated padding scheme such as PKCS1, or no padding at all, can weaken the encryption by making it vulnerable to a padding oracle attack.
</p>
</overview>

<recommendation>
<p>Use the OAEP scheme when using RSA encryption.</p>
</recommendation>

<example>
<p>In the following example, the BAD case shows no padding being used, whereas the GOOD case shows an OAEP scheme being used.</p>
<sample src="RsaWithoutOaep.java" />
</example>

<references>
<li>
<a href="https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04g-Testing-Cryptography.md#padding-oracle-attacks-due-to-weaker-padding-or-block-operation-implementations">Mobile Security Testing Guide</a>.
</li>
<li>
<a href="https://robertheaton.com/2013/07/29/padding-oracle-attack/">The Padding Oracle Attack</a>.
</li>
</references>
</qhelp>
20 changes: 20 additions & 0 deletions java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @name Use of RSA algorithm without OAEP
* @description Using RSA encryption without OAEP padding can result in a padding oracle attack, leading to a weaker encryption.
* @kind path-problem
* @problem.severity warning
* @security-severity 7.5
* @precision high
* @id java/rsa-without-oaep
* @tags security
* external/cwe/cwe-780
*/

import java
import semmle.code.java.security.RsaWithoutOaepQuery
import DataFlow::PathGraph

from RsaWithoutOaepConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink
where conf.hasFlowPath(source, sink)
select source, source, sink,
"This specification is used to initialize an RSA cipher without OAEP padding $@.", sink, "here"
4 changes: 4 additions & 0 deletions java/ql/src/change-notes/2022-08-05-rsa-without-oaep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: newQuery
---
* A new query "Use of RSA algorithm without OAEP" (`java/rsa-without-oaep`) has been added. This query finds uses of RSA encryption that don't use the OAEP scheme.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import javax.crypto.Cipher;

class RsaWithoutOaep {
public void test() throws Exception {
Cipher rsaBad = Cipher.getInstance("RSA/ECB/NoPadding"); // $hasTaintFlow

Cipher rsaGood = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
}

public Cipher getCipher(String spec) throws Exception {
return Cipher.getInstance(spec); // $hasTaintFlow
}

public void test2() throws Exception {
Cipher rsa = getCipher("RSA/ECB/NoPadding");
}
}
10 changes: 10 additions & 0 deletions java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import java
import TestUtilities.InlineExpectationsTest
import TestUtilities.InlineFlowTest
import semmle.code.java.security.RsaWithoutOaepQuery

class HasFlowTest extends InlineFlowTest {
override DataFlow::Configuration getTaintFlowConfig() { result instanceof RsaWithoutOaepConfig }

override DataFlow::Configuration getValueFlowConfig() { none() }
}