contrast-agent 3.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (500) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +5 -0
  3. data/.dockerignore +10 -0
  4. data/.gitignore +58 -0
  5. data/.gitmodules +6 -0
  6. data/.rspec +6 -0
  7. data/.simplecov +4 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE.txt +12 -0
  10. data/Rakefile +15 -0
  11. data/exe/contrast_service +29 -0
  12. data/ext/build_funchook.rb +48 -0
  13. data/ext/cs__assess_active_record_named/cs__active_record_named.c +47 -0
  14. data/ext/cs__assess_active_record_named/cs__active_record_named.h +10 -0
  15. data/ext/cs__assess_active_record_named/extconf.rb +2 -0
  16. data/ext/cs__assess_array/cs__assess_array.c +38 -0
  17. data/ext/cs__assess_array/cs__assess_array.h +9 -0
  18. data/ext/cs__assess_array/extconf.rb +2 -0
  19. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +50 -0
  20. data/ext/cs__assess_basic_object/cs__assess_basic_object.h +17 -0
  21. data/ext/cs__assess_basic_object/extconf.rb +2 -0
  22. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +86 -0
  23. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +34 -0
  24. data/ext/cs__assess_fiber_track/extconf.rb +2 -0
  25. data/ext/cs__assess_hash/cs__assess_hash.c +64 -0
  26. data/ext/cs__assess_hash/cs__assess_hash.h +24 -0
  27. data/ext/cs__assess_hash/extconf.rb +2 -0
  28. data/ext/cs__assess_kernel/cs__assess_kernel.c +36 -0
  29. data/ext/cs__assess_kernel/cs__assess_kernel.h +10 -0
  30. data/ext/cs__assess_kernel/extconf.rb +2 -0
  31. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +47 -0
  32. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +18 -0
  33. data/ext/cs__assess_marshal_module/extconf.rb +2 -0
  34. data/ext/cs__assess_module/cs__assess_module.c +78 -0
  35. data/ext/cs__assess_module/cs__assess_module.h +25 -0
  36. data/ext/cs__assess_module/extconf.rb +2 -0
  37. data/ext/cs__assess_regexp/cs__assess_regexp.c +48 -0
  38. data/ext/cs__assess_regexp/cs__assess_regexp.h +22 -0
  39. data/ext/cs__assess_regexp/extconf.rb +2 -0
  40. data/ext/cs__assess_regexp_track/cs__assess_regexp_track.c +63 -0
  41. data/ext/cs__assess_regexp_track/cs__assess_regexp_track.h +29 -0
  42. data/ext/cs__assess_regexp_track/extconf.rb +2 -0
  43. data/ext/cs__assess_string/cs__assess_string.c +38 -0
  44. data/ext/cs__assess_string/cs__assess_string.h +19 -0
  45. data/ext/cs__assess_string/extconf.rb +2 -0
  46. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +31 -0
  47. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.h +13 -0
  48. data/ext/cs__assess_string_interpolation26/extconf.rb +2 -0
  49. data/ext/cs__common/cs__common.c +60 -0
  50. data/ext/cs__common/cs__common.h +28 -0
  51. data/ext/cs__common/extconf.rb +20 -0
  52. data/ext/cs__contrast_patch/cs__contrast_patch.c +445 -0
  53. data/ext/cs__contrast_patch/cs__contrast_patch.h +196 -0
  54. data/ext/cs__contrast_patch/extconf.rb +2 -0
  55. data/ext/cs__protect_kernel/cs__protect_kernel.c +37 -0
  56. data/ext/cs__protect_kernel/cs__protect_kernel.h +11 -0
  57. data/ext/cs__protect_kernel/extconf.rb +2 -0
  58. data/ext/cs__scope/cs__scope.c +96 -0
  59. data/ext/cs__scope/cs__scope.h +33 -0
  60. data/ext/cs__scope/extconf.rb +2 -0
  61. data/ext/extconf_common.rb +49 -0
  62. data/funchook/LICENSE +360 -0
  63. data/funchook/Makefile +29 -0
  64. data/funchook/Makefile.in +29 -0
  65. data/funchook/README.md +121 -0
  66. data/funchook/appveyor.yml +42 -0
  67. data/funchook/autogen.sh +3 -0
  68. data/funchook/autom4te.cache/output.0 +4976 -0
  69. data/funchook/autom4te.cache/requests +78 -0
  70. data/funchook/autom4te.cache/traces.0 +364 -0
  71. data/funchook/config.guess +1530 -0
  72. data/funchook/config.log +490 -0
  73. data/funchook/config.status +1016 -0
  74. data/funchook/config.sub +1773 -0
  75. data/funchook/configure +4976 -0
  76. data/funchook/configure.ac +59 -0
  77. data/funchook/distorm/COPYING +26 -0
  78. data/funchook/distorm/MANIFEST +25 -0
  79. data/funchook/distorm/MANIFEST.in +4 -0
  80. data/funchook/distorm/README.md +12 -0
  81. data/funchook/distorm/disOps/disOps.py +795 -0
  82. data/funchook/distorm/disOps/x86db.py +404 -0
  83. data/funchook/distorm/disOps/x86header.py +247 -0
  84. data/funchook/distorm/disOps/x86sets.py +1664 -0
  85. data/funchook/distorm/examples/cs/TestdiStorm/Program.cs +79 -0
  86. data/funchook/distorm/examples/cs/TestdiStorm/Properties/AssemblyInfo.cs +36 -0
  87. data/funchook/distorm/examples/cs/TestdiStorm/TestdiStorm.csproj +69 -0
  88. data/funchook/distorm/examples/cs/distorm-net.sln +26 -0
  89. data/funchook/distorm/examples/cs/distorm-net/CodeInfo.cs +23 -0
  90. data/funchook/distorm/examples/cs/distorm-net/DecodedInst.cs +15 -0
  91. data/funchook/distorm/examples/cs/distorm-net/DecodedResult.cs +14 -0
  92. data/funchook/distorm/examples/cs/distorm-net/DecomposedInst.cs +36 -0
  93. data/funchook/distorm/examples/cs/distorm-net/DecomposedResult.cs +14 -0
  94. data/funchook/distorm/examples/cs/distorm-net/Opcodes.cs +1268 -0
  95. data/funchook/distorm/examples/cs/distorm-net/Opcodes.tt +37 -0
  96. data/funchook/distorm/examples/cs/distorm-net/Operand.cs +25 -0
  97. data/funchook/distorm/examples/cs/distorm-net/Properties/AssemblyInfo.cs +36 -0
  98. data/funchook/distorm/examples/cs/distorm-net/diStorm3.cs +411 -0
  99. data/funchook/distorm/examples/cs/distorm-net/distorm-net.csproj +80 -0
  100. data/funchook/distorm/examples/cs/readme +3 -0
  101. data/funchook/distorm/examples/ddk/README +48 -0
  102. data/funchook/distorm/examples/ddk/distorm.ini +11 -0
  103. data/funchook/distorm/examples/ddk/dummy.c +15 -0
  104. data/funchook/distorm/examples/ddk/main.c +91 -0
  105. data/funchook/distorm/examples/ddk/makefile +1 -0
  106. data/funchook/distorm/examples/ddk/sources +10 -0
  107. data/funchook/distorm/examples/java/Makefile +23 -0
  108. data/funchook/distorm/examples/java/distorm/src/Main.java +43 -0
  109. data/funchook/distorm/examples/java/distorm/src/diStorm3/CodeInfo.java +27 -0
  110. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedInst.java +32 -0
  111. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedResult.java +11 -0
  112. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedInst.java +89 -0
  113. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedResult.java +11 -0
  114. data/funchook/distorm/examples/java/distorm/src/diStorm3/OpcodeEnum.java +131 -0
  115. data/funchook/distorm/examples/java/distorm/src/diStorm3/Opcodes.java +1123 -0
  116. data/funchook/distorm/examples/java/distorm/src/diStorm3/Operand.java +24 -0
  117. data/funchook/distorm/examples/java/distorm/src/diStorm3/distorm3.java +41 -0
  118. data/funchook/distorm/examples/java/jdistorm.c +405 -0
  119. data/funchook/distorm/examples/java/jdistorm.h +40 -0
  120. data/funchook/distorm/examples/java/jdistorm.sln +20 -0
  121. data/funchook/distorm/examples/java/jdistorm.vcproj +208 -0
  122. data/funchook/distorm/examples/linux/Makefile +15 -0
  123. data/funchook/distorm/examples/linux/main.c +181 -0
  124. data/funchook/distorm/examples/tests/Makefile +15 -0
  125. data/funchook/distorm/examples/tests/main.cpp +42 -0
  126. data/funchook/distorm/examples/tests/main.py +66 -0
  127. data/funchook/distorm/examples/tests/test_distorm3.py +1672 -0
  128. data/funchook/distorm/examples/tests/tests.sln +20 -0
  129. data/funchook/distorm/examples/tests/tests.vcxproj +82 -0
  130. data/funchook/distorm/examples/tests/tests.vcxproj.filters +22 -0
  131. data/funchook/distorm/examples/win32/disasm.sln +25 -0
  132. data/funchook/distorm/examples/win32/disasm.vcxproj +201 -0
  133. data/funchook/distorm/examples/win32/disasm.vcxproj.filters +14 -0
  134. data/funchook/distorm/examples/win32/main.cpp +163 -0
  135. data/funchook/distorm/include/distorm.h +482 -0
  136. data/funchook/distorm/include/mnemonics.h +301 -0
  137. data/funchook/distorm/make/linux/Makefile +28 -0
  138. data/funchook/distorm/make/mac/Makefile +24 -0
  139. data/funchook/distorm/make/win32/cdistorm.vcxproj +239 -0
  140. data/funchook/distorm/make/win32/cdistorm.vcxproj.filters +80 -0
  141. data/funchook/distorm/make/win32/distorm.sln +25 -0
  142. data/funchook/distorm/make/win32/resource.h +14 -0
  143. data/funchook/distorm/make/win32/resource.rc +99 -0
  144. data/funchook/distorm/python/distorm3/__init__.py +957 -0
  145. data/funchook/distorm/python/distorm3/sample.py +51 -0
  146. data/funchook/distorm/setup.cfg +10 -0
  147. data/funchook/distorm/setup.py +266 -0
  148. data/funchook/distorm/src/config.h +169 -0
  149. data/funchook/distorm/src/decoder.c +641 -0
  150. data/funchook/distorm/src/decoder.h +33 -0
  151. data/funchook/distorm/src/distorm.c +413 -0
  152. data/funchook/distorm/src/instructions.c +597 -0
  153. data/funchook/distorm/src/instructions.h +463 -0
  154. data/funchook/distorm/src/insts.c +7939 -0
  155. data/funchook/distorm/src/insts.h +64 -0
  156. data/funchook/distorm/src/mnemonics.c +284 -0
  157. data/funchook/distorm/src/operands.c +1290 -0
  158. data/funchook/distorm/src/operands.h +28 -0
  159. data/funchook/distorm/src/prefix.c +368 -0
  160. data/funchook/distorm/src/prefix.h +64 -0
  161. data/funchook/distorm/src/textdefs.c +172 -0
  162. data/funchook/distorm/src/textdefs.h +57 -0
  163. data/funchook/distorm/src/wstring.c +47 -0
  164. data/funchook/distorm/src/wstring.h +35 -0
  165. data/funchook/distorm/src/x86defs.h +82 -0
  166. data/funchook/include/funchook.h +123 -0
  167. data/funchook/install-sh +527 -0
  168. data/funchook/src/Makefile +70 -0
  169. data/funchook/src/Makefile.in +70 -0
  170. data/funchook/src/__strerror.h +109 -0
  171. data/funchook/src/config.h +101 -0
  172. data/funchook/src/config.h.in +100 -0
  173. data/funchook/src/decoder.o +0 -0
  174. data/funchook/src/distorm.o +0 -0
  175. data/funchook/src/funchook.c +440 -0
  176. data/funchook/src/funchook.o +0 -0
  177. data/funchook/src/funchook_internal.h +155 -0
  178. data/funchook/src/funchook_io.c +182 -0
  179. data/funchook/src/funchook_io.h +64 -0
  180. data/funchook/src/funchook_io.o +0 -0
  181. data/funchook/src/funchook_syscall.S +134 -0
  182. data/funchook/src/funchook_syscall.o +0 -0
  183. data/funchook/src/funchook_unix.c +480 -0
  184. data/funchook/src/funchook_unix.o +0 -0
  185. data/funchook/src/funchook_windows.c +397 -0
  186. data/funchook/src/funchook_x86.c +622 -0
  187. data/funchook/src/funchook_x86.o +0 -0
  188. data/funchook/src/instructions.o +0 -0
  189. data/funchook/src/insts.o +0 -0
  190. data/funchook/src/libfunchook.so +0 -0
  191. data/funchook/src/mnemonics.o +0 -0
  192. data/funchook/src/operands.o +0 -0
  193. data/funchook/src/os_func.c +115 -0
  194. data/funchook/src/os_func.h +75 -0
  195. data/funchook/src/os_func.o +0 -0
  196. data/funchook/src/os_func_unix.c +94 -0
  197. data/funchook/src/os_func_unix.o +0 -0
  198. data/funchook/src/os_func_windows.c +32 -0
  199. data/funchook/src/prefix.o +0 -0
  200. data/funchook/src/printf_base.c +1688 -0
  201. data/funchook/src/printf_base.h +46 -0
  202. data/funchook/src/printf_base.o +0 -0
  203. data/funchook/src/textdefs.o +0 -0
  204. data/funchook/src/wstring.o +0 -0
  205. data/funchook/test/Makefile +43 -0
  206. data/funchook/test/Makefile.in +43 -0
  207. data/funchook/test/funchook_test +0 -0
  208. data/funchook/test/libfunchook_test.c +25 -0
  209. data/funchook/test/libfunchook_test.so +0 -0
  210. data/funchook/test/libfunchook_test2.c +18 -0
  211. data/funchook/test/suffix.list +600 -0
  212. data/funchook/test/test_main.c +430 -0
  213. data/funchook/test/test_main.o +0 -0
  214. data/funchook/test/x86_64_test.S +10 -0
  215. data/funchook/test/x86_64_test.o +0 -0
  216. data/funchook/test/x86_test.S +339 -0
  217. data/funchook/win32/config.h +1 -0
  218. data/funchook/win32/funchook.sln +52 -0
  219. data/funchook/win32/funchook.vcxproj +188 -0
  220. data/funchook/win32/funchook.vcxproj.filters +84 -0
  221. data/funchook/win32/funchook_test.vcxproj +170 -0
  222. data/funchook/win32/funchook_test.vcxproj.filters +22 -0
  223. data/funchook/win32/funchook_test_dll.vcxproj +184 -0
  224. data/funchook/win32/funchook_test_dll.vcxproj.filters +30 -0
  225. data/funchook/win32/funchook_test_exe.def +3 -0
  226. data/lib/contrast-agent.rb +8 -0
  227. data/lib/contrast.rb +57 -0
  228. data/lib/contrast/agent.rb +80 -0
  229. data/lib/contrast/agent/assess.rb +45 -0
  230. data/lib/contrast/agent/assess/adjusted_span.rb +25 -0
  231. data/lib/contrast/agent/assess/class_reverter.rb +82 -0
  232. data/lib/contrast/agent/assess/contrast_event.rb +398 -0
  233. data/lib/contrast/agent/assess/frozen_properties.rb +41 -0
  234. data/lib/contrast/agent/assess/insulator.rb +53 -0
  235. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +78 -0
  236. data/lib/contrast/agent/assess/policy/patcher.rb +85 -0
  237. data/lib/contrast/agent/assess/policy/policy.rb +116 -0
  238. data/lib/contrast/agent/assess/policy/policy_node.rb +289 -0
  239. data/lib/contrast/agent/assess/policy/policy_scanner.rb +44 -0
  240. data/lib/contrast/agent/assess/policy/preshift.rb +94 -0
  241. data/lib/contrast/agent/assess/policy/propagation_method.rb +260 -0
  242. data/lib/contrast/agent/assess/policy/propagation_node.rb +127 -0
  243. data/lib/contrast/agent/assess/policy/propagator.rb +35 -0
  244. data/lib/contrast/agent/assess/policy/propagator/append.rb +54 -0
  245. data/lib/contrast/agent/assess/policy/propagator/base.rb +37 -0
  246. data/lib/contrast/agent/assess/policy/propagator/center.rb +73 -0
  247. data/lib/contrast/agent/assess/policy/propagator/custom.rb +36 -0
  248. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +62 -0
  249. data/lib/contrast/agent/assess/policy/propagator/insert.rb +55 -0
  250. data/lib/contrast/agent/assess/policy/propagator/keep.rb +26 -0
  251. data/lib/contrast/agent/assess/policy/propagator/next.rb +42 -0
  252. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +50 -0
  253. data/lib/contrast/agent/assess/policy/propagator/remove.rb +76 -0
  254. data/lib/contrast/agent/assess/policy/propagator/replace.rb +27 -0
  255. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +38 -0
  256. data/lib/contrast/agent/assess/policy/propagator/select.rb +86 -0
  257. data/lib/contrast/agent/assess/policy/propagator/splat.rb +60 -0
  258. data/lib/contrast/agent/assess/policy/propagator/split.rb +49 -0
  259. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +169 -0
  260. data/lib/contrast/agent/assess/policy/propagator/trim.rb +81 -0
  261. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +79 -0
  262. data/lib/contrast/agent/assess/policy/source_method.rb +209 -0
  263. data/lib/contrast/agent/assess/policy/source_node.rb +62 -0
  264. data/lib/contrast/agent/assess/policy/trigger_method.rb +209 -0
  265. data/lib/contrast/agent/assess/policy/trigger_node.rb +198 -0
  266. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +77 -0
  267. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +31 -0
  268. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +40 -0
  269. data/lib/contrast/agent/assess/properties.rb +392 -0
  270. data/lib/contrast/agent/assess/rule.rb +18 -0
  271. data/lib/contrast/agent/assess/rule/base.rb +72 -0
  272. data/lib/contrast/agent/assess/rule/csrf.rb +66 -0
  273. data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +28 -0
  274. data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +69 -0
  275. data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +132 -0
  276. data/lib/contrast/agent/assess/rule/provider.rb +21 -0
  277. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +62 -0
  278. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +73 -0
  279. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +121 -0
  280. data/lib/contrast/agent/assess/rule/redos.rb +68 -0
  281. data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +47 -0
  282. data/lib/contrast/agent/assess/rule/response_watcher.rb +36 -0
  283. data/lib/contrast/agent/assess/rule/watcher.rb +36 -0
  284. data/lib/contrast/agent/assess/tag.rb +151 -0
  285. data/lib/contrast/agent/at_exit_hook.rb +33 -0
  286. data/lib/contrast/agent/class_reopener.rb +195 -0
  287. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +26 -0
  288. data/lib/contrast/agent/deadzone/policy/policy.rb +57 -0
  289. data/lib/contrast/agent/disable_reaction.rb +24 -0
  290. data/lib/contrast/agent/exclusion_matcher.rb +190 -0
  291. data/lib/contrast/agent/feature_state.rb +379 -0
  292. data/lib/contrast/agent/inventory/policy/policy.rb +32 -0
  293. data/lib/contrast/agent/inventory/policy/trigger_node.rb +22 -0
  294. data/lib/contrast/agent/logger_manager.rb +116 -0
  295. data/lib/contrast/agent/middleware.rb +352 -0
  296. data/lib/contrast/agent/module_data.rb +16 -0
  297. data/lib/contrast/agent/patching/policy/after_load_patch.rb +37 -0
  298. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +58 -0
  299. data/lib/contrast/agent/patching/policy/method_policy.rb +94 -0
  300. data/lib/contrast/agent/patching/policy/module_policy.rb +116 -0
  301. data/lib/contrast/agent/patching/policy/patch.rb +312 -0
  302. data/lib/contrast/agent/patching/policy/patch_status.rb +192 -0
  303. data/lib/contrast/agent/patching/policy/patcher.rb +310 -0
  304. data/lib/contrast/agent/patching/policy/policy.rb +138 -0
  305. data/lib/contrast/agent/patching/policy/policy_node.rb +80 -0
  306. data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +28 -0
  307. data/lib/contrast/agent/patching/policy/trigger_node.rb +81 -0
  308. data/lib/contrast/agent/protect/policy/policy.rb +37 -0
  309. data/lib/contrast/agent/protect/policy/trigger_node.rb +23 -0
  310. data/lib/contrast/agent/protect/rule.rb +58 -0
  311. data/lib/contrast/agent/protect/rule/base.rb +300 -0
  312. data/lib/contrast/agent/protect/rule/base_service.rb +88 -0
  313. data/lib/contrast/agent/protect/rule/cmd_injection.rb +156 -0
  314. data/lib/contrast/agent/protect/rule/csrf.rb +118 -0
  315. data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +103 -0
  316. data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +85 -0
  317. data/lib/contrast/agent/protect/rule/default_scanner.rb +300 -0
  318. data/lib/contrast/agent/protect/rule/deserialization.rb +193 -0
  319. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +80 -0
  320. data/lib/contrast/agent/protect/rule/no_sqli.rb +101 -0
  321. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +40 -0
  322. data/lib/contrast/agent/protect/rule/path_traversal.rb +143 -0
  323. data/lib/contrast/agent/protect/rule/sqli.rb +101 -0
  324. data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +16 -0
  325. data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +38 -0
  326. data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +22 -0
  327. data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +19 -0
  328. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +20 -0
  329. data/lib/contrast/agent/protect/rule/xss.rb +24 -0
  330. data/lib/contrast/agent/protect/rule/xxe.rb +120 -0
  331. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +82 -0
  332. data/lib/contrast/agent/railtie.rb +30 -0
  333. data/lib/contrast/agent/reaction_processor.rb +47 -0
  334. data/lib/contrast/agent/request.rb +493 -0
  335. data/lib/contrast/agent/request_context.rb +225 -0
  336. data/lib/contrast/agent/require_state.rb +61 -0
  337. data/lib/contrast/agent/response.rb +215 -0
  338. data/lib/contrast/agent/rewriter.rb +244 -0
  339. data/lib/contrast/agent/scope.rb +28 -0
  340. data/lib/contrast/agent/service_heartbeat.rb +37 -0
  341. data/lib/contrast/agent/settings_state.rb +148 -0
  342. data/lib/contrast/agent/socket_client.rb +125 -0
  343. data/lib/contrast/agent/thread.rb +26 -0
  344. data/lib/contrast/agent/tracepoint_hook.rb +51 -0
  345. data/lib/contrast/agent/version.rb +8 -0
  346. data/lib/contrast/api.rb +17 -0
  347. data/lib/contrast/api/.gitkeep +0 -0
  348. data/lib/contrast/api/connection_status.rb +49 -0
  349. data/lib/contrast/api/socket.rb +43 -0
  350. data/lib/contrast/api/speedracer.rb +206 -0
  351. data/lib/contrast/api/tcp_socket.rb +31 -0
  352. data/lib/contrast/api/unix_socket.rb +25 -0
  353. data/lib/contrast/common_agent_configuration.rb +86 -0
  354. data/lib/contrast/components/agent.rb +85 -0
  355. data/lib/contrast/components/app_context.rb +188 -0
  356. data/lib/contrast/components/assess.rb +67 -0
  357. data/lib/contrast/components/config.rb +135 -0
  358. data/lib/contrast/components/contrast_service.rb +113 -0
  359. data/lib/contrast/components/heap_dump.rb +34 -0
  360. data/lib/contrast/components/interface.rb +178 -0
  361. data/lib/contrast/components/inventory.rb +23 -0
  362. data/lib/contrast/components/logger.rb +92 -0
  363. data/lib/contrast/components/protect.rb +38 -0
  364. data/lib/contrast/components/sampling.rb +41 -0
  365. data/lib/contrast/components/scope.rb +106 -0
  366. data/lib/contrast/components/settings.rb +140 -0
  367. data/lib/contrast/config.rb +33 -0
  368. data/lib/contrast/config/agent_configuration.rb +24 -0
  369. data/lib/contrast/config/application_configuration.rb +27 -0
  370. data/lib/contrast/config/assess_configuration.rb +22 -0
  371. data/lib/contrast/config/assess_rules_configuration.rb +18 -0
  372. data/lib/contrast/config/base_configuration.rb +105 -0
  373. data/lib/contrast/config/default_value.rb +16 -0
  374. data/lib/contrast/config/exception_configuration.rb +21 -0
  375. data/lib/contrast/config/heap_dump_configuration.rb +23 -0
  376. data/lib/contrast/config/inventory_configuration.rb +20 -0
  377. data/lib/contrast/config/logger_configuration.rb +20 -0
  378. data/lib/contrast/config/protect_configuration.rb +20 -0
  379. data/lib/contrast/config/protect_rule_configuration.rb +37 -0
  380. data/lib/contrast/config/protect_rules_configuration.rb +30 -0
  381. data/lib/contrast/config/root_configuration.rb +26 -0
  382. data/lib/contrast/config/ruby_configuration.rb +39 -0
  383. data/lib/contrast/config/sampling_configuration.rb +22 -0
  384. data/lib/contrast/config/server_configuration.rb +23 -0
  385. data/lib/contrast/config/service_configuration.rb +22 -0
  386. data/lib/contrast/configuration.rb +214 -0
  387. data/lib/contrast/core_extensions/assess.rb +51 -0
  388. data/lib/contrast/core_extensions/assess/array.rb +58 -0
  389. data/lib/contrast/core_extensions/assess/assess_extension.rb +145 -0
  390. data/lib/contrast/core_extensions/assess/basic_object.rb +15 -0
  391. data/lib/contrast/core_extensions/assess/erb.rb +42 -0
  392. data/lib/contrast/core_extensions/assess/exec_trigger.rb +48 -0
  393. data/lib/contrast/core_extensions/assess/fiber.rb +125 -0
  394. data/lib/contrast/core_extensions/assess/hash.rb +22 -0
  395. data/lib/contrast/core_extensions/assess/kernel.rb +95 -0
  396. data/lib/contrast/core_extensions/assess/module.rb +14 -0
  397. data/lib/contrast/core_extensions/assess/regexp.rb +206 -0
  398. data/lib/contrast/core_extensions/assess/string.rb +75 -0
  399. data/lib/contrast/core_extensions/assess/tilt_template_trigger.rb +73 -0
  400. data/lib/contrast/core_extensions/delegator.rb +14 -0
  401. data/lib/contrast/core_extensions/eval_trigger.rb +52 -0
  402. data/lib/contrast/core_extensions/inventory.rb +22 -0
  403. data/lib/contrast/core_extensions/inventory/datastores.rb +37 -0
  404. data/lib/contrast/core_extensions/module.rb +42 -0
  405. data/lib/contrast/core_extensions/object.rb +27 -0
  406. data/lib/contrast/core_extensions/protect.rb +20 -0
  407. data/lib/contrast/core_extensions/protect/applies_command_injection_rule.rb +70 -0
  408. data/lib/contrast/core_extensions/protect/applies_deserialization_rule.rb +58 -0
  409. data/lib/contrast/core_extensions/protect/applies_no_sqli_rule.rb +81 -0
  410. data/lib/contrast/core_extensions/protect/applies_path_traversal_rule.rb +119 -0
  411. data/lib/contrast/core_extensions/protect/applies_sqli_rule.rb +63 -0
  412. data/lib/contrast/core_extensions/protect/applies_xxe_rule.rb +141 -0
  413. data/lib/contrast/core_extensions/protect/kernel.rb +30 -0
  414. data/lib/contrast/core_extensions/protect/psych.rb +7 -0
  415. data/lib/contrast/core_extensions/thread.rb +31 -0
  416. data/lib/contrast/internal_exception.rb +8 -0
  417. data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +48 -0
  418. data/lib/contrast/rails_extensions/assess/active_record.rb +32 -0
  419. data/lib/contrast/rails_extensions/assess/active_record_named.rb +61 -0
  420. data/lib/contrast/rails_extensions/assess/configuration.rb +26 -0
  421. data/lib/contrast/rails_extensions/buffer.rb +30 -0
  422. data/lib/contrast/rails_extensions/rack.rb +45 -0
  423. data/lib/contrast/security_exception.rb +14 -0
  424. data/lib/contrast/sinatra_extensions/assess/cookie.rb +26 -0
  425. data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +59 -0
  426. data/lib/contrast/tasks/service.rb +95 -0
  427. data/lib/contrast/utils/assess/sampling_util.rb +96 -0
  428. data/lib/contrast/utils/assess/tracking_util.rb +39 -0
  429. data/lib/contrast/utils/boolean_util.rb +33 -0
  430. data/lib/contrast/utils/cache.rb +69 -0
  431. data/lib/contrast/utils/class_util.rb +58 -0
  432. data/lib/contrast/utils/comment_range.rb +19 -0
  433. data/lib/contrast/utils/data_store_util.rb +23 -0
  434. data/lib/contrast/utils/duck_utils.rb +58 -0
  435. data/lib/contrast/utils/env_configuration_item.rb +52 -0
  436. data/lib/contrast/utils/environment_util.rb +152 -0
  437. data/lib/contrast/utils/freeze_util.rb +36 -0
  438. data/lib/contrast/utils/gemfile_reader.rb +191 -0
  439. data/lib/contrast/utils/hash_digest.rb +148 -0
  440. data/lib/contrast/utils/heap_dump_util.rb +113 -0
  441. data/lib/contrast/utils/invalid_configuration_util.rb +88 -0
  442. data/lib/contrast/utils/inventory_util.rb +126 -0
  443. data/lib/contrast/utils/io_util.rb +61 -0
  444. data/lib/contrast/utils/object_share.rb +117 -0
  445. data/lib/contrast/utils/operating_environment.rb +38 -0
  446. data/lib/contrast/utils/os.rb +49 -0
  447. data/lib/contrast/utils/path_util.rb +151 -0
  448. data/lib/contrast/utils/performs_logging.rb +152 -0
  449. data/lib/contrast/utils/preflight_util.rb +13 -0
  450. data/lib/contrast/utils/prevent_serialization.rb +52 -0
  451. data/lib/contrast/utils/rack_assess_session_cookie.rb +104 -0
  452. data/lib/contrast/utils/rails_assess_configuration.rb +95 -0
  453. data/lib/contrast/utils/random_util.rb +22 -0
  454. data/lib/contrast/utils/resource_loader.rb +23 -0
  455. data/lib/contrast/utils/ruby_ast_rewriter.rb +74 -0
  456. data/lib/contrast/utils/scope_util.rb +99 -0
  457. data/lib/contrast/utils/service_response_util.rb +116 -0
  458. data/lib/contrast/utils/service_sender_util.rb +98 -0
  459. data/lib/contrast/utils/sha256_builder.rb +69 -0
  460. data/lib/contrast/utils/sinatra_helper.rb +49 -0
  461. data/lib/contrast/utils/stack_trace_utils.rb +209 -0
  462. data/lib/contrast/utils/string_utils.rb +72 -0
  463. data/lib/contrast/utils/tag_util.rb +139 -0
  464. data/lib/contrast/utils/thread_tracker.rb +54 -0
  465. data/lib/contrast/utils/timer.rb +78 -0
  466. data/resources/assess/policy.json +1673 -0
  467. data/resources/csrf/inject.js +44 -0
  468. data/resources/deadzone/policy.json +55 -0
  469. data/resources/factory-bot-spec/spec_helper.rb +30 -0
  470. data/resources/inventory/policy.json +110 -0
  471. data/resources/protect/policy.json +417 -0
  472. data/resources/rubocops/kernel/catch_cop.rb +37 -0
  473. data/resources/rubocops/kernel/require_cop.rb +37 -0
  474. data/resources/rubocops/kernel/require_relative_cop.rb +33 -0
  475. data/resources/rubocops/module/autoload_cop.rb +37 -0
  476. data/resources/rubocops/module/const_defined_cop.rb +37 -0
  477. data/resources/rubocops/module/const_get_cop.rb +37 -0
  478. data/resources/rubocops/module/const_set_cop.rb +37 -0
  479. data/resources/rubocops/module/constants_cop.rb +37 -0
  480. data/resources/rubocops/module/name_cop.rb +37 -0
  481. data/resources/rubocops/object/class_cop.rb +37 -0
  482. data/resources/rubocops/object/freeze_cop.rb +37 -0
  483. data/resources/rubocops/object/frozen_cop.rb +37 -0
  484. data/resources/rubocops/object/is_a_cop.rb +37 -0
  485. data/resources/rubocops/object/method_cop.rb +37 -0
  486. data/resources/rubocops/object/respond_to_cop.rb +37 -0
  487. data/resources/rubocops/object/singleton_class_cop.rb +37 -0
  488. data/resources/rubocops/regexp/spelling_cop.rb +44 -0
  489. data/resources/rubocops/thread/new_cop.rb +39 -0
  490. data/resources/ruby-spec/ancestors_spec.rb +70 -0
  491. data/resources/ruby-spec/modulo_spec.rb +831 -0
  492. data/resources/ruby-spec/parameters_spec.rb +261 -0
  493. data/resources/ruby-spec/ruby_spec_spec_helper.rb +35 -0
  494. data/resources/test_marker.txt +1 -0
  495. data/ruby-agent.gemspec +129 -0
  496. data/service_executables/.gitkeep +0 -0
  497. data/service_executables/VERSION +1 -0
  498. data/service_executables/linux/contrast-service +0 -0
  499. data/service_executables/mac/contrast-service +0 -0
  500. metadata +945 -0
