GO SSTI

Sl0th Lv4

GO SSTI

SSTI

识别方法

代码中引入了text/template,会导致SSTI漏洞出现

运算符号在{{}}中是非法的,需要使用其他payload,比如占位符号{{.}},如果存在ssti,那么就无回显

信息泄露

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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, "tyskill", "tyskill"}
r.ParseForm()
arg := strings.Join(r.PostForm["name"], "")
tpl1 := fmt.Sprintf(`<h1>Hi, ` + arg + `</h1> Your name is {{ .Name }}`)
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("/string", StringTplExam)
server.ListenAndServe()
}

go通过结构体来类比一个对象,一个子段就是一个对象的属性,模版渲染也支持传入一个结构体的实例来渲染字段,上面代码中,name部分可控,可以仿造{{ .Name}},构造{{.Passw}},得到Passwd字段

user := &User{1, "tyskill", "tyskill"}使用了模版&User因此{{.Passwd}}可以得到它的属性

image-20230413215152150
image-20230413215152150

直接用.可以得到模版的全部内容

image-20230413215255743
image-20230413215255743

防御

拒绝拼接,直接传入.字段名

1
2
3
4
5
6
7
8
9
10
11
12
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)
}

XSS

go模版会打印字符串,如果是xss代码的话,也会直接执行,这个xss是拒绝拼接也无法防御的

1
2
{{"<script>alert(/xss/)</script>"}}
{{print "<script>alert(/xss/)</script>"}}

编码行为

1
2
{{define "T1"}}ONE{{end}}{{template "T1"}}
即{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}
  • {template "name"}} 执行名为name的模板,提供给模板的参数为nil,如模板不存在输出为””
  • {{define "name"}`模板内容`{{end}}}定义一个名为name的模板

这里实际上就是一个我们进行模板的定义,并输出的过程,这样我们就可以顺利的实现XSS了

防御方法

1.内置函数html转义特殊字符

1
2
{{html "<script>alert(/xss/)</script>"}}
{{js "js代码"}}

2.text/template在模版处理阶段还定义template.HTMLEscapeString等转义函数

3.html/template模版包自带转义效果

命令执行&任意文件读取

可以像{{ .Name}}一样调用对象方法,模板内部并不存在可以RCE的函数,所以除非有人为渲染对象定义了RCE或文件读取的方法,不然这个问题是不存在的。

1
2
3
4
5
6
7
8
9
10
11
12
13
func (u *User) System(cmd string, arg ...string) string {
out, _ := exec.Command(cmd, arg...).CombinedOutput()
return string(out)
}

func (u *User) FileRead(File string) string {
data, err := ioutil.ReadFile(File)
if err != nil {
fmt.Print("File read error")
}
return string(data)
}

如果定义了就可以通过{{.System "whoami"}}{{.FileRead "filepath"}}执行

正常程序猿都不会定义这么危险的函数

  • 标题: GO SSTI
  • 作者: Sl0th
  • 创建于 : 2023-03-13 22:43:14
  • 更新于 : 2024-11-11 18:23:06
  • 链接: http://sl0th.top/2023/03/13/GO-SSTI/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论