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,104 @@
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/components/interface'
5
+
6
+ module Contrast
7
+ module Utils
8
+ # This module is used to analyze non-rails session storage configuration for assess vulnerabilities
9
+ module RackAssessSessionCookie
10
+ include Contrast::Components::Interface
11
+
12
+ access_component :analysis, :logging, :scope
13
+
14
+ CS__SECURE_RULE_NAME = 'secure-flag-missing'
15
+ CS__HTTPONLY_NAME = 'rails-http-only-disabled'
16
+ CS__SESSION_TIMEOUT_NAME = 'session-timeout'
17
+ SAFE_SESSION_TIMEOUT = (30 * 60 * 60)
18
+ class << self
19
+ include Contrast::Utils::InvalidConfigurationUtil
20
+
21
+ def analyze_cookie_initialization options
22
+ return if PROTECT.enabled?
23
+
24
+ apply_session_timeout(options)
25
+ apply_httponly(options)
26
+ apply_secure_session(options)
27
+ end
28
+
29
+ def vulnerable_setting?(setting_key,
30
+ safe_settings_value,
31
+ options, safe_default: true,
32
+ comparison_type: nil)
33
+ # In most cases, Rack is pretty nice and the default value is safe
34
+ return !safe_default unless options&.key?(setting_key)
35
+
36
+ value = options[setting_key]
37
+
38
+ return value.to_i > safe_settings_value.to_i if comparison_type&.to_sym == :greater_than
39
+
40
+ value != safe_settings_value
41
+ end
42
+
43
+ def apply_secure_session options
44
+ return unless vulnerable_setting?(
45
+ :secure,
46
+ true,
47
+ options,
48
+ safe_default: false)
49
+
50
+ with_contrast_scope do
51
+ cs__report_finding(
52
+ CS__SECURE_RULE_NAME,
53
+ options,
54
+ caller_locations(10, 9)[0])
55
+ end
56
+ rescue StandardError => e
57
+ begin
58
+ logger.log_error('Unable to track call to secure session', e)
59
+ rescue StandardError
60
+ nil
61
+ end
62
+ end
63
+
64
+ def apply_session_timeout options
65
+ return unless vulnerable_setting?(:expire_after,
66
+ SAFE_SESSION_TIMEOUT,
67
+ options,
68
+ safe_default: false,
69
+ comparison_type: :greater_than)
70
+
71
+ with_contrast_scope do
72
+ cs__report_finding(
73
+ CS__SESSION_TIMEOUT_NAME,
74
+ options,
75
+ caller_locations(10, 9)[0])
76
+ end
77
+ rescue StandardError => e
78
+ begin
79
+ logger.log_error('Unable to track call to set session timeout', e)
80
+ rescue StandardError
81
+ nil
82
+ end
83
+ end
84
+
85
+ def apply_httponly options
86
+ return unless vulnerable_setting?(:httponly, true, options)
87
+
88
+ with_contrast_scope do
89
+ cs__report_finding(
90
+ CS__HTTPONLY_NAME,
91
+ options,
92
+ caller_locations(10, 9)[0])
93
+ end
94
+ rescue StandardError => e
95
+ begin
96
+ logger.log_error('Unable to track call to httponly', e)
97
+ rescue StandardError
98
+ nil
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,95 @@
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/components/interface'
5
+
6
+ module Contrast
7
+ module Utils
8
+ # This module is used to analyze rails session storage configuration for assess vulnerabilities
9
+ module RailsAssessConfiguration
10
+ include Contrast::Components::Interface
11
+
12
+ access_component :analysis, :logging, :scope
13
+
14
+ CS__SESSION_TIMEOUT_NAME = 'session-timeout'
15
+ SAFE_SESSION_TIMEOUT = (30 * 60 * 1000)
16
+ CS__SECURE_RULE_NAME = 'secure-flag-missing'
17
+ CS__HTTPONLY_RULE_NAME = 'rails-http-only-disabled'
18
+
19
+ class << self
20
+ include Contrast::Utils::InvalidConfigurationUtil
21
+
22
+ def analyze_session_store *args
23
+ return if PROTECT.enabled?
24
+
25
+ apply_httponly_disabled(*args)
26
+ apply_secure_cookie_disabled(*args)
27
+ apply_session_timeout(*args)
28
+ end
29
+
30
+ def vulnerable_setting? setting_key, safe_settings_value, original_args, safe_default: true, comparison_type: nil
31
+ # In most cases, Rails is pretty nice and the default value is safe
32
+ return !safe_default unless original_args && original_args.length > 1
33
+
34
+ # If the user overrode some args, but not ours, fall back on the default
35
+ rails_session_settings = original_args[1]
36
+ return !safe_default unless rails_session_settings&.key?(setting_key)
37
+
38
+ value = rails_session_settings[setting_key]
39
+
40
+ return value.to_i > safe_settings_value.to_i if comparison_type&.to_sym == :greater_than
41
+
42
+ value != safe_settings_value
43
+ end
44
+
45
+ def apply_session_timeout *args
46
+ return if ASSESS.rule_disabled? CS__SESSION_TIMEOUT_NAME
47
+ return unless vulnerable_setting?(:expire_after, SAFE_SESSION_TIMEOUT, args, comparison_type: :greater_than, safe_default: false)
48
+
49
+ rails_session_settings = args[1]
50
+ with_contrast_scope do
51
+ cs__report_finding(CS__SESSION_TIMEOUT_NAME, rails_session_settings, caller_locations(5, 4)[0])
52
+ end
53
+ rescue StandardError => e
54
+ begin
55
+ logger.log_error('Unable to track call to set session timeout', e)
56
+ rescue StandardError
57
+ nil
58
+ end
59
+ end
60
+
61
+ def apply_secure_cookie_disabled *args
62
+ return if ASSESS.rule_disabled? CS__SECURE_RULE_NAME
63
+ return unless vulnerable_setting?(:secure, true, args)
64
+
65
+ rails_session_settings = args[1]
66
+ with_contrast_scope do
67
+ cs__report_finding(CS__SECURE_RULE_NAME, rails_session_settings, caller_locations(5, 4)[0])
68
+ end
69
+ rescue StandardError => e
70
+ begin
71
+ logger.log_error('Unable to track call to disable secure cookies', e)
72
+ rescue StandardError
73
+ nil
74
+ end
75
+ end
76
+
77
+ def apply_httponly_disabled *args
78
+ return if ASSESS.rule_disabled? CS__HTTPONLY_RULE_NAME
79
+ return unless vulnerable_setting?(:httponly, true, args)
80
+
81
+ rails_session_settings = args[1]
82
+ with_contrast_scope do
83
+ cs__report_finding(CS__HTTPONLY_RULE_NAME, rails_session_settings, caller_locations(5, 4)[0])
84
+ end
85
+ rescue StandardError => e
86
+ begin
87
+ logger.log_error('Unable to track call to disable httponly in session cookie', e)
88
+ rescue StandardError
89
+ nil
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,22 @@
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 'securerandom'
5
+
6
+ module Contrast
7
+ module Utils
8
+ # Utilites for generating random strings
9
+ class RandomUtil
10
+ RANDOM_CHARS = (('0'..'9').to_a + ('A'..'Z').to_a).cs__freeze
11
+ RANDOM_LENGTH = RANDOM_CHARS.length
12
+
13
+ def self.secure_random_string len
14
+ arr = []
15
+ len.to_i.times do
16
+ arr << RANDOM_CHARS[SecureRandom.random_number(RANDOM_LENGTH)]
17
+ end
18
+ arr.join
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
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 Utils
6
+ # ResourceLoader can attempt to read a file from a predefined resource directory
7
+ class ResourceLoader
8
+ RESOURCES = 'resources'
9
+
10
+ # __FILE__/../../../resources
11
+ RESOURCE_ROOT = File.join(
12
+ File.dirname(__FILE__),
13
+ Contrast::Utils::ObjectShare::PARENT_PATH,
14
+ Contrast::Utils::ObjectShare::PARENT_PATH,
15
+ Contrast::Utils::ObjectShare::PARENT_PATH,
16
+ RESOURCES).cs__freeze
17
+
18
+ def self.load resource
19
+ File.read(File.join(RESOURCE_ROOT, resource))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: false
3
+
4
+ cs__scoped_require 'parser/current'
5
+
6
+ module Contrast
7
+ module Utils
8
+ # This utility allows us to parse and rewrite the AST in Ruby 2.4 & 2.5,
9
+ # allowing us to track String interpolation propagation by replacing those
10
+ # events with String#+ events instead.
11
+ class RubyAstRewriter < Parser::TreeRewriter
12
+ VARIABLES = %i[ivar cvar gvar].cs__freeze
13
+
14
+ # Rewrite the given source_string, converting the interpolation action
15
+ # therein to a concatenation action
16
+ #
17
+ # @param source_string [String] the String to rewrite
18
+ # @return [String] either the rewritten string or the original on error.
19
+ def rewrite source_string
20
+ ast = Parser::CurrentRuby.parse(source_string)
21
+ buffer = Parser::Source::Buffer.new('rewrite')
22
+ buffer.source = source_string
23
+ begin
24
+ super(buffer, ast)
25
+ rescue StandardError => _e
26
+ source_string
27
+ end
28
+ end
29
+
30
+ # This overloads the on_dstr method in Parser::AST::Processor to handle
31
+ # the replace within the given node.
32
+ def on_dstr node
33
+ return if node.children.all? { |child_node| child_node.type == :str }
34
+
35
+ new_content = '('
36
+ node.children.each_with_index do |child_node, index|
37
+ # A begin node looks like #{some_code} in ruby, we do a substring
38
+ # from [2...-1] to get rid of the #{ & trailing }.
39
+ if child_node.type == :begin
40
+ code = child_node.
41
+ location.
42
+ expression.
43
+ source_buffer.
44
+ source[child_node.location.begin.begin_pos...child_node.location.end.end_pos]
45
+ code = code[2...-1]
46
+ new_content += "((#{ code }).to_s)"
47
+
48
+ # For interpolations that use class, instance, or global variables,
49
+ # those are NOT within a begin block, but instead are a ivar, cvar,
50
+ # or gvar node, not stripping of interpolation markers required.
51
+ elsif VARIABLES.include?(child_node.type)
52
+ variable = child_node.children.first
53
+ new_content << "((#{ variable }).to_s)"
54
+
55
+ # When interpolation includes strings before or after an
56
+ # interpolation they are simple :str nodes, in order to preserve
57
+ # escaping we need to do a dump of the string value.
58
+ elsif child_node.type == :str
59
+ literal_value = child_node.children.first
60
+ literal_value = literal_value.dump[1...-1]
61
+ new_content << "\"#{ literal_value }\""
62
+ end
63
+ new_content << ' + ' unless index == node.children.length - 1
64
+ end
65
+ new_content << ')'
66
+ if node.location.cs__respond_to?(:heredoc_body)
67
+ replace(node.location.heredoc_body, new_content)
68
+ else
69
+ replace(node.location.expression, new_content)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,99 @@
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/components/interface'
5
+
6
+ module Kernel # :nodoc:
7
+ include Contrast::Components::Interface
8
+
9
+ access_component :scope
10
+
11
+ alias_method :cs__catch, :catch
12
+
13
+ # In the event of a `throw`, we need to override `catch`
14
+ # to save & restore scope state:
15
+ #
16
+ # scope_level == 0
17
+ #
18
+ # catch(:abc) do
19
+ # with_contrast_scope do
20
+ # throw :abc # will leak
21
+ # end
22
+ # end
23
+ #
24
+ # scope_level == 1
25
+ #
26
+ # While this will fix /all/ scope leaks, not just ones caused by `throw`,
27
+ # it shouldn't be relied upon as a catch-all (lmao) solution.
28
+
29
+ private
30
+
31
+ def catch *args, &block
32
+ # Save current scope level
33
+ scope_level = SCOPE.scope_for_current_ec.instance_variable_get(:@contrast_scope)
34
+
35
+ # Run original catch with block.
36
+ retval = cs__catch(*args, &block)
37
+
38
+ # Restore scope.
39
+ SCOPE.scope_for_current_ec.instance_variable_set(:@contrast_scope, scope_level)
40
+
41
+ retval
42
+ end
43
+ end
44
+
45
+ # ScopeUtil should probably be merged into Scope component.
46
+ module Contrast
47
+ module Utils
48
+ module ScopeUtil # :nodoc:
49
+ include Contrast::Components::Interface
50
+
51
+ access_component :analysis, :scope
52
+
53
+ # @return [Boolean]
54
+ def skip_contrast_analysis?
55
+ return true if in_contrast_scope?
56
+ return true unless Contrast::Agent::REQUEST_TRACKER.current&.analyze_request?
57
+
58
+ false
59
+ end
60
+
61
+ # Skip if we should skip_contrast_analysis?, sampling says to ignore this
62
+ # request, or assess has been disabled.
63
+ #
64
+ # @return [Boolean]
65
+ def skip_assess_analysis?
66
+ return true if skip_contrast_analysis?
67
+
68
+ current_context = Contrast::Agent::REQUEST_TRACKER.current
69
+ return true unless current_context.analyze_request?
70
+
71
+ !ASSESS.enabled?
72
+ end
73
+
74
+ def cs__enter_scope
75
+ enter_contrast_scope!
76
+ end
77
+
78
+ def cs__leave_scope
79
+ exit_contrast_scope!
80
+ end
81
+
82
+ def cs__enter_assess_scope
83
+ # If we shouldn't be doing assess things, don't propagate or whatever
84
+ disable_contrast = skip_assess_analysis?
85
+ return nil if disable_contrast
86
+
87
+ enter_contrast_scope!
88
+ end
89
+
90
+ def cs__enter_scope_contrast_patch
91
+ # If we're already in Contrast scope, don't propagate or whatever
92
+ disable_contrast = skip_contrast_analysis?
93
+ return nil if disable_contrast
94
+
95
+ enter_contrast_scope!
96
+ end
97
+ end
98
+ end
99
+ 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
+ module Contrast
5
+ module Utils
6
+ # Utility class for processing responses from the Contrast Service. Specifically, this class
7
+ # processes Server and Application settings and updates the Settings component.
8
+ module ServiceResponseUtil
9
+ include Contrast::Components::Interface
10
+ access_component :contrast_service, :logging, :settings, :analysis
11
+
12
+ class << self
13
+ # TODO: RUBY-119
14
+ def process_response response
15
+ fs = Contrast::Agent::FeatureState.instance
16
+ fs.last_update = response&.sent_ms
17
+ server_features = process_server_response(response)
18
+ app_settings = process_application_response(response)
19
+
20
+ # ReactionProcessor is a design pattern from TeamServer.
21
+ # Right now, there's one potential reaction, which is disabling the agent
22
+ Contrast::Agent::ReactionProcessor.process(response&.application_settings)
23
+ # Determine new accumulator state
24
+ if (new_accum = response&.accumulator_settings)
25
+ SETTINGS.accumulator_settings.replace(new_accum)
26
+ end
27
+
28
+ fs.logger_manager.update(server_features&.log_file, server_features&.log_level)
29
+ update_features(server_features, app_settings)
30
+ logger.debug("Agent modes: P-#{ fs.protect_enabled? ? 'ENABLED' : 'DISABLED' }, A-#{ fs.assess_enabled? ? 'ENABLED' : 'DISABLED' }")
31
+ end
32
+
33
+ private
34
+
35
+ # Given some protobuf messages, update settings.
36
+ # This is the bridge between Contrast Service <-> Settings.
37
+ LOG_SERVER_SETTINGS_UPDATE = 'Agent: Received updated server features'
38
+ LOG_UPDATE_PROTECT = 'Updating Protect state'
39
+ LOG_UPDATE_ASSESS = 'Updating Assess state'
40
+ def process_server_response response
41
+ server_features = response&.server_features
42
+ return unless server_features
43
+
44
+ logger.debug(LOG_SERVER_SETTINGS_UPDATE)
45
+ # 'defend' is legacy for 'protect' in the dtm.
46
+ protect = server_features.defend
47
+ assess = server_features.assess
48
+
49
+ protect_enable = !!protect.enabled
50
+ assess_enable = !!assess.enabled
51
+
52
+ # protect
53
+ begin
54
+ logger.debug(LOG_UPDATE_PROTECT)
55
+ SETTINGS.protect_state[:enabled] = protect_enable
56
+ end
57
+
58
+ # assess
59
+ begin
60
+ logger.debug(LOG_UPDATE_ASSESS)
61
+ SETTINGS.assess_state[:enabled] = assess_enable
62
+ SETTINGS.assess_state[:sampling_settings] = assess.sampling
63
+ end
64
+
65
+ server_features
66
+ end
67
+
68
+ MODE_WHITELIST = %i[NO_ACTION BLOCK_AT_PERIMETER MONITOR BLOCK].cs__freeze
69
+ LOG_APP_SETTINGS_UPDATE = 'Agent: Received updated application settings'
70
+ def process_application_response response
71
+ app_settings = response&.application_settings
72
+ return unless app_settings
73
+
74
+ logger.debug(LOG_APP_SETTINGS_UPDATE)
75
+ exclusion_matchers = app_settings.exclusions.map { |exc| Contrast::Agent::ExclusionMatcher.new(exc) }
76
+ protection_rules = app_settings.protection_rules.map { |pr, _hash| [pr.id, pr.mode] }
77
+ protection_rules.select! { |(_id, mode)| MODE_WHITELIST.include? mode }
78
+ modes_by_id = protection_rules.to_h
79
+ SETTINGS.application_state.merge!(
80
+ modes_by_id: modes_by_id,
81
+ exclusion_matchers: exclusion_matchers,
82
+ disabled_assess_rules: app_settings.disabled_assess_rules,
83
+ session_id: app_settings.session_id)
84
+
85
+ app_settings
86
+ end
87
+
88
+ # This is can also go into settings/c.service, but it
89
+ # requires protobuf decorators to be pretty and decomposed.
90
+ LOG_INFO_RULE_SETTINGS = 'Current rule settings:'
91
+ def update_features server_features, app_settings
92
+ if !!(server_features || app_settings)
93
+ logger.debug_with_time('Rebuilding rule modes') do
94
+ SETTINGS.build_protect_rules if PROTECT.enabled?
95
+ SETTINGS.build_assess_rules if ASSESS.enabled?
96
+
97
+ logger.info(LOG_INFO_RULE_SETTINGS)
98
+ PROTECT.rules.each { |k, v| logger.info(".. protect: #{ k } (#{ v.mode })") }
99
+ ASSESS.rules.each { |k, v| logger.info(".. assess: #{ k } (#{ v.enabled? })") }
100
+ end
101
+ end
102
+
103
+ if (dynamic_sources_map_pb = server_features&.assess&.dynamic_sources_map)
104
+ dynamic_sources_map = dynamic_sources_map_pb.keys.inject({}) do |hsh, key|
105
+ hsh[key] = dynamic_sources_map_pb[key]
106
+ end
107
+ Contrast::Agent::Assess::Policy::Policy.instance.update_dynamic_sources dynamic_sources_map
108
+ end
109
+ # This is for assess
110
+ # PERF, we could avoid here with dirty-tracking.
111
+ Contrast::Utils::Assess::SamplingUtil.instance.update
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end