CWE-359.2: Exposure of Private Personal Information to an Unauthorized Actor
Plugin ID
359.2
Vulnerability Description
Exposure of Private Personal Information (PII) to an unauthorized actor (United States social security number)
The target application was found to return social security number (SSN) information in the response. Organizations
found returning such information may be in violation of (United States) state or federal laws and may face stiff penalties.
Remediation Text
PII such as social security numbers should never be directly returned to the user. The majority of the information
should masked except the last few digits or characters of the identifier. For example, social security numbers
only be displayed with the last four digits: `***-**-1234`. Ensure this masking is done on the server
and only then send the masked data back to the client. Do not rely on client side javascript or other methods
to mask these values as the data could still be intercepted or unmasked.
Additionally, social security numbers should never be stored un-encrypted in files or databases.
External Links
- name: "OWASP Top 10 A3 2017 - Sensitive Data Exposure"
- url: "https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure"
- name: "CWE"
- url: "https://cwe.mitre.org/data/definitions/359.html"
- name: "Privacy Act (CMPPA)"
- url: "https://www.ssa.gov/dataexchange/privacyinfo.html"
Payloads
Payload YAML Details: https://gitlab.com/gitlab-org/security-products/dast-cwe-checks/-/blob/add_359/checks/359/359.2.yaml
Specification
Matching Social Security Numbers requires a number of pre-processing steps to be able to successfully match and reduce false positives. For performance and accuracy, we should only inspect responses that:
- Have a response body
- Have the content type of: text/xml, text/html, text/csv, application/json.
When analyzing a valid response that meets the above criteria, it is recommended to scan over each individual line of the response. This can be done with bufio.NewScanner([]byte input))
.
For each line, strip all space ' '
characters from the line: replacer := strings.NewReplacer(" ", "")
. This helps reduce the regular expression complexity required to match SSNs.
Unfortunately Go's regex system does not support negative lookahead checks, which in this case makes our jobs a bit tougher. In the interest of reducing false positives attempt to match using the following regex:
var ssnRe = regexp.MustCompile(`\d{3}-\d{2}-\d{4}`)
Note we are requiring social security numbers to be separated by '-'
here, this is to reduce false positives.
If a match is found, process the potential match further by:
- Ensuring no 'group' has all zeros, such as:
000-XX-XXXX
,XXX-00-XXXX
,XXX-XX-0000
. - Ensuring the first group does not contain 666 :devil:
666-XX-XXXX
- Ensuring the first group does not contain numbers between 900 and 999:
9YY-XX-XXXX
If the number passes the above three checks (e.g. they do not match those patterns) report the finding and stop processing the response any further.
Known Limitations
This spec does not attempt to find all variations, sites may split SSNs by fields <td>123</td><td>45</td><td>4652</td>
in which case we would not match. However the extra processing required most likely makes this not worth it. If we get reports of false negatives we can re-visit this decision. Additionally, we will not match SSNs in the format of XXX XX XXXX, this is due to high chance of creating a false positive.
Performance considerations
As we've seen regex's can end up causing lots of CPU cycles. Unfortunately since these are just numbers we can not use the string literal trick here. It might be worth limiting the number of iterations of lines we process. 65536 Lines "seems" like a good number to set a limit on, but it is up to the engineers discretion to set a hard limit.
Further reading:
How does this happen? Much like credit cards, it's usually poor server side masking, or dumps that is the culprit. Why is this important (for non-US citizens). US Social Security numbers are extremely powerful credentials that can allow malicious actors to assume the identity of the victim. This allows them to create new credit cards under their name, file fradulent tax reports to get refunds and much more. It's also really really hard (and extremely annoying) to get your identity back after it's been stolen. Take it from me (it happened to a relative) and they are still getting alerts 10+ years later.
Flow Chart for 359.1 PII (CC#s)
Expand Flow Chart
graph TD
Entry[Call matcher] --> HasResponseBody{Has response body > 0 ?};
HasResponseBody -- No --> DONE[StopProcessing]
HasResponseBody -- Yes --> IsValidResponseType{Valid response type html/csv/text/json etc}
IsValidResponseType -- No --> DONE[StopProcessing]
IsValidResponseType -- Yes --> Each[Each Line in response]
Each --> StripChars[Strip ' ']
StripChars --> MatchesRegex{Matches SSN Regex?}
MatchesRegex -- Yes --> PassesValidationCheck{Passes Validation Check: no 000, 900-999?}
PassesValidationCheck -- Yes --> Report[Report Finding]
Report --> DONE[StopProcessing]
Implementation Plan
-
Add matcher to Browser Based DAST scanner -
Upgrade scanner in DAST and deploy -
Regenerate check documentation to include 359.2