@@ -0,0 +1,94 @@
1
+ # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ module Contrast
5
+ module Agent
6
+ module Patching
7
+ module Policy
8
+ # This class is used to map each method to the trigger node that applies to it
9
+ class MethodPolicy
10
+ attr_accessor :source_node, :propagation_node, :trigger_node,
11
+ :inventory_node, :protect_node, :deadzone_node,
12
+ :method_name, :method_visibility, :instance_method
13
+ def initialize(source_node: nil, propagation_node: nil,
14
+ trigger_node: nil, inventory_node: nil,
15
+ protect_node: nil, deadzone_node: nil,
16
+ method_name: nil, method_visibility: nil,
17
+ instance_method: nil)
18
+ @method_name = method_name
19
+ @method_visibility = method_visibility
20
+ @instance_method = instance_method
21
+ @source_node = source_node
22
+ @propagation_node = propagation_node
23
+ @trigger_node = trigger_node
24
+ @inventory_node = inventory_node
25
+ @protect_node = protect_node
26
+ @deadzone_node = deadzone_node
27
+ end
28
+
29
+ def private_method?
30
+ method_visibility == :private
31
+ end
32
+
33
+ def empty?
34
+ return false if source_node
35
+ return false if propagation_node
36
+ return false if trigger_node
37
+ return false if inventory_node
38
+ return false if protect_node
39
+ return false if deadzone_node
40
+
41
+ true
42
+ end
43
+
44
+ def requires_custom_patch?
45
+ !!@trigger_node&.custom_patch?
46
+ end
47
+
48
+ class << self
49
+ # Given a Contrast::Agent::Patching::Policy::ModulePolicy, parse
50
+ # out its information for the given method in order to construct a
51
+ # Contrast::Agent::Patching::Policy::MethodPolicy
52
+ #
53
+ # @param method_name [Symbol] the name of the method for this policy
54
+ # @param module_policy [Contrast::Agent::Patching::Policy::ModulePolicy]
55
+ # the entire policy for this module
56
+ # @param instance_method [Boolean] true if this method is an
57
+ # instance method
58
+ # @return [Contrast::Agent::Patching::Policy::MethodPolicy]
59
+ def build_method_policy method_name, module_policy, instance_method
60
+ source_node = find_method_node(module_policy.source_nodes, method_name, instance_method)
61
+ propagation_node = find_method_node(module_policy.propagator_nodes, method_name, instance_method)
62
+ trigger_node = find_method_node(module_policy.trigger_nodes, method_name, instance_method)
63
+ protect_node = find_method_node(module_policy.protect_nodes, method_name, instance_method)
64
+ inventory_node = find_method_node(module_policy.inventory_nodes, method_name, instance_method)
65
+ deadzone_node = find_method_node(module_policy.deadzone_nodes, method_name, instance_method)
66
+ method_visibility = find_visibility(source_node, propagation_node, trigger_node, protect_node, inventory_node, deadzone_node)
67
+ MethodPolicy.new(method_name: method_name,
68
+ method_visibility: method_visibility,
69
+ instance_method: instance_method,
70
+ source_node: source_node,
71
+ propagation_node: propagation_node,
72
+ trigger_node: trigger_node,
73
+ protect_node: protect_node,
74
+ inventory_node: inventory_node,
75
+ deadzone_node: deadzone_node)
76
+ end
77
+
78
+ def find_method_node nodes, method_name, is_instance_method
79
+ return nil unless nodes
80
+
81
+ nodes.find do |node|
82
+ node.instance_method? == is_instance_method && node.method_name == method_name
83
+ end
84
+ end
85
+
86
+ def find_visibility *nodes
87
+ nodes.find { |node| node }&.method_visibility
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,116 @@
1
+ # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ cs__scoped_require 'contrast/agent/patching/policy/method_policy'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Patching
9
+ module Policy
10
+ # This class is used to map a class to all policy nodes utilizing that
11
+ # class. It should be initialized using the create_module_policy method
12
+ # rather than new.
13
+ class ModulePolicy
14
+ class << self
15
+ # Given the name of a module, create a :ModulePolicy for it using
16
+ # the Policy of each supported feature
17
+ #
18
+ # @param module_name [String] the name of the module to which the
19
+ # policy applies
20
+ # @return [Contrast::Agent::Patching::Policy::ModulePolicy]
21
+ def create_module_policy module_name
22
+ module_policy = Contrast::Agent::Patching::Policy::ModulePolicy.new
23
+ module_policy.source_nodes = nodes_for_module(Contrast::Agent::Assess::Policy::Policy.instance.sources, module_name)
24
+ module_policy.propagator_nodes = nodes_for_module(Contrast::Agent::Assess::Policy::Policy.instance.propagators, module_name)
25
+ module_policy.trigger_nodes = nodes_for_module(Contrast::Agent::Assess::Policy::Policy.instance.triggers, module_name)
26
+ module_policy.protect_nodes = nodes_for_module(Contrast::Agent::Protect::Policy::Policy.instance.triggers, module_name)
27
+ module_policy.inventory_nodes = nodes_for_module(Contrast::Agent::Inventory::Policy::Policy.instance.triggers, module_name)
28
+ module_policy.deadzone_nodes = nodes_for_module(Contrast::Agent::Deadzone::Policy::Policy.instance.deadzones, module_name)
29
+ module_policy
30
+ end
31
+
32
+ # Find any of the given patchers that match this class' names.
33
+ # Always returns an array, even if it's empty.
34
+ #
35
+ # @param nodes [Array(Contrast::Agent::Patching::Policy::PolicyNode)]
36
+ # an array of nodes
37
+ # @param class_name [String] the class to filter the nodes on
38
+ # @return [Array<Contrast::Agent::Patching::Policy::PolicyNode>]
39
+ # Subset of nodes which apply to the given class
40
+ def nodes_for_module nodes, class_name
41
+ nodes.select { |node| class_name == node.class_name }
42
+ end
43
+ end
44
+
45
+ attr_accessor :source_nodes, :propagator_nodes, :trigger_nodes, :inventory_nodes, :protect_nodes, :deadzone_nodes
46
+
47
+ def empty?
48
+ return false if source_nodes.any?
49
+ return false if propagator_nodes.any?
50
+ return false if trigger_nodes.any?
51
+ return false if inventory_nodes.any?
52
+ return false if protect_nodes.any?
53
+ return false if deadzone_nodes.any?
54
+
55
+ true
56
+ end
57
+
58
+ # The number of expected patches for this policy is the sum of unique
59
+ # targeted methods for the Module to which this policy applies.
60
+ #
61
+ # @return [Integer] count of methods to be patched
62
+ def num_expected_patches
63
+ @_num_expected_patches ||= begin
64
+ instance_methods = Set.new
65
+ singleton_methods = Set.new
66
+ sort_method_names(source_nodes, instance_methods, singleton_methods)
67
+ sort_method_names(propagator_nodes, instance_methods, singleton_methods)
68
+ sort_method_names(trigger_nodes, instance_methods, singleton_methods)
69
+ sort_method_names(inventory_nodes, instance_methods, singleton_methods)
70
+ sort_method_names(protect_nodes, instance_methods, singleton_methods)
71
+ sort_method_names(deadzone_nodes, instance_methods, singleton_methods)
72
+ instance_methods.length + singleton_methods.length
73
+ end
74
+ end
75
+
76
+ def collect_class_nodes nodes, clazz_name
77
+ return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless nodes
78
+
79
+ nodes.select { |policy_node| clazz_name == policy_node.class_name }
80
+ end
81
+
82
+ def collect_method_nodes nodes, method, instance_method
83
+ return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless nodes
84
+
85
+ nodes.select do |node|
86
+ node.instance_method? == instance_method && node.method_name == method
87
+ end
88
+ end
89
+
90
+ def create_method_policy_subset method, instance_method
91
+ method_policy = ModulePolicy.new
92
+ method_policy.source_nodes = collect_method_nodes(source_nodes, method, instance_method)
93
+ method_policy.propagator_nodes = collect_method_nodes(propagator_nodes, method, instance_method)
94
+ method_policy.trigger_nodes = collect_method_nodes(trigger_nodes, method, instance_method)
95
+ method_policy.inventory_nodes = collect_method_nodes(inventory_nodes, method, instance_method)
96
+ method_policy.protect_nodes = collect_method_nodes(protect_nodes, method, instance_method)
97
+ method_policy.deadzone_nodes = collect_method_nodes(deadzone_nodes, method, instance_method)
98
+ method_policy
99
+ end
100
+
101
+ private
102
+
103
+ def sort_method_names nodes, instance_methods, singleton_methods
104
+ nodes.each do |node|
105
+ if node.instance_method?
106
+ instance_methods << node.method_name
107
+ else
108
+ singleton_methods << node.method_name
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,312 @@
1
+ # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ cs__scoped_require 'monitor'
5
+ # base
6
+ cs__scoped_require 'contrast/core_extensions/module'
7
+ cs__scoped_require 'contrast/agent/patching/policy/method_policy'
8
+ cs__scoped_require 'contrast/agent/patching/policy/patch_status'
9
+ cs__scoped_require 'contrast/agent/patching/policy/trigger_node'
10
+ cs__scoped_require 'contrast/components/interface'
11
+ cs__scoped_require 'contrast/utils/scope_util'
12
+
13
+ # assess
14
+ cs__scoped_require 'contrast/agent/assess/policy/policy'
15
+ cs__scoped_require 'contrast/agent/assess/policy/propagation_method'
16
+ cs__scoped_require 'contrast/agent/assess/policy/source_method'
17
+ cs__scoped_require 'contrast/agent/assess/policy/trigger_method'
18
+ cs__scoped_require 'contrast/core_extensions/assess'
19
+
20
+ # inventory
21
+ cs__scoped_require 'contrast/agent/inventory/policy/policy'
22
+ cs__scoped_require 'contrast/core_extensions/inventory'
23
+
24
+ # protect
25
+ cs__scoped_require 'contrast/agent/protect/policy/policy'
26
+ cs__scoped_require 'contrast/core_extensions/protect'
27
+ cs__scoped_require 'contrast/core_extensions/protect/kernel'
28
+
29
+ module Contrast
30
+ module Agent
31
+ module Patching
32
+ module Policy
33
+ # This is how we patch into our customer's code. It provides a way to
34
+ # track which classes we need to patch into and, once we've woven,
35
+ # provides a map for which methods our renamed functions need to call
36
+ # and how.
37
+ module Patch
38
+ class << self
39
+ include Contrast::Agent::Assess::Policy::SourceMethod
40
+ include Contrast::Agent::Assess::Policy::PropagationMethod
41
+ include Contrast::Agent::Assess::Policy::TriggerMethod
42
+ extend Contrast::Utils::ScopeUtil
43
+
44
+ include Contrast::Components::Interface
45
+ access_component :logging, :analysis, :agent, :scope
46
+
47
+ POLICIES = [
48
+ Contrast::Agent::Assess::Policy::Policy,
49
+ Contrast::Agent::Inventory::Policy::Policy,
50
+ Contrast::Agent::Protect::Policy::Policy
51
+ ].cs__freeze
52
+
53
+ # THIS IS CALLED FROM C. Do not change the signature lightly.
54
+ #
55
+ # This method functions to call the infilter methods from our
56
+ # patches, allowing for analysis and reporting at the point just
57
+ # before the patched code is invoked.
58
+ #
59
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
60
+ # Mapping of the triggers on the given method.
61
+ # @param method [Symbol] The method into which we're patching
62
+ # @param exception [StandardError] Any exception raised during the
63
+ # call of the patched method.
64
+ # @param object [Object] The object on which the method is invoked,
65
+ # typically what would be returned by self.
66
+ # @param args [Array<Object>] The arguments passed to the method
67
+ # being invoked.
68
+ def apply_pre_patch method_policy, method, exception, object, args
69
+ apply_protect(method_policy, method, exception, object, args)
70
+ apply_inventory(method_policy, method, exception, object, args)
71
+ # We were told to block something, so we gotta. Don't catch this
72
+ # one, let it get back to our Middleware or even all the way out to
73
+ # the framework
74
+ rescue Contrast::SecurityException => e
75
+ # This can be C's responsibility, but it's a lot of code.
76
+ # Rewrite this to make C do it, once we have better macroing.
77
+ exit_contrast_scope!
78
+ raise e
79
+ # Anything else was our bad and we gotta catch that to allow for
80
+ # normal application flow
81
+ rescue StandardError => e
82
+ logger.error(e, 'Unable to apply pre patch to method.')
83
+ end
84
+
85
+ # THIS IS CALLED FROM C. Do not change the signature lightly.
86
+ #
87
+ # This method functions to call the infilter methods from our
88
+ # patches, allowing for analysis and reporting at the point just
89
+ # after the patched code is invoked
90
+ #
91
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
92
+ # Mapping of the triggers on the given method.
93
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture
94
+ # of the state of the code just prior to the invocation of the
95
+ # patched method.
96
+ # @param object [Object] The object on which the method was
97
+ # invoked, typically what would be returned by self.
98
+ # @param ret [Object] The return of the method that was invoked.
99
+ # @param args [Array<Object>] The arguments passed to the method
100
+ # being invoked.
101
+ # @param block [Proc] The block passed to the method that was
102
+ # invoked.
103
+ def apply_post_patch method_policy, preshift, object, ret, args, block
104
+ apply_assess(method_policy, preshift, object, ret, args, block)
105
+ rescue StandardError => e
106
+ logger.error(e, 'Unable to apply post patch to method.')
107
+ end
108
+
109
+ # Apply the Protect patch which applies to the given method.
110
+ #
111
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
112
+ # Mapping of the triggers on the given method.
113
+ # @param method [Symbol] The method into which we're patching
114
+ # @param exception [StandardError] Any exception raised during the
115
+ # call of the patched method.
116
+ # @param object [Object] The object on which the method is invoked,
117
+ # typically what would be returned by self.
118
+ # @param args [Array<Object>] The arguments passed to the method
119
+ # being invoked.
120
+ def apply_protect method_policy, method, exception, object, args
121
+ return unless PROTECT.enabled?
122
+
123
+ apply_trigger_only(method_policy&.protect_node,
124
+ method,
125
+ exception,
126
+ object,
127
+ args)
128
+ end
129
+
130
+ # Apply the Inventory patch which applies to the given method.
131
+ #
132
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
133
+ # Mapping of the triggers on the given method.
134
+ # @param method [Symbol] The method into which we're patching
135
+ # @param exception [StandardError] Any exception raised during the
136
+ # call of the patched method.
137
+ # @param object [Object] The object on which the method is invoked,
138
+ # typically what would be returned by self.
139
+ # @param args [Array<Object>] The arguments passed to the method
140
+ # being invoked.
141
+ def apply_inventory method_policy, method, exception, object, args
142
+ return unless INVENTORY.enabled?
143
+
144
+ apply_trigger_only(method_policy&.inventory_node,
145
+ method,
146
+ exception,
147
+ object,
148
+ args)
149
+ end
150
+
151
+ # Apply the Assess patches which apply to the given method.
152
+ #
153
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
154
+ # Mapping of the triggers on the given method.
155
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture
156
+ # of the state of the code just prior to the invocation of the
157
+ # patched method.
158
+ # @param object [Object] The object on which the method was
159
+ # invoked, typically what would be returned by self.
160
+ # @param ret [Object] The return of the method that was invoked.
161
+ # @param args [Array<Object>] The arguments passed to the method
162
+ # being invoked.
163
+ # @param block [Proc] The block passed to the method that was
164
+ # invoked.
165
+ def apply_assess method_policy, preshift, object, ret, args, block
166
+ source_ret = nil
167
+ propagated_ret = nil
168
+ return ret unless method_policy && ASSESS.enabled?
169
+
170
+ current_context = Contrast::Agent::REQUEST_TRACKER.current
171
+ return ret unless current_context.analyze_request?
172
+
173
+ trigger_node = method_policy.trigger_node
174
+ Contrast::Agent::Assess::Policy::TriggerMethod.apply_trigger_rule(trigger_node, object, ret, args) if trigger_node
175
+
176
+ if method_policy.source_node
177
+ # If we were given a frozen return, and it was the target of a
178
+ # source, and we have frozen sources enabled, we'll need to
179
+ # replace the return. Note, this is not the default case.
180
+ source_ret = Contrast::Agent::Assess::Policy::SourceMethod.source_patchers(method_policy, object, ret, args)
181
+ end
182
+
183
+ if method_policy.propagation_node
184
+ propagated_ret = Contrast::Agent::Assess::Policy::PropagationMethod.apply_propagation(
185
+ method_policy,
186
+ preshift,
187
+ object,
188
+ source_ret || ret,
189
+ args,
190
+ block)
191
+ end
192
+
193
+ handle_return(propagated_ret, source_ret, ret)
194
+ rescue StandardError => e
195
+ logger.error(e, 'Unable to assess method call.')
196
+ handle_return(propagated_ret, source_ret, ret)
197
+ rescue Exception => e # rubocop:disable Lint/RescueException
198
+ logger.error(e, 'Unable to assess method call.')
199
+ handle_return(propagated_ret, source_ret, ret)
200
+ # This will unwind the stack, so we handle our own scope exit.
201
+ # Move this to C when it's convenient.
202
+ exit_contrast_scope!
203
+ raise e
204
+ end
205
+
206
+ # Generic invocation of the Inventory or Protect patch which apply
207
+ # to the given method.
208
+ #
209
+ # @param trigger_node [Contrast::Agent::Inventory::Policy::TriggerNode]
210
+ # Mapping of the specific trigger on the given method.
211
+ # @param method [Symbol] The method into which we're patching
212
+ # @param exception [StandardError] Any exception raised during the
213
+ # call of the patched method.
214
+ # @param object [Object] The object on which the method is invoked,
215
+ # typically what would be returned by self.
216
+ # @param args [Array<Object>] The arguments passed to the method
217
+ # being invoked.
218
+ def apply_trigger_only trigger_node, method, exception, object, args
219
+ return unless trigger_node
220
+
221
+ # If that rule only applies in the case of an exception being
222
+ # thrown and there's no exception here, move along, or vice versa
223
+ return if trigger_node.on_exception && !exception
224
+ return if !trigger_node.on_exception && exception
225
+
226
+ # Each patch has an applicator that handles logic for it. Think
227
+ # of this as being similar to propagator actions, most closely
228
+ # resembling CUSTOM - they all have a common interface but their
229
+ # own logic based on what's in the method(s) they've been patched
230
+ # into.
231
+ applicator = trigger_node.applicator
232
+ # Each patch also knows the method of its applicator. Some
233
+ # things, like AppliesXxeRule, have different methods depending
234
+ # on the library patched. This lets us handle the boilerplate of
235
+ # patching while still allowing for custom handling of the
236
+ # methods.
237
+ applicator_method = trigger_node.applicator_method
238
+ # By calling send like this, we can reuse all the patching.
239
+ # We `send` to the given method of the given class
240
+ # (applicator) since they all accept the same inputs
241
+ applicator.send(applicator_method, method, exception, trigger_node.properties, object, args)
242
+ end
243
+
244
+ # Method to choose which replaced return from the post_patch to
245
+ # actually return
246
+ #
247
+ # @param propagated_ret [Object, nil] The replaced return from the
248
+ # propagation patch.
249
+ # @param source_ret [Object, nil] The replaced return from the
250
+ # source patch.
251
+ # @param ret [Object, nil] The original return of the patched
252
+ # method.
253
+ # @return [Object, nil] The thing to return from the post patch.
254
+ def handle_return propagated_ret, source_ret, ret
255
+ safe_return = propagated_ret || source_ret || ret
256
+ safe_return.rewind if Contrast::Utils::IOUtil.should_rewind?(safe_return)
257
+ safe_return
258
+ end
259
+
260
+ # Given a class, method, and type, return a symbol in the format
261
+ # <method_start>_<class_name>_<method_name>
262
+ def build_method_name patcher_class, patcher_method
263
+ (Contrast::Utils::ObjectShare::CONTRAST_PATCHED_METHOD_START +
264
+ patcher_class.cs__name.gsub('::', '_').downcase +
265
+ Contrast::Utils::ObjectShare::UNDERSCORE +
266
+ patcher_method.to_s).to_sym
267
+ end
268
+
269
+ # @param mod [Module] the module in which the patch should be
270
+ # placed.
271
+ # @param methods [Array(Symbol)] all the instance or singleton
272
+ # methods in this clazz.
273
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
274
+ # the policy that applies to the method to be patched.
275
+ # @return [Boolean] if patched, either by this invocation or a
276
+ # previous, or not
277
+ def instrument_with_alias mod, methods, method_policy
278
+ cs_method_name = build_method_name(mod, method_policy.method_name)
279
+ # we've already patched this class, don't do it again
280
+ return true if methods.include?(cs_method_name)
281
+
282
+ begin
283
+ contrast_define_method(mod, method_policy, cs_method_name)
284
+ rescue NameError => e
285
+ # This shouldn't happen anymore, but just in case calling alias
286
+ # results in a NameError, we'll be safe here.
287
+ logger.debug(
288
+ e,
289
+ "The class #{ mod.cs__name } does not respond to the "\
290
+ "method#{ method_policy.method_name }.")
291
+ return false
292
+ end
293
+ true
294
+ end
295
+
296
+ # @param mod [Module] the module in which the patch should be
297
+ # placed.
298
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
299
+ # the policy that applies to the method to be patched.
300
+ # @return [Boolean] if patched, either by this invocation or a
301
+ # previous, or not
302
+ def instrument_with_prepend mod, method_policy
303
+ contrast_prepend_method(mod, method_policy)
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
310
+ end
311
+
312
+ cs__scoped_require 'cs__contrast_patch/cs__contrast_patch'