Skip to content

Commit

Permalink
feat(js): add observable timing
Browse files Browse the repository at this point in the history
  • Loading branch information
cfabianski committed Feb 23, 2024
1 parent eaf98d0 commit 1003a32
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
80 changes: 80 additions & 0 deletions rules/javascript/lang/observable_timing.yml
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
18 changes: 18 additions & 0 deletions tests/javascript/lang/observable_timing/test.js
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([])
})
})
33 changes: 33 additions & 0 deletions tests/javascript/lang/observable_timing/testdata/app.js
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
}

0 comments on commit 1003a32

Please sign in to comment.