-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
96ba623
commit 0135cfc
Showing
7 changed files
with
356 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
patterns: | ||
- pattern: | | ||
$<KEY1> == $<KEY2> | ||
filters: | ||
- variable: KEY1 | ||
regex: /pass(word)?/ | ||
- variable: KEY2 | ||
regex: /pass(word)?/ | ||
# - pattern: | | ||
# return $X === auth_token; | ||
# - pattern: | | ||
# return auth_token === $X; | ||
# - pattern: | | ||
# return $X === token; | ||
# - pattern: | | ||
# return token === $X; | ||
# - pattern: | | ||
# return $X === hash; | ||
# - pattern: | | ||
# return hash === $X; | ||
# - pattern: | | ||
# return $X === password; | ||
# - pattern: | | ||
# return password === $X; | ||
# - pattern: | | ||
# return $X === pass; | ||
# - pattern: | | ||
# return pass === $X; | ||
# - pattern: | | ||
# return $X === apiKey; | ||
# - pattern: | | ||
# return apiKey === $X; | ||
# - pattern: | | ||
# return $X === apiSecret; | ||
# - pattern: | | ||
# return apiSecret === $X; | ||
# - pattern: | | ||
# return $X === api_key; | ||
# - pattern: | | ||
# return api_key === $X; | ||
# - pattern: | | ||
# return $X === api_secret; | ||
# - pattern: | | ||
# return api_secret === $X; | ||
# - pattern: | | ||
# return $X === secret; | ||
# - pattern: | | ||
# return secret === $X; | ||
# - pattern: | | ||
# return $X === api; | ||
# - pattern: | | ||
# return api === $X; | ||
# - pattern: | | ||
# return $X == auth_token; | ||
# - pattern: | | ||
# return auth_token == $X; | ||
# - pattern: | | ||
# return $X == token; | ||
# - pattern: | | ||
# return token == $X; | ||
# - pattern: | | ||
# return $X == hash; | ||
# - pattern: | | ||
# return hash == $X; | ||
# - pattern: | | ||
# return $X == password; | ||
# - pattern: | | ||
# return password == $X; | ||
# - pattern: | | ||
# return $X == pass; | ||
# - pattern: | | ||
# return pass == $X; | ||
# - pattern: | | ||
# return $X == apiKey; | ||
# - pattern: | | ||
# return apiKey == $X; | ||
# - pattern: | | ||
# return $X == apiSecret; | ||
# - pattern: | | ||
# return apiSecret == $X; | ||
# - pattern: | | ||
# return $X == api_key; | ||
# - pattern: | | ||
# return api_key == $X; | ||
# - pattern: | | ||
# return $X == api_secret; | ||
# - pattern: | | ||
# return api_secret == $X; | ||
# - pattern: | | ||
# return $X == secret; | ||
# - pattern: | | ||
# return secret == $X; | ||
# - pattern: | | ||
# return $X == api; | ||
# - pattern: | | ||
# return api == $X; | ||
# - pattern: | | ||
# return $X !== auth_token; | ||
# - pattern: | | ||
# return auth_token !== $X; | ||
# - pattern: | | ||
# return $X !== token; | ||
# - pattern: | | ||
# return token !== $X; | ||
# - pattern: | | ||
# return $X !== hash; | ||
# - pattern: | | ||
# return hash !== $X; | ||
# - pattern: | | ||
# return $X !== password; | ||
# - pattern: | | ||
# return password !== $X; | ||
# - pattern: | | ||
# return $X !== pass; | ||
# - pattern: | | ||
# return pass !== $X; | ||
# - pattern: | | ||
# return $X !== apiKey; | ||
# - pattern: | | ||
# return apiKey !== $X; | ||
# - pattern: | | ||
# return $X !== apiSecret; | ||
# - pattern: | | ||
# return apiSecret !== $X; | ||
# - pattern: | | ||
# return $X !== api_key; | ||
# - pattern: | | ||
# return api_key !== $X; | ||
# - pattern: | | ||
# return $X !== api_secret; | ||
# - pattern: | | ||
# return api_secret !== $X; | ||
# - pattern: | | ||
# return $X !== secret; | ||
# - pattern: | | ||
# return secret !== $X; | ||
# - pattern: | | ||
# return $X !== api; | ||
# - pattern: | | ||
# return api !== $X; | ||
# - pattern: | | ||
# return $X != auth_token; | ||
# - pattern: | | ||
# return auth_token != $X; | ||
# - pattern: | | ||
# return $X != token; | ||
# - pattern: | | ||
# return token != $X; | ||
# - pattern: | | ||
# return $X != hash; | ||
# - pattern: | | ||
# return hash != $X; | ||
# - pattern: | | ||
# return $X != password; | ||
# - pattern: | | ||
# return password != $X; | ||
# - pattern: | | ||
# return $X != pass; | ||
# - pattern: | | ||
# return pass != $X; | ||
# - pattern: | | ||
# return $X != apiKey; | ||
# - pattern: | | ||
# return apiKey != $X; | ||
# - pattern: | | ||
# return $X != apiSecret; | ||
# - pattern: | | ||
# return apiSecret != $X; | ||
# - pattern: | | ||
# return $X != api_key; | ||
# - pattern: | | ||
# return api_key != $X; | ||
# - pattern: | | ||
# return $X != api_secret; | ||
# - pattern: | | ||
# return api_secret != $X; | ||
# - pattern: | | ||
# return $X != secret; | ||
# - pattern: | | ||
# return secret != $X; | ||
# - pattern: | | ||
# return $X != api; | ||
# - pattern: | | ||
# return api != $X; | ||
# auxiliary: | ||
# - id: go_lang_observable_timing_init | ||
# patterns: | ||
# - pattern1 | ||
# - pattern: $<INIT> | ||
# filters: | ||
# - variable: INIT | ||
# detection: go_lang_observable_timing_instance | ||
# scope: cursor | ||
# - id: go_lang_observable_timing_instance | ||
# patterns: | ||
# - pattern2 | ||
languages: | ||
- go | ||
metadata: | ||
description: "" | ||
remediation_message: | | ||
## Description | ||
## Remediations | ||
✅ | ||
❌ | ||
## References | ||
- []() | ||
cwe_id: | ||
- 208 | ||
id: go_lang_observable_timing | ||
documentation_url: https://docs.bearer.com/reference/rules/go_lang_observable_timing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
patterns: | ||
- pattern: | | ||
$<KEY1> == $<OTHER> | ||
filters: | ||
- variable: KEY1 | ||
detection: javascript_lang_observable_timing_regex | ||
scope: cursor | ||
- not: | ||
variable: OTHER | ||
detection: javascript_lang_observable_timing_other | ||
scope: cursor | ||
- pattern: | | ||
$<OTHER> == $<KEY1> | ||
filters: | ||
- variable: KEY1 | ||
detection: javascript_lang_observable_timing_regex | ||
scope: cursor | ||
- not: | ||
variable: OTHER | ||
detection: javascript_lang_observable_timing_other | ||
scope: cursor | ||
auxiliary: | ||
- id: javascript_lang_observable_timing_regex | ||
patterns: | ||
- pattern: $<REGEX> | ||
filters: | ||
- variable: REGEX | ||
regex: (?i)\A(password)|hash|(api|auth)?.?(token|secret)\z | ||
|
||
- id: javascript_lang_observable_timing_other | ||
patterns: | ||
- pattern: $<OTHER> | ||
filters: | ||
- variable: OTHER | ||
regex: ^((null)|(undefined)) | ||
|
||
languages: | ||
- javascript | ||
metadata: | ||
description: "Observable Timing Discrepancy" | ||
remediation_message: | | ||
## Description | ||
Observable Timing Discrepancy refers to vulnerabilities arising from attackers being able to observe differences in the time it takes to perform certain operations. | ||
These discrepancies can lead to the exposure of sensitive information, as attackers can use timing analysis to infer secrets based on the execution time of algorithms, particularly during comparisons of user input against secret values. | ||
## Remediations | ||
✅ **Implement Constant Time Algorithms** | ||
Ensure algorithms that process sensitive information, such as password comparisons, execute in constant time to prevent timing attacks. | ||
✅ **Use Built-in Security Features** | ||
Leverage built-in cryptographic libraries that include timing-attack safe functions for comparing secrets. | ||
✅ **Minimize Client-Side Checks** | ||
Avoid sensitive comparisons directly in client-side JavaScript where possible, as the execution environment is more exposed to timing analysis by attackers. | ||
❌ **Avoid Direct Comparisons** | ||
Do not use direct string comparisons for sensitive information that can lead to early function termination based on the first incorrect character. | ||
❌ **Do Not Rely on Execution Time for Logic** | ||
Ensure the application's logic does not change execution paths in a way that could introduce observable timing differences based on user input or secret values. | ||
## Resources | ||
- [CWE-208: Observable Timing Discrepancy](https://cwe.mitre.org/data/definitions/208.html) | ||
- [OWASP Guide to Cryptography](https://owasp.org/www-project-cheat-sheets/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html) | ||
- [MDN Web Docs on SubtleCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) | ||
cwe_id: | ||
- 409 | ||
id: javascript_lang_observable_timing | ||
documentation_url: https://docs.bearer.com/reference/rules/javascript_lang_observable_timing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
const { | ||
createNewInvoker, | ||
getEnvironment, | ||
} = require("../../../helper.js") | ||
const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) | ||
|
||
describe(ruleId, () => { | ||
const invoke = createNewInvoker(ruleId, ruleFile, testBase) | ||
|
||
test("observable_timing", () => { | ||
const testCase = "app.js" | ||
|
||
const results = invoke(testCase) | ||
|
||
expect(results.Missing).toEqual([]) | ||
expect(results.Extra).toEqual([]) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Use bearer:expected javascript_lang_observable_timing to flag expected findings | ||
|
||
// bearer:expected javascript_lang_observable_timing | ||
password == "zDE9ET!TDq2uZx2oM!FD2" | ||
// bearer:expected javascript_lang_observable_timing | ||
"zDE9ET!TDq2uZx2oM!FD2" == password | ||
// bearer:expected javascript_lang_observable_timing | ||
"zDE9ET!TDq2uZx2oM!FD2" === password | ||
// bearer:expected javascript_lang_observable_timing | ||
password == passwordInput | ||
// bearer:expected javascript_lang_observable_timing | ||
hash === verify.toString("base64") | ||
|
||
function isAuthenticated(username, input) { | ||
var user = FetchUserFromDB(username) | ||
if (input.length !== user.token.length) { | ||
return false | ||
} | ||
|
||
// bearer:expected javascript_lang_observable_timing | ||
return input === user.token | ||
} | ||
|
||
if (password !== null) { | ||
} | ||
|
||
// bearer:expected javascript_lang_observable_timing | ||
if (apiToken === "zDE9ET!TDq2uZx2oM!FD2") { | ||
} | ||
|
||
if (inputToken.length !== secretToken.length) { | ||
return false | ||
} |