mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:07:30 +00:00
fix: correctly check denied domains and ips for actions (#8810)
# Which Problems Are Solved System administrators can block hosts and IPs for HTTP calls in actions. Using DNS, blocked IPs could be bypassed. # How the Problems Are Solved - Hosts are resolved (DNS lookup) to check whether their corresponding IP is blocked. # Additional Changes - Added complete lookup ip address range and "unspecified" address to the default `DenyList`
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -19,7 +20,7 @@ import (
|
||||
func WithHTTP(ctx context.Context) Option {
|
||||
return func(c *runConfig) {
|
||||
c.modules["zitadel/http"] = func(runtime *goja.Runtime, module *goja.Object) {
|
||||
requireHTTP(ctx, &http.Client{Transport: new(transport)}, runtime, module)
|
||||
requireHTTP(ctx, &http.Client{Transport: &transport{lookup: net.LookupIP}}, runtime, module)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,21 +171,34 @@ func parseHeaders(headers *goja.Object) http.Header {
|
||||
return h
|
||||
}
|
||||
|
||||
type transport struct{}
|
||||
type transport struct {
|
||||
lookup func(string) ([]net.IP, error)
|
||||
}
|
||||
|
||||
func (*transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if httpConfig == nil {
|
||||
return http.DefaultTransport.RoundTrip(req)
|
||||
}
|
||||
if isHostBlocked(httpConfig.DenyList, req.URL) {
|
||||
if t.isHostBlocked(httpConfig.DenyList, req.URL) {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "ACTIO-N72d0", "host is denied")
|
||||
}
|
||||
return http.DefaultTransport.RoundTrip(req)
|
||||
}
|
||||
|
||||
func isHostBlocked(denyList []AddressChecker, address *url.URL) bool {
|
||||
func (t *transport) isHostBlocked(denyList []AddressChecker, address *url.URL) bool {
|
||||
host := address.Hostname()
|
||||
ip := net.ParseIP(host)
|
||||
ips := []net.IP{ip}
|
||||
// if the hostname is a domain, we need to check resolve the ip(s), since it might be denied
|
||||
if ip == nil {
|
||||
var err error
|
||||
ips, err = t.lookup(host)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, blocked := range denyList {
|
||||
if blocked.Matches(address.Hostname()) {
|
||||
if blocked.Matches(ips, host) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -192,5 +206,5 @@ func isHostBlocked(denyList []AddressChecker, address *url.URL) bool {
|
||||
}
|
||||
|
||||
type AddressChecker interface {
|
||||
Matches(string) bool
|
||||
Matches([]net.IP, string) bool
|
||||
}
|
||||
|
Reference in New Issue
Block a user