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,152 @@
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 'socket'
5
+ cs__scoped_require 'contrast/core_extensions/module'
6
+ cs__scoped_require 'contrast/components/interface'
7
+ cs__scoped_require 'contrast/utils/object_share'
8
+ cs__scoped_require 'contrast/utils/string_utils'
9
+
10
+ module Contrast
11
+ module Utils
12
+ # Gather information about the application and server environment
13
+ # that the agent is running in.
14
+ class EnvironmentUtil
15
+ include Contrast::Components::Interface
16
+
17
+ access_component :analysis
18
+
19
+ DEFAULT_APP_NAME = 'rack'
20
+ DEFAULT_SERVER_NAME = 'localhost'
21
+
22
+ CS_VERSION = 'VERSION'
23
+
24
+ # Possible names of constants that would hold version info
25
+ VERSION_CONSTANT_CANDIDATES = %w[
26
+ VERSION
27
+ ::VERSION
28
+ Version::VERSION
29
+ ::Version::VERSION
30
+ ::Application::VERSION
31
+ ].cs__freeze
32
+
33
+ # Common places where view-layer files can be found in a Rails application
34
+ RAILS_VIEWS = [
35
+ ['app/assets', '*.coffee', %w[CoffeeScript]],
36
+ ['app/assets', '*.scss', %w[SASS]],
37
+ ['app/views', '*.html', %w[HTML5]],
38
+ ['app/views', '*.html.erb', %w[HTML5 ERB]],
39
+ ['app/views', '*.html.haml', %w[HTML5 HAML]],
40
+ ['public', '*.html', %w[HTML5]]
41
+ ].cs__freeze
42
+
43
+ class << self
44
+ ######### These are helpers ####################
45
+
46
+ def present? str
47
+ !str.nil? && !str.to_s.empty?
48
+ end
49
+
50
+ ######### Actually env/framework dependent ####################
51
+
52
+ # See CONTRAST-16380 for more details
53
+ def determine_application_version
54
+ @_determine_application_version ||= begin
55
+ candidates = VERSION_CONSTANT_CANDIDATES.map do |name|
56
+ # If there's a constant named 'name' (VERSION, etc.), get its value.
57
+ begin
58
+ name.split('::').inject(Object) do |mod, class_name|
59
+ mod.cs__const_get(class_name)
60
+ end
61
+ rescue LoadError, StandardError
62
+ nil
63
+ end
64
+ end
65
+ candidates.compact!
66
+ candidate = candidates.first || ENV[CS_VERSION]
67
+
68
+ case candidate
69
+ when Hash
70
+ candidate.values.join(Contrast::Utils::ObjectShare::PERIOD)
71
+ when Array
72
+ candidate.join(Contrast::Utils::ObjectShare::PERIOD)
73
+ when String
74
+ candidate
75
+ when NilClass
76
+ return nil
77
+ else
78
+ candidate.inspect
79
+ end
80
+ end
81
+ end
82
+
83
+ def platform
84
+ version = Rails.version rescue Sinatra::VERSION rescue Rack.version rescue '' # rubocop:disable Style/RescueModifier
85
+ major, minor, patch = *version.split(Contrast::Utils::ObjectShare::PERIOD)
86
+ major ||= ''
87
+ minor ||= ''
88
+ patch ||= ''
89
+
90
+ [major, minor, patch]
91
+ rescue StandardError
92
+ Contrast::Utils::ObjectShare::EMPTY_TRIPLE
93
+ end
94
+
95
+ # Read libraries from the gemfile and append to the given ApplicationUpdate message
96
+ # or other class that has a libraries map association
97
+ def add_library_to_app_update app_update_pb, library_tags = ''
98
+ libraries = Contrast::Utils::GemfileReader.instance.library_pb_list
99
+ libraries.each do |n|
100
+ n.tags = library_tags
101
+ app_update_pb.libraries[n.hash_code] = n
102
+ end
103
+ end
104
+
105
+ # Iterate through known locations, looking for files
106
+ # that represent view or template files. If found, for each file in the directory
107
+ # append the technology and the view object to the application update instance
108
+ def scan_views app_update_msg
109
+ return unless INVENTORY.enabled?
110
+
111
+ scan_rails_views(app_update_msg)
112
+ scan_sinatra_views(app_update_msg)
113
+ end
114
+
115
+ # Find all the predefined routes for this application and append them to the
116
+ # provided inventory message
117
+ # msg should be a Contrast::Api::Dtm::ApplicationUpdate or some other msg
118
+ # that has a routes array consisting of Contrast::Api::Dtm::RouteCoverage
119
+ def scan_routes msg
120
+ return unless INVENTORY.enabled?
121
+
122
+ Contrast::Utils::PathUtil.find_routes.each do |route|
123
+ msg.routes << route
124
+ end
125
+ end
126
+
127
+ private
128
+
129
+ def scan_view_directories app_update_msg, view_location_data
130
+ view_location_data.each do |path, extension, tech_names|
131
+ next if Dir["#{ path }/**/*#{ extension }"].empty?
132
+
133
+ tech_names.each do |tech|
134
+ app_update_msg.technologies[tech] = true
135
+ end
136
+ end
137
+ end
138
+
139
+ def scan_rails_views app_update_msg
140
+ scan_view_directories(app_update_msg, RAILS_VIEWS)
141
+ end
142
+
143
+ def scan_sinatra_views app_update_msg
144
+ sinatra_app = Contrast::Utils::SinatraHelper.app_class
145
+ return unless sinatra_app
146
+
147
+ scan_view_directories(app_update_msg, Contrast::Utils::SinatraHelper.scannable_view_dirs)
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,36 @@
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/core_extensions/object'
5
+ cs__scoped_require 'contrast/utils/duck_utils'
6
+
7
+ module Contrast
8
+ module Utils
9
+ # This utility allows us to act on frozen objects, creating an unfrozen
10
+ # duplicate in those cases where that is possible.
11
+ class FreezeUtil
12
+ class << self
13
+ # Make every attempt to duplicate the frozen object so that it can
14
+ # be tracked. Some things, like Nil, True, and False, respond to dup
15
+ # but throw a TypeError. This catches that case and returns the
16
+ # original. We luck out as these three cases do not get propagated to
17
+ #
18
+ # @param original [Object] something frozen, usually a String
19
+ # @return [Object] the original or an unfrozen copy
20
+ def unfreeze_dup original
21
+ return original unless original.cs__frozen?
22
+ return original unless Contrast::Utils::DuckUtils.quacks_like_duplicable?(original)
23
+
24
+ copy = original.dup
25
+ if Contrast::Utils::DuckUtils.quacks_like_tracked_hash?(copy)
26
+ copy.each_key do |key|
27
+ value = original[key]
28
+ copy[key] = Contrast::Utils::DuckUtils.quacks_like_duplicable?(original) ? value.dup : value
29
+ end
30
+ end
31
+ copy
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,191 @@
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 'set'
5
+ cs__scoped_require 'contrast/utils/sha256_builder'
6
+ cs__scoped_require 'contrast/utils/string_utils'
7
+ cs__scoped_require 'contrast/components/interface'
8
+ cs__scoped_require 'contrast/api'
9
+
10
+ module Contrast
11
+ module Utils
12
+ # GemfileReader has methods for extracting information from gem specs
13
+ # it also has a cache of library file digests to the lines of code found.
14
+ class GemfileReader
15
+ include Singleton
16
+ include Contrast::Components::Interface
17
+
18
+ access_component :logging
19
+
20
+ CONTRAST_AGENT = 'contrast-agent'
21
+
22
+ def initialize
23
+ # Map of a Gem's Spec Digest to all loaded files from that Gem
24
+ @spec_to_files = {}
25
+ end
26
+
27
+ # the #clone is necessary here, as a require in another thread could
28
+ # potentially result in adding a key to the loaded_specs hash during
29
+ # iteration. (as in RUBY-330)
30
+ def loaded_specs
31
+ Gem.loaded_specs.clone
32
+ end
33
+
34
+ # indicates if there's been an update to library information, allowing us
35
+ # to only serialize this information on change.
36
+ def updated?
37
+ @updated
38
+ end
39
+
40
+ def updated!
41
+ @updated = true
42
+ end
43
+
44
+ # Once we're Contrasted, we intercept require calls to do inventory.
45
+ # In order to catch up, we do a one-time manual catchup, & inventory
46
+ # all the already-loaded gems.
47
+ def map_loaded_classes
48
+ loaded_specs.each do |name, spec|
49
+ # Don't count Contrast gems
50
+ next if contrast_gems.include? name
51
+
52
+ # Get a digest of the Gem file itself
53
+ next unless (digest = Contrast::Utils::Sha256Builder.build_from_spec(spec))
54
+
55
+ paths = get_by_digest(digest)
56
+ path = spec.full_gem_path
57
+ $LOADED_FEATURES.each do |line|
58
+ next unless line.to_s.start_with?(path)
59
+
60
+ # logger.debug("Recording loaded gem at '#{ line }' for inventory analysis") if logger.trace? # TODO: RUBY-547
61
+ updated!
62
+ paths << adjust_lib(line)
63
+ end
64
+ end
65
+ end
66
+
67
+ def map_class path
68
+ path = adjust_lib(path)
69
+
70
+ return unless (spec = Gem::Specification.find_by_path(path))
71
+ return unless (digest = Contrast::Utils::Sha256Builder.build_from_spec(spec))
72
+
73
+ updated!
74
+ get_by_digest(digest) << path
75
+ end
76
+
77
+ def library_pb_list
78
+ loaded_specs.each_with_object([]) do |(name, spec), arr|
79
+ next if contrast_gems.include? name
80
+ next unless spec
81
+ next unless (digest = Contrast::Utils::Sha256Builder.build_from_spec(spec))
82
+
83
+ arr << build_library_pb(digest, spec)
84
+ end
85
+ end
86
+
87
+ def generate_library_usage activity = nil
88
+ return unless updated?
89
+
90
+ @spec_to_files.each_pair do |digest, files|
91
+ usage = Contrast::Api::Dtm::LibraryUsageUpdate.new
92
+ usage.hash_code = Contrast::Utils::StringUtils.force_utf8(digest)
93
+ activity.library_usages[usage.hash_code] = usage if activity
94
+ # TODO: PROD-35 once TS switches to take filenames, remove the count setter and
95
+ # send the class names in usage.class_names
96
+ usage.count = files.size
97
+ end
98
+ # TODO: PROD-35 once TS switches to take filenames, clear this and remove the
99
+ # @updated variable
100
+
101
+ # @spec_to_files.clear
102
+ @updated = false
103
+ end
104
+
105
+ private
106
+
107
+ # marker for the lib dir in an absolute file path. purposefully includes
108
+ # the trailing '/'
109
+ LIB = '/lib/'
110
+
111
+ # Kernel#load uses the absolute path, but Gems / Specs use the path after
112
+ # `/lib`. This method accounts for that and trims out the `/lib/` section
113
+ # and starts with the first `/` after and the trailing file extension, if
114
+ # present.
115
+ #
116
+ # @param path [String] the path to parse
117
+ # @return [String] the relative path of the file, after the lib directory
118
+ def adjust_lib path
119
+ idx = path.index(LIB)
120
+ path = path[(idx + 4)..-1] if idx
121
+ idx = path.rindex(Contrast::Utils::ObjectShare::PERIOD)
122
+ path = path[0..idx] if idx
123
+ path
124
+ end
125
+
126
+ def get_by_digest digest
127
+ @spec_to_files[digest] = Set.new unless @spec_to_files.key?(digest)
128
+ @spec_to_files[digest]
129
+ end
130
+
131
+ def build_library_pb digest, spec
132
+ lib = Contrast::Api::Dtm::Library.new
133
+ lib.file_path = Contrast::Utils::StringUtils.force_utf8(spec.name)
134
+ lib.hash_code = Contrast::Utils::StringUtils.force_utf8(digest)
135
+ lib.version = Contrast::Utils::StringUtils.force_utf8(spec.version)
136
+ lib.manifest = Contrast::Utils::StringUtils.force_utf8(build_manifest(spec))
137
+ lib.external_ms = date_to_ms(spec.date)
138
+ lib.internal_ms = lib.external_ms
139
+ lib.url = Contrast::Utils::StringUtils.force_utf8(spec.homepage)
140
+ update_class_counts(lib, digest, spec)
141
+ lib
142
+ end
143
+
144
+ def date_to_ms date
145
+ (date.to_f * 1000.0).to_i
146
+ end
147
+
148
+ def update_class_counts lib, digest, spec
149
+ # Updating the class counts
150
+ path = spec.full_gem_path.to_s
151
+ lib.class_count = all_files(path).length
152
+ lib.used_class_count = @spec_to_files.key?(digest) ? get_by_digest(digest).size : 0
153
+ lib
154
+ end
155
+
156
+ def build_manifest spec
157
+ Contrast::Utils::StringUtils.force_utf8(spec.to_yaml.to_s) if defined?(YAML)
158
+ rescue StandardError
159
+ nil
160
+ end
161
+
162
+ # These are all the code files that are located in the Gem directory loaded
163
+ # by the current environment; this includes more than Ruby files
164
+ def all_files path
165
+ Contrast::Utils::Sha256Builder.instance.files(path)
166
+ end
167
+
168
+ # Go through all dependents, given as a pair from the DependencyList: `dependency`
169
+ # is the dependency itself, filled with all its specs. `dependents` is the array of reverse
170
+ # dependencies for the aforementioned dependency. If the dependency is also in contrast_dep_set,
171
+ # then contrast depends on it. If its array of dependents is 1, then contrast is the
172
+ # only dependency in that list. Since only contrast depends on it, we should ignore it.
173
+ def contrast_gems
174
+ @_contrast_gems ||= find_contrast_gems
175
+ end
176
+
177
+ def find_contrast_gems
178
+ ignore = Set.new([CONTRAST_AGENT])
179
+ contrast_specs = Gem::DependencyList.from_specs.specs.find do |dependency|
180
+ dependency.name == CONTRAST_AGENT
181
+ end
182
+ contrast_dep_set = contrast_specs.dependencies.map(&:name).to_set
183
+
184
+ Gem::DependencyList.from_specs.spec_predecessors.each_pair do |dependency, dependents|
185
+ ignore.add(dependency.name) if contrast_dep_set.include?(dependency.name) && dependents.length == 1
186
+ end
187
+ ignore
188
+ end
189
+ end
190
+ end
191
+ 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 'digest'
5
+
6
+ module Contrast
7
+ module Utils
8
+ # We use this class to provide hashes for our Request and Finding objects
9
+ # based upon our definitions of uniqueness.
10
+ # While the uniqueness of the request object is something internal to the
11
+ # Ruby agent, the uniqueness of the Finding hash is defined by a
12
+ # specification shared across all agent teams. The spec can be found here:
13
+ # https://bitbucket.org/contrastsecurity/assess-specifications/src/master/vulnerability/preflight.md
14
+ class HashDigest < Digest::Class
15
+ include Digest::Instance
16
+
17
+ CONTENT_LENGTH_HEADER = 'Content-Length'
18
+ CRYPTO_RULES = %w[
19
+ crypto-bad-ciphers
20
+ crypto-bad-mac
21
+ ].cs__freeze
22
+ CONFIG_PATH_KEY = 'path'
23
+ CONFIG_SESSION_ID_KEY = 'sessionId'
24
+ CLASS_SOURCE_KEY = 'source'
25
+ CLASS_CONSTANT_NAME_KEY = 'name'
26
+ CLASS_LINE_NO_KEY = 'lineNo'
27
+ class << self
28
+ def generate_request_hash request
29
+ hash = new
30
+ hash.update(request.request_method)
31
+ hash.update(request.normalized_uri)
32
+ request.parameters.each_key do |name|
33
+ hash.update(name)
34
+ end
35
+ cl = request.normalized_request_headers[CONTENT_LENGTH_HEADER]
36
+ hash.update(request.normalized_length_header(cl)) if cl
37
+ hash.finish
38
+ end
39
+
40
+ def generate_event_hash finding, source
41
+ return generate_dataflow_hash(finding) if finding.events.length.to_i > 1
42
+
43
+ id = finding.rule_id
44
+ return generate_crypto_hash(finding, source) if CRYPTO_RULES.include?(id)
45
+
46
+ generate_trigger_hash(finding)
47
+ end
48
+
49
+ def generate_config_hash finding
50
+ hash = new
51
+ hash.update(finding.rule_id)
52
+ path = finding.properties[CONFIG_PATH_KEY]
53
+ hash.update(path)
54
+ method = finding.properties[CONFIG_SESSION_ID_KEY]
55
+ hash.update(method)
56
+ hash.finish
57
+ end
58
+
59
+ def generate_class_scanning_hash finding
60
+ hash = new
61
+ hash.update(finding.rule_id)
62
+ module_name = finding.properties[CLASS_SOURCE_KEY]
63
+ hash.update(module_name)
64
+ # We're not currently collecting this. 30/7/19 HM
65
+ line_no = finding.properties[CLASS_LINE_NO_KEY]
66
+ hash.update(line_no)
67
+ field = finding.properties[CLASS_CONSTANT_NAME_KEY]
68
+ hash.update(field)
69
+ hash.finish
70
+ end
71
+
72
+ def generate_crypto_hash finding, algorithm
73
+ hash = new
74
+ hash.update(finding.rule_id)
75
+ hash.update(algorithm)
76
+ hash.update_on_request
77
+ hash.finish
78
+ end
79
+
80
+ def generate_dataflow_hash finding
81
+ hash = new
82
+ hash.update(finding.rule_id)
83
+ hash.update_on_sources(finding.events)
84
+ hash.update_on_request
85
+ hash.finish
86
+ end
87
+
88
+ def generate_response_hash finding
89
+ hash = new
90
+ hash.update(finding.rule_id)
91
+ hash.update_on_request
92
+ hash.finish
93
+ end
94
+
95
+ def generate_trigger_hash finding
96
+ hash = new
97
+ hash.update(finding.rule_id)
98
+ hash.update_on_request
99
+ hash.finish
100
+ end
101
+ end
102
+
103
+ def update_on_request
104
+ context = Contrast::Agent::REQUEST_TRACKER.current
105
+ return unless context
106
+
107
+ route = context.route
108
+ request = context.request
109
+ if route
110
+ update(route.route)
111
+ update(route.verb)
112
+ elsif request
113
+ update(request.normalized_uri)
114
+ update(request.request_method)
115
+ end
116
+ end
117
+
118
+ def update_on_sources events
119
+ return unless events&.any?
120
+
121
+ events.each do |event|
122
+ event.event_sources.each do |source|
123
+ update(source.type)
124
+ update(source.name)
125
+ end
126
+ end
127
+ end
128
+
129
+ def initialize
130
+ @crc32 = 0
131
+ end
132
+
133
+ def update str
134
+ return unless str
135
+
136
+ @crc32 = Zlib.crc32(str, @crc32)
137
+ end
138
+
139
+ def reset
140
+ @crc32 = 0
141
+ end
142
+
143
+ def finish
144
+ @crc32.to_s
145
+ end
146
+ end
147
+ end
148
+ end