Skip to content

Commit

Permalink
feat(python): add cwe-328 weak hash rules (#414)
Browse files Browse the repository at this point in the history
  • Loading branch information
didroe authored May 22, 2024
1 parent a02dc8d commit 6132fad
Show file tree
Hide file tree
Showing 14 changed files with 368 additions and 10 deletions.
4 changes: 2 additions & 2 deletions rules/php/lang/weak_hash_adler32.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ patterns:
- hash_update_stream
- hash_update
- variable: CONTEXT
detection: php_lang_weak_hash_crc32_context
detection: php_lang_weak_hash_adler32_context
scope: cursor
auxiliary:
- id: php_lang_weak_hash_crc32_context
- id: php_lang_weak_hash_adler32_context
patterns:
- pattern: hash_init($<ALGORITHM>$<...>)
filters:
Expand Down
47 changes: 47 additions & 0 deletions rules/python/lang/weak_hash_adler32.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
imports:
- python_shared_lang_import1
- python_shared_lang_datatype
patterns:
- pattern: |
$<FUNCTION>($<OPTIONAL_DATA_TYPE>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [zlib]
- variable: NAME
values: [adler32]
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- not:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
languages:
- python
metadata:
description: "Usage of weak hashing library (Adler-32)"
remediation_message: |-
## Description
Adler-32 is a weak hashing algorithm that offers minimal security. It is not suitable for protecting data against intentional modifications.
## Remediations
- **Do not** use Adler-32 for hashing when security is a concern. Its simplicity and speed do not compensate for its lack of protection against data tampering.
```python
myhash = zlib.adler32(data) # unsafe
```
- **Do** opt for stronger hashing algorithms like SHA-256 to ensure data integrity and security.
```python
myhash = hashlib.sha256(data).digest()
```
cwe_id:
- 328
id: python_lang_weak_hash_adler32
documentation_url: https://docs.bearer.com/reference/rules/python_lang_weak_hash_adler32
severity: medium
47 changes: 47 additions & 0 deletions rules/python/lang/weak_hash_crc32.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
imports:
- python_shared_lang_import1
- python_shared_lang_datatype
patterns:
- pattern: |
$<FUNCTION>($<OPTIONAL_DATA_TYPE>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [zlib]
- variable: NAME
values: [crc32]
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- not:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
languages:
- python
metadata:
description: "Usage of weak hashing library (CRC32)"
remediation_message: |-
## Description
The use of CRC32 for hashing is insecure. CRC32 is designed for error-checking and not for security purposes, making it vulnerable to intentional data tampering.
## Remediations
- **Do not** use CRC32 for hashing when security is a concern. It is not secure against intentional data modifications.
```python
myhash = zlib.crc32(data) # unsafe
```
- **Do** opt for stronger hashing algorithms like SHA-256 to ensure data integrity and security.
```python
myhash = hashlib.sha256(data).digest()
```
cwe_id:
- 328
id: python_lang_weak_hash_crc32
documentation_url: https://docs.bearer.com/reference/rules/python_lang_weak_hash_crc32
severity: medium
80 changes: 80 additions & 0 deletions rules/python/lang/weak_hash_dss.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
imports:
- python_shared_lang_import1
- python_shared_lang_datatype
patterns:
- pattern: $<FUNCTION>($<ALGORITHM>, $<OPTIONAL_DATA_TYPE>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [new]
- variable: ALGORITHM
string_regex: (?i)\Adss
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- not:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- pattern: $<DSS>.update($<OPTIONAL_DATA_TYPE>)
filters:
- variable: DSS
detection: python_lang_weak_hash_dss_init
scope: cursor
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- not:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
auxiliary:
- id: python_lang_weak_hash_dss_init
patterns:
- pattern: $<FUNCTION>($<ALGORITHM>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [new]
- variable: ALGORITHM
string_regex: (?i)\Adss
languages:
- python
skip_data_types:
- "Unique Identifier"
- "Passwords" # see python_lang_weak_password_hash_dss
metadata:
description: "Usage of weak hashing library (DSS)"
remediation_message: |-
## Description
Using a weak hashing library like DSS increases the risk of data breaches. DSS has known security flaws and vulnerabilities, and its use is no longer recommended.
## Remediations
- **Do not** use DSS for hashing as it is considered a weak algorithm. This can compromise data security.
```python
hashlib.new('dss', data).digest() # unsafe
```
- **Do** opt for stronger hashing algorithms like SHA-256 to enhance security.
```python
hashlib.sha256(data).digest()
```
cwe_id:
- 328
id: python_lang_weak_hash_dss
documentation_url: https://docs.bearer.com/reference/rules/python_lang_weak_hash_dss
cloud_code_suggestions: true
severity: medium
60 changes: 55 additions & 5 deletions rules/python/lang/weak_hash_md5.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
imports:
- python_shared_lang_datatype
- python_shared_lang_import1
patterns:
- pattern: hashlib.md5($<OPTIONAL_DATA_TYPE>)
- pattern: $<FUNCTION>($<ALGORITHM>, $<OPTIONAL_DATA_TYPE>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [new]
- variable: ALGORITHM
string_regex: (?i)\Amd\d
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- not:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- pattern: $<FUNCTION>($<OPTIONAL_DATA_TYPE>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [md5]
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
Expand All @@ -11,9 +40,9 @@ patterns:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- pattern: $<MD5_INIT>.update($<OPTIONAL_DATA_TYPE>)
- pattern: $<MD_INIT>.update($<OPTIONAL_DATA_TYPE>)
filters:
- variable: MD5_INIT
- variable: MD_INIT
detection: python_lang_weak_hash_md5_init
scope: cursor
- either:
Expand All @@ -27,14 +56,35 @@ patterns:
auxiliary:
- id: python_lang_weak_hash_md5_init
patterns:
- hashlib.md5()
- pattern: $<FUNCTION>($<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [md5]
- pattern: $<FUNCTION>($<ALGORITHM>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [new]
- variable: ALGORITHM
string_regex: (?i)\Amd\d
languages:
- python
skip_data_types:
- "Unique Identifier"
- "Passwords" # see python_lang_weak_password_encryption_md5
metadata:
description: "Usage of weak hashing library (MD5)"
description: "Usage of weak hashing library (MDx)"
remediation_message: |-
## Description
Expand Down
54 changes: 52 additions & 2 deletions rules/python/lang/weak_hash_sha1.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
imports:
- python_shared_lang_datatype
- python_shared_lang_import1
patterns:
- pattern: hashlib.sha1($<OPTIONAL_DATA_TYPE>)
- pattern: $<FUNCTION>($<ALGORITHM>, $<OPTIONAL_DATA_TYPE>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [new]
- variable: ALGORITHM
string_regex: (?i)\Asha1?\z
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- not:
variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
scope: result
- pattern: $<FUNCTION>($<OPTIONAL_DATA_TYPE>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [sha1]
- either:
- variable: OPTIONAL_DATA_TYPE
detection: python_shared_lang_datatype
Expand All @@ -27,7 +56,28 @@ patterns:
auxiliary:
- id: python_lang_weak_hash_sha1_init
patterns:
- hashlib.sha1()
- pattern: $<FUNCTION>($<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [sha1]
- pattern: $<FUNCTION>($<ALGORITHM>$<...>)
filters:
- variable: FUNCTION
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [hashlib]
- variable: NAME
values: [new]
- variable: ALGORITHM
string_regex: (?i)\Asha1?\z
languages:
- python
skip_data_types:
Expand Down
20 changes: 20 additions & 0 deletions tests/python/lang/weak_hash_adler32/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const {
createNewInvoker,
getEnvironment,
} = require("../../../helper.js")
const { ruleId, ruleFile, testBase } = getEnvironment(__dirname)

describe(ruleId, () => {
const invoke = createNewInvoker(ruleId, ruleFile, testBase)

test("weak_hash_adler32", () => {
const testCase = "main.py"

const results = invoke(testCase)

expect(results).toEqual({
Missing: [],
Extra: []
})
})
})
4 changes: 4 additions & 0 deletions tests/python/lang/weak_hash_adler32/testdata/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import zlib

# bearer:expected python_lang_weak_hash_adler32
zlib.adler32(user.email, 42)
20 changes: 20 additions & 0 deletions tests/python/lang/weak_hash_crc32/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const {
createNewInvoker,
getEnvironment,
} = require("../../../helper.js")
const { ruleId, ruleFile, testBase } = getEnvironment(__dirname)

describe(ruleId, () => {
const invoke = createNewInvoker(ruleId, ruleFile, testBase)

test("weak_hash_crc32", () => {
const testCase = "main.py"

const results = invoke(testCase)

expect(results).toEqual({
Missing: [],
Extra: []
})
})
})
Loading

0 comments on commit 6132fad

Please sign in to comment.