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,192 @@
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
cs__scoped_require 'contrast/core_extensions/object'
|
5
|
+
|
6
|
+
module Contrast
|
7
|
+
module Agent
|
8
|
+
module Patching
|
9
|
+
module Policy
|
10
|
+
# This indicates the status of the Module into which Contrast is being
|
11
|
+
# woven
|
12
|
+
class PatchStatus
|
13
|
+
class << self
|
14
|
+
# Gives the current status for the provided module, setting one if
|
15
|
+
# one does not exist.
|
16
|
+
#
|
17
|
+
# @param mod [Module] the Module for which the status is asked
|
18
|
+
# @return [Contrast::Agent::Patching::Policy::PolicyStatus]
|
19
|
+
def get_status mod
|
20
|
+
if mod.cs__const_defined?(status_key, false)
|
21
|
+
mod.cs__const_get(status_key, false)
|
22
|
+
else
|
23
|
+
s = new
|
24
|
+
mod.cs__const_set(status_key, s)
|
25
|
+
s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Allows our C patches to look up the :MethodPolicy for a given
|
30
|
+
# Module and method
|
31
|
+
#
|
32
|
+
# @param mod [Module or Class] the entity on which the patch has
|
33
|
+
# been placed
|
34
|
+
# @param method [Symbol] the name of the method to which the patch
|
35
|
+
# applies
|
36
|
+
# @param is_instance_method [Boolean] is the method being patched
|
37
|
+
# an instance method or not (not implying class method).
|
38
|
+
# @return [Contrast::Agent::Patching::Policy::MethodPolicy]
|
39
|
+
def info_for mod, method, is_instance_method
|
40
|
+
mod = mod.cs__class unless mod.cs__is_a?(Module)
|
41
|
+
method_key = method_name_key(method, is_instance_method)
|
42
|
+
# Ideally, we'll get to a point where this is all that is needed
|
43
|
+
ret = find_info_for_one(mod, method_key)
|
44
|
+
return ret if ret
|
45
|
+
|
46
|
+
# But to start, the lookup will be on the ancestor, not the
|
47
|
+
# calling class. We need to traverse the ancestors, included
|
48
|
+
# modules, and Module itself the first time a method is called in
|
49
|
+
# a given class. Then we save that lookup to the class
|
50
|
+
ret = find_info_for(mod.ancestors, method_key)
|
51
|
+
ret ||= find_info_for(mod.cs__singleton_class.included_modules, method_key)
|
52
|
+
ret ||= find_info_for(MOD_ARRAY, method_key)
|
53
|
+
update_holder(mod, method_key, ret) if ret
|
54
|
+
ret
|
55
|
+
end
|
56
|
+
|
57
|
+
# Allows our C patches to set the :MethodPolicy for a given
|
58
|
+
# Module and method
|
59
|
+
#
|
60
|
+
# @param mod [Module or Class] the entity on which the patch will
|
61
|
+
# be placed
|
62
|
+
# @param method [Symbol] the name of the method to which the patch
|
63
|
+
# applies
|
64
|
+
# @param method_policy [:MethodPolicy] the policy that applies to
|
65
|
+
# the given mod & method
|
66
|
+
# @param is_instance_method [Boolean] is the method being patched
|
67
|
+
# an instance method or not (not implying class method).
|
68
|
+
# @param cs_method [Symbol] the name to which the original method
|
69
|
+
# was aliased, cached for performance reasons
|
70
|
+
def set_info_for mod, method, method_policy, is_instance_method, cs_method
|
71
|
+
mod.instance_variable_set(method_info_key, {}) unless mod.instance_variable_defined?(method_info_key)
|
72
|
+
holder = mod.instance_variable_get(method_info_key)
|
73
|
+
holder[method_name_key(method, is_instance_method)] = [method_policy, cs_method] unless holder.key?(method)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def method_info_key
|
79
|
+
:@cs__patched_method_info
|
80
|
+
end
|
81
|
+
|
82
|
+
# holder for each method - instance combination we've seen, done to
|
83
|
+
# avoid rebuilding the key on every method invocation.
|
84
|
+
def translated_names
|
85
|
+
@_translated_names ||= {}
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param method [Symbol] the name of the method to which the patch
|
89
|
+
# applies
|
90
|
+
# @param is_instance_method [Boolean] is the method being patched
|
91
|
+
# an instance method or not (not implying class method).
|
92
|
+
# @return [Symbol] :"method[true|false]"
|
93
|
+
def method_name_key method, is_instance_method
|
94
|
+
translated_names[method] = [] unless translated_names.key?(method)
|
95
|
+
pre_built = translated_names[method]
|
96
|
+
idx = is_instance_method ? 0 : 1
|
97
|
+
pre_built[idx] = :"#{ method }#{ is_instance_method }" unless pre_built[idx]
|
98
|
+
pre_built[idx]
|
99
|
+
end
|
100
|
+
|
101
|
+
def status_key
|
102
|
+
:CONTRAST_PATCH_POLICY_STATUS
|
103
|
+
end
|
104
|
+
|
105
|
+
def update_holder mod, method, ret
|
106
|
+
mod.instance_variable_set(method_info_key, {}) unless mod.instance_variable_defined?(method_info_key)
|
107
|
+
holder = mod.instance_variable_get(method_info_key)
|
108
|
+
holder[method] = ret
|
109
|
+
end
|
110
|
+
|
111
|
+
def find_info_for candidates, method
|
112
|
+
candidates.each do |candidate|
|
113
|
+
new_ret = find_info_for_one(candidate, method)
|
114
|
+
return new_ret if new_ret
|
115
|
+
end
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_info_for_one mod, method
|
120
|
+
return unless mod.instance_variable_defined?(method_info_key)
|
121
|
+
|
122
|
+
holder = mod.instance_variable_get(method_info_key)
|
123
|
+
return unless holder&.key?(method)
|
124
|
+
|
125
|
+
holder[method]
|
126
|
+
end
|
127
|
+
|
128
|
+
MOD_ARRAY = [Module].cs__freeze
|
129
|
+
end
|
130
|
+
|
131
|
+
attr_reader :patch_status, :rewrite_status
|
132
|
+
|
133
|
+
def patching!
|
134
|
+
@patch_status = :PATCHING
|
135
|
+
end
|
136
|
+
|
137
|
+
def partial_patch!
|
138
|
+
@patch_status = :PARTIAL
|
139
|
+
end
|
140
|
+
|
141
|
+
def no_patch!
|
142
|
+
@patch_status = :NONE
|
143
|
+
end
|
144
|
+
|
145
|
+
def patched!
|
146
|
+
@patch_status = :PATCHED
|
147
|
+
end
|
148
|
+
|
149
|
+
def failed_patch!
|
150
|
+
@patch_status = :FAILED
|
151
|
+
end
|
152
|
+
|
153
|
+
def patching?
|
154
|
+
@patch_status == :PATCHING
|
155
|
+
end
|
156
|
+
|
157
|
+
def patched?
|
158
|
+
@patch_status == :PATCHED ||
|
159
|
+
@patch_status == :NONE ||
|
160
|
+
@patch_status == :FAILED
|
161
|
+
end
|
162
|
+
|
163
|
+
def rewriting!
|
164
|
+
@rewrite_status = :REWRITING
|
165
|
+
end
|
166
|
+
|
167
|
+
def no_rewrite!
|
168
|
+
@rewrite_status = :NO_REWRITE
|
169
|
+
end
|
170
|
+
|
171
|
+
def rewritten!
|
172
|
+
@rewrite_status = :REWRITTEN
|
173
|
+
end
|
174
|
+
|
175
|
+
def failed_rewrite!
|
176
|
+
@rewrite_status = :FAILED_REWRITE
|
177
|
+
end
|
178
|
+
|
179
|
+
def rewriting?
|
180
|
+
@rewrite_status == :REWRITING
|
181
|
+
end
|
182
|
+
|
183
|
+
def rewritten?
|
184
|
+
@rewrite_status == :REWRITTEN ||
|
185
|
+
@rewrite_status == :NO_REWRITE ||
|
186
|
+
@rewrite_status == :FAILED_REWRITE
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -0,0 +1,310 @@
|
|
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 'monitor'
|
5
|
+
|
6
|
+
# base
|
7
|
+
cs__scoped_require 'contrast/agent/patching/policy/patch_status'
|
8
|
+
cs__scoped_require 'contrast/agent/patching/policy/method_policy'
|
9
|
+
cs__scoped_require 'contrast/agent/patching/policy/module_policy'
|
10
|
+
cs__scoped_require 'contrast/agent/patching/policy/policy_unpatcher'
|
11
|
+
cs__scoped_require 'contrast/components/interface'
|
12
|
+
cs__scoped_require 'contrast/utils/class_util'
|
13
|
+
cs__scoped_require 'contrast/utils/scope_util'
|
14
|
+
|
15
|
+
# assess
|
16
|
+
cs__scoped_require 'contrast/agent/assess/policy/policy'
|
17
|
+
cs__scoped_require 'contrast/agent/assess/policy/policy_scanner'
|
18
|
+
cs__scoped_require 'contrast/agent/assess/policy/rewriter_patch'
|
19
|
+
cs__scoped_require 'contrast/agent/assess/policy/source_method'
|
20
|
+
cs__scoped_require 'contrast/agent/assess/policy/trigger_method'
|
21
|
+
|
22
|
+
# deadzone
|
23
|
+
cs__scoped_require 'contrast/agent/deadzone/policy/policy'
|
24
|
+
|
25
|
+
# inventory
|
26
|
+
cs__scoped_require 'contrast/agent/inventory/policy/policy'
|
27
|
+
|
28
|
+
# protect
|
29
|
+
cs__scoped_require 'contrast/agent/protect/policy/policy'
|
30
|
+
|
31
|
+
# patch
|
32
|
+
cs__scoped_require 'contrast/agent/patching/policy/patch'
|
33
|
+
|
34
|
+
# after load patched
|
35
|
+
cs__scoped_require 'contrast/agent/patching/policy/after_load_patcher'
|
36
|
+
|
37
|
+
module Contrast
|
38
|
+
module Agent
|
39
|
+
module Patching
|
40
|
+
module Policy
|
41
|
+
# This is how we patch into our customer's code. It provides a way to
|
42
|
+
# track which classes we need to patch into and, once we've woven,
|
43
|
+
# provides a map for which methods our renamed functions need to call
|
44
|
+
# and how.
|
45
|
+
module Patcher
|
46
|
+
extend Contrast::Utils::ScopeUtil
|
47
|
+
extend Contrast::Agent::Patching::Policy::AfterLoadPatcher
|
48
|
+
|
49
|
+
include Contrast::Components::Interface
|
50
|
+
access_component :logging, :analysis, :agent, :scope
|
51
|
+
|
52
|
+
class << self
|
53
|
+
# Hook to install the Contrast changes needed to allow for the
|
54
|
+
# instrumentation of the application - this only occurs once, during
|
55
|
+
# startup to catchup on everything we didn't see get loaded
|
56
|
+
def patch
|
57
|
+
logger.debug_with_time("\tPatching") do
|
58
|
+
catchup_after_load_patches
|
59
|
+
patch_methods
|
60
|
+
Contrast::Agent::Assess::Policy::RewriterPatch.rewrite_interpolations
|
61
|
+
Contrast::Agent::Patching::Policy::PolicyUnpatcher.revert_conflicting_patches
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Hook to only monkeypatch Contrast. This will not trigger any
|
66
|
+
# other functions, like rewriting or scanning. Exposed for those
|
67
|
+
# situations, like ActiveRecord dynamically defining functions,
|
68
|
+
# where only a subset of the Assess changes are needed.
|
69
|
+
PATCH_MONITOR = Monitor.new
|
70
|
+
|
71
|
+
def patch_methods
|
72
|
+
PATCH_MONITOR.synchronize do
|
73
|
+
t = Contrast::Agent::Thread.new do
|
74
|
+
synchronized_patch_methods
|
75
|
+
end
|
76
|
+
# aborting on exception makes exceptions propagate.
|
77
|
+
t.abort_on_exception = true
|
78
|
+
t.priority = Thread.current.priority + 1
|
79
|
+
t.join
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# This method is called by TracePointHook to instrument a specific class during a require
|
84
|
+
# or eval of dynamic class definition
|
85
|
+
def patch_specific_module mod
|
86
|
+
mod_name = mod.cs__name
|
87
|
+
return unless Module.cs__truly_defined?(mod_name)
|
88
|
+
|
89
|
+
load_patches_for_module(mod_name)
|
90
|
+
|
91
|
+
return unless all_module_names.any? { |name| name == mod_name }
|
92
|
+
|
93
|
+
module_data = Contrast::Agent::ModuleData.new(mod, mod_name)
|
94
|
+
patch_into_module(module_data)
|
95
|
+
all_module_names.delete(mod_name) if status_type.get_status(mod).patched?
|
96
|
+
rescue StandardError => e
|
97
|
+
logger.error("Unable to patch into #{ mod_name }", e)
|
98
|
+
end
|
99
|
+
|
100
|
+
# We did it, team. We found a patcher(s) that applies to the given
|
101
|
+
# class (or module) and the given method. Time to do some tracking.
|
102
|
+
#
|
103
|
+
# @param mod [Module] the module in which the patch should be
|
104
|
+
# placed.
|
105
|
+
# @param methods [Array(Symbol)] all the instance or singleton
|
106
|
+
# methods in this clazz.
|
107
|
+
# @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
|
108
|
+
# the policy that applies to the given method_name.
|
109
|
+
# @return [Boolean] if patched, either by this invocation or a
|
110
|
+
# previous, or not
|
111
|
+
def patch_method mod, methods, method_policy
|
112
|
+
return false unless methods&.any? # don't even build the name if there are no methods
|
113
|
+
|
114
|
+
if Contrast::Utils::ClassUtil.prepended_method?(mod, method_policy)
|
115
|
+
Contrast::Agent::Patching::Policy::Patch.instrument_with_prepend(mod, method_policy)
|
116
|
+
else
|
117
|
+
Contrast::Agent::Patching::Policy::Patch.instrument_with_alias(mod, methods, method_policy)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
POLICIES = [
|
124
|
+
Contrast::Agent::Assess::Policy::Policy,
|
125
|
+
Contrast::Agent::Inventory::Policy::Policy,
|
126
|
+
Contrast::Agent::Protect::Policy::Policy,
|
127
|
+
Contrast::Agent::Deadzone::Policy::Policy
|
128
|
+
].cs__freeze
|
129
|
+
|
130
|
+
def status_type
|
131
|
+
Contrast::Agent::Patching::Policy::PatchStatus
|
132
|
+
end
|
133
|
+
|
134
|
+
# Find, and return, the constant with the given name. If none
|
135
|
+
# exists, return nil.
|
136
|
+
#
|
137
|
+
# @param name [String] the constant whose value should be retrieved
|
138
|
+
# @return [Object, nil]
|
139
|
+
def patchable name
|
140
|
+
return unless Module.cs__truly_defined?(name)
|
141
|
+
|
142
|
+
Module.cs__const_get(name)
|
143
|
+
end
|
144
|
+
|
145
|
+
# @return [Array<String>] the names of all the Modules for which
|
146
|
+
# there patches in our policies
|
147
|
+
def all_module_names
|
148
|
+
@_all_module_names ||= POLICIES.each_with_object(Set.new) { |policy, set| set.merge(policy.instance.module_names) }
|
149
|
+
end
|
150
|
+
|
151
|
+
# Hook to only monkeypatch Contrast. This will not trigger any
|
152
|
+
# other functions, like rewriting or scanning. This method should
|
153
|
+
# only be invoked by the patch_methods method above in order to
|
154
|
+
# ensure it is wrapped in a synchronize call
|
155
|
+
def synchronized_patch_methods
|
156
|
+
# logger.trace_with_time("\t\tRunning patching") do # TODO: RUBY-547
|
157
|
+
patched = []
|
158
|
+
all_module_names.each do |patchable_name|
|
159
|
+
patchable_mod = patchable(patchable_name)
|
160
|
+
next unless patchable_mod
|
161
|
+
|
162
|
+
module_data = Contrast::Agent::ModuleData.new(patchable_mod, patchable_name)
|
163
|
+
patch_into_module(module_data)
|
164
|
+
patched << patchable_name if status_type.get_status(patchable_mod).patched?
|
165
|
+
end
|
166
|
+
all_module_names.subtract(patched)
|
167
|
+
# end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Given the patchers that apply to this class that may apply, patch
|
171
|
+
# Contrast method calls into the methods for which we have rules.
|
172
|
+
#
|
173
|
+
# @param module_data [Contrast::Agent::ModuleData] the module, and
|
174
|
+
# its name, that's being patched into
|
175
|
+
# @param redo_patch [Boolean] a trigger to force patching
|
176
|
+
# regardless of the state of the
|
177
|
+
# Contrast::Agent::Patching::Policy::PatchStatus status on the
|
178
|
+
# Module
|
179
|
+
def patch_into_module module_data, redo_patch = false
|
180
|
+
status = status_type.get_status(module_data.mod)
|
181
|
+
return if (status&.patched? || status&.patching?) && !redo_patch
|
182
|
+
|
183
|
+
# Begin patching our sources into the given clazz (or module)
|
184
|
+
# Any patcher that has the name of the clazz will be evaluated for
|
185
|
+
# patching.
|
186
|
+
# Find all the patchers that apply to this class, sorted by type.
|
187
|
+
module_policy = Contrast::Agent::Patching::Policy::ModulePolicy.create_module_policy(module_data.name)
|
188
|
+
|
189
|
+
clazz = module_data.mod
|
190
|
+
|
191
|
+
status = status_type.get_status(clazz)
|
192
|
+
return if (status.patched? || status.patching?) && !redo_patch
|
193
|
+
|
194
|
+
status.patching!
|
195
|
+
patched = include_module(module_data)
|
196
|
+
|
197
|
+
counts = 0
|
198
|
+
# Monkey patch any methods in this class that have matching nodes in the policy
|
199
|
+
unless module_policy.empty?
|
200
|
+
instance_methods = all_instance_methods(clazz, true)
|
201
|
+
singleton_methods = clazz.singleton_methods(false)
|
202
|
+
counts += patch_into_methods(clazz, instance_methods, module_policy, true)
|
203
|
+
counts += patch_into_methods(clazz, singleton_methods, module_policy, false)
|
204
|
+
counts = module_policy.num_expected_patches if adjust_for_prepend(clazz)
|
205
|
+
patched = true
|
206
|
+
end
|
207
|
+
|
208
|
+
if patched
|
209
|
+
if module_policy.num_expected_patches == counts
|
210
|
+
status.patched!
|
211
|
+
else
|
212
|
+
status.partial_patch!
|
213
|
+
end
|
214
|
+
else
|
215
|
+
status.no_patch!
|
216
|
+
end
|
217
|
+
rescue StandardError => e
|
218
|
+
status ||= status_type.get_status(module_data.mod)
|
219
|
+
status.failed_patch!
|
220
|
+
logger.warn(e, "Unable to patch into #{ module_data.name }")
|
221
|
+
ensure
|
222
|
+
logger.debug(nil, "Patching #{ module_data.name } resulted in #{ status_type.get_status(module_data.mod).patch_status }")
|
223
|
+
end
|
224
|
+
|
225
|
+
# Includes the given module with the
|
226
|
+
# Contrast::CoreExtensions::Assess::AssessExtension
|
227
|
+
# @param module_data [Contrast::Agent::ModuleData] the module, and
|
228
|
+
# its name, that's being patched into
|
229
|
+
def include_module module_data
|
230
|
+
return false unless Contrast::Agent::Assess::Policy::Policy.instance.tracked_classes.include?(module_data.name)
|
231
|
+
|
232
|
+
module_data.mod.send(:include, Contrast::CoreExtensions::Assess::AssessExtension)
|
233
|
+
true
|
234
|
+
end
|
235
|
+
|
236
|
+
# Get all of the instance methods on the given module, excluding
|
237
|
+
# those from super classes. this list will always include the
|
238
|
+
# initialize method
|
239
|
+
#
|
240
|
+
# @param mod [Module] The module from which to retrieve instance
|
241
|
+
# methods.
|
242
|
+
# @param private [Boolean] Indicate if the query should include
|
243
|
+
# private, as well as public, instance methods
|
244
|
+
# @return [Array<Symbol>]
|
245
|
+
def all_instance_methods mod, private = false
|
246
|
+
instance_methods = mod.instance_methods(false)
|
247
|
+
# C magic rb_define_global_function creates private instance
|
248
|
+
# methods. We need to instrument those dudes
|
249
|
+
# https://www.thecodingforums.com/threads/object-private_instance_methods-kernel-singleton_methods.843013/
|
250
|
+
instance_methods.concat(mod.private_instance_methods(false)) if private
|
251
|
+
# initialize is an exception to the inheritance rule.
|
252
|
+
instance_methods << :initialize unless instance_methods.include?(:initialize)
|
253
|
+
instance_methods
|
254
|
+
end
|
255
|
+
|
256
|
+
# We've found the patchers that apply to this class (or module). Now we'll
|
257
|
+
# filter on the given method.
|
258
|
+
#
|
259
|
+
# @param mod [Module] The module from which to retrieve instance
|
260
|
+
# methods.
|
261
|
+
# @param methods [Array<Symbol>] The names of all the methods in
|
262
|
+
# in this module
|
263
|
+
# @param module_policy [Contrast::Agent::Patching::Policy::ModulePolicy]
|
264
|
+
# All the patchers that apply to this class, sorted by type.
|
265
|
+
# @param is_instance_method [Boolean] Indicates if these methods
|
266
|
+
# are the instance or singleton methods for this module.
|
267
|
+
# @return [Integer] number of methods patched
|
268
|
+
def patch_into_methods mod, methods, module_policy, is_instance_method
|
269
|
+
count = 0
|
270
|
+
methods.each do |method|
|
271
|
+
method_policy = Contrast::Agent::Patching::Policy::MethodPolicy.build_method_policy(method, module_policy, is_instance_method)
|
272
|
+
next if method_policy.empty?
|
273
|
+
|
274
|
+
patched = patch_method(mod, methods, method_policy)
|
275
|
+
count += 1 if patched
|
276
|
+
end
|
277
|
+
count
|
278
|
+
end
|
279
|
+
|
280
|
+
# CGI falls pray to the weirdness that is the history of a
|
281
|
+
# previously included Module being prepended - the class that has
|
282
|
+
# already included the Module does not learn about the prepend and
|
283
|
+
# it has to be reapplied.
|
284
|
+
# TODO: RUBY-620 should remove the need for this
|
285
|
+
#
|
286
|
+
# @param mod[Module] the Module for which a prepend action needs to
|
287
|
+
# be accounted
|
288
|
+
# @return [Boolean] if an adjustment was made or not
|
289
|
+
def adjust_for_prepend mod
|
290
|
+
return false unless mod.cs__name == 'CGI::Util'
|
291
|
+
|
292
|
+
CGI.include(CGI::Util)
|
293
|
+
CGI.extend(CGI::Util)
|
294
|
+
true
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# core extensions
|
304
|
+
cs__scoped_require 'contrast/core_extensions/module'
|
305
|
+
cs__scoped_require 'contrast/core_extensions/assess'
|
306
|
+
cs__scoped_require 'contrast/core_extensions/inventory'
|
307
|
+
cs__scoped_require 'contrast/core_extensions/protect'
|
308
|
+
cs__scoped_require 'contrast/core_extensions/protect/kernel'
|
309
|
+
|
310
|
+
cs__scoped_require 'cs__contrast_patch/cs__contrast_patch'
|