forked from yahoo/webseclab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprocess.go
141 lines (131 loc) · 4.12 KB
/
process.go
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2015, Yahoo Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package webseclab
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"net/url"
"strings"
)
func DoLabTestStandard(w http.ResponseWriter, r *http.Request) *LabResp {
// split r.URL.RawQuery into a param map
rawParams := make(map[string][]string)
ParseRawQuery(rawParams, r.URL.RawQuery)
input := &InData{}
inputRaw, ok := rawParams["in"]
if ok && len(inputRaw) > 0 {
input.InRaw = inputRaw[0]
unesc, err := url.QueryUnescape(input.InRaw)
if err != nil {
fmt.Printf("ERROR in url.QueryUnescape on %s\n", input.InRaw)
}
input.In = unesc
}
err := DoTemplate(w, r.URL.Path, input)
if err != nil {
httpcode := http.StatusInternalServerError
log.Printf("Error returned from DoTemplate: %s\n", err)
if _, ok := err.(ErrNotFound); ok {
httpcode = http.StatusNotFound
}
return &LabResp{Err: err, Code: httpcode}
}
return &LabResp{Err: nil, Code: http.StatusOK}
}
type ErrNotFound struct {
text string
}
func NewErrNotFound(text string) (e ErrNotFound) {
e = ErrNotFound{text: text}
return
}
func (e ErrNotFound) Error() string {
return e.text
}
// DoTemplate opens the template file and processes the template with the passed input
// if the URL Path ends with ".ok", it uses an HTML context-escaped template
// (html/template - safe version), otherwise - text/template (exploitable)
func DoTemplate(w io.Writer, path string, input *InData) (err error) {
if input == nil {
return errors.New("ERROR Internal - Nil passed to DoTemplate as InData")
}
if path == "" {
return errors.New("ERROR Internal - empty path passed to DoTemplate")
}
if len(path) == 1 {
return errors.New("ERROR Internal - too short (len = 1) path passed to DoTemplate: " + path)
}
hasOk := strings.HasSuffix(path, ".ok")
var fpath string // filepath
if hasOk {
fpath = path[1 : len(path)-3]
} else {
fpath = path[1:]
}
if hasOk {
// try text template with the literal ".ok" first for special cases (templates with broken HTML)
_, ok := LookupTextTemplate(fpath + ".ok")
// text/template - no context-sensitive escaping
if ok {
return doTextTemplate(w, fpath+".ok", input)
}
return doHtmlTemplate(w, fpath, input)
}
return doTextTemplate(w, fpath, input)
}
func doHtmlTemplate(w io.Writer, fpath string, input *InData) (err error) {
// html/template - context-sensitive escaping
tmpl, ok := LookupHtmlTemplate(fpath)
if ok == false {
return errors.New("Error in DoTemplate - html template " + fpath + " not found.")
}
parts := strings.Split(fpath, "/")
err = tmpl.ExecuteTemplate(w, parts[len(parts)-1], *input)
if err != nil {
log.Printf("Error in DoTemplate (html) - tmpl.Execute: %s\n", err)
return err
}
return nil
}
func doTextTemplate(w io.Writer, fpath string, input *InData) (err error) {
tmpl, ok := LookupTextTemplate(fpath)
if ok == false {
err := NewErrNotFound("Error in DoTemplate - text template " + fpath + " not found.")
return err
}
parts := strings.Split(fpath, "/")
err = tmpl.ExecuteTemplate(w, parts[len(parts)-1], *input)
if err != nil {
log.Printf("Error in DoTemplate (text) - tmpl.Execute's err: %s\n", err)
return err
}
return nil
}
// HandleFilterBased factors out the common handling for the "typical" -
// filter-based tests (listed in the map in custom.go, filters are in filters.go)
func HandleFilterBased(w http.ResponseWriter, r *http.Request, filters []filter) *LabResp {
var input InData
rawParams := make(map[string][]string)
ParseRawQuery(rawParams, r.URL.RawQuery)
inputRaw, ok := rawParams["in"]
if ok && len(inputRaw) > 0 {
input.InRaw = inputRaw[0]
unesc, err := url.QueryUnescape(input.InRaw)
if err != nil {
log.Printf("Error in %s: %s\n", r.URL.Path, err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
tr := NewTransformer(filters...)
input.In = tr.Transform(unesc)
}
err := DoTemplate(w, r.URL.Path, &input)
if err != nil {
log.Printf("Error in DoTemplate: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
return &LabResp{Err: nil, Code: http.StatusOK}
}