Created
November 5, 2023 06:51
-
-
Save iwanhae/b4df2d332c505170b35f024d94f4c461 to your computer and use it in GitHub Desktop.
Kubernetes API Audit PoC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"compress/gzip" | |
"context" | |
"crypto/tls" | |
"errors" | |
"fmt" | |
"io" | |
"log" | |
"net/http" | |
"net/http/httputil" | |
"os" | |
"strings" | |
"sync" | |
"sync/atomic" | |
) | |
var key = &struct{}{} | |
func main() { | |
mu := &sync.Mutex{} | |
proxy := httputil.ReverseProxy{ | |
Transport: &http.Transport{ | |
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | |
}, | |
Rewrite: func(r *httputil.ProxyRequest) { | |
req := r.In | |
// Print Request | |
mu.Lock() | |
defer mu.Unlock() | |
fmt.Println("--------", req.Method, req.URL) | |
r.Out.URL.Host = "YOUR_HOST_HERE:6443" | |
r.Out.URL.Scheme = "https" | |
r.Out.Header.Set("X-Forwarded-For", req.RemoteAddr) | |
r.Out.Header.Set("X-Forwarded-Host", req.Host) | |
r.Out.Header.Set("X-Forwarded-Proto", "http") | |
r.Out.Header.Set("Authorization", "Bearer YOURSECRETHERE") | |
f := r.In.Context().Value(key).(*os.File) | |
fmt.Fprintf(f, "%s %s %s\n", req.Method, req.URL, req.Proto) | |
for k, v := range req.Header { | |
fmt.Fprintf(f, "%s: %s\n", k, strings.Join(v, ",")) | |
} | |
fmt.Fprintf(f, "\n") | |
r.In.Body = TeeReadCloser(r.In.Body, f) | |
}, | |
ModifyResponse: func(r *http.Response) error { | |
f := r.Request.Context().Value(key).(*os.File) | |
fmt.Fprintf(f, "===\n") | |
fmt.Fprintf(f, "%s\n", r.Status) | |
for k, v := range r.Header { | |
fmt.Fprintf(f, "%s: %s\n", k, strings.Join(v, ",")) | |
} | |
fmt.Fprintf(f, "\n") | |
r.Body = TeeReadCloser(r.Body, f) | |
return nil | |
}, | |
} | |
// Start the proxy server | |
log.Fatal(http.ListenAndServe(":8000", &FileOpenMW{&proxy, atomic.Int32{}})) | |
} | |
type Decompressor struct { | |
io.WriteCloser | |
*io.PipeReader | |
*io.PipeWriter | |
*gzip.Reader | |
} | |
type FileOpenMW struct { | |
http.Handler | |
counter atomic.Int32 | |
} | |
func (t *FileOpenMW) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
t.counter.Add(1) | |
f, err := os.OpenFile(fmt.Sprintf("audit/%v.http", t.counter.Load()), os.O_CREATE|os.O_WRONLY, 0644) | |
if err != nil { | |
panic(err) | |
} | |
r = r.WithContext(context.WithValue(r.Context(), key, f)) | |
t.Handler.ServeHTTP(w, r) | |
} | |
type teeReadCloser struct { | |
r io.ReadCloser | |
rWraiteable io.Writer | |
w io.WriteCloser | |
} | |
func TeeReadCloser(r io.ReadCloser, w io.WriteCloser) io.ReadCloser { | |
var rWraiteable io.Writer = nil | |
if rw, ok := r.(io.Writer); ok { | |
rWraiteable = rw | |
} | |
return &teeReadCloser{ | |
r: r, | |
rWraiteable: rWraiteable, | |
w: w, | |
} | |
} | |
// Write implements io.ReadWriteCloser. | |
func (t *teeReadCloser) Write(p []byte) (n int, err error) { | |
return t.rWraiteable.Write(p) | |
} | |
func (t *teeReadCloser) Close() error { | |
return errors.Join(t.w.Close(), t.r.Close()) | |
} | |
func (t *teeReadCloser) Read(p []byte) (n int, err error) { | |
n, err = t.r.Read(p) | |
if n > 0 { | |
if n, err := t.w.Write(p[:n]); err != nil { | |
return n, err | |
} | |
} | |
return | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment