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,125 @@
|
|
|
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 'uri'
|
|
6
|
+
|
|
7
|
+
cs__scoped_require 'contrast/api/speedracer'
|
|
8
|
+
cs__scoped_require 'contrast/api/tcp_socket'
|
|
9
|
+
cs__scoped_require 'contrast/api/unix_socket'
|
|
10
|
+
cs__scoped_require 'contrast/api/connection_status'
|
|
11
|
+
cs__scoped_require 'contrast/components/interface'
|
|
12
|
+
|
|
13
|
+
module Contrast
|
|
14
|
+
module Agent
|
|
15
|
+
# SocketClient acts as a interface between the agent and the service. It instantiates a
|
|
16
|
+
# service proxy and tracks the state of that proxy.
|
|
17
|
+
class SocketClient
|
|
18
|
+
include Contrast::Components::Interface
|
|
19
|
+
|
|
20
|
+
access_component :logging, :contrast_service, :app_context
|
|
21
|
+
|
|
22
|
+
attr_accessor :speedracer, :status
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@status = Contrast::Api::ConnectionStatus.new
|
|
26
|
+
@speedracer = Contrast::Api::Speedracer.new(init_connection)
|
|
27
|
+
@ensure_running = Mutex.new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def init_connection
|
|
31
|
+
if CONTRAST_SERVICE.use_tcp?
|
|
32
|
+
Contrast::Api::TcpSocket.new(CONTRAST_SERVICE.host, CONTRAST_SERVICE.port)
|
|
33
|
+
else
|
|
34
|
+
Contrast::Api::UnixSocket.new(CONTRAST_SERVICE.socket_path)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def service_unavailable?
|
|
39
|
+
speedracer.nil?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def connection_established?
|
|
43
|
+
status.connected?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Attempt to send the passed message to SpeedRacer. If we're using bundled
|
|
47
|
+
# service config option, we must first start up the service. Afterwards, we
|
|
48
|
+
# must send agent startup messages no matter what the config options are.
|
|
49
|
+
#
|
|
50
|
+
# @param msg [Contrast::Api::Dtm::Message] the message to be sent.
|
|
51
|
+
# @return [Array<Contrast::Api::Settings::AgentSettings>] the response from SpeedRacer or nil
|
|
52
|
+
# if it failed to send or the service is unavailable.
|
|
53
|
+
def send_to_speedracer msg
|
|
54
|
+
return if service_unavailable?
|
|
55
|
+
|
|
56
|
+
@ensure_running.synchronize do
|
|
57
|
+
if CONTRAST_SERVICE.use_bundled_service?
|
|
58
|
+
return unless start_or_restart
|
|
59
|
+
end
|
|
60
|
+
build_service_context unless status.startup_messages_sent?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
logger.debug_with_time(msg.cs__class.name) do
|
|
64
|
+
logger.debug "[m__id__:#{ msg.__id__ }]\tSending message."
|
|
65
|
+
response = speedracer.send_one msg
|
|
66
|
+
status.success!
|
|
67
|
+
logger.debug "[m__id__:#{ msg.__id__ }]\tReceived response:#{ response ? response.__id__ : '[No Response]' } for message."
|
|
68
|
+
response
|
|
69
|
+
end
|
|
70
|
+
rescue StandardError => e
|
|
71
|
+
status.failure!
|
|
72
|
+
logger.error(e, "Unable to send message=#{ msg.cs__class }.")
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def restart?
|
|
79
|
+
status.was_connected? && status.failed?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Now that we know we're running with bundled service option, we can tell SpeedRacer that we're
|
|
83
|
+
# ready for it to be started up.
|
|
84
|
+
#
|
|
85
|
+
# @return [Boolean] true if the service is started, false if the service is still offline after
|
|
86
|
+
# we've attempted to start it up.
|
|
87
|
+
def start_or_restart
|
|
88
|
+
if restart?
|
|
89
|
+
logger.info(nil, 'Attempting to restart service.')
|
|
90
|
+
return speedracer.start_service
|
|
91
|
+
elsif !status.was_connected?
|
|
92
|
+
logger.info(nil, 'Attempting to start service.')
|
|
93
|
+
return speedracer.start_service
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
true
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def build_service_context
|
|
100
|
+
agent_startup_msg = APP_CONTEXT.build_agent_startup_message
|
|
101
|
+
app_startup_msg = APP_CONTEXT.build_app_startup_message
|
|
102
|
+
|
|
103
|
+
# 1 initial attempt, + 3 potential retries.
|
|
104
|
+
# The agent-service-api REQUIREMENTS.md spec mandates this #.
|
|
105
|
+
4.times do
|
|
106
|
+
next unless (agent_response = speedracer.send_one(agent_startup_msg))
|
|
107
|
+
|
|
108
|
+
# Connection was successful
|
|
109
|
+
app_response = speedracer.send_one(app_startup_msg)
|
|
110
|
+
[agent_response, app_response].each do |msg|
|
|
111
|
+
Contrast::Utils::ServiceResponseUtil.process_response msg
|
|
112
|
+
end
|
|
113
|
+
status.success!
|
|
114
|
+
logger.debug(nil, 'Successfully sent startup messages to service.')
|
|
115
|
+
return
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
logger.error('Could not send agent startup message context')
|
|
119
|
+
rescue StandardError => e
|
|
120
|
+
logger.error(e, 'Could not build service context')
|
|
121
|
+
raise # re-raise the error to be caught by SocketClient#send_to_speedracer
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
# Threads used by Contrast.
|
|
9
|
+
class Thread < ::Thread
|
|
10
|
+
include Contrast::Components::Interface
|
|
11
|
+
|
|
12
|
+
access_component :logging, :scope
|
|
13
|
+
|
|
14
|
+
# Make our internal code run in Contrast scope.
|
|
15
|
+
def initialize *args
|
|
16
|
+
wrapped_block = proc do |block_args|
|
|
17
|
+
with_contrast_scope do
|
|
18
|
+
yield(*block_args)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
super(*args, &wrapped_block)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
# This module is used to apply instrumentation to classes as they are required
|
|
9
|
+
module TracePointHook
|
|
10
|
+
include Contrast::Components::Interface
|
|
11
|
+
|
|
12
|
+
access_component :logging, :scope
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def active?
|
|
16
|
+
instance_variable_defined?(:@require_hook) && @require_hook.enabled?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def enable!
|
|
20
|
+
@require_hook ||= TracePoint.new(:end) do |tracepoint_event|
|
|
21
|
+
process(tracepoint_event)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@require_hook.enable
|
|
25
|
+
logger.debug('Enabled :end event tracing')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def disable
|
|
29
|
+
instance_variable_defined?(:@require_hook) && @require_hook.disable
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def process tracepoint_event
|
|
35
|
+
with_contrast_scope do
|
|
36
|
+
logger.debug("Received end event for #{ tracepoint_event.self }")
|
|
37
|
+
|
|
38
|
+
loaded_module = tracepoint_event.self
|
|
39
|
+
path = tracepoint_event.path
|
|
40
|
+
return if path&.include?('contrast')
|
|
41
|
+
|
|
42
|
+
Contrast::Utils::InventoryUtil.inventory_class(path) if path
|
|
43
|
+
Contrast::Agent::Patching::Policy::Patcher.patch_specific_module(loaded_module)
|
|
44
|
+
Contrast::Agent::Assess::Policy::RewriterPatch.rewrite_interpolation(loaded_module)
|
|
45
|
+
Contrast::Agent::Assess::Policy::PolicyScanner.scan(tracepoint_event)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/contrast/api.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
# Builds out the Contrast::Api namespace and requires the classes in the api
|
|
6
|
+
# directory, making available those classes required to communicate with the
|
|
7
|
+
# Contrast Service, including those generated from Protobuf
|
|
8
|
+
module Api
|
|
9
|
+
ENCODING_STRING = 'I>'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
cs__scoped_require 'contrast/api/dtm_pb'
|
|
14
|
+
cs__scoped_require 'contrast/api/settings_pb'
|
|
15
|
+
cs__scoped_require 'contrast/api/unix_socket'
|
|
16
|
+
cs__scoped_require 'contrast/api/tcp_socket'
|
|
17
|
+
cs__scoped_require 'contrast/api/speedracer'
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Api
|
|
6
|
+
# Keeps track of the state of connections to the service.
|
|
7
|
+
class ConnectionStatus
|
|
8
|
+
def initialize
|
|
9
|
+
@last_success = nil
|
|
10
|
+
@last_failure = nil
|
|
11
|
+
@startup_messages_sent = false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Whether we have sent startup message to the service. True after successfully
|
|
15
|
+
# sending startup messages to service and reset to false if we lose connection
|
|
16
|
+
# to the service.
|
|
17
|
+
def startup_messages_sent?
|
|
18
|
+
@startup_messages_sent
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# A message was successfully sent to the service at some point
|
|
22
|
+
def was_connected?
|
|
23
|
+
@last_success
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The last message sent was successful
|
|
27
|
+
def connected?
|
|
28
|
+
@last_success && (@last_failure.nil? || @last_success > @last_failure)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# The last message sent was unsuccessful
|
|
32
|
+
def failed?
|
|
33
|
+
@last_failure && (@last_success.nil? || @last_failure > @last_success)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The current state of the service is active with a successful message sent
|
|
37
|
+
def success!
|
|
38
|
+
@startup_messages_sent = true
|
|
39
|
+
@last_success = Time.now.to_f
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# The service may be in some sort of error state
|
|
43
|
+
def failure!
|
|
44
|
+
@startup_messages_sent = false
|
|
45
|
+
@last_failure = Time.now.to_f
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Api
|
|
6
|
+
# Behavior common to all sockets used
|
|
7
|
+
# to communicate with the Contrast Service.
|
|
8
|
+
module Socket
|
|
9
|
+
SOCKET_MONITOR = Monitor.new
|
|
10
|
+
|
|
11
|
+
# Send a message across the socket and read back the response.
|
|
12
|
+
# @param marshaled [String] some marshaled form of data to be sent across
|
|
13
|
+
# the socket. Typically an encoded form of Contrast::Api::Dtm::Message.
|
|
14
|
+
# @return [String] some marshalled form of data returned by the socket.
|
|
15
|
+
# Typically an encoded form of Contrast::Api::Settings::AgentSettings.
|
|
16
|
+
def send_marshaled marshaled
|
|
17
|
+
SOCKET_MONITOR.synchronize do
|
|
18
|
+
socket = new_socket
|
|
19
|
+
|
|
20
|
+
# write message length
|
|
21
|
+
len = marshaled.length
|
|
22
|
+
socket.write([len].pack(Contrast::Api::ENCODING_STRING))
|
|
23
|
+
|
|
24
|
+
# write the entire message
|
|
25
|
+
socket.write(marshaled)
|
|
26
|
+
socket.close_write
|
|
27
|
+
|
|
28
|
+
# read the response length
|
|
29
|
+
len = socket.read(4).unpack1(Contrast::Api::ENCODING_STRING)
|
|
30
|
+
|
|
31
|
+
# read expected response to end
|
|
32
|
+
socket.read(len)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Override this method to return a socket.
|
|
37
|
+
# Should be interface compatible with TCPSocket, UNIXSocket, etc.
|
|
38
|
+
def new_socket
|
|
39
|
+
raise NotImplementedError, 'This is abstract, override it.'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
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/utils/object_share'
|
|
5
|
+
cs__scoped_require 'contrast/utils/os'
|
|
6
|
+
cs__scoped_require 'contrast/components/interface'
|
|
7
|
+
|
|
8
|
+
module Contrast
|
|
9
|
+
module Api
|
|
10
|
+
# This class acts as the interface for the communication between the Agent
|
|
11
|
+
# and the Service (SpeedRacer) as well as functions as a way for the Agent
|
|
12
|
+
# to manage the bundled Service.
|
|
13
|
+
class Speedracer
|
|
14
|
+
include Contrast::Components::Interface
|
|
15
|
+
access_component :logging, :contrast_service, :app_context
|
|
16
|
+
|
|
17
|
+
attr_reader :client_number,
|
|
18
|
+
:host,
|
|
19
|
+
:port,
|
|
20
|
+
:socket,
|
|
21
|
+
:connection,
|
|
22
|
+
:messages_total
|
|
23
|
+
|
|
24
|
+
@instance_count = 0
|
|
25
|
+
@instance_mutex = Mutex.new
|
|
26
|
+
|
|
27
|
+
def self.next_client_number
|
|
28
|
+
@instance_mutex.synchronize do
|
|
29
|
+
begin
|
|
30
|
+
@instance_count += 1
|
|
31
|
+
# Rollover things
|
|
32
|
+
rescue StandardError
|
|
33
|
+
@instance_count = 1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.read_only_instance_count
|
|
39
|
+
@instance_count.dup
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def initialize connection
|
|
43
|
+
@client_number = Contrast::Api::Speedracer.next_client_number
|
|
44
|
+
@messages_total = 0
|
|
45
|
+
|
|
46
|
+
@pid = Process.pid.to_i
|
|
47
|
+
@ppid = Process.ppid.to_i
|
|
48
|
+
@connection = connection
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Allow for the start of a Service, but block so that we only attempt to
|
|
52
|
+
# start the service one try at a time in the case multiple threads are
|
|
53
|
+
# trying to send messages.
|
|
54
|
+
def start_service
|
|
55
|
+
zombie_check
|
|
56
|
+
service_starter_thread.join(5)
|
|
57
|
+
is_service_started = Contrast::Utils::OS.running?
|
|
58
|
+
logger.error(nil, 'The bundled service could not be started. The agent will not function properly.') unless is_service_started
|
|
59
|
+
is_service_started
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def send_one msg
|
|
63
|
+
case msg
|
|
64
|
+
when Contrast::Api::Dtm::ServerActivity
|
|
65
|
+
send_server_activity(msg)
|
|
66
|
+
when Contrast::Api::Dtm::AgentStartup
|
|
67
|
+
send_agent_startup(msg)
|
|
68
|
+
when Contrast::Api::Dtm::ApplicationCreate
|
|
69
|
+
send_application_create(msg)
|
|
70
|
+
when Contrast::Api::Dtm::ApplicationUpdate
|
|
71
|
+
send_application_update(msg)
|
|
72
|
+
when Contrast::Api::Dtm::Activity
|
|
73
|
+
send_application_activity(msg)
|
|
74
|
+
when Contrast::Api::Dtm::HttpRequest
|
|
75
|
+
send_prefilter(msg)
|
|
76
|
+
when Contrast::Api::Dtm::HttpResponse
|
|
77
|
+
send_postfilter(msg)
|
|
78
|
+
when Contrast::Api::Dtm::Noop
|
|
79
|
+
send_noop(msg)
|
|
80
|
+
when Contrast::Api::Dtm::ObservedRoute
|
|
81
|
+
send_observed_route(msg)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# check if there's a zombie service that exists, and wait on it if so.
|
|
88
|
+
# currently, this only happens when trying to initialize speedracer
|
|
89
|
+
def zombie_check
|
|
90
|
+
return if windows?
|
|
91
|
+
|
|
92
|
+
zombie_pid_list = Contrast::Utils::OS.zombie_pids
|
|
93
|
+
zombie_pid_list.each do |pid|
|
|
94
|
+
Process.wait(pid.to_i)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def windows?
|
|
99
|
+
@_windows = Contrast::Utils::OS.windows? if @_windows.nil?
|
|
100
|
+
@_windows
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def determine_startup_options
|
|
104
|
+
return { out: :out, err: :err } if Contrast::Agent::FeatureState.instance.service_control[:logger_path] == 'STDOUT'
|
|
105
|
+
|
|
106
|
+
{ out: File::NULL, err: File::NULL }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# This is a separate method so we can overwrite it globally in specs
|
|
110
|
+
def spawn_service
|
|
111
|
+
options = determine_startup_options
|
|
112
|
+
spawn 'contrast_service', options
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def service_starter_thread
|
|
116
|
+
Contrast::Agent::Thread.new do
|
|
117
|
+
# Always check to see if it already started
|
|
118
|
+
unless Contrast::Utils::OS.running?
|
|
119
|
+
# Spawn the service process
|
|
120
|
+
spawn_service
|
|
121
|
+
# Block until service is running
|
|
122
|
+
sleep(0.1) until Contrast::Utils::OS.running?
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def send_server_activity server_activity
|
|
128
|
+
msg = base_message
|
|
129
|
+
msg.server_activity = server_activity
|
|
130
|
+
send_message(msg)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def send_agent_startup agent_startup
|
|
134
|
+
msg = base_message
|
|
135
|
+
msg.agent_startup = agent_startup
|
|
136
|
+
send_message(msg)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def send_application_create app_create
|
|
140
|
+
msg = base_message
|
|
141
|
+
msg.application_create = app_create
|
|
142
|
+
send_message(msg)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def send_application_update app_update
|
|
146
|
+
msg = base_message
|
|
147
|
+
msg.application_update = app_update
|
|
148
|
+
send_message(msg)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def send_application_activity activity
|
|
152
|
+
msg = base_message
|
|
153
|
+
msg.activity = activity
|
|
154
|
+
send_message(msg)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def send_prefilter http_request
|
|
158
|
+
msg = base_message
|
|
159
|
+
msg.prefilter = http_request
|
|
160
|
+
send_message(msg)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def send_postfilter http_response
|
|
164
|
+
msg = base_message
|
|
165
|
+
msg.postfilter = http_response
|
|
166
|
+
send_message(msg)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def send_noop noop = nil
|
|
170
|
+
msg = base_message
|
|
171
|
+
msg.noop = noop || Contrast::Api::Dtm::Noop.new
|
|
172
|
+
send_message(msg)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def send_observed_route observed_route
|
|
176
|
+
msg = base_message
|
|
177
|
+
msg.observed_route = observed_route
|
|
178
|
+
send_message(msg)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def base_message
|
|
182
|
+
msg = Contrast::Api::Dtm::Message.new
|
|
183
|
+
msg.app_name = APP_CONTEXT.name
|
|
184
|
+
msg.app_path = APP_CONTEXT.path
|
|
185
|
+
msg.app_language = Contrast::Utils::ObjectShare::RUBY
|
|
186
|
+
msg.client_id = APP_CONTEXT.client_id
|
|
187
|
+
msg.client_number = client_number
|
|
188
|
+
msg.client_total = Contrast::Api::Speedracer.read_only_instance_count
|
|
189
|
+
msg.message_count = (@messages_total += 1)
|
|
190
|
+
msg.pid = APP_CONTEXT.pid
|
|
191
|
+
msg.ppid = APP_CONTEXT.ppid
|
|
192
|
+
msg
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def send_message message
|
|
196
|
+
to_service = Contrast::Api::Dtm::Message.encode(message)
|
|
197
|
+
from_service = send_marshaled(to_service)
|
|
198
|
+
Contrast::Api::Settings::AgentSettings.decode(from_service)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def send_marshaled marshaled
|
|
202
|
+
connection.send_marshaled(marshaled)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|