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,75 @@
|
|
|
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
|
+
# This patch installs our extension as early as possible. The alternative is to
|
|
7
|
+
# litter our code with responds_to? checks.
|
|
8
|
+
class String
|
|
9
|
+
include Contrast::CoreExtensions::Assess::AssessExtension
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Contrast
|
|
13
|
+
module CoreExtensions
|
|
14
|
+
module Assess
|
|
15
|
+
# This Class provides us with a way to invoke String propagation for those
|
|
16
|
+
# methods which are too complex to fit into one of the standard
|
|
17
|
+
# Contrast::Agent::Assess::Policy::Propagator molds without cluttering up the
|
|
18
|
+
# String Class or exposing our methods there.
|
|
19
|
+
class StringPropagator
|
|
20
|
+
include Contrast::Components::Interface
|
|
21
|
+
|
|
22
|
+
access_component :analysis, :agent, :logging, :scope
|
|
23
|
+
|
|
24
|
+
NODE_HASH = {
|
|
25
|
+
'class_name' => 'String',
|
|
26
|
+
'instance_method' => true,
|
|
27
|
+
'method_name' => 'interpolate',
|
|
28
|
+
'method_visibility' => 'public',
|
|
29
|
+
'action' => 'CUSTOM',
|
|
30
|
+
'source' => 'O,P0',
|
|
31
|
+
'target' => 'R',
|
|
32
|
+
'patch_class' => 'NOOP',
|
|
33
|
+
'patch_method' => 'track_interpolation'
|
|
34
|
+
}.cs__freeze
|
|
35
|
+
INTERPOLATION_NODE = Contrast::Agent::Assess::Policy::PropagationNode.new(NODE_HASH)
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
def track_interpolation inputs, result
|
|
39
|
+
return unless AGENT.interpolation_enabled?
|
|
40
|
+
return if in_contrast_scope?
|
|
41
|
+
return unless inputs.any?(&:cs__tracked?)
|
|
42
|
+
|
|
43
|
+
with_contrast_scope do
|
|
44
|
+
offset = 0
|
|
45
|
+
inputs.each do |input|
|
|
46
|
+
result.cs__copy_from(input, offset)
|
|
47
|
+
offset += input.length
|
|
48
|
+
end
|
|
49
|
+
result.cs__properties.build_event(INTERPOLATION_NODE, result, inputs, result, inputs)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def instrument_string_interpolation
|
|
54
|
+
if @_instrument_string_interpolation.nil?
|
|
55
|
+
@_instrument_string_interpolation = begin
|
|
56
|
+
if AGENT.patch_interpolation?
|
|
57
|
+
cs__scoped_require 'cs__assess_string_interpolation26/cs__assess_string_interpolation26'
|
|
58
|
+
end
|
|
59
|
+
true
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
logger.error(e, 'Error loading interpolation patch')
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
@_instrument_string_interpolation
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
cs__scoped_require 'cs__assess_string/cs__assess_string'
|
|
74
|
+
|
|
75
|
+
Contrast::CoreExtensions::Assess::StringPropagator.instrument_string_interpolation
|
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
# This module acts a trigger & propagator for Tilt::Template evaluation
|
|
6
|
+
module TiltTemplateTrigger
|
|
7
|
+
include Contrast::Components::Interface
|
|
8
|
+
access_component :logging
|
|
9
|
+
class << self
|
|
10
|
+
NODE_HASH = {
|
|
11
|
+
'class_name' => 'Tilt::Template',
|
|
12
|
+
'instance_method' => true,
|
|
13
|
+
'method_name' => 'render',
|
|
14
|
+
'method_visibility' => 'public',
|
|
15
|
+
'action' => 'CUSTOM',
|
|
16
|
+
'source' => 'O,P0',
|
|
17
|
+
'target' => 'R',
|
|
18
|
+
'patch_class' => 'NOOP',
|
|
19
|
+
'patch_method' => 'track_template_evaluation'
|
|
20
|
+
}.cs__freeze
|
|
21
|
+
TEMPLATE_PROPAGATION_NODE = Contrast::Agent::Assess::Policy::PropagationNode.new(NODE_HASH)
|
|
22
|
+
|
|
23
|
+
def render_trigger_check context, trigger_node, _source, object, ret, invoked, *args
|
|
24
|
+
logger.debug { 'Tilt::Template Trigger - running propagation' }
|
|
25
|
+
|
|
26
|
+
scope = args[0]
|
|
27
|
+
binding_variables = scope.instance_variables
|
|
28
|
+
erb_template_prerender = object.instance_variable_get(:@data)
|
|
29
|
+
interpolated_inputs = []
|
|
30
|
+
binding_variables.each do |bound_variable_sym|
|
|
31
|
+
bound_variable_value = scope.instance_variable_get(bound_variable_sym)
|
|
32
|
+
|
|
33
|
+
next unless bound_variable_value.cs__respond_to?(:cs__tracked?) && bound_variable_value.cs__tracked?
|
|
34
|
+
next unless erb_template_prerender.include?(bound_variable_sym.to_s)
|
|
35
|
+
|
|
36
|
+
start_index = ret.index(bound_variable_value)
|
|
37
|
+
next if start_index.nil?
|
|
38
|
+
|
|
39
|
+
logger.debug('Tilt::Template Trigger - found bound_variable in erb template result')
|
|
40
|
+
ret.cs__copy_from(bound_variable_value, start_index)
|
|
41
|
+
interpolated_inputs << bound_variable_sym
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
locals = args[1]
|
|
45
|
+
locals.each do |local_name, local_value|
|
|
46
|
+
next unless local_value.cs__respond_to?(:cs__tracked?) && local_value.cs__tracked?
|
|
47
|
+
next unless erb_template_prerender.include?(local_name.to_s)
|
|
48
|
+
|
|
49
|
+
start_index = ret.index(local_value)
|
|
50
|
+
next if start_index.nil?
|
|
51
|
+
|
|
52
|
+
logger.debug('Tilt:Template Trigger - found local_value in erb template result')
|
|
53
|
+
ret.cs__copy_from(local_value, start_index)
|
|
54
|
+
interpolated_inputs << local_name
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
unless interpolated_inputs.empty?
|
|
58
|
+
interpolated_inputs.each do |input|
|
|
59
|
+
input.cs__properties.events.each do |event|
|
|
60
|
+
ret.cs__properties.events << event
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
ret.cs__properties.build_event(TEMPLATE_PROPAGATION_NODE, ret, erb_template_prerender, ret, interpolated_inputs, invoked + 1)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if ret.cs__tracked?
|
|
67
|
+
Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(context, trigger_node, ret, erb_template_prerender, ret, invoked + 1, interpolated_inputs)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
ret
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
# Some developers override various methods on Delegator, which can often
|
|
5
|
+
# involve changing expected method parity/behavior which in turn prevents us
|
|
6
|
+
# from being able to reliably use affected methods. Let's alias these methods
|
|
7
|
+
# so that we always have access to them.
|
|
8
|
+
#
|
|
9
|
+
# This is a special case in that we're those developers, so we violate the cs__
|
|
10
|
+
# namespacing here to avoid that.
|
|
11
|
+
class Delegator
|
|
12
|
+
# breaks from convention to not conflict w/ Object#respond_to?
|
|
13
|
+
alias_method :cs__delegator_respond_to?, :respond_to?
|
|
14
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
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 CoreExtensions
|
|
6
|
+
module Assess
|
|
7
|
+
# This Module allows us to track calls to the BasicObject#eval method,
|
|
8
|
+
# which violates the design of most methods we track in that we have to
|
|
9
|
+
# apply the trigger in a custom patch over one of the generic triggers in
|
|
10
|
+
# TriggerMethod.
|
|
11
|
+
module EvalTrigger
|
|
12
|
+
def instance_eval_trigger_check source, ret
|
|
13
|
+
apply_trigger(source, ret, 'BasicObject', :instance_eval)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def eval_trigger_check source, ret, method
|
|
17
|
+
apply_trigger(source, ret, 'Module', method)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def apply_trigger source, ret, clazz, method
|
|
21
|
+
current_context = Contrast::Agent::REQUEST_TRACKER.current
|
|
22
|
+
return unless current_context
|
|
23
|
+
|
|
24
|
+
# Since we know this is the source of the trigger, we can do some
|
|
25
|
+
# optimization here and return when it is not tracked
|
|
26
|
+
return unless Contrast::Utils::Assess::TrackingUtil.tracked?(source)
|
|
27
|
+
|
|
28
|
+
# source might not be all the args passed in, but it is the one we care
|
|
29
|
+
# about. we could pass in all the args in the last param here if it
|
|
30
|
+
# becomes an issue in rendering on TS
|
|
31
|
+
Contrast::Agent::Assess::Policy::TriggerMethod.cs__apply_trigger(
|
|
32
|
+
current_context,
|
|
33
|
+
trigger_node(clazz, method),
|
|
34
|
+
source,
|
|
35
|
+
self,
|
|
36
|
+
ret,
|
|
37
|
+
1,
|
|
38
|
+
source)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def trigger_node clazz, method
|
|
44
|
+
triggers = Contrast::Agent::Assess::Policy::Policy.instance.triggers
|
|
45
|
+
return unless triggers
|
|
46
|
+
|
|
47
|
+
triggers.find { |node| node.class_name == clazz && node.method_name == method }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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 CoreExtensions
|
|
6
|
+
# Our top level Inventory namespace in the Core Extensions section of our
|
|
7
|
+
# code. These patches are those that are invoked directly from a patched
|
|
8
|
+
# Class.
|
|
9
|
+
#
|
|
10
|
+
# @deprecated This is one of our earliest designs and is not nearly as
|
|
11
|
+
# relevant given the move to C based patching and the lessons learned
|
|
12
|
+
# therein.
|
|
13
|
+
module Inventory
|
|
14
|
+
cs__scoped_require 'contrast/internal_exception'
|
|
15
|
+
cs__scoped_require 'contrast/security_exception'
|
|
16
|
+
# patching
|
|
17
|
+
cs__scoped_require 'contrast/agent/inventory/policy/trigger_node'
|
|
18
|
+
cs__scoped_require 'contrast/agent/inventory/policy/policy'
|
|
19
|
+
cs__scoped_require 'contrast/agent/patching/policy/patcher'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/components/interface'
|
|
5
|
+
cs__scoped_require 'contrast/utils/data_store_util'
|
|
6
|
+
|
|
7
|
+
module Contrast
|
|
8
|
+
module CoreExtensions
|
|
9
|
+
module Inventory
|
|
10
|
+
# This Module is how we apply the Data Store detection required for the
|
|
11
|
+
# FlowMap feature. It is called from our patches of the targeted methods
|
|
12
|
+
# in which database operations occur. It is responsible for deciding if
|
|
13
|
+
# the given invocation is worth reporting or not.
|
|
14
|
+
module DataStores
|
|
15
|
+
class << self
|
|
16
|
+
include Contrast::Components::Interface
|
|
17
|
+
|
|
18
|
+
access_component :logging, :analysis
|
|
19
|
+
# The key used in policy.json to indicate the database type to
|
|
20
|
+
# report.
|
|
21
|
+
DATA_STORE_MARKER = 'data_store'
|
|
22
|
+
|
|
23
|
+
def cs__patched_report_data_store _method, _exception, properties, object, _args
|
|
24
|
+
return unless INVENTORY.enabled?
|
|
25
|
+
|
|
26
|
+
marker = properties[DATA_STORE_MARKER]
|
|
27
|
+
return unless marker
|
|
28
|
+
|
|
29
|
+
Contrast::Utils::DataStoreUtil.report_data_store(marker)
|
|
30
|
+
rescue StandardError => e
|
|
31
|
+
logger.error(e, "Error reporting database call in #{ object }")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
|
|
6
|
+
# Some developers override various methods on Module, which can often involve
|
|
7
|
+
# changing expected method parity/behavior which in turn prevents us from being
|
|
8
|
+
# able to reliably use affected methods. Let's alias these method so that we
|
|
9
|
+
# always have access to them.
|
|
10
|
+
class Module
|
|
11
|
+
alias_method :cs__name, :name
|
|
12
|
+
alias_method :cs__constants, :constants
|
|
13
|
+
alias_method :cs__const_defined?, :const_defined?
|
|
14
|
+
alias_method :cs__const_get, :const_get
|
|
15
|
+
alias_method :cs__const_set, :const_set
|
|
16
|
+
alias_method :cs__autoload?, :autoload?
|
|
17
|
+
|
|
18
|
+
# The method const_defined? can cause autoload, which is bad for us. The
|
|
19
|
+
# method autoload? doesn't traverse namespaces. This method lets us provide a
|
|
20
|
+
# constant, as a String, and parse it to determine if it has been truly
|
|
21
|
+
# truly defined, meaning it existed before this method was invoked, not as a
|
|
22
|
+
# result of it.
|
|
23
|
+
#
|
|
24
|
+
# @param name [String] the name of the constant to look up
|
|
25
|
+
# @return [Boolean]
|
|
26
|
+
def cs__truly_defined? name
|
|
27
|
+
return false unless name
|
|
28
|
+
|
|
29
|
+
segments = name.split(Contrast::Utils::ObjectShare::DOUBLE_COLON)
|
|
30
|
+
previous_module = Module
|
|
31
|
+
segments.each do |segment|
|
|
32
|
+
return false if previous_module.cs__autoload?(segment)
|
|
33
|
+
return false unless previous_module.cs__const_defined?(segment)
|
|
34
|
+
|
|
35
|
+
previous_module = previous_module.cs__const_get(segment)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
true
|
|
39
|
+
rescue NameError # account for nonsense / poorly formatted constants
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
|
|
6
|
+
# Some aliases within Object have to happen especially early, because they're
|
|
7
|
+
# core to class definitions. See lib/contrast.rb.
|
|
8
|
+
# ONLY very core aliasing should go there. All the routine extension should
|
|
9
|
+
# happen here, where you'd expect it.
|
|
10
|
+
class Object
|
|
11
|
+
# Return a String representing the self invoking this method.
|
|
12
|
+
def cs__inspect
|
|
13
|
+
if cs__is_a?(String)
|
|
14
|
+
return Contrast::Utils::ObjectShare::EMPTY_STRING if empty?
|
|
15
|
+
|
|
16
|
+
dup
|
|
17
|
+
elsif cs__is_a?(Symbol)
|
|
18
|
+
":#{ self }"
|
|
19
|
+
elsif cs__is_a?(Numeric)
|
|
20
|
+
to_s
|
|
21
|
+
elsif cs__is_a?(Module)
|
|
22
|
+
"#{ cs__name }@#{ __id__ }"
|
|
23
|
+
else
|
|
24
|
+
"#{ cs__class.cs__name }@#{ __id__ }"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
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 CoreExtensions
|
|
6
|
+
# Our top level Protect namespace in the Core Extensions section of our
|
|
7
|
+
# code. These patches are those that are invoked directly from a patched
|
|
8
|
+
# Class.
|
|
9
|
+
#
|
|
10
|
+
# @deprecated This is one of our earliest designs and is not nearly as
|
|
11
|
+
# relevant given the move to C based patching and the lessons learned
|
|
12
|
+
# therein.
|
|
13
|
+
module Protect
|
|
14
|
+
cs__scoped_require 'contrast/security_exception'
|
|
15
|
+
# patching
|
|
16
|
+
cs__scoped_require 'contrast/agent/protect/policy/trigger_node'
|
|
17
|
+
cs__scoped_require 'contrast/agent/protect/policy/policy'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
cs__scoped_require 'contrast/core_extensions/protect/applies_deserialization_rule'
|
|
6
|
+
|
|
7
|
+
module Contrast
|
|
8
|
+
module CoreExtensions
|
|
9
|
+
module Protect
|
|
10
|
+
# This Module is how we apply the Command Injection rule. It is called
|
|
11
|
+
# from our patches of the targeted methods in which command execution
|
|
12
|
+
# occurs. It is responsible for deciding if the infilter methods of the
|
|
13
|
+
# rule should be invoked.
|
|
14
|
+
# In addition, b/c of the nature of Deserialization's sand boxing
|
|
15
|
+
# function, this Module's apply methods call through to the
|
|
16
|
+
# {#cs__patched_apply_deserialization_command_check} method of the
|
|
17
|
+
# Deserialization applicator.
|
|
18
|
+
module AppliesCommandInjectionRule
|
|
19
|
+
CS__SEMICOLON = '; '
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
include Contrast::Components::Interface
|
|
23
|
+
access_component :logging, :analysis
|
|
24
|
+
|
|
25
|
+
def cs__patched_apply_command_injection_rule method, _exception, _properties, object, args
|
|
26
|
+
return unless valid_command?(args)
|
|
27
|
+
|
|
28
|
+
command = build_command(args)
|
|
29
|
+
Contrast::CoreExtensions::Protect::AppliesDeserializationRule.cs__patched_apply_deserialization_command_check(command)
|
|
30
|
+
return if cs__skip_analysis?
|
|
31
|
+
|
|
32
|
+
begin
|
|
33
|
+
clazz = object.is_a?(Module) ? object : object.cs__class
|
|
34
|
+
class_name = clazz.cs__name
|
|
35
|
+
rule.infilter(Contrast::Agent::REQUEST_TRACKER.current, class_name, method, command)
|
|
36
|
+
end
|
|
37
|
+
rescue Contrast::SecurityException => e
|
|
38
|
+
raise e
|
|
39
|
+
rescue StandardError => e
|
|
40
|
+
msg = "command injection: class=#{ object }.#{ method }"
|
|
41
|
+
logger.error(e, msg)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def rule
|
|
45
|
+
PROTECT.rule Contrast::Agent::Protect::Rule::CmdInjection::NAME
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def cs__skip_analysis?
|
|
49
|
+
context = Contrast::Agent::REQUEST_TRACKER.current
|
|
50
|
+
return true unless context&.app_loaded?
|
|
51
|
+
return true unless rule&.enabled?
|
|
52
|
+
|
|
53
|
+
false
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def valid_command? command
|
|
57
|
+
command && (command.is_a?(String) || command.is_a?(Array))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def build_command command
|
|
61
|
+
return command if command.is_a?(String)
|
|
62
|
+
|
|
63
|
+
command = command.drop(1) if command.length > 1
|
|
64
|
+
command.join(CS__SEMICOLON)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
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 CoreExtensions
|
|
8
|
+
module Protect
|
|
9
|
+
# This Module is how we apply the Deserialization rule. It is called from
|
|
10
|
+
# our patches of the targeted methods in which deserialization occurs.
|
|
11
|
+
# It is responsible for deciding if the infilter methods of the rule
|
|
12
|
+
# should be invoked.
|
|
13
|
+
module AppliesDeserializationRule
|
|
14
|
+
include Contrast::Components::Interface
|
|
15
|
+
access_component :logging, :analysis
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
def cs__patched_apply_deserialization_rule method, _exception, _properties, object, args
|
|
19
|
+
return unless valid_input?(args)
|
|
20
|
+
return if cs__skip_analysis?
|
|
21
|
+
|
|
22
|
+
rule.infilter(Contrast::Agent::REQUEST_TRACKER.current, args[0])
|
|
23
|
+
rescue Contrast::SecurityException => e
|
|
24
|
+
raise e
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
logger.error(e, "Error running untrusted-deserialization rule in #{ object }.#{ method }")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def cs__patched_apply_deserialization_command_check command
|
|
30
|
+
return unless command
|
|
31
|
+
return if cs__skip_analysis?
|
|
32
|
+
|
|
33
|
+
rule.check_command_scope(command)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def rule
|
|
37
|
+
PROTECT.rule Contrast::Agent::Protect::Rule::Deserialization::NAME
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def valid_input? args
|
|
41
|
+
return false unless args&.any?
|
|
42
|
+
|
|
43
|
+
input = args[0]
|
|
44
|
+
input.is_a?(String)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def cs__skip_analysis?
|
|
48
|
+
context = Contrast::Agent::REQUEST_TRACKER.current
|
|
49
|
+
return true unless context&.app_loaded?
|
|
50
|
+
return true unless rule&.enabled?
|
|
51
|
+
|
|
52
|
+
false
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|