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