Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit c07db2a

Browse files
authored
Merge pull request #289 from smowton/gorand
(admin) Slightly cleaned up version of Insufficient Randomness
2 parents d675daa + 986f3c3 commit c07db2a

File tree

8 files changed

+218
-13
lines changed

8 files changed

+218
-13
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
Generating secure random numbers can be an important part of creating a
8+
secure software system. This can be done using APIs that create
9+
cryptographically secure random numbers.
10+
</p>
11+
<p>
12+
However, using an insecure random number generator can make it easier for an attacker to guess the random
13+
numbers, and thereby break the security of the software system.
14+
</p>
15+
</overview>
16+
<recommendation>
17+
<p>
18+
Be very careful not to use insecure random number generation as keys in cryptographic algorithms.
19+
</p>
20+
<p>
21+
If possible, avoid using math/rand for cryptographic algorithms, and use crypto/rand instead.
22+
</p>
23+
</recommendation>
24+
<example>
25+
<p>
26+
The example below uses the math/rand package instead of crypto/rand to hash and encrypt a password,
27+
demonstrating an insecure use of random number generation.
28+
</p>
29+
<sample src="examples/InsecureRandomness.go" />
30+
</example>
31+
32+
33+
<references>
34+
<li>OWASP: <a href="https://owasp.org/www-community/vulnerabilities/Insecure_Randomness">Insecure Randomness</a>.</li>
35+
<li>OWASP: <a
36+
href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation">Secure Random Number Generation</a>.
37+
</li>
38+
</references>
39+
40+
</qhelp>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* @name Use of insufficient randomness as the key of a cryptographic algorithm
3+
* @description Using insufficient randomness as the key of a cryptographic algorithm can allow an attacker to compromise security.
4+
* @kind path-problem
5+
* @problem.severity error
6+
* @id go/insecure-randomness
7+
* @tags security
8+
* external/cwe/cwe-327
9+
*/
10+
11+
import go
12+
import InsecureRandomnessCustomizations::InsecureRandomness
13+
import DataFlow::PathGraph
14+
15+
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
16+
where cfg.hasFlowPath(source, sink)
17+
select sink.getNode(), source, sink, "$@ is a weak key used in cryptographic algorithm.",
18+
source.getNode(), "Random number"
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Provides default sources, sinks and sanitizers for reasoning about
3+
* insufficient random sources used as keys in cryptographic algorithms,
4+
* as well as extension points for adding your own.
5+
*/
6+
7+
import go
8+
9+
module InsecureRandomness {
10+
/**
11+
* A data flow source for insufficient random sources
12+
*/
13+
abstract class Source extends DataFlow::Node { }
14+
15+
/**
16+
* A data flow sink for cryptographic algorithms that take a key as input
17+
*/
18+
abstract class Sink extends DataFlow::Node { }
19+
20+
/**
21+
* A sanitizer for insufficient random sources used as cryptographic keys
22+
*/
23+
abstract class Sanitizer extends DataFlow::Node { }
24+
25+
/**
26+
* A random source that is not sufficient for security use. So far this is only made up
27+
* of the math package's rand function, more insufficient random sources can be added here.
28+
*/
29+
class InsecureRandomSource extends Source, DataFlow::CallNode {
30+
InsecureRandomSource() { this.getTarget().getPackage().getPath() = "math/rand" }
31+
}
32+
33+
/**
34+
* A cryptographic algorithm.
35+
*/
36+
class CryptographicSink extends Sink, DataFlow::Node {
37+
CryptographicSink() {
38+
exists(DataFlow::CallNode call |
39+
call.getTarget().getPackage().getPath().regexpMatch("crypto/.*") and
40+
this = call.getAnArgument()
41+
)
42+
}
43+
}
44+
45+
/**
46+
* A configuration depicting taint flow from insufficient random sources to cryptographic
47+
* algorithms that take a key as input.
48+
*/
49+
class Configuration extends TaintTracking::Configuration {
50+
Configuration() { this = "InsecureRandomness" }
51+
52+
override predicate isSource(DataFlow::Node source) { source instanceof Source }
53+
54+
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
55+
56+
override predicate isSanitizer(DataFlow::Node node) { none() }
57+
}
58+
}

ql/src/experimental/CWE-327/examples/Crypto.go

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,44 @@ import (
1010
)
1111

