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.
- checksums.yaml +7 -0
- data/.clang-format +5 -0
- data/.dockerignore +10 -0
- data/.gitignore +58 -0
- data/.gitmodules +6 -0
- data/.rspec +6 -0
- data/.simplecov +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +12 -0
- data/Rakefile +15 -0
- data/exe/contrast_service +29 -0
- data/ext/build_funchook.rb +48 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.c +47 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.h +10 -0
- data/ext/cs__assess_active_record_named/extconf.rb +2 -0
- data/ext/cs__assess_array/cs__assess_array.c +38 -0
- data/ext/cs__assess_array/cs__assess_array.h +9 -0
- data/ext/cs__assess_array/extconf.rb +2 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +50 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.h +17 -0
- data/ext/cs__assess_basic_object/extconf.rb +2 -0
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +86 -0
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +34 -0
- data/ext/cs__assess_fiber_track/extconf.rb +2 -0
- data/ext/cs__assess_hash/cs__assess_hash.c +64 -0
- data/ext/cs__assess_hash/cs__assess_hash.h +24 -0
- data/ext/cs__assess_hash/extconf.rb +2 -0
- data/ext/cs__assess_kernel/cs__assess_kernel.c +36 -0
- data/ext/cs__assess_kernel/cs__assess_kernel.h +10 -0
- data/ext/cs__assess_kernel/extconf.rb +2 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +47 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +18 -0
- data/ext/cs__assess_marshal_module/extconf.rb +2 -0
- data/ext/cs__assess_module/cs__assess_module.c +78 -0
- data/ext/cs__assess_module/cs__assess_module.h +25 -0
- data/ext/cs__assess_module/extconf.rb +2 -0
- data/ext/cs__assess_regexp/cs__assess_regexp.c +48 -0
- data/ext/cs__assess_regexp/cs__assess_regexp.h +22 -0
- data/ext/cs__assess_regexp/extconf.rb +2 -0
- data/ext/cs__assess_regexp_track/cs__assess_regexp_track.c +63 -0
- data/ext/cs__assess_regexp_track/cs__assess_regexp_track.h +29 -0
- data/ext/cs__assess_regexp_track/extconf.rb +2 -0
- data/ext/cs__assess_string/cs__assess_string.c +38 -0
- data/ext/cs__assess_string/cs__assess_string.h +19 -0
- data/ext/cs__assess_string/extconf.rb +2 -0
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +31 -0
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.h +13 -0
- data/ext/cs__assess_string_interpolation26/extconf.rb +2 -0
- data/ext/cs__common/cs__common.c +60 -0
- data/ext/cs__common/cs__common.h +28 -0
- data/ext/cs__common/extconf.rb +20 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +445 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.h +196 -0
- data/ext/cs__contrast_patch/extconf.rb +2 -0
- data/ext/cs__protect_kernel/cs__protect_kernel.c +37 -0
- data/ext/cs__protect_kernel/cs__protect_kernel.h +11 -0
- data/ext/cs__protect_kernel/extconf.rb +2 -0
- data/ext/cs__scope/cs__scope.c +96 -0
- data/ext/cs__scope/cs__scope.h +33 -0
- data/ext/cs__scope/extconf.rb +2 -0
- data/ext/extconf_common.rb +49 -0
- data/funchook/LICENSE +360 -0
- data/funchook/Makefile +29 -0
- data/funchook/Makefile.in +29 -0
- data/funchook/README.md +121 -0
- data/funchook/appveyor.yml +42 -0
- data/funchook/autogen.sh +3 -0
- data/funchook/autom4te.cache/output.0 +4976 -0
- data/funchook/autom4te.cache/requests +78 -0
- data/funchook/autom4te.cache/traces.0 +364 -0
- data/funchook/config.guess +1530 -0
- data/funchook/config.log +490 -0
- data/funchook/config.status +1016 -0
- data/funchook/config.sub +1773 -0
- data/funchook/configure +4976 -0
- data/funchook/configure.ac +59 -0
- data/funchook/distorm/COPYING +26 -0
- data/funchook/distorm/MANIFEST +25 -0
- data/funchook/distorm/MANIFEST.in +4 -0
- data/funchook/distorm/README.md +12 -0
- data/funchook/distorm/disOps/disOps.py +795 -0
- data/funchook/distorm/disOps/x86db.py +404 -0
- data/funchook/distorm/disOps/x86header.py +247 -0
- data/funchook/distorm/disOps/x86sets.py +1664 -0
- data/funchook/distorm/examples/cs/TestdiStorm/Program.cs +79 -0
- data/funchook/distorm/examples/cs/TestdiStorm/Properties/AssemblyInfo.cs +36 -0
- data/funchook/distorm/examples/cs/TestdiStorm/TestdiStorm.csproj +69 -0
- data/funchook/distorm/examples/cs/distorm-net.sln +26 -0
- data/funchook/distorm/examples/cs/distorm-net/CodeInfo.cs +23 -0
- data/funchook/distorm/examples/cs/distorm-net/DecodedInst.cs +15 -0
- data/funchook/distorm/examples/cs/distorm-net/DecodedResult.cs +14 -0
- data/funchook/distorm/examples/cs/distorm-net/DecomposedInst.cs +36 -0
- data/funchook/distorm/examples/cs/distorm-net/DecomposedResult.cs +14 -0
- data/funchook/distorm/examples/cs/distorm-net/Opcodes.cs +1268 -0
- data/funchook/distorm/examples/cs/distorm-net/Opcodes.tt +37 -0
- data/funchook/distorm/examples/cs/distorm-net/Operand.cs +25 -0
- data/funchook/distorm/examples/cs/distorm-net/Properties/AssemblyInfo.cs +36 -0
- data/funchook/distorm/examples/cs/distorm-net/diStorm3.cs +411 -0
- data/funchook/distorm/examples/cs/distorm-net/distorm-net.csproj +80 -0
- data/funchook/distorm/examples/cs/readme +3 -0
- data/funchook/distorm/examples/ddk/README +48 -0
- data/funchook/distorm/examples/ddk/distorm.ini +11 -0
- data/funchook/distorm/examples/ddk/dummy.c +15 -0
- data/funchook/distorm/examples/ddk/main.c +91 -0
- data/funchook/distorm/examples/ddk/makefile +1 -0
- data/funchook/distorm/examples/ddk/sources +10 -0
- data/funchook/distorm/examples/java/Makefile +23 -0
- data/funchook/distorm/examples/java/distorm/src/Main.java +43 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/CodeInfo.java +27 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedInst.java +32 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedResult.java +11 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedInst.java +89 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedResult.java +11 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/OpcodeEnum.java +131 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/Opcodes.java +1123 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/Operand.java +24 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/distorm3.java +41 -0
- data/funchook/distorm/examples/java/jdistorm.c +405 -0
- data/funchook/distorm/examples/java/jdistorm.h +40 -0
- data/funchook/distorm/examples/java/jdistorm.sln +20 -0
- data/funchook/distorm/examples/java/jdistorm.vcproj +208 -0
- data/funchook/distorm/examples/linux/Makefile +15 -0
- data/funchook/distorm/examples/linux/main.c +181 -0
- data/funchook/distorm/examples/tests/Makefile +15 -0
- data/funchook/distorm/examples/tests/main.cpp +42 -0
- data/funchook/distorm/examples/tests/main.py +66 -0
- data/funchook/distorm/examples/tests/test_distorm3.py +1672 -0
- data/funchook/distorm/examples/tests/tests.sln +20 -0
- data/funchook/distorm/examples/tests/tests.vcxproj +82 -0
- data/funchook/distorm/examples/tests/tests.vcxproj.filters +22 -0
- data/funchook/distorm/examples/win32/disasm.sln +25 -0
- data/funchook/distorm/examples/win32/disasm.vcxproj +201 -0
- data/funchook/distorm/examples/win32/disasm.vcxproj.filters +14 -0
- data/funchook/distorm/examples/win32/main.cpp +163 -0
- data/funchook/distorm/include/distorm.h +482 -0
- data/funchook/distorm/include/mnemonics.h +301 -0
- data/funchook/distorm/make/linux/Makefile +28 -0
- data/funchook/distorm/make/mac/Makefile +24 -0
- data/funchook/distorm/make/win32/cdistorm.vcxproj +239 -0
- data/funchook/distorm/make/win32/cdistorm.vcxproj.filters +80 -0
- data/funchook/distorm/make/win32/distorm.sln +25 -0
- data/funchook/distorm/make/win32/resource.h +14 -0
- data/funchook/distorm/make/win32/resource.rc +99 -0
- data/funchook/distorm/python/distorm3/__init__.py +957 -0
- data/funchook/distorm/python/distorm3/sample.py +51 -0
- data/funchook/distorm/setup.cfg +10 -0
- data/funchook/distorm/setup.py +266 -0
- data/funchook/distorm/src/config.h +169 -0
- data/funchook/distorm/src/decoder.c +641 -0
- data/funchook/distorm/src/decoder.h +33 -0
- data/funchook/distorm/src/distorm.c +413 -0
- data/funchook/distorm/src/instructions.c +597 -0
- data/funchook/distorm/src/instructions.h +463 -0
- data/funchook/distorm/src/insts.c +7939 -0
- data/funchook/distorm/src/insts.h +64 -0
- data/funchook/distorm/src/mnemonics.c +284 -0
- data/funchook/distorm/src/operands.c +1290 -0
- data/funchook/distorm/src/operands.h +28 -0
- data/funchook/distorm/src/prefix.c +368 -0
- data/funchook/distorm/src/prefix.h +64 -0
- data/funchook/distorm/src/textdefs.c +172 -0
- data/funchook/distorm/src/textdefs.h +57 -0
- data/funchook/distorm/src/wstring.c +47 -0
- data/funchook/distorm/src/wstring.h +35 -0
- data/funchook/distorm/src/x86defs.h +82 -0
- data/funchook/include/funchook.h +123 -0
- data/funchook/install-sh +527 -0
- data/funchook/src/Makefile +70 -0
- data/funchook/src/Makefile.in +70 -0
- data/funchook/src/__strerror.h +109 -0
- data/funchook/src/config.h +101 -0
- data/funchook/src/config.h.in +100 -0
- data/funchook/src/decoder.o +0 -0
- data/funchook/src/distorm.o +0 -0
- data/funchook/src/funchook.c +440 -0
- data/funchook/src/funchook.o +0 -0
- data/funchook/src/funchook_internal.h +155 -0
- data/funchook/src/funchook_io.c +182 -0
- data/funchook/src/funchook_io.h +64 -0
- data/funchook/src/funchook_io.o +0 -0
- data/funchook/src/funchook_syscall.S +134 -0
- data/funchook/src/funchook_syscall.o +0 -0
- data/funchook/src/funchook_unix.c +480 -0
- data/funchook/src/funchook_unix.o +0 -0
- data/funchook/src/funchook_windows.c +397 -0
- data/funchook/src/funchook_x86.c +622 -0
- data/funchook/src/funchook_x86.o +0 -0
- data/funchook/src/instructions.o +0 -0
- data/funchook/src/insts.o +0 -0
- data/funchook/src/libfunchook.so +0 -0
- data/funchook/src/mnemonics.o +0 -0
- data/funchook/src/operands.o +0 -0
- data/funchook/src/os_func.c +115 -0
- data/funchook/src/os_func.h +75 -0
- data/funchook/src/os_func.o +0 -0
- data/funchook/src/os_func_unix.c +94 -0
- data/funchook/src/os_func_unix.o +0 -0
- data/funchook/src/os_func_windows.c +32 -0
- data/funchook/src/prefix.o +0 -0
- data/funchook/src/printf_base.c +1688 -0
- data/funchook/src/printf_base.h +46 -0
- data/funchook/src/printf_base.o +0 -0
- data/funchook/src/textdefs.o +0 -0
- data/funchook/src/wstring.o +0 -0
- data/funchook/test/Makefile +43 -0
- data/funchook/test/Makefile.in +43 -0
- data/funchook/test/funchook_test +0 -0
- data/funchook/test/libfunchook_test.c +25 -0
- data/funchook/test/libfunchook_test.so +0 -0
- data/funchook/test/libfunchook_test2.c +18 -0
- data/funchook/test/suffix.list +600 -0
- data/funchook/test/test_main.c +430 -0
- data/funchook/test/test_main.o +0 -0
- data/funchook/test/x86_64_test.S +10 -0
- data/funchook/test/x86_64_test.o +0 -0
- data/funchook/test/x86_test.S +339 -0
- data/funchook/win32/config.h +1 -0
- data/funchook/win32/funchook.sln +52 -0
- data/funchook/win32/funchook.vcxproj +188 -0
- data/funchook/win32/funchook.vcxproj.filters +84 -0
- data/funchook/win32/funchook_test.vcxproj +170 -0
- data/funchook/win32/funchook_test.vcxproj.filters +22 -0
- data/funchook/win32/funchook_test_dll.vcxproj +184 -0
- data/funchook/win32/funchook_test_dll.vcxproj.filters +30 -0
- data/funchook/win32/funchook_test_exe.def +3 -0
- data/lib/contrast-agent.rb +8 -0
- data/lib/contrast.rb +57 -0
- data/lib/contrast/agent.rb +80 -0
- data/lib/contrast/agent/assess.rb +45 -0
- data/lib/contrast/agent/assess/adjusted_span.rb +25 -0
- data/lib/contrast/agent/assess/class_reverter.rb +82 -0
- data/lib/contrast/agent/assess/contrast_event.rb +398 -0
- data/lib/contrast/agent/assess/frozen_properties.rb +41 -0
- data/lib/contrast/agent/assess/insulator.rb +53 -0
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +78 -0
- data/lib/contrast/agent/assess/policy/patcher.rb +85 -0
- data/lib/contrast/agent/assess/policy/policy.rb +116 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +289 -0
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +44 -0
- data/lib/contrast/agent/assess/policy/preshift.rb +94 -0
- data/lib/contrast/agent/assess/policy/propagation_method.rb +260 -0
- data/lib/contrast/agent/assess/policy/propagation_node.rb +127 -0
- data/lib/contrast/agent/assess/policy/propagator.rb +35 -0
- data/lib/contrast/agent/assess/policy/propagator/append.rb +54 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +37 -0
- data/lib/contrast/agent/assess/policy/propagator/center.rb +73 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +36 -0
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +62 -0
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +55 -0
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +26 -0
- data/lib/contrast/agent/assess/policy/propagator/next.rb +42 -0
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +50 -0
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +76 -0
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +27 -0
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +38 -0
- data/lib/contrast/agent/assess/policy/propagator/select.rb +86 -0
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +60 -0
- data/lib/contrast/agent/assess/policy/propagator/split.rb +49 -0
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +169 -0
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +81 -0
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +79 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +209 -0
- data/lib/contrast/agent/assess/policy/source_node.rb +62 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +209 -0
- data/lib/contrast/agent/assess/policy/trigger_node.rb +198 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +77 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +31 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +40 -0
- data/lib/contrast/agent/assess/properties.rb +392 -0
- data/lib/contrast/agent/assess/rule.rb +18 -0
- data/lib/contrast/agent/assess/rule/base.rb +72 -0
- data/lib/contrast/agent/assess/rule/csrf.rb +66 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +28 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +69 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +132 -0
- data/lib/contrast/agent/assess/rule/provider.rb +21 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +62 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +73 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +121 -0
- data/lib/contrast/agent/assess/rule/redos.rb +68 -0
- data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +47 -0
- data/lib/contrast/agent/assess/rule/response_watcher.rb +36 -0
- data/lib/contrast/agent/assess/rule/watcher.rb +36 -0
- data/lib/contrast/agent/assess/tag.rb +151 -0
- data/lib/contrast/agent/at_exit_hook.rb +33 -0
- data/lib/contrast/agent/class_reopener.rb +195 -0
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +26 -0
- data/lib/contrast/agent/deadzone/policy/policy.rb +57 -0
- data/lib/contrast/agent/disable_reaction.rb +24 -0
- data/lib/contrast/agent/exclusion_matcher.rb +190 -0
- data/lib/contrast/agent/feature_state.rb +379 -0
- data/lib/contrast/agent/inventory/policy/policy.rb +32 -0
- data/lib/contrast/agent/inventory/policy/trigger_node.rb +22 -0
- data/lib/contrast/agent/logger_manager.rb +116 -0
- data/lib/contrast/agent/middleware.rb +352 -0
- data/lib/contrast/agent/module_data.rb +16 -0
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +37 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +58 -0
- data/lib/contrast/agent/patching/policy/method_policy.rb +94 -0
- data/lib/contrast/agent/patching/policy/module_policy.rb +116 -0
- data/lib/contrast/agent/patching/policy/patch.rb +312 -0
- data/lib/contrast/agent/patching/policy/patch_status.rb +192 -0
- data/lib/contrast/agent/patching/policy/patcher.rb +310 -0
- data/lib/contrast/agent/patching/policy/policy.rb +138 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +80 -0
- data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +28 -0
- data/lib/contrast/agent/patching/policy/trigger_node.rb +81 -0
- data/lib/contrast/agent/protect/policy/policy.rb +37 -0
- data/lib/contrast/agent/protect/policy/trigger_node.rb +23 -0
- data/lib/contrast/agent/protect/rule.rb +58 -0
- data/lib/contrast/agent/protect/rule/base.rb +300 -0
- data/lib/contrast/agent/protect/rule/base_service.rb +88 -0
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +156 -0
- data/lib/contrast/agent/protect/rule/csrf.rb +118 -0
- data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +103 -0
- data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +85 -0
- data/lib/contrast/agent/protect/rule/default_scanner.rb +300 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +193 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +80 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +101 -0
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +40 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +143 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +101 -0
- data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +16 -0
- data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +38 -0
- data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +22 -0
- data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +19 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +20 -0
- data/lib/contrast/agent/protect/rule/xss.rb +24 -0
- data/lib/contrast/agent/protect/rule/xxe.rb +120 -0
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +82 -0
- data/lib/contrast/agent/railtie.rb +30 -0
- data/lib/contrast/agent/reaction_processor.rb +47 -0
- data/lib/contrast/agent/request.rb +493 -0
- data/lib/contrast/agent/request_context.rb +225 -0
- data/lib/contrast/agent/require_state.rb +61 -0
- data/lib/contrast/agent/response.rb +215 -0
- data/lib/contrast/agent/rewriter.rb +244 -0
- data/lib/contrast/agent/scope.rb +28 -0
- data/lib/contrast/agent/service_heartbeat.rb +37 -0
- data/lib/contrast/agent/settings_state.rb +148 -0
- data/lib/contrast/agent/socket_client.rb +125 -0
- data/lib/contrast/agent/thread.rb +26 -0
- data/lib/contrast/agent/tracepoint_hook.rb +51 -0
- data/lib/contrast/agent/version.rb +8 -0
- data/lib/contrast/api.rb +17 -0
- data/lib/contrast/api/.gitkeep +0 -0
- data/lib/contrast/api/connection_status.rb +49 -0
- data/lib/contrast/api/socket.rb +43 -0
- data/lib/contrast/api/speedracer.rb +206 -0
- data/lib/contrast/api/tcp_socket.rb +31 -0
- data/lib/contrast/api/unix_socket.rb +25 -0
- data/lib/contrast/common_agent_configuration.rb +86 -0
- data/lib/contrast/components/agent.rb +85 -0
- data/lib/contrast/components/app_context.rb +188 -0
- data/lib/contrast/components/assess.rb +67 -0
- data/lib/contrast/components/config.rb +135 -0
- data/lib/contrast/components/contrast_service.rb +113 -0
- data/lib/contrast/components/heap_dump.rb +34 -0
- data/lib/contrast/components/interface.rb +178 -0
- data/lib/contrast/components/inventory.rb +23 -0
- data/lib/contrast/components/logger.rb +92 -0
- data/lib/contrast/components/protect.rb +38 -0
- data/lib/contrast/components/sampling.rb +41 -0
- data/lib/contrast/components/scope.rb +106 -0
- data/lib/contrast/components/settings.rb +140 -0
- data/lib/contrast/config.rb +33 -0
- data/lib/contrast/config/agent_configuration.rb +24 -0
- data/lib/contrast/config/application_configuration.rb +27 -0
- data/lib/contrast/config/assess_configuration.rb +22 -0
- data/lib/contrast/config/assess_rules_configuration.rb +18 -0
- data/lib/contrast/config/base_configuration.rb +105 -0
- data/lib/contrast/config/default_value.rb +16 -0
- data/lib/contrast/config/exception_configuration.rb +21 -0
- data/lib/contrast/config/heap_dump_configuration.rb +23 -0
- data/lib/contrast/config/inventory_configuration.rb +20 -0
- data/lib/contrast/config/logger_configuration.rb +20 -0
- data/lib/contrast/config/protect_configuration.rb +20 -0
- data/lib/contrast/config/protect_rule_configuration.rb +37 -0
- data/lib/contrast/config/protect_rules_configuration.rb +30 -0
- data/lib/contrast/config/root_configuration.rb +26 -0
- data/lib/contrast/config/ruby_configuration.rb +39 -0
- data/lib/contrast/config/sampling_configuration.rb +22 -0
- data/lib/contrast/config/server_configuration.rb +23 -0
- data/lib/contrast/config/service_configuration.rb +22 -0
- data/lib/contrast/configuration.rb +214 -0
- data/lib/contrast/core_extensions/assess.rb +51 -0
- data/lib/contrast/core_extensions/assess/array.rb +58 -0
- data/lib/contrast/core_extensions/assess/assess_extension.rb +145 -0
- data/lib/contrast/core_extensions/assess/basic_object.rb +15 -0
- data/lib/contrast/core_extensions/assess/erb.rb +42 -0
- data/lib/contrast/core_extensions/assess/exec_trigger.rb +48 -0
- data/lib/contrast/core_extensions/assess/fiber.rb +125 -0
- data/lib/contrast/core_extensions/assess/hash.rb +22 -0
- data/lib/contrast/core_extensions/assess/kernel.rb +95 -0
- data/lib/contrast/core_extensions/assess/module.rb +14 -0
- data/lib/contrast/core_extensions/assess/regexp.rb +206 -0
- data/lib/contrast/core_extensions/assess/string.rb +75 -0
- data/lib/contrast/core_extensions/assess/tilt_template_trigger.rb +73 -0
- data/lib/contrast/core_extensions/delegator.rb +14 -0
- data/lib/contrast/core_extensions/eval_trigger.rb +52 -0
- data/lib/contrast/core_extensions/inventory.rb +22 -0
- data/lib/contrast/core_extensions/inventory/datastores.rb +37 -0
- data/lib/contrast/core_extensions/module.rb +42 -0
- data/lib/contrast/core_extensions/object.rb +27 -0
- data/lib/contrast/core_extensions/protect.rb +20 -0
- data/lib/contrast/core_extensions/protect/applies_command_injection_rule.rb +70 -0
- data/lib/contrast/core_extensions/protect/applies_deserialization_rule.rb +58 -0
- data/lib/contrast/core_extensions/protect/applies_no_sqli_rule.rb +81 -0
- data/lib/contrast/core_extensions/protect/applies_path_traversal_rule.rb +119 -0
- data/lib/contrast/core_extensions/protect/applies_sqli_rule.rb +63 -0
- data/lib/contrast/core_extensions/protect/applies_xxe_rule.rb +141 -0
- data/lib/contrast/core_extensions/protect/kernel.rb +30 -0
- data/lib/contrast/core_extensions/protect/psych.rb +7 -0
- data/lib/contrast/core_extensions/thread.rb +31 -0
- data/lib/contrast/internal_exception.rb +8 -0
- data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +48 -0
- data/lib/contrast/rails_extensions/assess/active_record.rb +32 -0
- data/lib/contrast/rails_extensions/assess/active_record_named.rb +61 -0
- data/lib/contrast/rails_extensions/assess/configuration.rb +26 -0
- data/lib/contrast/rails_extensions/buffer.rb +30 -0
- data/lib/contrast/rails_extensions/rack.rb +45 -0
- data/lib/contrast/security_exception.rb +14 -0
- data/lib/contrast/sinatra_extensions/assess/cookie.rb +26 -0
- data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +59 -0
- data/lib/contrast/tasks/service.rb +95 -0
- data/lib/contrast/utils/assess/sampling_util.rb +96 -0
- data/lib/contrast/utils/assess/tracking_util.rb +39 -0
- data/lib/contrast/utils/boolean_util.rb +33 -0
- data/lib/contrast/utils/cache.rb +69 -0
- data/lib/contrast/utils/class_util.rb +58 -0
- data/lib/contrast/utils/comment_range.rb +19 -0
- data/lib/contrast/utils/data_store_util.rb +23 -0
- data/lib/contrast/utils/duck_utils.rb +58 -0
- data/lib/contrast/utils/env_configuration_item.rb +52 -0
- data/lib/contrast/utils/environment_util.rb +152 -0
- data/lib/contrast/utils/freeze_util.rb +36 -0
- data/lib/contrast/utils/gemfile_reader.rb +191 -0
- data/lib/contrast/utils/hash_digest.rb +148 -0
- data/lib/contrast/utils/heap_dump_util.rb +113 -0
- data/lib/contrast/utils/invalid_configuration_util.rb +88 -0
- data/lib/contrast/utils/inventory_util.rb +126 -0
- data/lib/contrast/utils/io_util.rb +61 -0
- data/lib/contrast/utils/object_share.rb +117 -0
- data/lib/contrast/utils/operating_environment.rb +38 -0
- data/lib/contrast/utils/os.rb +49 -0
- data/lib/contrast/utils/path_util.rb +151 -0
- data/lib/contrast/utils/performs_logging.rb +152 -0
- data/lib/contrast/utils/preflight_util.rb +13 -0
- data/lib/contrast/utils/prevent_serialization.rb +52 -0
- data/lib/contrast/utils/rack_assess_session_cookie.rb +104 -0
- data/lib/contrast/utils/rails_assess_configuration.rb +95 -0
- data/lib/contrast/utils/random_util.rb +22 -0
- data/lib/contrast/utils/resource_loader.rb +23 -0
- data/lib/contrast/utils/ruby_ast_rewriter.rb +74 -0
- data/lib/contrast/utils/scope_util.rb +99 -0
- data/lib/contrast/utils/service_response_util.rb +116 -0
- data/lib/contrast/utils/service_sender_util.rb +98 -0
- data/lib/contrast/utils/sha256_builder.rb +69 -0
- data/lib/contrast/utils/sinatra_helper.rb +49 -0
- data/lib/contrast/utils/stack_trace_utils.rb +209 -0
- data/lib/contrast/utils/string_utils.rb +72 -0
- data/lib/contrast/utils/tag_util.rb +139 -0
- data/lib/contrast/utils/thread_tracker.rb +54 -0
- data/lib/contrast/utils/timer.rb +78 -0
- data/resources/assess/policy.json +1673 -0
- data/resources/csrf/inject.js +44 -0
- data/resources/deadzone/policy.json +55 -0
- data/resources/factory-bot-spec/spec_helper.rb +30 -0
- data/resources/inventory/policy.json +110 -0
- data/resources/protect/policy.json +417 -0
- data/resources/rubocops/kernel/catch_cop.rb +37 -0
- data/resources/rubocops/kernel/require_cop.rb +37 -0
- data/resources/rubocops/kernel/require_relative_cop.rb +33 -0
- data/resources/rubocops/module/autoload_cop.rb +37 -0
- data/resources/rubocops/module/const_defined_cop.rb +37 -0
- data/resources/rubocops/module/const_get_cop.rb +37 -0
- data/resources/rubocops/module/const_set_cop.rb +37 -0
- data/resources/rubocops/module/constants_cop.rb +37 -0
- data/resources/rubocops/module/name_cop.rb +37 -0
- data/resources/rubocops/object/class_cop.rb +37 -0
- data/resources/rubocops/object/freeze_cop.rb +37 -0
- data/resources/rubocops/object/frozen_cop.rb +37 -0
- data/resources/rubocops/object/is_a_cop.rb +37 -0
- data/resources/rubocops/object/method_cop.rb +37 -0
- data/resources/rubocops/object/respond_to_cop.rb +37 -0
- data/resources/rubocops/object/singleton_class_cop.rb +37 -0
- data/resources/rubocops/regexp/spelling_cop.rb +44 -0
- data/resources/rubocops/thread/new_cop.rb +39 -0
- data/resources/ruby-spec/ancestors_spec.rb +70 -0
- data/resources/ruby-spec/modulo_spec.rb +831 -0
- data/resources/ruby-spec/parameters_spec.rb +261 -0
- data/resources/ruby-spec/ruby_spec_spec_helper.rb +35 -0
- data/resources/test_marker.txt +1 -0
- data/ruby-agent.gemspec +129 -0
- data/service_executables/.gitkeep +0 -0
- data/service_executables/VERSION +1 -0
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- 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
|