diff --git a/admin.go b/admin.go
index 25606501..048a1576 100644
--- a/admin.go
+++ b/admin.go
@@ -55,6 +55,7 @@ func init() {
beeAdminApp = &adminApp{
routers: make(map[string]http.HandlerFunc),
}
+ // keep in mind that all data should be html escaped to avoid XSS attack
beeAdminApp.Route("/", adminIndex)
beeAdminApp.Route("/qps", qpsIndex)
beeAdminApp.Route("/prof", profIndex)
@@ -105,8 +106,8 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
case "conf":
m := make(M)
list("BConfig", BConfig, m)
- m["AppConfigPath"] = appConfigPath
- m["AppConfigProvider"] = appConfigProvider
+ m["AppConfigPath"] = template.HTMLEscapeString(appConfigPath)
+ m["AppConfigProvider"] = template.HTMLEscapeString(appConfigProvider)
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
tmpl = template.Must(tmpl.Parse(configTpl))
tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
@@ -151,8 +152,9 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
resultList := new([][]string)
for _, f := range bf {
var result = []string{
- f.pattern,
- utils.GetFuncName(f.filterFunc),
+ // void xss
+ template.HTMLEscapeString(f.pattern),
+ template.HTMLEscapeString(utils.GetFuncName(f.filterFunc)),
}
*resultList = append(*resultList, result)
}
@@ -207,8 +209,8 @@ func PrintTree() M {
printTree(resultList, t)
- methods = append(methods, method)
- methodsData[method] = resultList
+ methods = append(methods, template.HTMLEscapeString(method))
+ methodsData[template.HTMLEscapeString(method)] = resultList
}
content["Data"] = methodsData
@@ -227,21 +229,21 @@ func printTree(resultList *[][]string, t *Tree) {
if v, ok := l.runObject.(*ControllerInfo); ok {
if v.routerType == routerTypeBeego {
var result = []string{
- v.pattern,
- fmt.Sprintf("%s", v.methods),
- v.controllerType.String(),
+ template.HTMLEscapeString(v.pattern),
+ template.HTMLEscapeString(fmt.Sprintf("%s", v.methods)),
+ template.HTMLEscapeString(v.controllerType.String()),
}
*resultList = append(*resultList, result)
} else if v.routerType == routerTypeRESTFul {
var result = []string{
- v.pattern,
- fmt.Sprintf("%s", v.methods),
+ template.HTMLEscapeString(v.pattern),
+ template.HTMLEscapeString(fmt.Sprintf("%s", v.methods)),
"",
}
*resultList = append(*resultList, result)
} else if v.routerType == routerTypeHandler {
var result = []string{
- v.pattern,
+ template.HTMLEscapeString(v.pattern),
"",
"",
}
@@ -266,7 +268,7 @@ func profIndex(rw http.ResponseWriter, r *http.Request) {
result bytes.Buffer
)
toolbox.ProcessInput(command, &result)
- data["Content"] = result.String()
+ data["Content"] = template.HTMLEscapeString(result.String())
if format == "json" && command == "gc summary" {
dataJSON, err := json.Marshal(data)
@@ -280,7 +282,7 @@ func profIndex(rw http.ResponseWriter, r *http.Request) {
return
}
- data["Title"] = command
+ data["Title"] = template.HTMLEscapeString(command)
defaultTpl := defaultScriptsTpl
if command == "gc summary" {
defaultTpl = gcAjaxTpl
@@ -304,13 +306,13 @@ func healthcheck(rw http.ResponseWriter, _ *http.Request) {
if err := h.Check(); err != nil {
result = []string{
"error",
- name,
- err.Error(),
+ template.HTMLEscapeString(name),
+ template.HTMLEscapeString(err.Error()),
}
} else {
result = []string{
"success",
- name,
+ template.HTMLEscapeString(name),
"OK",
}
}
@@ -334,11 +336,11 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
if taskname != "" {
if t, ok := toolbox.AdminTaskList[taskname]; ok {
if err := t.Run(); err != nil {
- data["Message"] = []string{"error", fmt.Sprintf("%s", err)}
+ data["Message"] = []string{"error", template.HTMLEscapeString(fmt.Sprintf("%s", err))}
}
- data["Message"] = []string{"success", fmt.Sprintf("%s run success,Now the Status is
%s", taskname, t.GetStatus())}
+ data["Message"] = []string{"success", template.HTMLEscapeString(fmt.Sprintf("%s run success,Now the Status is
%s", taskname, t.GetStatus()))}
} else {
- data["Message"] = []string{"warning", fmt.Sprintf("there's no task which named: %s", taskname)}
+ data["Message"] = []string{"warning", template.HTMLEscapeString(fmt.Sprintf("there's no task which named: %s", taskname))}
}
}
@@ -354,10 +356,10 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
}
for tname, tk := range toolbox.AdminTaskList {
result := []string{
- tname,
- tk.GetSpec(),
- tk.GetStatus(),
- tk.GetPrev().String(),
+ template.HTMLEscapeString(tname),
+ template.HTMLEscapeString(tk.GetSpec()),
+ template.HTMLEscapeString(tk.GetStatus()),
+ template.HTMLEscapeString(tk.GetPrev().String()),
}
*resultList = append(*resultList, result)
}
diff --git a/context/input.go b/context/input.go
index 8bf74b7f..7b522c36 100644
--- a/context/input.go
+++ b/context/input.go
@@ -284,7 +284,12 @@ func (input *BeegoInput) ParamsLen() int {
func (input *BeegoInput) Param(key string) string {
for i, v := range input.pnames {
if v == key && i <= len(input.pvalues) {
- return url.PathEscape(input.pvalues[i])
+ // we cannot use url.PathEscape(input.pvalues[i])
+ // for example, if the value is /a/b
+ // after url.PathEscape(input.pvalues[i]), the value is %2Fa%2Fb
+ // However, the value is used in ControllerRegister.ServeHTTP
+ // and split by "/", so function crash...
+ return input.pvalues[i]
}
}
return ""
diff --git a/go.mod b/go.mod
index 17d66efa..d77f9438 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 // indirect
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a // indirect
- github.com/elastic/go-elasticsearch/v6 v6.8.5 // indirect
+ github.com/elastic/go-elasticsearch/v6 v6.8.5
github.com/elazarl/go-bindata-assetfs v1.0.0
github.com/go-redis/redis v6.14.2+incompatible
github.com/go-sql-driver/mysql v1.4.1