MM-55320 - Limit length of browser user agent version; ratelimit the /sessions endpoint (#25900)

* add ratelimit to /sessions; cap userAgent version length; tests

* add MaxSessionsLimit; remove oldest session first; tests

* can't use slices in 1.20; improve test

* nits

* add GetLRUSessions; move limiting to CreateSession; remove rate limiting

* use queryBuilder

* mysql needs a limit when using offset

* update i18n

* refactor into limitNumberOfSessions; protect createSessionForUserAccessToken

* add comment to GetLRUSessions

* add limit to oauth path; PR comments
Этот коммит содержится в:
Christopher Poile
2024-03-21 08:48:24 -04:00
коммит произвёл GitHub
родитель 9a2d96073e
Коммит 17d11db395
16 изменённых файлов: 321 добавлений и 4 удалений

Просмотреть файл

@@ -10,6 +10,8 @@ import (
"github.com/avct/uasurfer"
)
const maxUserAgentVersionLength = 128
var platformNames = map[uasurfer.Platform]string{
uasurfer.PlatformUnknown: "Windows",
uasurfer.PlatformWindows: "Windows",
@@ -86,27 +88,33 @@ func getOSName(ua *uasurfer.UserAgent) string {
func getBrowserVersion(ua *uasurfer.UserAgent, userAgentString string) string {
if index := strings.Index(userAgentString, "Mattermost Mobile/"); index != -1 {
afterVersion := userAgentString[index+len("Mattermost Mobile/"):]
return strings.Fields(afterVersion)[0]
// MM-55320: limitStringLength prevents potential DOS caused by filling an unbounded string with junk data
return limitStringLength(strings.Fields(afterVersion)[0], maxUserAgentVersionLength)
}
if index := strings.Index(userAgentString, "Mattermost/"); index != -1 {
afterVersion := userAgentString[index+len("Mattermost/"):]
return strings.Fields(afterVersion)[0]
return limitStringLength(strings.Fields(afterVersion)[0], maxUserAgentVersionLength)
}
if index := strings.Index(userAgentString, "mmctl/"); index != -1 {
afterVersion := userAgentString[index+len("mmctl/"):]
return strings.Fields(afterVersion)[0]
return limitStringLength(strings.Fields(afterVersion)[0], maxUserAgentVersionLength)
}
if index := strings.Index(userAgentString, "Franz/"); index != -1 {
afterVersion := userAgentString[index+len("Franz/"):]
return strings.Fields(afterVersion)[0]
return limitStringLength(strings.Fields(afterVersion)[0], maxUserAgentVersionLength)
}
return getUAVersion(ua.Browser.Version)
}
func limitStringLength(field string, limit int) string {
endPos := min(len(field), limit)
return field[:endPos]
}
func getUAVersion(version uasurfer.Version) string {
if version.Patch == 0 {
return fmt.Sprintf("%v.%v", version.Major, version.Minor)
@@ -151,3 +159,11 @@ func getBrowserName(ua *uasurfer.UserAgent, userAgentString string) string {
return browserNames[uasurfer.BrowserUnknown]
}
// min should be replaced by to go 1.21 built-in generic function, see MM-57356.
func min(a, b int) int {
if a < b {
return a
}
return b
}