1212
func main() {
13-
password := []byte("password")
13+
public := []byte("hello")
1414

15-
// BAD, des is a weak crypto algorithm
16-
des.NewTripleDESCipher(password)
15+
password := []byte("123456")
16+
buf := password // testing dataflow by passing into different variable
1717

18-
// BAD, md5 is a weak crypto algorithm
19-
md5.Sum(password)
18+
// BAD, des is a weak crypto algorithm and password is sensitive data
19+
des.NewTripleDESCipher(buf)
2020

21-
// BAD, rc4 is a weak crypto algorithm
22-
rc4.NewCipher(password)
21+
// BAD, md5 is a weak crypto algorithm and password is sensitive data
22+
md5.Sum(buf)
2323

24-
// BAD, sha1 is a weak crypto algorithm
25-
sha1.Sum(password)
24+
// BAD, rc4 is a weak crypto algorithm and password is sensitive data
25+
rc4.NewCipher(buf)
2626

27-
// GOOD, aes is a strong crypto algorithm
28-
aes.NewCipher(password)
27+
// BAD, sha1 is a weak crypto algorithm and password is sensitive data
28+
sha1.Sum(buf)
2929

30-
// GOOD, sha256 is a strong crypto algorithm
31-
sha256.Sum256(password)
30+
// GOOD, password is sensitive data but aes is a strong crypto algorithm
31+
aes.NewCipher(buf)
3232

33+
// GOOD, password is sensitive data but sha256 is a strong crypto algorithm
34+
sha256.Sum256(buf)
35+
36+
// GOOD, des is a weak crypto algorithm but public is not sensitive data
37+
des.NewTripleDESCipher(public)
38+
39+
// GOOD, md5 is a weak crypto algorithm but public is not sensitive data
40+
md5.Sum(public)
41+
42+
// GOOD, rc4 is a weak crypto algorithm but public is not sensitive data
43+
rc4.NewCipher(public)
44+
45+
// GOOD, sha1 is a weak crypto algorithm but public is not sensitive data
46+
sha1.Sum(public)
47+
48+
// GOOD, aes is a strong crypto algorithm and public is not sensitive data
49+
aes.NewCipher(public)
50+
51+
// GOOD, sha256 is a strong crypto algorithm and public is not sensitive data
52+
sha256.Sum256(public)
3353
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"crypto/aes"
5+
"crypto/cipher"
6+
"crypto/sha256"
7+
"encoding/hex"
8+
"io"
9+
"math/rand"
10+
)
11+
12+
func createHash(key string) string {
13+
hash := sha256.New()
14+
hash.Write([]byte(key))
15+
return hex.EncodeToString(hash.Sum(nil))
16+
}
17+
18+
func encrypt(data []byte, password string) []byte {
19+
20+
block, _ := aes.NewCipher([]byte(createHash(password)))
21+
gcm, _ := cipher.NewGCM(block)
22+
23+
nonce := make([]byte, gcm.NonceSize())
24+
random := rand.New(rand.NewSource(999))
25+
io.ReadFull(random, nonce)
26+
27+
ciphertext := gcm.Seal(nonce, nonce, data, nil)
28+
return ciphertext
29+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
edges
2+
| InsecureRandomness.go:24:12:24:40 | call to New : pointer type | InsecureRandomness.go:27:25:27:29 | nonce |
3+
| InsecureRandomness.go:24:12:24:40 | call to New : pointer type | InsecureRandomness.go:27:32:27:36 | nonce |
4+
nodes
5+
| InsecureRandomness.go:24:12:24:40 | call to New : pointer type | semmle.label | call to New : pointer type |
6+
| InsecureRandomness.go:27:25:27:29 | nonce | semmle.label | nonce |
7+
| InsecureRandomness.go:27:32:27:36 | nonce | semmle.label | nonce |
8+
#select
9+
| InsecureRandomness.go:27:25:27:29 | nonce | InsecureRandomness.go:24:12:24:40 | call to New : pointer type | InsecureRandomness.go:27:25:27:29 | nonce | $@ is a weak key used in cryptographic algorithm. | InsecureRandomness.go:24:12:24:40 | call to New | Random number |
10+
| InsecureRandomness.go:27:32:27:36 | nonce | InsecureRandomness.go:24:12:24:40 | call to New : pointer type | InsecureRandomness.go:27:32:27:36 | nonce | $@ is a weak key used in cryptographic algorithm. | InsecureRandomness.go:24:12:24:40 | call to New | Random number |
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"crypto/aes"
5+
"crypto/cipher"
6+
"crypto/sha256"
7+
"encoding/hex"
8+
"io"
9+
"math/rand"
10+
)
11+
12+
func createHash(key string) string {
13+
hash := sha256.New()
14+
hash.Write([]byte(key))
15+
return hex.EncodeToString(hash.Sum(nil))
16+
}
17+
18+
func encrypt(data []byte, password string) []byte {
19+
20+
block, _ := aes.NewCipher([]byte(createHash(password)))
21+
gcm, _ := cipher.NewGCM(block)
22+
23+
nonce := make([]byte, gcm.NonceSize())
24+
random := rand.New(rand.NewSource(999))
25+
io.ReadFull(random, nonce)
26+
27+
ciphertext := gcm.Seal(nonce, nonce, data, nil)
28+
return ciphertext
29+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/CWE-327/InsecureRandomness.ql

0 commit comments

Comments
 (0)