diff --git a/.img/maxstreams.png b/.img/maxstreams.png new file mode 100644 index 0000000..9c5c69d Binary files /dev/null and b/.img/maxstreams.png differ diff --git a/.img/packets.png b/.img/packets.png new file mode 100644 index 0000000..e44a7eb Binary files /dev/null and b/.img/packets.png differ diff --git a/.img/ynoreset.png b/.img/ynoreset.png new file mode 100644 index 0000000..da2c6cf Binary files /dev/null and b/.img/ynoreset.png differ diff --git a/README.md b/README.md index cac04bb..c0b6117 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # rr-dev +based on observations made by cloudflare in the excellent blog: https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/ +no clue if this actually works, but it seems to match the same behavior +mentioned in the cloudflare blog, which seems to no longer be available +from their blog link. + +## collecting and analyzing 1. start http/2 enabled nginx server: ``` cd server @@ -17,10 +23,26 @@ python rr.py 5. compare against the cloudflare blog notes (unless you have the pcap which seems to be gone now) ## notes -no clue if this actually works, but it seems to match the same behavior -mentioned in the cloudflare blog. +server advertises maximum stream concurrency of 128: -obviously to weaponize it, it will take some extra effort like multithreading but i sure as fuck -am not releasing a weaponized version fo free. +![Maximum concurrent streams](.img/maxstreams.png) -greets to psyk0, slerig, and all the other juggalols out there +1000 stream headers are sent split into two packets: + +![Wireshark packet list](.img/packets.png) + +>Interestingly, the RST_STREAM for stream 1051 doesn't fit in packet 15, so in packet 16 we see the server respond with a 404 response. Then in packet 17 the client does send the RST_STREAM, before moving on to sending the remaining 475 requests. + +despite exceeding maximum number of advertised streams, the server never sends a RST_FRAME: + +![No RST_STREAM frames from server](.img/ynoreset.png) + +> No server RST_STREAM frames are seen in this trace, indicating that the server did not observe a concurrent stream violation. + +obviously to weaponize it, it will take some extra effort like implementing concurrency. but don't do +that shit for any reason other than research. i'm saying this explicitly because +we've seen examples of "illegal code" before. i do this solely for research, and fun of +course, because c'mon this shit is so interesting. + +## greetz +greetz to psyk0, shifty, and slerig. who needa stop slackin, but i still love em anyway. diff --git a/src/rr.py b/src/rr.py index 2fbb140..794b2f6 100644 --- a/src/rr.py +++ b/src/rr.py @@ -24,7 +24,7 @@ def send_rr_packets(server='localhost', port=443, max_streams=1000): headers = [ (':method', 'GET'), - (':path', '/foo'), + (':path', '/lol'), (':authority', server), (':scheme', 'https'), ] @@ -47,7 +47,7 @@ def send_rr_packets(server='localhost', port=443, max_streams=1000): def main(): - send_rr_packets(server='localhost', port=443) + send_rr_packets(server='localhost', port=443, max_streams=1000) if __name__ == '__main__':