codeql
codeql copied to clipboard
Python: Timing attack
A constant-time algorithm should be used for checking the value of info. In other words, the comparison time should not depend on the content of the input, Otherwise, an attacker may be able to implement a timing attacks that may reveal the value of sensitive info
Hi @tausbn , I'm sorry for the delay. you can feel comfortable to review the PR now, let me know if there is a problem with the query.
Hi @ahmed-farid-dev, please ensure all your .ql and .qll files are autoformatted, and that test passes (they currently don't). There is also a problem with your .qhelp, since there needs to be one .qhelp file for each .ql query file.
For testing, see this reference: https://codeql.github.com/docs/codeql-for-visual-studio-code/testing-codeql-queries-in-visual-studio-code/
(to perform autoformatting, use the Format Document command in VS Code -- there is an option to do this every time you save your file)
@ahmed-farid-dev I triggered CI for your latest commit, but there are still problems running the tests due to compilation errors (as highlighted by my previous comment). Please just let me know once you've solved the problems, then I can take a look at the PR :blush:
hi @RasmusWL , you can take a look now.
Hi @tausbn, Tell me if anything i can do to help the test get passe
I think the tests should pass now. I'll proceed with the review.
HI @tausbn , you can run the tests now :+1:
Hi @tausbn, any update ?
Hi @tausbn, any update ?
Hi @ahmed-farid-dev. I'm currently waiting for the Security Lab to finish their analysis of the results for your query. As I understand it, they are currently looking at your other timing attack submission (for Java), and as there is considerable overlap in the approaches used in the two PRs, I will wait on submitting my review until that PR has been assessed.
QHelp previews:
python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qhelp
Timing attack against Hash
Timing Attack is based on the leakage of information by studying how long it takes the system to respond to different inputs. it can be circumvented by using a constant-time algorithm for checking the value of Hash, more precisely, the comparison time should not depend on the content of the input. Otherwise the attacker gains information that is indirectly leaked by the application. This information may then be used for malicious purposes.
Recommendation
Two types of countermeasures can be applied against timing attacks. The first one consists in eliminating timing variations whereas the second renders these variations useless for an attacker. The only absolute way to prevent timing attacks is to make the computation strictly constant time, independent of the input. Use hmac.compare_digest() method to securely check the value of Hash. If this method is used, then the calculation time depends only on the length of input byte arrays, and does not depend on the contents of the arrays. Unlike == is a fail fast check, If the first byte is not equal, it will return immediately.
Example
The following example uses == which is a fail fast check for validating a Hash.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :timing attack Against Hash
"""
import hmac
import hashlib
key = "e179017a-62b0-4996-8a38-e91aa9f1"
msg = "Test"
def sign(pre_key, imsg, alg):
return hmac.new(pre_key, imsg, alg).digest()
def verify(msg, sig):
return sig == sign(key, msg, hashlib.sha256) #bad
The next example use a safe constant-time algorithm for validating a Hash:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :preventing timing attack Against Hash
"""
import hmac
import hashlib
key = "e179017a-62b0-4996-8a38-e91aa9f1"
msg = "Test"
def sign(pre_key, imsg, alg):
return hmac.new(pre_key, imsg, alg).digest()
def verify(msg, sig):
return hmac.compare_digest(sig, sign(key, msg, hashlib.sha256)) #good
References
- Wikipedia: Timing attack.
- hmac.compare_digest() method
- HMAC: RFC 2104
- Common Weakness Enumeration: CWE-208.
python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qhelp
Timing attack against Hash
Timing Attack is based on the leakage of information by studying how long it takes the system to respond to different inputs. it can be circumvented by using a constant-time algorithm for checking the value of Hash, more precisely, the comparison time should not depend on the content of the input. Otherwise the attacker gains information that is indirectly leaked by the application. This information may then be used for malicious purposes.
Recommendation
Two types of countermeasures can be applied against timing attacks. The first one consists in eliminating timing variations whereas the second renders these variations useless for an attacker. The only absolute way to prevent timing attacks is to make the computation strictly constant time, independent of the input. Use hmac.compare_digest() method to securely check the value of Hash. If this method is used, then the calculation time depends only on the length of input byte arrays, and does not depend on the contents of the arrays. Unlike == is a fail fast check, If the first byte is not equal, it will return immediately.
Example
The following example uses == which is a fail fast check for validating a Hash.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :timing attack Against Hash
"""
import hmac
import hashlib
key = "e179017a-62b0-4996-8a38-e91aa9f1"
msg = "Test"
def sign(pre_key, imsg, alg):
return hmac.new(pre_key, imsg, alg).digest()
def verify(msg, sig):
return sig == sign(key, msg, hashlib.sha256) #bad
The next example use a safe constant-time algorithm for validating a Hash:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :preventing timing attack Against Hash
"""
import hmac
import hashlib
key = "e179017a-62b0-4996-8a38-e91aa9f1"
msg = "Test"
def sign(pre_key, imsg, alg):
return hmac.new(pre_key, imsg, alg).digest()
def verify(msg, sig):
return hmac.compare_digest(sig, sign(key, msg, hashlib.sha256)) #good
References
- Wikipedia: Timing attack.
- hmac.compare_digest() method
- HMAC: RFC 2104
- Common Weakness Enumeration: CWE-208.
python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qhelp
Timing attack against header value
A constant-time algorithm should be used for checking the value of sensitive headers. In other words, the comparison time should not depend on the content of the input. Otherwise timing information could be used to infer the header's expected, secret value.
Recommendation
Two types of countermeasures can be applied against timing attacks. The first one consists in eliminating timing variations whereas the second renders these variations useless for an attacker. The only absolute way to prevent timing attacks is to make the computation strictly constant time, independent of the input. Use hmac.compare_digest() method to securely check the secret value. If this method is used, then the calculation time depends only on the length of input byte arrays, and does not depend on the contents of the arrays. Unlike == is a fail fast check, If the first byte is not equal, it will return immediately.
Example
The following example uses == which is a fail fast check for validating the value of sensitive headers.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :preventing timing attack against header value
"""
from flask import Flask
from flask import request
@app.route('/bad')
def bad():
secret = request.headers.get('X-Auth-Token')
if secret == "token":
raise Exception('bad token')
return 'bad'
if __name__ == '__main__':
app.debug = True
app.run()
The next example use a safe constant-time algorithm for validating the value of sensitive headers:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :preventing timing attack against header value
"""
from flask import Flask
from flask import request
import hmac
@app.route('/good')
def good():
secret = request.headers.get('X-Auth-Token')
if not hmac.compare_digest(secret, "token"):
raise Exception('bad token')
return 'good'
if __name__ == '__main__':
app.debug = True
app.run()
References
- Wikipedia: Timing attack.
- hmac.compare_digest() method
- Common Weakness Enumeration: CWE-208.
python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qhelp
Timing attack against secret
Timing Attack is based on the leakage of information of secret parameters by studying how long it takes the system to respond to different inputs. it can be circumvented by using a constant-time algorithm for checking the value of sensitive info, more precisely, the comparison time should not depend on the content of the input. Otherwise the attacker gains information that is indirectly leaked by the application. This information is then used for malicious purposes.
Recommendation
Two types of countermeasures can be applied against timing attacks. The first one consists in eliminating timing variations whereas the second renders these variations useless for an attacker. The only absolute way to prevent timing attacks is to make the computation strictly constant time, independent of the input. Use hmac.compare_digest() method to securely check the value of sensitive info. If this method is used, then the calculation time depends only on the length of input byte arrays, and does not depend on the contents of the arrays. Unlike == is a fail fast check, If the first byte is not equal, it will return immediately.
Example
The following example uses == which is a fail fast check for validating a secret.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :timing attack against sensitive info
"""
from flask import Flask
from flask import request
@app.route('/bad', methods = ['POST', 'GET'])
def bad():
if request.method == 'POST':
password = request.form['pwd']
return password == "test"
if __name__ == '__main__':
app.debug = True
app.run()
The next example use a safe constant-time algorithm for validating a secret:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :preventing timing attack sensitive info
"""
from flask import Flask
from flask import request
import hmac
app = Flask(__name__)
@app.route('/bad', methods = ['POST', 'GET'])
def bad():
if request.method == 'POST':
password = request.form['pwd']
return hmac.compare_digest(password, "1234")
if __name__ == '__main__':
app.debug = True
app.run()
References
- Wikipedia: Timing attack.
- hmac.compare_digest() method
- Common Weakness Enumeration: CWE-208.
python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.qhelp
Timing attack against secret
Timing Attack is based on the leakage of information of secret parameters by studying how long it takes the system to respond to different inputs. it can be circumvented by using a constant-time algorithm for checking the value of sensitive info, more precisely, the comparison time should not depend on the content of the input. Otherwise the attacker gains information that is indirectly leaked by the application. This information is then used for malicious purposes.
Recommendation
Two types of countermeasures can be applied against timing attacks. The first one consists in eliminating timing variations whereas the second renders these variations useless for an attacker. The only absolute way to prevent timing attacks is to make the computation strictly constant time, independent of the input. Use hmac.compare_digest() method to securely check the value of sensitive info. If this method is used, then the calculation time depends only on the length of input byte arrays, and does not depend on the contents of the arrays. Unlike == is a fail fast check, If the first byte is not equal, it will return immediately.
Example
The following example uses == which is a fail fast check for validating a secret.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :timing attack against sensitive info
"""
from flask import Flask
from flask import request
@app.route('/bad', methods = ['POST', 'GET'])
def bad():
if request.method == 'POST':
password = request.form['pwd']
return password == "test"
if __name__ == '__main__':
app.debug = True
app.run()
The next example use a safe constant-time algorithm for validating a secret:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Desc :preventing timing attack sensitive info
"""
from flask import Flask
from flask import request
import hmac
app = Flask(__name__)
@app.route('/bad', methods = ['POST', 'GET'])
def bad():
if request.method == 'POST':
password = request.form['pwd']
return hmac.compare_digest(password, "1234")
if __name__ == '__main__':
app.debug = True
app.run()
References
- Wikipedia: Timing attack.
- hmac.compare_digest() method
- Common Weakness Enumeration: CWE-208.