CVE-2023-37265 (published 2023-07-17T21:15Z)

CasaOS is an open-source Personal Cloud system. Due to a lack of IP address verification an unauthenticated attackers can execute arbitrary commands as `root` on CasaOS instances. The problem was addressed by improving the detection of client IP addresses in `391dd7f`. This patch is part of CasaOS 0.4.4. Users should upgrade to CasaOS 0.4.4. If they can't, they should temporarily restrict access to CasaOS to untrusted users, for instance by not exposing it publicly. 

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: CWE-306
cwe_name: Missing Authentication for Critical Function
description: The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/IceWhaleTech/CasaOS-Gateway
commit_details: repo_url: https://github.com/IceWhaleTech/CasaOS-Gateway
author: CorrectRoadH
author_date: 2023-07-07 08:59:02+08:00
msg: Merge pull request from GHSA-vjh7-5r6x-xh6g

* fix:Incorrect identification of source IP addresses

* feat: support reverse proxy

* stash

* stash

* fix: the bug

* fix: the bug

* fix: the bug

* fix: the bug

* delete unused comment

* refacotr the proccess

* add comment to notice user to config correct proxy setting

* fix:some problems

* refactor the ip

* Update gateway_route.go
repository: repo_url: https://github.com/IceWhaleTech/CasaOS-Gateway
repo_name: IceWhaleTech/CasaOS-Gateway
description: CasaOS Gateway is a dynamic API gateway service that can be used to expose APIs from different other HTTP based services.
repo_language: Go
owner: IceWhaleTech
file_changes: filename: gateway_route.go
change_type: ModificationType.MODIFY
diff: @@ -2,6 +2,7 @@ package route
 
 import (
 	"net/http"
+	"strings"
 
 	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"github.com/IceWhaleTech/CasaOS-Gateway/service"
@@ -18,6 +19,38 @@ func NewGatewayRoute(management *service.Management) *GatewayRoute {
 	}
 }
 
+// the function is to ensure the request source IP is correct.
+func rewriteRequestSourceIP(r *http.Request) {
+	// we may receive two kinds of requests. a request from reverse proxy. a request from client.
+
+	// in reverse proxy, X-Forwarded-For will like
+	// `X-Forwarded-For:[192.168.6.102]`(normal)
+	// `X-Forwarded-For:[::1, 192.168.6.102]`(hacked) Note: the ::1 is inject by attacker.
+	// `X-Forwarded-For:[::1]`(normal or hacked) local request. But it from browser have JWT. So we can and need to verify it
+	// `X-Forwarded-For:[::1,::1]`(normal or hacked) attacker can build the request to bypass the verification.
+	// But in the case. the remoteAddress should be the real ip. So we can use remoteAddress to verify it.
+
+	ipList := strings.Split(r.Header.Get("X-Forwarded-For"), ",")
+
+	r.Header.Del("X-Forwarded-For")
+	r.Header.Del("X-Real-IP")
+
+	// Note: the X-Forwarded-For depend the correct config from reverse proxy.
+	// otherwise the X-Forwarded-For may be empty.
+	remoteIP := r.RemoteAddr[:strings.LastIndex(r.RemoteAddr, ":")]
+	if len(ipList) > 0 && (remoteIP == "127.0.0.1" || remoteIP == "::1") {
+		// to process the request from reverse proxy
+
+		// in reverse proxy, X-Forwarded-For will container multiple IPs.
+		// if the request is from reverse proxy, the r.RemoteAddr will be 127.0.0.1.
+		// So we need get ip from X-Forwarded-For
+		r.Header.Add("X-Forwarded-For", ipList[len(ipList)-1])
+	}
+	// to process the request from client.
+	// the gateway will add the X-Forwarded-For to request header.
+	// So we didn't need to add it.
+}
+
 func (g *GatewayRoute) GetRoute() *http.ServeMux {
 	gatewayMux := http.NewServeMux()
 	gatewayMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
@@ -36,6 +69,10 @@ func (g *GatewayRoute) GetRoute() *http.ServeMux {
 			return
 		}
 
+		// to fix https://github.com/IceWhaleTech/CasaOS/security/advisories/GHSA-32h8-rgcj-2g3c#event-102885
+		// API V1 and V2 both read ip from request header. So the fix is effective for v1 and v2.
+		rewriteRequestSourceIP(r)
+
 		proxy.ServeHTTP(w, r)
 	})
 

programming_language: Go