Fix reachable security issues found in the audit
This commit is contained in:
@@ -112,6 +112,26 @@ func (m *Manager) servePreview(port int) error {
|
|||||||
ln.Close()
|
ln.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// HTTP previews also arrive through the app's loopback forwards. Reject
|
||||||
|
// attacker-controlled hostnames before proxying: DNS rebinding makes those
|
||||||
|
// requests same-origin, so cross-origin protection alone cannot stop them.
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
status, err := lc.StatusWithoutPeers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ln.Close()
|
||||||
|
return fmt.Errorf("get preview hostnames: %w", err)
|
||||||
|
}
|
||||||
|
hosts := map[string]bool{}
|
||||||
|
if status.Self != nil {
|
||||||
|
name := strings.ToLower(strings.TrimSuffix(status.Self.DNSName, "."))
|
||||||
|
hosts[name] = true
|
||||||
|
hosts[strings.SplitN(name, ".", 2)[0]] = true
|
||||||
|
}
|
||||||
|
for _, ip := range status.TailscaleIPs {
|
||||||
|
hosts[ip.String()] = true
|
||||||
|
}
|
||||||
|
|
||||||
tracked := &previewListener{Listener: ln, conns: map[net.Conn]bool{}}
|
tracked := &previewListener{Listener: ln, conns: map[net.Conn]bool{}}
|
||||||
m.previewMu.Lock()
|
m.previewMu.Lock()
|
||||||
m.previewListeners[port] = tracked
|
m.previewListeners[port] = tracked
|
||||||
@@ -126,6 +146,16 @@ func (m *Manager) servePreview(port int) error {
|
|||||||
FlushInterval: -1,
|
FlushInterval: -1,
|
||||||
}
|
}
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
host := r.Host
|
||||||
|
if h, _, err := net.SplitHostPort(host); err == nil {
|
||||||
|
host = h
|
||||||
|
}
|
||||||
|
host = strings.ToLower(strings.TrimSuffix(host, "."))
|
||||||
|
ip := net.ParseIP(host)
|
||||||
|
if host == "" || !(hosts[host] || host == "localhost" || strings.HasSuffix(host, ".localhost") || (ip != nil && ip.IsLoopback())) {
|
||||||
|
http.Error(w, "forbidden preview host", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
who, err := lc.WhoIs(r.Context(), r.RemoteAddr)
|
who, err := lc.WhoIs(r.Context(), r.RemoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusForbidden)
|
http.Error(w, err.Error(), http.StatusForbidden)
|
||||||
|
|||||||
Reference in New Issue
Block a user