generated from ossf/project-template
-
Notifications
You must be signed in to change notification settings - Fork 184
CWE-755 and CWE-532 #647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
CWE-755 and CWE-532 #647
Changes from 8 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
5dd8ddc
CWE-755 and CWE-732
BartKaras1128 275b4d5
Updated README.md
BartyBoi1128 6fbc20f
Update README.md
BartyBoi1128 1011ea2
Update README.md
BartyBoi1128 e5dc2f6
Update README.md
BartyBoi1128 ab142f6
Merge branch 'ossf:main' into LoggingBranch
BartyBoi1128 6e879b3
Merge branch 'ossf:main' into LoggingBranch
BartyBoi1128 59d06fc
Update main readme.md to contain links to CWE-532 and CWE-755
BartyBoi1128 e41d6d5
Updated CWE-532 README.md
BartyBoi1128 a3dde75
Adding licenses on top of compliant01.py
BartyBoi1128 d95908d
Adding licenses on top of compliant02.py
BartyBoi1128 b6fbccb
Added licenses on top of example01.py
BartyBoi1128 16176b0
Added licenses on top of noncompliant01.py
BartyBoi1128 506e6da
Added licenses on top of noncompliant02.py
BartyBoi1128 c650b8e
Cosmetic changes to CWE-755 README.md
BartyBoi1128 59c0fe2
Added licenses on top of complian01.py (CWE-755)
BartyBoi1128 f3dbcaf
Added licenses on top of complian02.py (CWE-755)
BartyBoi1128 9c8d660
Added licenses on top of noncompliant01.py (CWE-755)
BartyBoi1128 23bac1d
Added licenses on top of noncompliant02.py (CWE-755)
BartyBoi1128 da2cb03
Added licenses on top of noncompliant03.py (CWE-755)
BartyBoi1128 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
233 changes: 233 additions & 0 deletions
233
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/README.md
This file contains hidden or 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,233 @@ | ||
# CWE-532: Insertion of Sensitive Information into Log File | ||
|
||
Do not log any sensitive information such as passwords or credit card numbers. Encrypt or anonymize personal information such as user names, and date of birth in plain text. | ||
|
||
Logging is crucial for tasks like debugging, forensic analysis, and the general management of various incidents, however, it poses significant challenges when it comes to personal information and sensitive information. | ||
|
||
National authorities have fines for data protection violations such as: | ||
|
||
* California Consumer Privacy Act (CCPA) USA [CCPA DIVISION 3. OBLIGATIONS [1427 - 3273.16]](https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=CIV§ionNum=1798.150) | ||
* General Data Protection Regulation (GDPR) [Fines / Penalties - General Data Protection Regulation (GDPR) (gdpr-info.eu)](https://gdpr-info.eu/issues/fines-penalties/) | ||
|
||
Cross-border data transfer regulations limit what type of data can be transferred across borders even within a single company or organization such as the [Rules on international data transfers - European Commission (europa.eu)](https://commission.europa.eu/law/law-topic/data-protection/international-dimension-data-protection/rules-international-data-transfers_en) | ||
|
||
Software applications often offer different levels of data protection. Certain data, such as access times, can be logged without concern. Other data can be logged but should be accessible only to specific administrators. Sensitive information, such as credit card numbers, should be logged only in encrypted form, while passwords should never be logged. [[SEI CERT 2021 FIO13-J. Do not log sensitive information outside a trust boundary]](https://wiki.sei.cmu.edu/confluence/display/java/FIO13-J.+Do+not+log+sensitive+information+outside+a+trust+boundary) | ||
|
||
## Noncompliant Code Example (Logging) | ||
|
||
In the `noncompliant01.py` code example the user is asked to input sensitive information during login, and the entered information is logged. | ||
|
||
In a real-world scenario, the logging data printed by the `noncompliant01.py` would have to be forwarded to a central logging system. | ||
|
||
Storing or displaying a password typically exposes it to a wider audience and must be avoided. | ||
|
||
*[noncompliant01.py](noncompliant01.py):* | ||
|
||
```py | ||
""" Non-compliant Code Example """ | ||
|
||
import logging | ||
|
||
|
||
def login_user(username, password, security_question): | ||
"""Function to login user with username password, and security question""" | ||
logging.info( | ||
"User %s login attempt: password=%s, security answer=%s", | ||
username, password, security_question | ||
) | ||
|
||
# Continue to other login functionality | ||
|
||
|
||
def main(): | ||
"""Main function showing login functionality""" | ||
logger = logging.getLogger() | ||
logger.setLevel(logging.INFO) | ||
username = input("Enter your username: ") | ||
password = input("Enter your password: ") | ||
security_question = input("What is the name of your favorite pet?: ") | ||
login_user(username, password, security_question) | ||
|
||
|
||
main() | ||
``` | ||
|
||
## Example Solution | ||
|
||
The `example01.py` solution uses a custom filter in Python's logging module to automatically mask sensitive data in the logs. While this is a good solution for central handling in large software project it does require that all modules use the same string such as `password=`, variation's such as `pass=` or pass: won't work and continue to print the plain text password. | ||
|
||
*[example01.py](example01.py):* | ||
|
||
```py | ||
""" Code Example """ | ||
|
||
import logging | ||
import re | ||
|
||
|
||
class RedactingFilter(logging.Filter): | ||
"""Function to redact any sensitive information from getting logged""" | ||
def filter(self, record): | ||
message = record.getMessage() | ||
|
||
# Perform redactions on copy of message | ||
message = re.sub(r"password=\S+", "password=REDACTED", message) | ||
message = re.sub(r"security_question_answer=\S+", | ||
"security_question_answer=REDACTED", message) | ||
|
||
record.msg = message | ||
record.args = () # Clear args to prevent further formatting attempts | ||
|
||
return True | ||
|
||
|
||
def login_user(username, password, security_question): | ||
"""Function to login user with username password, and security question""" | ||
logging.info( | ||
"User %s login attempt: password=%s, security_question_answer=%s", | ||
username, | ||
password, | ||
security_question, | ||
) | ||
|
||
# Continue to other login functionality | ||
|
||
|
||
def main(): | ||
"""Main function showing login functionality""" | ||
logger = logging.getLogger() | ||
logger.setLevel(logging.INFO) | ||
|
||
# Add the custom filter to the logger | ||
redacting_filter = RedactingFilter() | ||
logger.addFilter(redacting_filter) | ||
username = input("Enter your username: ") | ||
password = input("Enter your password: ") | ||
security_question = input("What is the name of your favorite pet?: ") | ||
|
||
login_user(username, password, security_question) | ||
|
||
|
||
main() | ||
``` | ||
|
||
## Compliant Solution (Logging) | ||
|
||
The `compliant01.py` solution doesn't log any sensitive information in the first place, which is a more ideal solution and position to be in. Instead of trying to conceal logged strings at a later stage, control over "classification" is decided during the collection/creation of the data. | ||
|
||
*[compliant01.py](compliant01.py):* | ||
|
||
```py | ||
""" Compliant Code Example """ | ||
|
||
import logging | ||
|
||
|
||
def login_user(username, password, security_question): | ||
"""Function to login user with username password, and security question""" | ||
logging.info("User %s login attempt", username) | ||
|
||
# Continue to other login functionality | ||
|
||
|
||
def main(): | ||
"""Main function showing login functionality""" | ||
logger = logging.getLogger() | ||
logger.setLevel(logging.INFO) | ||
username = input("Enter your username: ") | ||
password = input("Enter your password: ") | ||
security_question = input("What is the name of your favorite pet?: ") | ||
login_user(username, password, security_question) | ||
|
||
|
||
main() | ||
``` | ||
|
||
## Non-Compliant Code Example (Debugging) | ||
|
||
For security purposes, sensitive information should never be printed to the console in log messages (for instance, a passenger's age). In Python's logging module, there are five logging levels: | ||
|
||
* `DEBUG` | ||
* `INFO` | ||
* WARNING (default) | ||
* ERROR | ||
* CRITICAL | ||
BartyBoi1128 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
If we set the level to DEBUG or INFO we will see the info and debug logs being printed to the console. | ||
The `noncompliant02.py` code has the log level set to DEBUG is causing the customer's address to appear in the console. | ||
BartyBoi1128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
*[noncompliant02.py](noncompliant02.py):* | ||
|
||
```py | ||
""" Non-compliant Code Example """ | ||
|
||
import logging | ||
|
||
|
||
def process_order(address): | ||
"""Function for processing some online order""" | ||
logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', | ||
level=logging.DEBUG) | ||
logger = logging.getLogger(__name__) | ||
logger.info("Initial logging level: %s", | ||
logging.getLevelName(logger.getEffectiveLevel())) | ||
logger.debug("Processing order for address: %s", address) | ||
|
||
# Continue to process the order. | ||
|
||
|
||
process_order("10 Grafton Street") | ||
``` | ||
|
||
## Compliant Solution (Debugging) | ||
|
||
In the `compliant02.py` solution we set the log level to INFO , this ensures that only Info logs will get outputted to the console. The log level should only be set to DEBUG when the code is not on a live deployment. This configuration should be managed at the service or deployment level, not within individual code files. | ||
|
||
*[compliant02.py](compliant02.py):* | ||
|
||
```py | ||
""" Compliant Code Example """ | ||
|
||
import logging | ||
|
||
|
||
def process_order(address): | ||
logging.basicConfig( | ||
format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO | ||
) | ||
logger = logging.getLogger(__name__) | ||
|
||
logger.info("Initial logging level: %s", logger.getEffectiveLevel()) | ||
|
||
logger.debug("Processing order for address: %s", address) | ||
|
||
# Continue to process the order. | ||
|
||
|
||
process_order("10 Grafton Street") | ||
``` | ||
|
||
## Related Guidelines | ||
|
||
||| | ||
|:---|:---| | ||
|[SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java?src=breadcrumbs)|[FIO13-J. Do not log sensitive information outside a trust boundary - SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/FIO13-J.+Do+not+log+sensitive+information+outside+a+trust+boundary)| | ||
|[MITRE CWE Base](http://cwe.mitre.org/)|[CWE-359](http://cwe.mitre.org/data/definitions/359.html), Privacy Violation| | ||
|[MITRE CWE Base](http://cwe.mitre.org/)|[CWE-532](http://cwe.mitre.org/data/definitions/532.html), Information Exposure through Log Files| | ||
|[MITRE CWE Pillar](http://cwe.mitre.org/)| [CWE-664](https://cwe.mitre.org/data/definitions/664.html), Improper Control of a Resource Through its Lifetime| | ||
|[RFC](https://www.rfc-editor.org/)| [RFC 5424: The Syslog Protocol](https://www.rfc-editor.org/rfc/rfc5424.html)| | ||
|
||
## Automated Detection | ||
|
||
|Tool|Version|Checker|Description| | ||
|:----|:----|:----|:----| | ||
|[Pylint](https://pylint.pycqa.org/)|2023.10.1|[W1203:logging-fstring-interpolation](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/logging-fstring-interpolation.html)|Use lazy % formatting in logging functions| | ||
|
||
## Biblography | ||
|
||
||| | ||
|:---|:---| | ||
|(Python Software Foundation 2023)|[logging - Logging facilty for Python](https://docs.python.org/3/library/logging.html) [accessed 11 May 2023]| | ||
|California Consumer Privacy Act (CCPA) USA|[CCPA DIVISION 3. OBLIGATIONS [1427 - 3273.16]](https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=CIV§ionNum=1798.150) [accessed 16 October 2024]| | ||
|General Data Protection Regulation (GDPR)|[Fines / Penalties - General Data Protection Regulation (GDPR) (gdpr-info.eu)](https://gdpr-info.eu/issues/fines-penalties/) [accessed 16 October 2024]| | ||
|European Commission International Data Protection|[Rules on international data transfers](https://commission.europa.eu/law/law-topic/data-protection/international-dimension-data-protection/rules-international-data-transfers_en) [accessed 16 October 2024]| |
23 changes: 23 additions & 0 deletions
23
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant01.py
This file contains hidden or 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,23 @@ | ||
""" Compliant Code Example """ | ||
BartyBoi1128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import logging | ||
|
||
|
||
def login_user(username, password, security_question): | ||
"""Function to login user with username password, and security question""" | ||
logging.info("User %s login attempt", username) | ||
|
||
# Continue to other login functionality | ||
|
||
|
||
def main(): | ||
"""Main function showing login functionality""" | ||
logger = logging.getLogger() | ||
logger.setLevel(logging.INFO) | ||
username = input("Enter your username: ") | ||
password = input("Enter your password: ") | ||
security_question = input("What is the name of your favorite pet?: ") | ||
login_user(username, password, security_question) | ||
|
||
|
||
main() |
20 changes: 20 additions & 0 deletions
20
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant02.py
This file contains hidden or 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,20 @@ | ||
""" Compliant Code Example """ | ||
BartyBoi1128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import logging | ||
|
||
|
||
def process_order(address): | ||
"""Function for processing some online order""" | ||
logging.basicConfig( | ||
format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO | ||
) | ||
logger = logging.getLogger(__name__) | ||
|
||
logger.info("Initial logging level: %s", logger.getEffectiveLevel()) | ||
|
||
logger.debug("Processing order for address: %s", address) | ||
|
||
# Continue to process the order. | ||
|
||
|
||
process_order("10 Grafton Street") |
50 changes: 50 additions & 0 deletions
50
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/example01.py
This file contains hidden or 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,50 @@ | ||
""" Code Example """ | ||
BartyBoi1128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import logging | ||
import re | ||
|
||
|
||
class RedactingFilter(logging.Filter): | ||
"""Function to redact any sensitive information from getting logged""" | ||
def filter(self, record): | ||
message = record.getMessage() | ||
|
||
# Perform redactions on copy of message | ||
message = re.sub(r"password=\S+", "password=REDACTED", message) | ||
message = re.sub(r"security_question_answer=\S+", | ||
"security_question_answer=REDACTED", message) | ||
|
||
record.msg = message | ||
record.args = () # Clear args to prevent further formatting attempts | ||
|
||
return True | ||
|
||
|
||
def login_user(username, password, security_question): | ||
"""Function to login user with username password, and security question""" | ||
logging.info( | ||
"User %s login attempt: password=%s, security_question_answer=%s", | ||
username, | ||
password, | ||
security_question, | ||
) | ||
|
||
# Continue to other login functionality | ||
|
||
|
||
def main(): | ||
"""Main function showing login functionality""" | ||
logger = logging.getLogger() | ||
logger.setLevel(logging.INFO) | ||
|
||
# Add the custom filter to the logger | ||
redacting_filter = RedactingFilter() | ||
logger.addFilter(redacting_filter) | ||
username = input("Enter your username: ") | ||
password = input("Enter your password: ") | ||
security_question = input("What is the name of your favorite pet?: ") | ||
|
||
login_user(username, password, security_question) | ||
|
||
|
||
main() |
26 changes: 26 additions & 0 deletions
26
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant01.py
This file contains hidden or 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,26 @@ | ||
""" Non-compliant Code Example """ | ||
BartyBoi1128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import logging | ||
|
||
|
||
def login_user(username, password, security_question): | ||
"""Function to login user with username password, and security question""" | ||
logging.info( | ||
"User %s login attempt: password=%s, security answer=%s", | ||
username, password, security_question | ||
) | ||
|
||
# Continue to other login functionality | ||
|
||
|
||
def main(): | ||
"""Main function showing login functionality""" | ||
logger = logging.getLogger() | ||
logger.setLevel(logging.INFO) | ||
username = input("Enter your username: ") | ||
password = input("Enter your password: ") | ||
security_question = input("What is the name of your favorite pet?: ") | ||
login_user(username, password, security_question) | ||
|
||
|
||
main() |
18 changes: 18 additions & 0 deletions
18
docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant02.py
This file contains hidden or 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 @@ | ||
""" Non-compliant Code Example """ | ||
BartyBoi1128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import logging | ||
|
||
|
||
def process_order(address): | ||
"""Function for processing some online order""" | ||
logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', | ||
level=logging.DEBUG) | ||
logger = logging.getLogger(__name__) | ||
logger.info("Initial logging level: %s", | ||
logging.getLevelName(logger.getEffectiveLevel())) | ||
logger.debug("Processing order for address: %s", address) | ||
|
||
# Continue to process the order. | ||
|
||
|
||
process_order("10 Grafton Street") |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.