Title: Reflected XSS + Server-Side Template Injection in HubSpot CMS Affecting Thousands of Websites Author: Mohamed Haroun Discovery Date: January 2018 Impact: More than 10,000 websites affected ---------------------------------------------------------------------------------------------- Back in early 2018, while performing a routine security assessment, I discovered one of my favorite bugs ever. The vulnerability affected HubSpot CMS, a popular platform used by thousands of companies to host landing pages, marketing content, and call-to-action (CTA) widgets. During my testing, I noticed the path: /_hcms/ This indicated that the page was being rendered by HubSpot’s backend services. After digging deeper, I focused on a specific endpoint: /_hcms/cta This endpoint included a parameter named: referrerUrl The parameter was not properly sanitized, which opened the door for two serious vulnerabilities: 1. Server-Side Template Injection (SSTI) - Partly 2. Reflected Cross-Site Scripting (XSS) --- Server-Side Template Injection (SSTI) Server-Side Template Injection happens when user-controlled input is placed inside a server-side template without proper sanitization. If interpreted as executable code, an attacker may run their own logic on the server. To test this, I simply passed: ?referrerUrl={{7*7}} The server responded with: 49 This confirmed that the input was being evaluated. I tried pushing the limits using template loops like: %for c in [1,2,3]%{{c,c,c}}% endfor % However, the server blocked some payloads and returned errors such as: Malformed escape pair at index... Illegal character in query at index... Even though full template execution was restricted, the evaluation behavior confirmed the presence of template parsing — a strong indicator of SSTI. --- Reflected XSS via Template Injection With help from Frans Rosén, I was able to break out of the template and achieve XSS. Working payload: {%25+macro+field(x)+%25}[http://www.com](http://www.com) {{x}} ok{%25+endmacro+%25}{{ field(1)|urlize }} Example: https://www.example.com/_hcms/cta?referrerUrl={%25+macro+field%28x%29+%25}http://www.com) {{x}}+ok{%25+endmacro+%25}{{+field(1)%7curlize+}} This proved that: * The template executed macros * User input controlled the output From there, generating JavaScript execution was possible. --- Final XSS Payload {%25+macro+field()+%25}moc.okok//:ptth//)niamod.tnemucod(trela:tpircsavaj=daolno+gvshttp://http:""//{%25+endmacro+%25}{{+field(1)%7curlize%7creverse%7curlize%7creverse%7curlize%7creverse+}} This payload achieved full reflected XSS on HubSpot-powered websites. --- Affected Websites Some confirmed affected websites: www.hubspot.com blog.bugcrowd.com cashflows.com pages.bugcrowd.com www.itbit.com However, based on HubSpot’s customer base, the total exposure exceeded 10,000+ websites. --- Timeline 22 January 2018 — Report submitted 22 January 2018 — HubSpot Security set priority to P2 23 January 2018 — Issue resolved Reward: 20 points HubSpot’s security team responded quickly and professionally. --- Why This Bug Was Special This bug was one of my favorites for many reasons: * It started with a small overlooked parameter in a CMS path * It escalated from SSTI partly to full XSS * It impacted massive infrastructure at scale * It reinforced the importance of sanitizing template inputs