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,244 @@
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
+ # intentional -- we're using a << operator here
5
+
6
+ cs__scoped_require 'contrast/agent/class_reopener'
7
+ cs__scoped_require 'contrast/agent/patching/policy/patch_status'
8
+ cs__scoped_require 'contrast/components/interface'
9
+ cs__scoped_require 'contrast/utils/ruby_ast_rewriter'
10
+
11
+ module Contrast
12
+ module Agent
13
+ # Used for Ruby 2.4 & 2.5 to allow us to rewrite those methods which have
14
+ # interpolation in them.
15
+ # @deprecated Changes to this class are discouraged as this approach is
16
+ # being phased out with support for those language versions.
17
+ class Rewriter
18
+ include Contrast::Components::Interface
19
+ access_component :logging, :scope
20
+
21
+ SELF_DEFINITION = 'def self.'.cs__freeze
22
+ DEFINITION = 'def '.cs__freeze
23
+
24
+ class << self
25
+ def rewrite_class module_data, redo_rewrite = false
26
+ mod = module_data.mod
27
+ return unless mod
28
+
29
+ status = Contrast::Agent::Patching::Policy::PatchStatus.get_status(mod)
30
+ return if (status.rewritten? || status.rewriting?) && !redo_rewrite
31
+
32
+ status.rewriting!
33
+
34
+ # default-initialize to nil within top-level method scope
35
+ # so that it's available w/in the `ensure` block
36
+ opener = nil
37
+ with_contrast_scope do
38
+ unless should_rewrite?(module_data)
39
+ status.no_rewrite!
40
+ return
41
+ end
42
+
43
+ opener = Contrast::Agent::ClassReopener.new(module_data)
44
+ if opener.nil? || (instance_methods.empty? && singleton_methods.empty?)
45
+ status.no_rewrite!
46
+ return
47
+ end
48
+
49
+ rewrite_all_methods(opener, mod, mod.public_instance_methods(false), :PUBLIC_INSTANCE)
50
+ rewrite_all_methods(opener, mod, mod.protected_instance_methods(false), :PROTECTED_INSTANCE)
51
+ rewrite_all_methods(opener, mod, mod.private_instance_methods(false), :PRIVATE_INSTANCE)
52
+ rewrite_all_methods(opener, mod, mod.singleton_methods(false), :SINGLETON)
53
+ status.rewritten!
54
+ end
55
+ rescue SyntaxError, StandardError => e
56
+ opener = nil
57
+ mod ||= module_data.mod
58
+ logger.debug(e, "Reopening #{ mod } threw a handled exception - skipping rewriting")
59
+ status ||= Contrast::Agent::Patching::Policy::PatchStatus.get_status(mod)
60
+ status.failed_rewrite!
61
+ ensure
62
+ with_contrast_scope do
63
+ opener&.commit_patches
64
+ end
65
+ logger.debug(
66
+ nil,
67
+ "Rewriting #{ module_data.name } resulted in #{ Contrast::Agent::Patching::Policy::PatchStatus.get_status(module_data.mod).rewrite_status }")
68
+ end
69
+
70
+ private
71
+
72
+ def rewrite_all_methods opener, clazz, methods, type
73
+ methods.each do |method|
74
+ # Skip contrast woven methods.
75
+ # There should be a better way to do this
76
+ next if method.to_s.start_with?('cs__')
77
+
78
+ original_source_code = source_code(opener, clazz, method, type)
79
+ next if original_source_code.nil?
80
+ next if unrepeatable?(original_source_code)
81
+ next unless interpolations?(original_source_code)
82
+
83
+ replace_method_definition(opener, clazz, method, original_source_code, type)
84
+ end
85
+ end
86
+
87
+ def source_code opener, clazz, method_name, type
88
+ return unless method_exists?(clazz, method_name, type)
89
+
90
+ method_instance = method_instance(clazz, method_name, type)
91
+ return nil if method_instance.nil?
92
+
93
+ location = method_instance.source_location
94
+ return nil if location.nil?
95
+ return nil if location.empty? || location[0].empty? || location[0].include?('eval')
96
+ return nil if opener.written_from_location?(location)
97
+
98
+ opener.source_code(location, method_name)
99
+ rescue SyntaxError
100
+ logger.debug(nil, "SyntaxError: Can't parse method source from #{ clazz }##{ method_name }")
101
+ rescue StandardError => e
102
+ if defined?(MethodSource) && defined?(MethodSource::SourceNotFoundError)
103
+ logger.debug(nil, "SourceNotFoundError: Can't parse method source from #{ clazz }##{ method_name }")
104
+ else
105
+ logger.debug(e, "Method source lookup of #{ clazz }##{ method_name } failed")
106
+ end
107
+ end
108
+
109
+ def method_exists? clazz, method_name, type
110
+ case type
111
+ when :SINGLETON
112
+ clazz.cs__singleton_class.public_method_defined?(method_name)
113
+ when :PUBLIC_INSTANCE
114
+ clazz.public_method_defined?(method_name)
115
+ when :PROTECTED_INSTANCE
116
+ clazz.protected_method_defined?(method_name)
117
+ when :PRIVATE_INSTANCE
118
+ clazz.private_method_defined?(method_name)
119
+ end
120
+ end
121
+
122
+ def method_instance clazz, method_name, type
123
+ case type
124
+ when :SINGLETON
125
+ clazz.singleton_method(method_name)
126
+ else
127
+ clazz.instance_method(method_name)
128
+ end
129
+ end
130
+
131
+ def replace_method_definition opener, clazz, method, original_source_code, type
132
+ new_method_source = rewrite_method(original_source_code)
133
+ return unless valid_code?(new_method_source)
134
+
135
+ case type
136
+ when :SINGLETON
137
+ opener.public_singleton_methods << new_method_source
138
+ when :PUBLIC_INSTANCE
139
+ opener.public_instance_methods << new_method_source
140
+ when :PROTECTED_INSTANCE
141
+ opener.protected_instance_methods << new_method_source
142
+ when :PRIVATE_INSTANCE
143
+ opener.private_instance_methods << new_method_source
144
+ end
145
+ rescue StandardError => e
146
+ logger.debug(e, "Error in rewriter class_eval for of #{ clazz }##{ method }")
147
+ end
148
+
149
+ def rewrite_method original_source_code
150
+ new_code = rewrite(original_source_code)
151
+ new_code = remove_self_definition(new_code)
152
+ new_code
153
+ end
154
+
155
+ def rewrite source
156
+ @rewriter ||= Contrast::Utils::RubyAstRewriter.new
157
+ @rewriter.rewrite(source)
158
+ end
159
+
160
+ def remove_self_definition new_code
161
+ new_code.gsub(SELF_DEFINITION, DEFINITION)
162
+ end
163
+
164
+ # attempt to generate an AST for the rewritten code, if one can be generated we can assume it is at least valid ruby
165
+ # if it returns nil that means that the AST was unable to build due to an error and we should use the original source code
166
+ def valid_code? new_content
167
+ !Ripper.sexp(new_content).nil?
168
+ end
169
+
170
+ def interpolations? method_source
171
+ method_source.match?(/^.*".*#(\$\w+|@\w+|@@\w+|\{.*\}).*".*$/)
172
+ end
173
+
174
+ # These functions cannot be repeated -- when doing replace things, we
175
+ # should comment these lines out.
176
+ # cannot repeat class foo <
177
+ # bar
178
+ UNREPEATABLE_FUNCTIONS = /(^|\s)(class\s*\W.*<|included(\s+do|\s*{))/.cs__freeze
179
+
180
+ # these methods dynamically create functions. replacing them in rails
181
+ # resulted in a lot of undefined_ errors. i know we'll have to figure
182
+ # out how to support them, but baby steps
183
+ UNREPEATABLE_ACCESSOR_FUNCTIONS =
184
+ /(^|\s)((cattr_accessor|cattr_reader|cattr_writer|attr_reader|attr_writer|attr_accessor|mattr_accessor|mattr_reader|mattr_writer|public) )/.cs__freeze
185
+ # evals are scary and terrify me. we shouldn't rewrite them if we don't
186
+ # have to
187
+ POTENTIALLY_UNREPEATABLE_FUNCTIONS =
188
+ /(class_eval|instance_eval|method_eval|eval|module_eval|define_method|define_method_attribute|require_dependency|instance_predicate)/.cs__freeze
189
+ # Binding a Constant, ie starting with ::, affects the lookup of that
190
+ # Constant. Since we're effectively moving the file in which it would
191
+ # be declared, we cannot repeat this lookup, so we cannot replace this
192
+ # file
193
+ BOUND_CONSTANTS = /(^|\s)::\w/.cs__freeze
194
+
195
+ DISABLE_FUNCTIONS_REGEXP = /(^|\s)((undef|include|extend|alias|alias_method|require|require_relative|send) )/.cs__freeze
196
+ def unrepeatable? original_source_code
197
+ (original_source_code.index('__dir__') ||
198
+ original_source_code.index('File.dirname') ||
199
+ original_source_code.index('__FILE__') ||
200
+ original_source_code.match?(UNREPEATABLE_FUNCTIONS) ||
201
+ original_source_code.match?(UNREPEATABLE_ACCESSOR_FUNCTIONS) ||
202
+ original_source_code.match?(POTENTIALLY_UNREPEATABLE_FUNCTIONS) ||
203
+ original_source_code.match?(BOUND_CONSTANTS) ||
204
+ original_source_code.match?(DISABLE_FUNCTIONS_REGEXP))
205
+ end
206
+
207
+ UNTOUCHABLE_MODULES = %w[
208
+ AbstractController
209
+ ActionCable ActionController ActionDispatch ActionMailer ActionPack ActionView
210
+ ActiveModel ActiveRecord ActiveSupport
211
+ Brakeman
212
+ Contrast
213
+ Debase
214
+ Debugger
215
+ Erubis
216
+ GraphQL
217
+ NewRelic
218
+ Pry
219
+ Puma
220
+ PhusionPassenger
221
+ Rails::Application Rails::Engine Rails::Railtie
222
+ Rake
223
+ RSpec
224
+ Warden
225
+ WEBrick
226
+ ].cs__freeze
227
+ def should_rewrite? module_data
228
+ clazz = module_data.mod
229
+ name = module_data.name
230
+ return false unless clazz
231
+
232
+ # Name can be nil for anonymous modules. We won't work on them.
233
+ return false unless name
234
+ return false if name == Contrast::Utils::ObjectShare::CLASS
235
+ return false if name == Contrast::Utils::ObjectShare::MODULE
236
+
237
+ # We've ran into issues rewriting these Modules. Ideally, we'll solve
238
+ # the issues and this check will go away
239
+ UNTOUCHABLE_MODULES.none? { |untouchable| name.include?(untouchable) }
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,28 @@
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
+ # Scope lets us disable Contrast for certain code calls. We need to do this so
5
+ # that we don't propagate through our own code.
6
+ #
7
+ # Think logging: If you have
8
+ # something like "The source was '" + source + "'", and source is tracked,
9
+ # you'll trigger propagation with the + method. This in turn would cause
10
+ # propagation if you log there "The target ''" + target + "' was propagated'"
11
+ # Which would then cause another propagation with the '+' method, forever.
12
+ #
13
+ # Instead, we should say "If I'm already doing Contrast things, don't track
14
+ # this"
15
+ #
16
+ # NOTE: DO NOT DO ANYTHING IN THIS CLASS THAT COULD RESULT IN A MONKEY PATCHED
17
+ # ACTION. WE CAN'T ENTER SCOPE BEFORE WE HAVE A SCOPE! YOU HAVE BEEN WARNED!!!
18
+ module Contrast
19
+ module Agent
20
+ class Scope
21
+ # At first, all scopes are 0, meaning we're not in Contrast land
22
+ # NOTE: DO NOT DO ANYTHING IN THIS CLASS THAT COULD RESULT IN A MONKEY
23
+ # PATCHED ACTION. WE CAN'T ENTER SCOPE BEFORE WE HAVE A SCOPE! YOU HAVE
24
+ # BEEN WARNED!!! (again)
25
+ end
26
+ end
27
+ end
28
+ cs__scoped_require 'cs__scope/cs__scope'
@@ -0,0 +1,37 @@
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 Agent
8
+ # The ServiceHeartbeat functions to keep the Contrast Service alive and
9
+ # ensure that it maintains this Agent's ApplicationContext.
10
+ class ServiceHeartbeat
11
+ include Contrast::Components::Interface
12
+ access_component :contrast_service, :logging
13
+
14
+ # Spec recommends 30 seconds, we're going with 15.
15
+ REFRESH_INTERVAL_SEC = 15
16
+
17
+ def updater_thread
18
+ @_updater_thread ||= Contrast::Agent::Thread.new do
19
+ logger.debug(nil, 'Starting heartbeat thread.')
20
+ loop do
21
+ begin
22
+ logger.debug(nil, 'Sending Heartbeat...')
23
+ # TODO: RUBY-672: Change noop to poll messages
24
+ CONTRAST_SERVICE.queue_message(Contrast::Api::Dtm::Noop.new)
25
+ end
26
+ sleep REFRESH_INTERVAL_SEC
27
+ end
28
+ end
29
+ end
30
+ alias_method :start, :updater_thread
31
+
32
+ def stop
33
+ Thread.kill(@_updater_thread) if @_updater_thread&.alive?
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,148 @@
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
+ cs__scoped_require 'set'
6
+
7
+ cs__scoped_require 'contrast/utils/assess/sampling_util'
8
+ cs__scoped_require 'contrast/utils/assess/tracking_util'
9
+ cs__scoped_require 'contrast/utils/environment_util'
10
+ cs__scoped_require 'contrast/utils/env_configuration_item'
11
+ cs__scoped_require 'contrast/utils/gemfile_reader'
12
+ cs__scoped_require 'contrast/utils/object_share'
13
+ cs__scoped_require 'contrast/utils/performs_logging'
14
+ cs__scoped_require 'contrast/utils/string_utils'
15
+ cs__scoped_require 'contrast/agent/reaction_processor'
16
+ cs__scoped_require 'contrast/agent/require_state'
17
+ cs__scoped_require 'contrast/agent/assess/policy/patcher'
18
+ cs__scoped_require 'contrast/agent/patching/policy/patcher'
19
+ cs__scoped_require 'contrast/components/interface'
20
+
21
+ module Contrast
22
+ module Agent
23
+ # This class functions as a way to query the Agent for its current
24
+ # configuration without having to expose other sections of code to the
25
+ # decision tree needed to make that determination.
26
+ # It should not be accessed directly, but should instead be inherited from
27
+ #
28
+ # @abstract Use the methods in FeatureState to access this data
29
+ class SettingsState
30
+ include Contrast::Utils::PerformsLogging
31
+ include Contrast::Components::Interface
32
+
33
+ INVALID_CONFIG = '!!! CONFIG FILE IS INVALID - DISABLING CONTRAST AGENT !!!'
34
+
35
+ access_component :agent, :analysis, :settings, :config, :contrast_service
36
+
37
+ MODE_WHITELIST = %i[NO_ACTION BLOCK_AT_PERIMETER MONITOR BLOCK].cs__freeze
38
+
39
+ # These are components.
40
+ attr_accessor :last_update,
41
+ :log_file,
42
+ :log_level
43
+
44
+ # These represent process-level attributes,
45
+ # not directly related to Contrast function itself.
46
+ attr_reader :pid,
47
+ :ppid
48
+
49
+ def initialize
50
+ @instrumentation_mutex = Mutex.new
51
+ @instrumented_packages = {}
52
+
53
+ # Last we heard from the Contrast Service
54
+ @last_update = nil
55
+
56
+ # keep track of which process instantiated this instance
57
+ @pid = Process.pid.to_i
58
+ @ppid = Process.ppid.to_i
59
+
60
+ init_log_queueing
61
+
62
+ check_config
63
+
64
+ flush_log_queues
65
+ end
66
+
67
+ def check_config
68
+ SETTINGS.reset_state
69
+
70
+ if CONFIG.invalid?
71
+ AGENT.disable!
72
+ self.class.log_error(INVALID_CONFIG)
73
+ abort_log_queues
74
+ elseif CONFIG.disabled?
75
+ AGENT.disable!
76
+ self.class.log_warn(LOG_CONFIGURATION_DISABLED)
77
+ else
78
+ AGENT.enable!
79
+ end
80
+ end
81
+
82
+ # workaround to mixed use of class/instance
83
+ def self.logger
84
+ instance.logger
85
+ end
86
+
87
+ def logger
88
+ logger_manager.current
89
+ end
90
+
91
+ def logger_manager
92
+ (@_logger_manager ||= Contrast::Agent::LoggerManager.new.tap(&:update))
93
+ end
94
+
95
+ def assess_rule name
96
+ ASSESS.rule name
97
+ end
98
+
99
+ def instrument package
100
+ return if @instrumented_packages[package] # double check is intentional
101
+
102
+ @instrumentation_mutex.synchronize do
103
+ return if @instrumented_packages[package]
104
+
105
+ @instrumented_packages[package] = true
106
+ end
107
+
108
+ self.class.debug_with_time("instrumenting #{ package }") do
109
+ cs__scoped_require(package)
110
+ end
111
+ rescue LoadError, StandardError => e
112
+ @instrumented_packages[package] = false
113
+ self.class.log_error("[e.class: #{ e.class }] unable to instrument: #{ package }", e)
114
+ end
115
+
116
+ def protect_rule name
117
+ PROTECT.rule name
118
+ end
119
+
120
+ def send_inventory_message
121
+ return unless INVENTORY.enabled?
122
+
123
+ msg = Contrast::Api::Dtm::ApplicationUpdate.new
124
+ msg.platform = Contrast::Api::Dtm::Platform.new
125
+ msg.platform.major, msg.platform.minor, msg.platform.build = *Contrast::Utils::EnvironmentUtil.platform
126
+
127
+ Contrast::Utils::EnvironmentUtil.add_library_to_app_update(msg, protobuf_format(CONFIG.root.inventory.tags))
128
+ Contrast::Utils::EnvironmentUtil.scan_views(msg)
129
+ Contrast::Utils::EnvironmentUtil.scan_routes(msg)
130
+ Contrast::Utils::InventoryUtil.append_db_config(msg)
131
+
132
+ CONTRAST_SERVICE.queue_message msg
133
+ end
134
+
135
+ def present? str
136
+ Contrast::Utils::EnvironmentUtil.present?(str)
137
+ end
138
+
139
+ # CONTRAST-35326, move this responsibility toward the protobuf object
140
+ def protobuf_format param, truncate: true
141
+ param = param&.to_s
142
+ param = Contrast::Utils::StringUtils.force_utf8(param)
143
+ param = Contrast::Utils::StringUtils.truncate(param) if truncate
144
+ param
145
+ end
146
+ end
147
+ end
148
+ end