Mastodon
New gist
Recent
API
Trending
Blog
Guest
Sign Up or Login
Login
Sign Up
New Gist
Syntax Highlighting
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}} <b>ok</b>{%25+endmacro+%25}{{ field(1)|urlize }} Example: https://www.example.com/_hcms/cta?referrerUrl={%25+macro+field%28x%29+%25}http://www.com) {{x}}+<b>ok</b>{%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
Optional Gist Settings
Gist Name/Title:
Category:
None
Cryptocurrency
Cybersecurity
Fixit
Food
Gaming
Haiku
Help
History
Housing
Jokes
Legal
Money
Movies
Music
Pets
Photo
Science
Software
Source Code
Spirit
Sports
Travel
TV
Writing
Syntax Highlighting:
None
Bash
C
C++
C#
CSS
HTML
Java
JavaScript
Lua
Objective C
Perl
PHP
Python
Ruby
JSON
Swift
Markdown
ActionScript
Ada
Apache Log
AppleScript
ASM (NASM)
ASP
Bash
C
C for Macs
CAD DCL
CAD Lisp
C++
C#
ColdFusion
CSS
D
Delphi
Diff
Batch
Eiffel
Fortran
FreeBasic
Game Maker
HTML
INI file
Java
JavaScript
Lisp
Lua
MPASM
MySQL
NullSoft Installer
Objective C
OCaml
Openoffice BASIC
Oracle 8
Pascal
Perl
PHP
Python
QBasic
Robots
Ruby
Scheme
Smarty
SQL
VisualBasic
VB.NET
VisualFoxPro
XML
AutoIt
Blitz Basic
BNF
Erlang
Genero
Groovy
Haskell
Inno Script
Latex
Linden Scripting
MatLab
M68000 Assembler
mIRC
Rails
PL/SQL
Smalltalk
TCL
Z80 Assembler
ABAP
ActionScript 3
APT Sources
Avisynth
Basic4GL
BibTeX
BrainFuck
BOO
CFDG
C Intermediate Language
CMake
COBOL
DCS
DIV
DOT
Email
FO Language
GetText
OpenGL Shading
Ruby Gnuplot
HQ9 Plus
IDL
INTERCAL
IO
Java 5
KiXtart
Clone C
Clone C++
Loco Basic
LOL Code
Lotus Formulas
Lotus Script
LScript
Make
Modula 3
MXML
Oberon 2
OCaml Brief
Oracle 11
Per
PHP Brief
Pic 16
Pixel Bender
POV-Ray
PowerShell
Progress
Prolog
Properties
ProvideX
REBOL
REG
SAS
Scala
Scilab
SdlBasic
Tera Term
thinBasic
T-SQL
TypoScript
VeriLog
VHDL
VIM
Visual Pro Log
WhiteSpace
WHOIS
Winbatch
Xorg Config
XPP
Pawn
4CS
6502 ACME Cross Assembler
6502 Kick Assembler
6502 TASM/64TASS
Motorola 68000 HiSoft Dev
ALGOL 68
autoconf
Autohotkey
Awk
Cuesheet
ChaiScript
Clojure
C++ (with Qt extensions)
E
ECMAScript
Formula One
F#
GAMBAS
GDB
Genie
Go
GwBasic
HicEst
Icon
J
jQuery
Liberty BASIC
Logtalk
MagikSF
MapBasic
MIX Assembler
Modula 2
newLISP
Objeck Programming Language
Oz
Delphi Prism (Oxygene)
Oz
PCRE
Perl 6
OpenBSD PACKET FILTER
Pike
PostgreSQL
PowerBuilder
PureBasic
q/kdb+
RPM Spec
R
SystemVerilog
Vala
Unicon
Vala
XBasic
ZXBasic
UnrealScript
HTML 5
ProFTPd
BASCOM AVR
C: Loadrunner
CoffeeScript
EPC
Falcon
LLVM
PyCon
YAML
FreeSWITCH
ARM
Asymptote
DCL
DCPU-16
Haxe
LDIF
Nagios
Octave
ParaSail
PARI/GP
Python for S60
Rexx
SPARK
SPARQL
StoneScript
UPC
Urbi
Vedit
AIMMS
Chapel
Dart
Easytrieve
ISPF Panel Definition
JCL
Nginx
Nim
PostScript
QML
Racket
RBScript
Rust
SCL
StandardML
VBScript
C (WinAPI)
C++ (WinAPI)
NetRexx
JSON
Swift
SuperCollider
Julia
Blitz3D
BlitzMax
SQF
Puppet
Filemaker
Euphoria
PL/I
Open Object Rexx
Markdown
Kotlin
Ceylon
Arduino
YARA
TypeScript
Mercury
MetaPost
MK-61/52
Phix
Roff Manpage
SSH Config
TeXgraph
Xojo
KSP (Kontakt Script)
GDScript
Godot GLSL
None
Tags:
Gist Exposure:
Public
Unlisted
Private
Gist Expiration:
Never
Burn after read
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Password
Enabled
Disabled
Folder:
(members only)
Burn after read
Create New Gist
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Public Gists
Building a Mortgage Document Classification Model using an LLM Library
Python | 8 hours ago | 18 Views
Reflected XSS and Server-Side Template Injection Found in HubSpot CMS
None | 1 day ago | 465 Views
Installing and Running LM Studio on Ubuntu as a Headless Server
Markdown | 3 days ago | 43 Views
Kaldığın Yerden: A Turkish Love Song
None | 3 days ago | 35 Views
Untitled
None | 3 days ago | 29 Views
oprendszerBashZH
None | 3 days ago | 33 Views
ESP8266 Wi-Fi Module to Control LED using Blynk App
C++ | 3 days ago | 35 Views
Not a member of GistPad yet?
Sign Up
, it unlocks many cool features!
We use cookies for various purposes including analytics. By continuing to use GistPad, you agree to our use of cookies as described in the
Privacy Policy
.
OK, I Understand