Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

NullCheck

NullCheck is a critical (CVSS 9.1 max) bundle of vulnerabilities I discovered around the beginning of July, towards the middle of July, reported on the 6th July at 2AM & 16th July at 8PM to the GoogleVRP, regarding Google's ProjectShield. Now, ProjectShield is a free (if eligible) service enabling DDoS protection for:

  • Independent media and investigative journalism outlets
  • Election monitoring and human rights groups
  • Non-profit arts and sciences initiatives
  • Political organizations and democratic campaigns
  • Marginalised community defense groups

The reason its important to mention who is eligible for ProjectShield, is due to how the vulnerabilities affect users, and how they can be utilised by threat actors for very malicious purposes, as follows:

  1. Malicious file storage

    • Attacker can upload arbitrary files (executable, scripts, payloads) to Google's ProjectShield database
    • Files persist indefinitely with valid Salesforce record IDs
  2. Supply chain risk

    • ProjectShield protects nonprofits and activists from DDoS attacks. These vulnerabilities, collectively, can damage that protection.
    • Compromise of ProjectShield infrastructure could affect protected organizations
    • Malicious files could be used as pivot point for further attacks
  3. Scale of attack

    • No rate limiting observed - attacker can create thousands of records per minute, which enables high-scale malware attacks as a single script can i.e.,automatically change a CNC beaconing destination
    • Can upload files of arbitrary size
    • Can enumerate and download existing Attachment records via same Aura endpoint
    • Potential for mass data exfiltration from ProjectShield database

Initial Arbitrary File Upload vulnerability

Google's ProjectShield runs multiple Salesforce instances, but for this particular area of the write-up we're going to focus on https://help.projectshield.google. The Aura framework allows unauthenticated users to create and upload files to the Attachment object. The vulnerability exists due to improper permission configuration on the guest-accessible recordGlobalValueProvider.RecordGvpController Aura service component.

Salesforce can, a lot of the time, mean literally anything. However, in this context that is only true on the surface - as the help. subdomain simply looks like your average "Contact us" / FAQ page, but when you look a little deeper, that is but the case.

help.projectshield.google

I got curious. So, I started off by first extracting the Aura context (CSRF Token and FWUID):

extracting aura context

Response (real FWUID redacted):

fwuid response

Nice. Decided to skip all the basic boxes I usually tick off with Salesforce auditing (usually not the best idea, this can waste a lot of time, going backwards) and go straight to testing the Attachment apiName with ACTION$saveRecord. This should not give a 200 OK, and certainly no response body, right? So, I craft a JSON payload for file upload. The body field contains Base64-encoded file content - example below decodes to "TEST FILE CONTENT":

crafted payload file

Looks good, now its time to actually send the request. This may give a 200 OK response, I said to myself doubtingly, replacing <PAYLOAD_JSON> with the crafted payload from above, and <FWUID_FROM_STEP_1> with the actual Framework UID:

exploit request

Wow. Okay, it actually worked. The server actually sent a response with both 200 status code and response body. Hoping this wasn't a false positive, I checked the actual body, and of course, there it is.

real ID replaced successful exploit response

What this proves

  • state: SUCCESS confirms the actual Salesforce host accepted the request
  • id: 00P5b000001ABCDE is a valid Salesforce Attachment record ID
  • Record is persisted in production database (not temporary)
  • File content is stored in the Body field
  • HTTP 200 confirms no errors

Now all I had to do was confirm persistence, report, and wait. If you understand this write-up, then you've probably noticed that we haven't gotten to any auth bypass, but that's a key part of the vulnerability. Here is where it comes in. Its a very simple auth bypass that's commonly found in a lot of:

  • New MCP servers
  • AI generated middlewares
  • Beginner login-flow setups

It is, of course, the guest session ID. So we can either retrieve the file via Salesforce DetailController:

real ID replaced detailcontroller curl

Or directly via Aura getRecord:

real ID replaced aura getrecord

And so, I reported the vulnerability, and waited for a response.

report

Note: Don't do this when reporting a vulnerability

