Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
9b7df35
move files
Sep 29, 2022
3643c9e
update metadata
Sep 29, 2022
657e1e6
start refactoring query logic into lib file
Sep 29, 2022
9eb45c3
refactor tests and code, update help file
Oct 3, 2022
7d94590
add change note
Oct 3, 2022
75794ec
false negative testing - before rewrite for variable dataflow
Oct 4, 2022
7de9c05
use CompileTimeConstantExpr for FN with VarAccess, and remove KeyGene…
Oct 4, 2022
d3b1a04
handle FN case with simple VarAccess; add draft of dataflow config to…
Oct 5, 2022
8ffd252
add draft code to find algo type to replace tainttracking configs
Oct 5, 2022
ac70719
commit before adding taint flow back (since no taint flow doesn't cap…
Oct 5, 2022
5e2ef66
refactoring to use both dataflow configs; commit before deleting unus…
Oct 6, 2022
c414ee0
add ECC dataflow config; passes all test cases; still don't have algo…
Oct 6, 2022
cdac0e2
add local algo name tracking, still need to add ability to track algo…
Oct 7, 2022
b7123c1
draft of adding kpg tracking into dataflow config
Oct 8, 2022
b0af9f9
added kg taintracking config to all
Oct 10, 2022
f5a2fef
update tests for non-path version
Oct 10, 2022
3cc7f14
clean up code somewhat
Oct 10, 2022
0c2cff2
updates from discussing with Tony
Oct 10, 2022
bd76b1f
clean-up and update configurations to have specs as sink
Oct 10, 2022
b6a8c27
delete experimental files
Oct 10, 2022
e64825f
fix code-scanning bot problems
Oct 11, 2022
26f4abf
remove globalflow for key(pair)gen
Oct 11, 2022
3e8748e
add path-graph back to query alerts
Oct 11, 2022
29de0c6
make one config for asymm with flow states; seems to work...
Oct 12, 2022
01c2a8c
add symm to the single config; still seems to work
Oct 12, 2022
0fc4a33
remove commented-out code
Oct 12, 2022
37d8558
refactor code into InsufficientKeySize.qll
Oct 12, 2022
bfbb6db
clean up code
Oct 12, 2022
bcb506b
add placeholder qldocs
Oct 12, 2022
e0f0d55
condense code
Oct 13, 2022
2daa345
combine three configs into one
Oct 13, 2022
c61f23b
experiment with more code condensing
Oct 14, 2022
6eb58d8
remove dependence on typeFlag
Oct 14, 2022
47030df
remove commented-out 3 configs
Oct 14, 2022
0334470
remove commented out predicates that relied on typeFlag
Oct 14, 2022
da218fd
clean up code
Oct 14, 2022
2714c7f
update tests
Oct 14, 2022
5f39888
minor code restructure
Oct 17, 2022
383b8a8
update select statement to be closer to cpp's
Oct 19, 2022
ff557a2
add min key size predicates
Oct 19, 2022
dc8b62b
add support for AlgorithmParameterGenerator
Oct 19, 2022
4df0fbc
update tests
Oct 19, 2022
961e5c7
minor updates
Oct 19, 2022
e5982f1
minor updates
Oct 19, 2022
b7f3606
rename change note
Oct 19, 2022
345e4e0
remove unnecessary 'exists'
Oct 21, 2022
4c8e0a7
update qldoc of JavaSecurityKeyPairGenerator and JavaSecurityAlgoPara…
Oct 24, 2022
2ee23f0
update qldoc for AlgorithmParameterSpec
Oct 24, 2022
eb69b98
remove separators
Oct 24, 2022
8bc0a64
remove KeyGenInitMethodAccess class
Oct 24, 2022
09829d7
simplify instanceof usage
Oct 24, 2022
d569f93
update getAlgoSpec
Oct 24, 2022
c742a09
remove AlgoSpec class
Oct 24, 2022
1a12453
remove getNodeIntValue
Oct 24, 2022
1e80fa1
add modules
Oct 25, 2022
1bfdfc9
shorten class/predicate names
Oct 26, 2022
65f7474
simplify algorithm.matches
Oct 27, 2022
f40eefc
use CompileTimeConstantExpr instead of StringLiteral
Oct 27, 2022
910eebc
update change note
Nov 3, 2022
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
Prev Previous commit
Next Next commit
draft of adding kpg tracking into dataflow config
  • Loading branch information
Jami Cogswell Jami Cogswell
Jami Cogswell authored and Jami Cogswell committed Oct 11, 2022
commit b7123c17f8f0c871e1cf53a51027e5abc6c69a77
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking2
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.DataFlow

Expand All @@ -11,7 +12,7 @@ import semmle.code.java.dataflow.DataFlow
/**
* Asymmetric (RSA, DSA, DH) key length data flow tracking configuration.
*/
class AsymmetricKeyTrackingConfiguration extends DataFlow::Configuration {
class AsymmetricKeyTrackingConfiguration extends TaintTracking2::Configuration {
AsymmetricKeyTrackingConfiguration() { this = "AsymmetricKeyTrackingConfiguration" }

override predicate isSource(DataFlow::Node source) {
Expand All @@ -27,15 +28,25 @@ class AsymmetricKeyTrackingConfiguration extends DataFlow::Configuration {
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma, VarAccess va |
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
va.getVariable()
.getAnAssignedValue()
.(JavaSecurityKeyPairGenerator)
.getAlgoSpec()
.(StringLiteral)
.getValue()
.toUpperCase()
.matches(["RSA", "DSA", "DH"]) and
ma.getQualifier() = va and
ma.getFile().getBaseName().matches("SignatureTest.java") and
// va.getVariable()
// .getAnAssignedValue()
// .(JavaSecurityKeyPairGenerator)
// .getAlgoSpec()
// .(StringLiteral)
// .getValue()
// .toUpperCase()
// .matches(["RSA", "DSA", "DH"]) and
// ma.getQualifier() = va and
exists(
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kpgConfig,
DataFlow::PathNode source, DataFlow::PathNode dest
|
jpg.getAlgoSpec().(StringLiteral).getValue().toUpperCase().matches(["RSA", "DSA", "DH"]) and
source.getNode().asExpr() = jpg and
dest.getNode().asExpr() = ma.getQualifier() and
kpgConfig.hasFlowPath(source, dest)
) and
sink.asExpr() = ma.getArgument(0)
)
}
Expand Down Expand Up @@ -102,12 +113,11 @@ class SymmetricKeyTrackingConfiguration extends DataFlow::Configuration {
}

// ! below doesn't work for some reason...
predicate hasInsufficientKeySize2(DataFlow::PathNode source, DataFlow::PathNode sink) {
exists(AsymmetricKeyTrackingConfiguration config1 | config1.hasFlowPath(source, sink))
or
exists(SymmetricKeyTrackingConfiguration config2 | config2.hasFlowPath(source, sink))
}

// predicate hasInsufficientKeySize2(DataFlow::PathNode source, DataFlow::PathNode sink) {
// exists(AsymmetricKeyTrackingConfiguration config1 | config1.hasFlowPath(source, sink))
// or
// exists(SymmetricKeyTrackingConfiguration config2 | config2.hasFlowPath(source, sink))
// }
// ******** Need the below for the above ********
// ! move to Encryption.qll?
/** The Java class `java.security.spec.ECGenParameterSpec`. */
Expand Down
20 changes: 14 additions & 6 deletions java/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,17 @@ import DataFlow::PathGraph
// cfg2.hasFlowPath(source, sink)
// select sink.getNode(), source, sink, "The $@ of an asymmetric key should be at least 2048 bits.",
// sink.getNode(), "size"
from DataFlow::PathNode source, DataFlow::PathNode sink
where
exists(AsymmetricKeyTrackingConfiguration config1 | config1.hasFlowPath(source, sink)) or
exists(AsymmetricECCKeyTrackingConfiguration config2 | config2.hasFlowPath(source, sink)) or
exists(SymmetricKeyTrackingConfiguration config3 | config3.hasFlowPath(source, sink))
select sink.getNode(), source, sink, "This $@ is too small.", sink.getNode(), "key size"
// * Use Below
// from DataFlow::PathNode source, DataFlow::PathNode sink
// where exists(AsymmetricKeyTrackingConfiguration config1 | config1.hasFlowPath(source, sink)) //or
// //exists(AsymmetricECCKeyTrackingConfiguration config2 | config2.hasFlowPath(source, sink)) //or
// //exists(SymmetricKeyTrackingConfiguration config3 | config3.hasFlowPath(source, sink))
// select sink.getNode(), source, sink, "This $@ is too small, and flows to $@.", source.getNode(),
// "key size", sink.getNode(), "here"
// * Use Above
from DataFlow::Node source, DataFlow::Node sink
where exists(AsymmetricKeyTrackingConfiguration config1 | config1.hasFlow(source, sink)) //or
//exists(AsymmetricECCKeyTrackingConfiguration config2 | config2.hasFlowPath(source, sink)) //or
//exists(SymmetricKeyTrackingConfiguration config3 | config3.hasFlowPath(source, sink))
select sink, source, sink, "This $@ is too small, and flows to $@.", source, "key size", sink,
"here"
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import javax.crypto.KeyGenerator;
import java.security.KeyPairGenerator;

import java.security.spec.ECGenParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import javax.crypto.KeyGenerator;
import java.security.spec.DSAGenParameterSpec;
import javax.crypto.spec.DHGenParameterSpec;


public class InsufficientKeySizeTest {
public void keySizeTesting() throws java.security.NoSuchAlgorithmException, java.security.InvalidAlgorithmParameterException {
Expand Down Expand Up @@ -49,6 +53,16 @@ public void keySizeTesting() throws java.security.NoSuchAlgorithmException, java
// GOOD: Key size is no less than 2048
KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("DSA");
keyPairGen4.initialize(2048); // Safe

// test with spec?
// // BAD: Key size is less than 2048
// KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("DSA");
// DSAGenParameterSpec dsaSpec = new DSAGenParameterSpec(1024, null);
// keyPairGen5.initialize(dsaSpec); // $ hasInsufficientKeySize

// // BAD: Key size is less than 2048
// KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("DSA");
// keyPairGen6.initialize(new DSAGenParameterSpec(1024, null)); // $ hasInsufficientKeySize
}

// DH (Asymmetric)
Expand All @@ -60,6 +74,16 @@ public void keySizeTesting() throws java.security.NoSuchAlgorithmException, java
// GOOD: Key size is no less than 2048
KeyPairGenerator keyPairGen17 = KeyPairGenerator.getInstance("DH");
keyPairGen17.initialize(2048); // Safe

// test with spec?
// // BAD: Key size is less than 2048
// KeyPairGenerator keyPairGen3 = KeyPairGenerator.getInstance("DH");
// DHGenParameterSpec dhSpec = new DHGenParameterSpec(1024, null);
// keyPairGen3.initialize(dhSpec); // $ hasInsufficientKeySize

// // BAD: Key size is less than 2048
// KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("DH");
// keyPairGen4.initialize(new DHGenParameterSpec(1024, null)); // $ hasInsufficientKeySize
}

// EC (Asymmetric)
Expand Down
196 changes: 196 additions & 0 deletions java/ql/test/query-tests/security/CWE-326/SignatureTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
//package org.bouncycastle.jce.provider.test;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;

// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
// import org.bouncycastle.jce.provider.BouncyCastleProvider;
// import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
// import org.bouncycastle.jce.spec.GOST3410ParameterSpec;
// import org.bouncycastle.util.encoders.Hex;
// import org.bouncycastle.util.test.SimpleTest;

public class SignatureTest
//extends SimpleTest
{
// private static final byte[] DATA = Hex.decode("00000000deadbeefbeefdeadffffffff00000000");

private void checkSig(KeyPair kp, String name)
throws Exception
{
// Signature sig = Signature.getInstance(name, "BC");

// sig.initSign(kp.getPrivate());
// sig.update(DATA);

// byte[] signature1 = sig.sign();

// sig.update(DATA);

// byte[] signature2 = sig.sign();

// sig.initVerify(kp.getPublic());

// sig.update(DATA);
// if (!sig.verify(signature1))
// {
// fail("did not verify: " + name);
// }

// // After verify, should be reusable as if we are after initVerify
// sig.update(DATA);
// if (!sig.verify(signature1))
// {
// fail("second verify failed: " + name);
// }

// sig.update(DATA);
// if (!sig.verify(signature2))
// {
// fail("second verify failed (2): " + name);
// }
}

public void performTest()
throws Exception
{
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");

kpGen.initialize(2048); // Safe

KeyPair kp = kpGen.generateKeyPair();

checkSig(kp, "SHA1withRSA");
checkSig(kp, "SHA224withRSA");
checkSig(kp, "SHA256withRSA");
checkSig(kp, "SHA384withRSA");
checkSig(kp, "SHA512withRSA");

checkSig(kp, "SHA3-224withRSA");
checkSig(kp, "SHA3-256withRSA");
checkSig(kp, "SHA3-384withRSA");
checkSig(kp, "SHA3-512withRSA");

checkSig(kp, "MD2withRSA");
checkSig(kp, "MD4withRSA");
checkSig(kp, "MD5withRSA");
checkSig(kp, "RIPEMD160withRSA");
checkSig(kp, "RIPEMD128withRSA");
checkSig(kp, "RIPEMD256withRSA");

checkSig(kp, "SHA1withRSAandMGF1");
checkSig(kp, "SHA1withRSAandMGF1");
checkSig(kp, "SHA224withRSAandMGF1");
checkSig(kp, "SHA256withRSAandMGF1");
checkSig(kp, "SHA384withRSAandMGF1");
checkSig(kp, "SHA512withRSAandMGF1");

checkSig(kp, "SHA1withRSAandSHAKE128");
checkSig(kp, "SHA1withRSAandSHAKE128");
checkSig(kp, "SHA224withRSAandSHAKE128");
checkSig(kp, "SHA256withRSAandSHAKE128");
checkSig(kp, "SHA384withRSAandSHAKE128");
checkSig(kp, "SHA512withRSAandSHAKE128");

checkSig(kp, "SHA1withRSAandSHAKE256");
checkSig(kp, "SHA1withRSAandSHAKE256");
checkSig(kp, "SHA224withRSAandSHAKE256");
checkSig(kp, "SHA256withRSAandSHAKE256");
checkSig(kp, "SHA384withRSAandSHAKE256");
checkSig(kp, "SHA512withRSAandSHAKE256");

checkSig(kp, "SHAKE128withRSAPSS");
checkSig(kp, "SHAKE256withRSAPSS");

checkSig(kp, "SHA1withRSA/ISO9796-2");
checkSig(kp, "MD5withRSA/ISO9796-2");
checkSig(kp, "RIPEMD160withRSA/ISO9796-2");

// checkSig(kp, "SHA1withRSA/ISO9796-2PSS");
// checkSig(kp, "MD5withRSA/ISO9796-2PSS");
// checkSig(kp, "RIPEMD160withRSA/ISO9796-2PSS");

checkSig(kp, "RIPEMD128withRSA/X9.31");
checkSig(kp, "RIPEMD160withRSA/X9.31");
checkSig(kp, "SHA1withRSA/X9.31");
checkSig(kp, "SHA224withRSA/X9.31");
checkSig(kp, "SHA256withRSA/X9.31");
checkSig(kp, "SHA384withRSA/X9.31");
checkSig(kp, "SHA512withRSA/X9.31");
checkSig(kp, "WhirlpoolwithRSA/X9.31");

kpGen = KeyPairGenerator.getInstance("DSA", "BC");

kpGen.initialize(2048); // Safe

kp = kpGen.generateKeyPair();

checkSig(kp, "SHA1withDSA");
checkSig(kp, "SHA224withDSA");
checkSig(kp, "SHA256withDSA");
checkSig(kp, "SHA384withDSA");
checkSig(kp, "SHA512withDSA");
checkSig(kp, "NONEwithDSA");

kpGen = KeyPairGenerator.getInstance("EC", "BC");

kpGen.initialize(256); // Safe

kp = kpGen.generateKeyPair();

checkSig(kp, "SHA1withECDSA");
checkSig(kp, "SHA224withECDSA");
checkSig(kp, "SHA256withECDSA");
checkSig(kp, "SHA384withECDSA");
checkSig(kp, "SHA512withECDSA");
checkSig(kp, "RIPEMD160withECDSA");
checkSig(kp, "SHAKE128withECDSA");
checkSig(kp, "SHAKE256withECDSA");

kpGen = KeyPairGenerator.getInstance("EC", "BC");

kpGen.initialize(521); // Safe

kp = kpGen.generateKeyPair();

checkSig(kp, "SHA1withECNR");
checkSig(kp, "SHA224withECNR");
checkSig(kp, "SHA256withECNR");
checkSig(kp, "SHA384withECNR");
checkSig(kp, "SHA512withECNR");

// kpGen = KeyPairGenerator.getInstance("ECGOST3410", "BC");

// kpGen.initialize(new ECNamedCurveGenParameterSpec("GostR3410-2001-CryptoPro-A"), new SecureRandom());

// kp = kpGen.generateKeyPair();

// checkSig(kp, "GOST3411withECGOST3410");

// kpGen = KeyPairGenerator.getInstance("GOST3410", "BC");

// GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A.getId());

// kpGen.initialize(gost3410P);

// kp = kpGen.generateKeyPair();

// checkSig(kp, "GOST3411withGOST3410");
}

public String getName()
{
return "SigNameTest";
}

// public static void main(
// String[] args)
// {
// //Security.addProvider(new BouncyCastleProvider());

// //runTest(new SignatureTest());
// }
}