mirror of
https://github.com/github/codeql.git
synced 2026-01-31 07:12:57 +01:00
Merge pull request #289 from smowton/gorand
(admin) Slightly cleaned up version of Insufficient Randomness
This commit is contained in:
40
ql/src/experimental/CWE-327/InsecureRandomness.qhelp
Normal file
40
ql/src/experimental/CWE-327/InsecureRandomness.qhelp
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Generating secure random numbers can be an important part of creating a
|
||||
secure software system. This can be done using APIs that create
|
||||
cryptographically secure random numbers.
|
||||
</p>
|
||||
<p>
|
||||
However, using an insecure random number generator can make it easier for an attacker to guess the random
|
||||
numbers, and thereby break the security of the software system.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
Be very careful not to use insecure random number generation as keys in cryptographic algorithms.
|
||||
</p>
|
||||
<p>
|
||||
If possible, avoid using math/rand for cryptographic algorithms, and use crypto/rand instead.
|
||||
</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
The example below uses the math/rand package instead of crypto/rand to hash and encrypt a password,
|
||||
demonstrating an insecure use of random number generation.
|
||||
</p>
|
||||
<sample src="examples/InsecureRandomness.go" />
|
||||
</example>
|
||||
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://owasp.org/www-community/vulnerabilities/Insecure_Randomness">Insecure Randomness</a>.</li>
|
||||
<li>OWASP: <a
|
||||
href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation">Secure Random Number Generation</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
18
ql/src/experimental/CWE-327/InsecureRandomness.ql
Normal file
18
ql/src/experimental/CWE-327/InsecureRandomness.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @name Use of insufficient randomness as the key of a cryptographic algorithm
|
||||
* @description Using insufficient randomness as the key of a cryptographic algorithm can allow an attacker to compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id go/insecure-randomness
|
||||
* @tags security
|
||||
* external/cwe/cwe-327
|
||||
*/
|
||||
|
||||
import go
|
||||
import InsecureRandomnessCustomizations::InsecureRandomness
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "$@ is a weak key used in cryptographic algorithm.",
|
||||
source.getNode(), "Random number"
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Provides default sources, sinks and sanitizers for reasoning about
|
||||
* insufficient random sources used as keys in cryptographic algorithms,
|
||||
* as well as extension points for adding your own.
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
module InsecureRandomness {
|
||||
/**
|
||||
* A data flow source for insufficient random sources
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for cryptographic algorithms that take a key as input
|
||||
*/
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer for insufficient random sources used as cryptographic keys
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A random source that is not sufficient for security use. So far this is only made up
|
||||
* of the math package's rand function, more insufficient random sources can be added here.
|
||||
*/
|
||||
class InsecureRandomSource extends Source, DataFlow::CallNode {
|
||||
InsecureRandomSource() { this.getTarget().getPackage().getPath() = "math/rand" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A cryptographic algorithm.
|
||||
*/
|
||||
class CryptographicSink extends Sink, DataFlow::Node {
|
||||
CryptographicSink() {
|
||||
exists(DataFlow::CallNode call |
|
||||
call.getTarget().getPackage().getPath().regexpMatch("crypto/.*") and
|
||||
this = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration depicting taint flow from insufficient random sources to cryptographic
|
||||
* algorithms that take a key as input.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "InsecureRandomness" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
}
|
||||
}
|
||||
@@ -10,24 +10,44 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
password := []byte("password")
|
||||
public := []byte("hello")
|
||||
|
||||
// BAD, des is a weak crypto algorithm
|
||||
des.NewTripleDESCipher(password)
|
||||
password := []byte("123456")
|
||||
buf := password // testing dataflow by passing into different variable
|
||||
|
||||
// BAD, md5 is a weak crypto algorithm
|
||||
md5.Sum(password)
|
||||
// BAD, des is a weak crypto algorithm and password is sensitive data
|
||||
des.NewTripleDESCipher(buf)
|
||||
|
||||
// BAD, rc4 is a weak crypto algorithm
|
||||
rc4.NewCipher(password)
|
||||
// BAD, md5 is a weak crypto algorithm and password is sensitive data
|
||||
md5.Sum(buf)
|
||||
|
||||
// BAD, sha1 is a weak crypto algorithm
|
||||
sha1.Sum(password)
|
||||
// BAD, rc4 is a weak crypto algorithm and password is sensitive data
|
||||
rc4.NewCipher(buf)
|
||||
|
||||
// GOOD, aes is a strong crypto algorithm
|
||||
aes.NewCipher(password)
|
||||
// BAD, sha1 is a weak crypto algorithm and password is sensitive data
|
||||
sha1.Sum(buf)
|
||||
|
||||
// GOOD, sha256 is a strong crypto algorithm
|
||||
sha256.Sum256(password)
|
||||
// GOOD, password is sensitive data but aes is a strong crypto algorithm
|
||||
aes.NewCipher(buf)
|
||||
|
||||
// GOOD, password is sensitive data but sha256 is a strong crypto algorithm
|
||||
sha256.Sum256(buf)
|
||||
|
||||
// GOOD, des is a weak crypto algorithm but public is not sensitive data
|
||||
des.NewTripleDESCipher(public)
|
||||
|
||||
// GOOD, md5 is a weak crypto algorithm but public is not sensitive data
|
||||
md5.Sum(public)
|
||||
|
||||
// GOOD, rc4 is a weak crypto algorithm but public is not sensitive data
|
||||
rc4.NewCipher(public)
|
||||
|
||||
// GOOD, sha1 is a weak crypto algorithm but public is not sensitive data
|
||||
sha1.Sum(public)
|
||||
|
||||
// GOOD, aes is a strong crypto algorithm and public is not sensitive data
|
||||
aes.NewCipher(public)
|
||||
|
||||
// GOOD, sha256 is a strong crypto algorithm and public is not sensitive data
|
||||
sha256.Sum256(public)
|
||||
}
|
||||
|
||||
29
ql/src/experimental/CWE-327/examples/InsecureRandomness.go
Normal file
29
ql/src/experimental/CWE-327/examples/InsecureRandomness.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func createHash(key string) string {
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(key))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
func encrypt(data []byte, password string) []byte {
|
||||
|
||||
block, _ := aes.NewCipher([]byte(createHash(password)))
|
||||
gcm, _ := cipher.NewGCM(block)
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
random := rand.New(rand.NewSource(999))
|
||||
io.ReadFull(random, nonce)
|
||||
|
||||
ciphertext := gcm.Seal(nonce, nonce, data, nil)
|
||||
return ciphertext
|
||||
}
|
||||
10
ql/test/experimental/CWE-327/InsecureRandomness.expected
Normal file
10
ql/test/experimental/CWE-327/InsecureRandomness.expected
Normal file
@@ -0,0 +1,10 @@
|
||||
edges
|
||||
| InsecureRandomness.go:24:12:24:40 | call to New : pointer type | InsecureRandomness.go:27:25:27:29 | nonce |
|
||||
| InsecureRandomness.go:24:12:24:40 | call to New : pointer type | InsecureRandomness.go:27:32:27:36 | nonce |
|
||||
nodes
|
||||
| InsecureRandomness.go:24:12:24:40 | call to New : pointer type | semmle.label | call to New : pointer type |
|
||||
| InsecureRandomness.go:27:25:27:29 | nonce | semmle.label | nonce |
|
||||
| InsecureRandomness.go:27:32:27:36 | nonce | semmle.label | nonce |
|
||||
#select
|
||||
| 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 |
|
||||
| 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 |
|
||||
29
ql/test/experimental/CWE-327/InsecureRandomness.go
Normal file
29
ql/test/experimental/CWE-327/InsecureRandomness.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func createHash(key string) string {
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(key))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
func encrypt(data []byte, password string) []byte {
|
||||
|
||||
block, _ := aes.NewCipher([]byte(createHash(password)))
|
||||
gcm, _ := cipher.NewGCM(block)
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
random := rand.New(rand.NewSource(999))
|
||||
io.ReadFull(random, nonce)
|
||||
|
||||
ciphertext := gcm.Seal(nonce, nonce, data, nil)
|
||||
return ciphertext
|
||||
}
|
||||
1
ql/test/experimental/CWE-327/InsecureRandomness.qlref
Normal file
1
ql/test/experimental/CWE-327/InsecureRandomness.qlref
Normal file
@@ -0,0 +1 @@
|
||||
experimental/CWE-327/InsecureRandomness.ql
|
||||
Reference in New Issue
Block a user