The same day I uploaded the initial vulnerability, I had realised I uploaded the completely wrong scan log to the VRP without double-checking. This scan log was for multiple .gov websites that had the same vulnerability as ProjectShield, that I had planned to report to the U.S. Department of State the same day. So, quickly, I left a comment on my report apologising for the mishap and explaining. Lesson learned, always double-check your reports

dont do this

Between then and 16th July 4PM, I had 2 comments to read. One, on 13th July 2PM mentioning that based upon their initial assessment, "it seems this issue is not severe enough to qualify for a reward. However, the VRP panel will take a closer look at this report at their next meeting." I thought "eh thats not a total rejection," so I continued waiting. On 16th July 4PM, I received a notification from the buganizer-system, the following is what I read:

no reward

RIP. No financial reward. I decided instead of pouting and being bummed theres no financial reward, I'd attempt to escalate. Boy was that a good idea.

Escalation leading to 3 more vulnerabilities (CVSS 9.1)

I noticed that in previous scans over ProjectShield I had also caught another Salesforce instance, at https://support.projectshield.withgoogle.com. I cannot believe I missed this, seriously.

So, upon digging, I noticed I wasn't only able to access ACTION$saveRecord (write access,) but also ACTION$getRecord/getItems (read access.)

vulnerable controllers

In my repport, I highlighted that, while the original report focused strictly on guest-creatable Attachment uploads, this addition shows that unauthenticated users have write access to eight distinct Salesforce tables (including User and Chatter FeedItem tables) and unauthenticated read/download access to internal documents, workflow tracking items, and tenant infrastructure configuration.

Unauthenticated Record Creation (8 objects writable)

This particular vulnerability contains 7 parts, as follows:

seven parts

The first part, User (005), allows unauth users to insert new user records, which enables record injection and backdoor profile creation. When replacing <VULNERABLE_PROFILE_ID>, Salesforce attempts to assign that profile to the newly created user record. cURL command below:

005

Second part, ContentVersion (068), as you can see from the screenshot showing the seven parts, allows juploading arbitrary files utilising the modern Salesforce Files architecture - replacing <BASE64_ENCODED_PAYLOAD> with the desired payload, malware.exe with desired file name, and Malicious_Payload with the desired title:

068

Chatter Feed Spam via FeedItem (0D5), replace <TARGET_RECORD_OR_USER_ID> with the target record or User ID & replace Body value with whatever is desired, you get the point:

0D5

Attachment Creation (00P):

00P

With ContenDocumentLink (06A), the request attempts to link an existing ContentDocument (such as a file uploaded via ContentVersion, <CONTENT_DOCUMENT_ID>) to a target record (e.g., a specific User, Case, or Account, <TARGET_RECORD_ID>), changing file visibility (AllUsers):

06A

ContentNote (069) & Note (002):

069 002

Now, ObjectRelatedUrl (0zC) is an interesting one, as it allows you to inject a custom link or URL entry associated with a specific object, enabling phishing, social engineering, and defacement attacks on a real Google page:

0zC

Unauthenticated Document & Workflow Exfiltration (160+ records exposed)

This vulnerability allowed you to query and extract internal Salesforce CRM records. By targeting the ACTION$getRecord and ACTION$getItems methods, bypassing restrictions to retrieve corporate files, internal workflows, and user directory information is made trivial.

ContentVersion & ContentDocument Retrieval:

cvcd

Extracting internal workflows via ProcessInstanceWorkitem, showing active internal approval workflows, queues, and operational transit states, which exposes internal processes and pending company actions:

processinstanceworkitem

If you've dealt with Salesforce auditing before, you know that Knowledge__kav is usually public, and just FAQ stuff for support, so it isn't much impact, so I have refrained from putting it here.

Internal Infrastructure disclosed

Making a guest call to ACTION$getConfigData returns the internal Salesforce routing domains, such as:

  • defaultOrgDomain
  • setupOrgOrigin
  • vfDomain
  • lightningOrgOrigin

getconfigdata

Active Session JWT and pre-generated CSRF disclosed

Guest requests retrieve a pre-generated CSRF token and a valid JWT token representing guest roles ['gud:0050b000005eOKTAA2'] allowing the authorisation bypass.

About

Critical bundle of vulnerabilities for Google's ProjectShield

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors