CVE-2021-30080 (published 2022-04-05T16:15Z)

An issue was discovered in the route lookup process in beego before 1.12.11 that allows attackers to bypass access control.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/beego/beego
commit_details: repo_url: https://github.com/beego/beego
author: Ming Deng
author_date: 2021-01-25 23:49:18+08:00
msg: Fix BUG: /abc.html/aaa match /abc/aaa
repository: repo_url: https://github.com/beego/beego
repo_name: beego/beego
description: beego is an open-source, high-performance web framework for the Go programming language.
repo_language: Go
owner: beego
file_changes: filename: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,5 @@
 # developing
+- Fix: /abc.html/aaa match /abc/aaa. [4459](https://github.com/beego/beego/pull/4459)
 - ORM mock. [4407](https://github.com/beego/beego/pull/4407)
 - Add sonar check and ignore test. [4432](https://github.com/beego/beego/pull/4432) [4433](https://github.com/beego/beego/pull/4433)
 - Update changlog.yml to check every PR to develop branch.[4427](https://github.com/beego/beego/pull/4427)

programming_language: Markdown
filename: tree.go
change_type: ModificationType.MODIFY
diff: @@ -342,8 +342,9 @@ func (t *Tree) match(treePattern string, pattern string, wildcardValues []string
 	if runObject == nil && len(t.fixrouters) > 0 {
 		// Filter the .json .xml .html extension
 		for _, str := range allowSuffixExt {
-			if strings.HasSuffix(seg, str) {
+			if strings.HasSuffix(seg, str) && strings.HasSuffix(treePattern, seg){
 				for _, subTree := range t.fixrouters {
+					// strings.HasSuffix(treePattern, seg) avoid cases: /aaa.html/bbb could access /aaa/bbb
 					if subTree.prefix == seg[:len(seg)-len(str)] {
 						runObject = subTree.match(treePattern, pattern, wildcardValues, ctx)
 						if runObject != nil {

programming_language: Go
filename: tree_test.go
change_type: ModificationType.MODIFY
diff: @@ -17,6 +17,7 @@ package web
 import (
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/beego/beego/v2/server/web/context"
 )
@@ -49,7 +50,7 @@ func notMatchTestInfo(pattern, url string) testInfo {
 }
 
 func init() {
-	routers = make([]testInfo, 0)
+	routers = make([]testInfo, 0, 128)
 	// match example
 	routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic", nil))
 	routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}))
@@ -108,12 +109,23 @@ func init() {
 	routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", "/read_222_htm"))
 	routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", " /read_262shtm"))
 
+	// test .html, .json not suffix
+	const abcHtml = "/suffix/abc.html"
+	routers = append(routers, notMatchTestInfo(abcHtml, "/suffix.html/abc"))
+	routers = append(routers, matchTestInfo("/suffix/abc", abcHtml, nil))
+	routers = append(routers, matchTestInfo("/suffix/*", abcHtml, nil))
+	routers = append(routers, notMatchTestInfo("/suffix/*", "/suffix.html/a"))
+	const abcSuffix = "/abc/suffix/*"
+	routers = append(routers, notMatchTestInfo(abcSuffix, "/abc/suffix.html/a"))
+	routers = append(routers, matchTestInfo(abcSuffix, "/abc/suffix/a", nil))
+	routers = append(routers, notMatchTestInfo(abcSuffix, "/abc.j/suffix/a"))
+
 }
 
 func TestTreeRouters(t *testing.T) {
 	for _, r := range routers {
-		shouldMatch := r.shouldMatchOrNot
 
+		shouldMatch := r.shouldMatchOrNot
 		tr := NewTree()
 		tr.AddRouter(r.pattern, "astaxie")
 		ctx := context.NewContext()
@@ -122,7 +134,7 @@ func TestTreeRouters(t *testing.T) {
 			if obj != nil {
 				t.Fatal("pattern:", r.pattern, ", should not match", r.requestUrl)
 			} else {
-				return
+				continue
 			}
 		}
 		if obj == nil || obj.(string) != "astaxie" {
@@ -138,6 +150,7 @@ func TestTreeRouters(t *testing.T) {
 			}
 		}
 	}
+	time.Sleep(time.Second)
 }
 
 func TestStaticPath(t *testing.T) {

programming_language: Go