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()
|
||||
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{}}
|
||||
m.previewMu.Lock()
|
||||
m.previewListeners[port] = tracked
|
||||
@@ -126,6 +146,16 @@ func (m *Manager) servePreview(port int) error {
|
||||
FlushInterval: -1,
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusForbidden)
|
||||
|
||||
Reference in New Issue
Block a user