Skip to content

Commit 13701d0

Browse files
fix[backend](threat_intelligense): added header injection protection and sanitized id on proxy requests
1 parent 99c85dd commit 13701d0

3 files changed

Lines changed: 31 additions & 6 deletions

File tree

backend/modules/threatintel/handler/proxy.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"io"
66
"net/http"
77
"net/http/httputil"
8+
"net/textproto"
89
"net/url"
10+
"time"
911

1012
"github.com/gin-gonic/gin"
1113
"github.com/utmstack/utmstack/backend/modules/threatintel/internal"
@@ -96,10 +98,21 @@ func (h *ReverseProxyHandler) HandleUsageEndpoint(c *gin.Context) {
9698
return
9799
}
98100

101+
allowed := map[string]struct{}{
102+
"Accept": {},
103+
"Content-Type": {},
104+
"User-Agent": {},
105+
"X-Request-Id": {},
106+
"X-Correlation-Id": {},
107+
}
108+
99109
// Copy headers
100-
for k, v := range c.Request.Header {
101-
if k != "Authorization" && k != "Id" && k != "Key" {
102-
req.Header[k] = v
110+
for k, values := range c.Request.Header {
111+
canonical := textproto.CanonicalMIMEHeaderKey(k)
112+
if _, ok := allowed[canonical]; ok {
113+
for _, v := range values {
114+
req.Header.Add(canonical, v)
115+
}
103116
}
104117
}
105118

@@ -108,7 +121,9 @@ func (h *ReverseProxyHandler) HandleUsageEndpoint(c *gin.Context) {
108121
req.Header.Set("key", cfg.InstanceKey)
109122

110123
// Execute request
111-
client := &http.Client{}
124+
client := &http.Client{
125+
Timeout: 20* time.Second,
126+
}
112127
resp, err := client.Do(req)
113128
if err != nil {
114129
c.JSON(http.StatusBadGateway, gin.H{"error": "upstream service error"})

backend/modules/threatintel/internal/instanceconfig.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"path/filepath"
66
"sync"
77

8+
"github.com/threatwinds/go-sdk/catcher"
89
"gopkg.in/yaml.v3"
910
)
1011

@@ -27,10 +28,12 @@ func LoadInstanceConfig(updatesDir string) (*InstanceConfig, error) {
2728
configOnce.Do(func() {
2829
data, err := os.ReadFile(filepath.Join(updatesDir, "instance-config.yml"))
2930
if err != nil {
31+
_ = catcher.Error("error loading instance configuration",err,map[string]any{})
3032
return
3133
}
3234
var cfg InstanceConfig
3335
if err := yaml.Unmarshal(data, &cfg); err != nil {
36+
_ = catcher.Error("error loading instance configuration",err,map[string]any{})
3437
return
3538
}
3639
instanceConfig = &cfg

backend/modules/threatintel/routes.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package threatintel
22

33
import (
4+
"strings"
5+
46
"github.com/gin-gonic/gin"
57
"github.com/utmstack/utmstack/backend/modules/threatintel/handler"
68
)
@@ -15,15 +17,15 @@ func RegisterRoutes(api *gin.RouterGroup, m *Module, userAuth gin.HandlerFunc) {
1517
// GET /api/v1/threat-intel/entity/:id → /proxy/api/analytics/v1/entity/{id}/details
1618
g.GET("/entity/:id", func(c *gin.Context) {
1719
id := c.Param("id")
18-
targetPath := "/proxy/api/analytics/v1/entity/" + id + "/details"
20+
targetPath := "/proxy/api/analytics/v1/entity/" + sanitizeId(id) + "/details"
1921
h := handler.NewReverseProxyHandler(targetPath)
2022
h.Handle(c)
2123
})
2224

2325
// GET /api/v1/threat-intel/entity/:id/relations → /proxy/api/analytics/v1/entity/{id}/relations
2426
g.GET("/entity/:id/relations", func(c *gin.Context) {
2527
id := c.Param("id")
26-
targetPath := "/proxy/api/analytics/v1/entity/" + id + "/relations"
28+
targetPath := "/proxy/api/analytics/v1/entity/" + sanitizeId(id) + "/relations"
2729
h := handler.NewReverseProxyHandler(targetPath)
2830
h.Handle(c)
2931
})
@@ -40,3 +42,8 @@ func RegisterRoutes(api *gin.RouterGroup, m *Module, userAuth gin.HandlerFunc) {
4042
usageHandler := handler.NewReverseProxyHandler("/proxy/usage")
4143
g.GET("/usage", usageHandler.HandleUsageEndpoint)
4244
}
45+
46+
func sanitizeId(id string) string{
47+
replacer := strings.NewReplacer(".", "", "\\", "","/","")
48+
return replacer.Replace(id)
49+
}

0 commit comments

Comments
 (0)