test_ssrf_1411.nim 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. # SPDX-License-Identifier: AGPL-3.0-only
  2. # Reproduction + regression test for issue #1411:
  3. # SSRF via /video proxy with default HMAC key and missing host validation.
  4. import std/[unittest, uri]
  5. import ".."/src/utils
  6. suite "issue #1411 SSRF via /video proxy":
  7. setup:
  8. # The default key shipped in nitter.example.conf / config.nim.
  9. setHmacKey("secretkey")
  10. test "HMAC for arbitrary SSRF URLs is forgeable with the default key":
  11. # These signatures were independently computed (Python hmac-sha256, uppercase
  12. # hex, first 13 chars) and observed live in the issue report.
  13. check getHmac("http://172.17.0.1:19999/secret_data.m3u8") == "BBD19ACC6C012"
  14. check getHmac("http://172.17.0.1:19999/secret_data.mp4") == "0780F00DDF3E7"
  15. test "isTwitterUrl rejects SSRF targets (the guard /video is missing)":
  16. # Internal / metadata hosts an attacker would target.
  17. check isTwitterUrl(parseUri("http://172.17.0.1:19999/secret_data.m3u8")) == false
  18. check isTwitterUrl(parseUri("http://169.254.169.254/latest/meta-data/x.m3u8")) == false
  19. check isTwitterUrl(parseUri("http://localhost/x.mp4")) == false
  20. check isTwitterUrl(parseUri("http://[::1]/x.mp4")) == false
  21. test "isTwitterUrl rejects userinfo / look-alike host bypass attempts":
  22. check isTwitterUrl(parseUri("http://video.twimg.com@169.254.169.254/x.mp4")) == false
  23. check isTwitterUrl(parseUri("http://video.twimg.com.evil.com/x.mp4")) == false
  24. check isTwitterUrl(parseUri("http://evilvideo.twimg.com.attacker/x.mp4")) == false
  25. test "isTwitterUrl rejects non-http schemes even on a Twitter host":
  26. check isTwitterUrl(parseUri("gopher://video.twimg.com/x.mp4")) == false
  27. check isTwitterUrl(parseUri("file:///etc/passwd")) == false
  28. check isTwitterUrl(parseUri("ftp://video.twimg.com/x.mp4")) == false
  29. test "isTwitterUrl still allows legitimate Twitter video hosts":
  30. check isTwitterUrl(parseUri("https://video.twimg.com/ext_tw_video/1/pu/pl/x.m3u8")) == true
  31. check isTwitterUrl(parseUri("https://video.twimg.com/amplify_video/1/vid/x.mp4")) == true
  32. check isTwitterUrl(parseUri("https://prod-fastly-us-east-1.video.pscp.tv/x.m3u8")) == true