Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

injectionhelpers.py 5.5KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. """
  2. Helpers for URI and method injection tests.
  3. @see: U{CVE-2019-12387}
  4. """
  5. import string
  6. UNPRINTABLE_ASCII = frozenset(range(0, 128)) - frozenset(
  7. bytearray(string.printable, "ascii")
  8. )
  9. NONASCII = frozenset(range(128, 256))
  10. class MethodInjectionTestsMixin:
  11. """
  12. A mixin that runs HTTP method injection tests. Define
  13. L{MethodInjectionTestsMixin.attemptRequestWithMaliciousMethod} in
  14. a L{twisted.trial.unittest.SynchronousTestCase} subclass to test
  15. how HTTP client code behaves when presented with malicious HTTP
  16. methods.
  17. @see: U{CVE-2019-12387}
  18. """
  19. def attemptRequestWithMaliciousMethod(self, method):
  20. """
  21. Attempt to send a request with the given method. This should
  22. synchronously raise a L{ValueError} if either is invalid.
  23. @param method: the method (e.g. C{GET\x00})
  24. @param uri: the URI
  25. @type method:
  26. """
  27. raise NotImplementedError()
  28. def test_methodWithCLRFRejected(self):
  29. """
  30. Issuing a request with a method that contains a carriage
  31. return and line feed fails with a L{ValueError}.
  32. """
  33. with self.assertRaises(ValueError) as cm:
  34. method = b"GET\r\nX-Injected-Header: value"
  35. self.attemptRequestWithMaliciousMethod(method)
  36. self.assertRegex(str(cm.exception), "^Invalid method")
  37. def test_methodWithUnprintableASCIIRejected(self):
  38. """
  39. Issuing a request with a method that contains unprintable
  40. ASCII characters fails with a L{ValueError}.
  41. """
  42. for c in UNPRINTABLE_ASCII:
  43. method = b"GET%s" % (bytearray([c]),)
  44. with self.assertRaises(ValueError) as cm:
  45. self.attemptRequestWithMaliciousMethod(method)
  46. self.assertRegex(str(cm.exception), "^Invalid method")
  47. def test_methodWithNonASCIIRejected(self):
  48. """
  49. Issuing a request with a method that contains non-ASCII
  50. characters fails with a L{ValueError}.
  51. """
  52. for c in NONASCII:
  53. method = b"GET%s" % (bytearray([c]),)
  54. with self.assertRaises(ValueError) as cm:
  55. self.attemptRequestWithMaliciousMethod(method)
  56. self.assertRegex(str(cm.exception), "^Invalid method")
  57. class URIInjectionTestsMixin:
  58. """
  59. A mixin that runs HTTP URI injection tests. Define
  60. L{MethodInjectionTestsMixin.attemptRequestWithMaliciousURI} in a
  61. L{twisted.trial.unittest.SynchronousTestCase} subclass to test how
  62. HTTP client code behaves when presented with malicious HTTP
  63. URIs.
  64. """
  65. def attemptRequestWithMaliciousURI(self, method):
  66. """
  67. Attempt to send a request with the given URI. This should
  68. synchronously raise a L{ValueError} if either is invalid.
  69. @param uri: the URI.
  70. @type method:
  71. """
  72. raise NotImplementedError()
  73. def test_hostWithCRLFRejected(self):
  74. """
  75. Issuing a request with a URI whose host contains a carriage
  76. return and line feed fails with a L{ValueError}.
  77. """
  78. with self.assertRaises(ValueError) as cm:
  79. uri = b"http://twisted\r\n.invalid/path"
  80. self.attemptRequestWithMaliciousURI(uri)
  81. self.assertRegex(str(cm.exception), "^Invalid URI")
  82. def test_hostWithWithUnprintableASCIIRejected(self):
  83. """
  84. Issuing a request with a URI whose host contains unprintable
  85. ASCII characters fails with a L{ValueError}.
  86. """
  87. for c in UNPRINTABLE_ASCII:
  88. uri = b"http://twisted%s.invalid/OK" % (bytearray([c]),)
  89. with self.assertRaises(ValueError) as cm:
  90. self.attemptRequestWithMaliciousURI(uri)
  91. self.assertRegex(str(cm.exception), "^Invalid URI")
  92. def test_hostWithNonASCIIRejected(self):
  93. """
  94. Issuing a request with a URI whose host contains non-ASCII
  95. characters fails with a L{ValueError}.
  96. """
  97. for c in NONASCII:
  98. uri = b"http://twisted%s.invalid/OK" % (bytearray([c]),)
  99. with self.assertRaises(ValueError) as cm:
  100. self.attemptRequestWithMaliciousURI(uri)
  101. self.assertRegex(str(cm.exception), "^Invalid URI")
  102. def test_pathWithCRLFRejected(self):
  103. """
  104. Issuing a request with a URI whose path contains a carriage
  105. return and line feed fails with a L{ValueError}.
  106. """
  107. with self.assertRaises(ValueError) as cm:
  108. uri = b"http://twisted.invalid/\r\npath"
  109. self.attemptRequestWithMaliciousURI(uri)
  110. self.assertRegex(str(cm.exception), "^Invalid URI")
  111. def test_pathWithWithUnprintableASCIIRejected(self):
  112. """
  113. Issuing a request with a URI whose path contains unprintable
  114. ASCII characters fails with a L{ValueError}.
  115. """
  116. for c in UNPRINTABLE_ASCII:
  117. uri = b"http://twisted.invalid/OK%s" % (bytearray([c]),)
  118. with self.assertRaises(ValueError) as cm:
  119. self.attemptRequestWithMaliciousURI(uri)
  120. self.assertRegex(str(cm.exception), "^Invalid URI")
  121. def test_pathWithNonASCIIRejected(self):
  122. """
  123. Issuing a request with a URI whose path contains non-ASCII
  124. characters fails with a L{ValueError}.
  125. """
  126. for c in NONASCII:
  127. uri = b"http://twisted.invalid/OK%s" % (bytearray([c]),)
  128. with self.assertRaises(ValueError) as cm:
  129. self.attemptRequestWithMaliciousURI(uri)
  130. self.assertRegex(str(cm.exception), "^Invalid URI")