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,33 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/components/interface'
|
|
5
|
+
|
|
6
|
+
module Contrast
|
|
7
|
+
module Agent
|
|
8
|
+
# This module adds an at_exit hook for us to send messages that may be lost at process exit
|
|
9
|
+
module AtExitHook
|
|
10
|
+
include Contrast::Components::Interface
|
|
11
|
+
access_component :logging, :contrast_service
|
|
12
|
+
|
|
13
|
+
TERMINATION_NOTICE = 'at_exit invoked, host application terminating'
|
|
14
|
+
|
|
15
|
+
def self.exit_hook
|
|
16
|
+
@_exit_hook ||= begin
|
|
17
|
+
at_exit do
|
|
18
|
+
logger.debug(TERMINATION_NOTICE)
|
|
19
|
+
|
|
20
|
+
context = Contrast::Agent::REQUEST_TRACKER.current
|
|
21
|
+
CONTRAST_SERVICE.send_message(context.activity) if context
|
|
22
|
+
|
|
23
|
+
logger.debug(" - current PID #{ @pid }")
|
|
24
|
+
logger.debug(" - current PPID #{ @ppid }")
|
|
25
|
+
logger.debug(" - process PID #{ Process.pid }")
|
|
26
|
+
logger.debug(" - process PPID #{ Process.ppid }")
|
|
27
|
+
end
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'ripper'
|
|
5
|
+
cs__scoped_require 'contrast/core_extensions/module'
|
|
6
|
+
cs__scoped_require 'contrast/components/interface'
|
|
7
|
+
|
|
8
|
+
# This method is left purposefully at the top level namespace. Moving it
|
|
9
|
+
# elsewhere will break functionality as it executes evaluations against the
|
|
10
|
+
# namespace from which it is called -- ie putting it in Contrast would make all
|
|
11
|
+
# changes it intends for Foo happen to Contrast::Foo instead
|
|
12
|
+
#
|
|
13
|
+
# @param class_name [String] the name of the class in which the eval will
|
|
14
|
+
# redefine functionality
|
|
15
|
+
# @param content [String] the String content that will function as the code in
|
|
16
|
+
# the given class
|
|
17
|
+
def unbound_eval class_name, content
|
|
18
|
+
# Yuck, this is a top-level method that has to break encapsulation
|
|
19
|
+
# in order to access scoping!
|
|
20
|
+
Contrast::Components::Scope::COMPONENT_INTERFACE.scope_for_current_ec.enter_contrast_scope
|
|
21
|
+
eval(content) # rubocop:disable Security/Eval
|
|
22
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
|
23
|
+
Contrast::Agent::SettingsState.log_error("Unable to perform unbound eval of new content for #{ class_name }.")
|
|
24
|
+
ensure
|
|
25
|
+
Contrast::Components::Scope::COMPONENT_INTERFACE.scope_for_current_ec.exit_contrast_scope
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module Contrast
|
|
29
|
+
module Agent
|
|
30
|
+
# Used for Ruby 2.4 & 2.5 to allow us to rewrite those methods which have
|
|
31
|
+
# interpolation in them.
|
|
32
|
+
# @deprecated Changes to this class are discouraged as this approach is
|
|
33
|
+
# being phased out with support for those language versions.
|
|
34
|
+
class ClassReopener
|
|
35
|
+
END_NEW_LINE = "end\n".cs__freeze
|
|
36
|
+
PROTECTED_WITH_NEW_LINE = "protected\n".cs__freeze
|
|
37
|
+
PRIVATE_WITH_NEW_LINE = "private\n".cs__freeze
|
|
38
|
+
CLASS_SELF_LINE = "class << self\n".cs__freeze
|
|
39
|
+
|
|
40
|
+
attr_reader :public_singleton_methods, :class_module_path, :class_name, :files, :is_class, :name_space,
|
|
41
|
+
:public_instance_methods, :protected_instance_methods, :private_instance_methods, :locations
|
|
42
|
+
|
|
43
|
+
def initialize module_data
|
|
44
|
+
@class_module_path = module_data.name
|
|
45
|
+
clazz = module_data.mod
|
|
46
|
+
@is_class = clazz.is_a?(Class)
|
|
47
|
+
@public_instance_methods = []
|
|
48
|
+
@protected_instance_methods = []
|
|
49
|
+
@private_instance_methods = []
|
|
50
|
+
@public_singleton_methods = []
|
|
51
|
+
@files = {}
|
|
52
|
+
@name_space = []
|
|
53
|
+
@class_name = nil
|
|
54
|
+
@locations = Hash.new { |h, k| h[k] = [] }
|
|
55
|
+
gather_modules
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def gather_modules
|
|
59
|
+
return if class_module_path.nil?
|
|
60
|
+
|
|
61
|
+
segments = class_module_path.split(Contrast::Utils::ObjectShare::DOUBLE_COLON)
|
|
62
|
+
@class_name = segments.last
|
|
63
|
+
current = nil
|
|
64
|
+
segments[0..-2].each do |chunk|
|
|
65
|
+
defined = current ? current.cs__const_defined?(chunk) : Module.cs__const_defined?(chunk)
|
|
66
|
+
next unless defined
|
|
67
|
+
|
|
68
|
+
current = current ? current.cs__const_get(chunk) : Module.cs__const_get(chunk)
|
|
69
|
+
if current.is_a?(Class)
|
|
70
|
+
name_space << [chunk, Class]
|
|
71
|
+
elsif current.is_a?(Module)
|
|
72
|
+
name_space << [chunk, Module]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def staged_changes?
|
|
78
|
+
public_singleton_methods.any? ||
|
|
79
|
+
public_instance_methods.any? ||
|
|
80
|
+
protected_instance_methods.any? ||
|
|
81
|
+
private_instance_methods.any?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def written_from_location? source_location
|
|
85
|
+
return false unless source_location
|
|
86
|
+
|
|
87
|
+
file = source_location[0]
|
|
88
|
+
location = source_location[1]
|
|
89
|
+
locs = locations[file]
|
|
90
|
+
return true if locs.include?(location)
|
|
91
|
+
|
|
92
|
+
locs << location
|
|
93
|
+
false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def commit_patches
|
|
97
|
+
return unless staged_changes?
|
|
98
|
+
|
|
99
|
+
content = build_content
|
|
100
|
+
valid = Ripper.sexp(content)
|
|
101
|
+
unbound_eval(class_name, content) if !!valid && !class_name.empty?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def source_code location, method_name
|
|
105
|
+
file_name = location[0]
|
|
106
|
+
line_number = location[1]
|
|
107
|
+
return unless file_name && line_number
|
|
108
|
+
|
|
109
|
+
unless files.key?(file_name)
|
|
110
|
+
return unless File.exist?(file_name)
|
|
111
|
+
|
|
112
|
+
files[file_name] = File.readlines(file_name)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
lines = files[file_name]
|
|
116
|
+
|
|
117
|
+
old_verbose = $VERBOSE
|
|
118
|
+
$VERBOSE = nil
|
|
119
|
+
code = ''
|
|
120
|
+
complete = false
|
|
121
|
+
# location#line_number is 1 based, arrays are 0 based
|
|
122
|
+
line_number -= 1
|
|
123
|
+
lines[line_number..-1].each do |line|
|
|
124
|
+
begin
|
|
125
|
+
code << line
|
|
126
|
+
RubyVM::InstructionSequence.compile(code) # this will raise SyntaxError for malformed code
|
|
127
|
+
# Assert that a line which ends with a , or \ is incomplete.
|
|
128
|
+
complete = code !~ /[,\\]\s*\z/
|
|
129
|
+
break if complete
|
|
130
|
+
rescue SyntaxError
|
|
131
|
+
code.gsub(/\#\{.*?\}/, 'temp')
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
$VERBOSE = old_verbose
|
|
135
|
+
raise SyntaxError, "Failure: method #{ method_name } in #{ file_name } at #{ line_number }" unless complete
|
|
136
|
+
|
|
137
|
+
code
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
def build_content
|
|
143
|
+
content = ''
|
|
144
|
+
name_space.each do |arr|
|
|
145
|
+
name = arr[0]
|
|
146
|
+
type = arr[1]
|
|
147
|
+
if type == Class
|
|
148
|
+
content << "class #{ name }\n"
|
|
149
|
+
elsif type == Module
|
|
150
|
+
content << "module #{ name }\n"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Set the name to be a class or module
|
|
155
|
+
content << if is_class
|
|
156
|
+
"class #{ class_name }\n"
|
|
157
|
+
else
|
|
158
|
+
"module #{ class_name }\n"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Recreate the updated class methods
|
|
162
|
+
if public_singleton_methods.any?
|
|
163
|
+
content << CLASS_SELF_LINE
|
|
164
|
+
content << public_singleton_methods.join(Contrast::Utils::ObjectShare::NEW_LINE)
|
|
165
|
+
content << Contrast::Utils::ObjectShare::NEW_LINE
|
|
166
|
+
content << END_NEW_LINE
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Recreate the updated instance methods
|
|
170
|
+
if public_instance_methods.any?
|
|
171
|
+
content << public_instance_methods.join(Contrast::Utils::ObjectShare::NEW_LINE)
|
|
172
|
+
content << Contrast::Utils::ObjectShare::NEW_LINE
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
if protected_instance_methods.any?
|
|
176
|
+
content << PROTECTED_WITH_NEW_LINE
|
|
177
|
+
content << protected_instance_methods.join(Contrast::Utils::ObjectShare::NEW_LINE)
|
|
178
|
+
content << Contrast::Utils::ObjectShare::NEW_LINE
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if private_instance_methods.any?
|
|
182
|
+
content << PRIVATE_WITH_NEW_LINE
|
|
183
|
+
content << private_instance_methods.join(Contrast::Utils::ObjectShare::NEW_LINE)
|
|
184
|
+
content << Contrast::Utils::ObjectShare::NEW_LINE
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
content << END_NEW_LINE
|
|
188
|
+
name_space.length.times do
|
|
189
|
+
content << END_NEW_LINE
|
|
190
|
+
end
|
|
191
|
+
content
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/agent/patching/policy/policy_node'
|
|
5
|
+
|
|
6
|
+
module Contrast
|
|
7
|
+
module Agent
|
|
8
|
+
module Deadzone
|
|
9
|
+
module Policy
|
|
10
|
+
# This class functions to translate our policy.json into an actionable
|
|
11
|
+
# Ruby object, allowing for dynamic patching over hardcoded patching,
|
|
12
|
+
# specifically for those methods in which other Contrast operations
|
|
13
|
+
# should not apply
|
|
14
|
+
class DeadzoneNode < Contrast::Agent::Patching::Policy::PolicyNode
|
|
15
|
+
def node_class
|
|
16
|
+
'Deadzone'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def feature
|
|
20
|
+
'Deadzone'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
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/agent/deadzone/policy/deadzone_node'
|
|
5
|
+
cs__scoped_require 'contrast/agent/patching/policy/policy'
|
|
6
|
+
|
|
7
|
+
module Contrast
|
|
8
|
+
module Agent
|
|
9
|
+
module Deadzone
|
|
10
|
+
module Policy
|
|
11
|
+
# This is just a holder for our policy. Takes the policy JSON and
|
|
12
|
+
# converts it into hashes that we can access nicely
|
|
13
|
+
class Policy < Contrast::Agent::Patching::Policy::Policy
|
|
14
|
+
def self.policy_folder
|
|
15
|
+
'deadzone'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
DEADZONES_KEY = 'deadzones'
|
|
19
|
+
attr_reader :deadzones
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@deadzones = []
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def node_type
|
|
27
|
+
Contrast::Agent::Deadzone::Policy::DeadzoneNode
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def from_hash_string string
|
|
31
|
+
policy_data = JSON.parse(string)
|
|
32
|
+
|
|
33
|
+
policy_data[DEADZONES_KEY].each do |deadzone_hash|
|
|
34
|
+
add_node(node_type.new(deadzone_hash))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def add_node node, _node_type = :deadzones
|
|
39
|
+
unless node
|
|
40
|
+
logger.error(nil, 'Node was nil when adding node to policy')
|
|
41
|
+
return
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
begin
|
|
45
|
+
node.validate
|
|
46
|
+
rescue ArgumentError => e
|
|
47
|
+
logger.error(e, e.message)
|
|
48
|
+
return
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@deadzones << node
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/components/interface'
|
|
5
|
+
|
|
6
|
+
module Contrast
|
|
7
|
+
module Agent
|
|
8
|
+
# A Reaction from TeamServer which indicates the Agent should be disabled,
|
|
9
|
+
# typically because some configuration setting did not satisfy requirements
|
|
10
|
+
# set by the Organization's Administrator
|
|
11
|
+
class DisableReaction
|
|
12
|
+
include Contrast::Components::Interface
|
|
13
|
+
access_component :logging, :agent
|
|
14
|
+
|
|
15
|
+
def self.run _reaction, level
|
|
16
|
+
logger.with_level(
|
|
17
|
+
nil,
|
|
18
|
+
'Contrast received instructions to disable itself - Disabling now',
|
|
19
|
+
level)
|
|
20
|
+
AGENT.disable!
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/components/interface'
|
|
5
|
+
|
|
6
|
+
module Contrast
|
|
7
|
+
module Agent
|
|
8
|
+
# Exclusions are ways for the User to tell the Agent to ignore sections of
|
|
9
|
+
# the Application. If a request or an event matches one of these, the
|
|
10
|
+
# functions of the Agent are suppressed for that request or event.
|
|
11
|
+
class ExclusionMatcher
|
|
12
|
+
include Contrast::Components::Interface
|
|
13
|
+
access_component :logging
|
|
14
|
+
|
|
15
|
+
def initialize excl
|
|
16
|
+
@exclusion = excl
|
|
17
|
+
@protect = @exclusion.protect
|
|
18
|
+
@assess = @exclusion.assess
|
|
19
|
+
|
|
20
|
+
handle_wildcard_input
|
|
21
|
+
handle_wildcard_url
|
|
22
|
+
handle_wildcard_code
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# According to the docs for exclusions, user input applies to all inputs if
|
|
26
|
+
# the name supplied is an '*' or '.*'. The name matcher does NOT support
|
|
27
|
+
# regexp beyond this.
|
|
28
|
+
# https://docs.contrastsecurity.com/admin-policymgmt.html#exclude
|
|
29
|
+
def handle_wildcard_input
|
|
30
|
+
return unless @exclusion.input_name
|
|
31
|
+
|
|
32
|
+
@wildcard_input = @exclusion.input_name == '.*' ||
|
|
33
|
+
@exclusion.input_name == Contrast::Utils::ObjectShare::ASTERISK
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# According to the docs for exclusions, urls apply to all urls if the url
|
|
37
|
+
# supplied is '/.*' or if the URL mode is all. Otherwise, the URL supplied is
|
|
38
|
+
# to be treated as a regular expression that must match the entire URL
|
|
39
|
+
# against which it is tested.
|
|
40
|
+
# https://docs.contrastsecurity.com/admin-policymgmt.html#exclude
|
|
41
|
+
def handle_wildcard_url
|
|
42
|
+
@wildcard_url = match_all?
|
|
43
|
+
return if @wildcard_url
|
|
44
|
+
return unless @exclusion.urls&.any?
|
|
45
|
+
|
|
46
|
+
@wildcard_url ||= @exclusion.urls.any? { |test| test == '/.*' }
|
|
47
|
+
return if @wildcard_url
|
|
48
|
+
|
|
49
|
+
@urls = []
|
|
50
|
+
@exclusion.urls.each do |url|
|
|
51
|
+
url_pattern = build_regexp(url, true, true)
|
|
52
|
+
@urls << url_pattern if url_pattern
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# According to the docs for exclusions, code applies to the entire stacktrace
|
|
57
|
+
# of the caller, and can act as a regexp. Per our user instructions in the
|
|
58
|
+
# Contrast UI, these comparisons must be done at the end of the input.
|
|
59
|
+
# https://docs.contrastsecurity.com/admin-policymgmt.html#exclude
|
|
60
|
+
def handle_wildcard_code
|
|
61
|
+
return unless @exclusion.blacklist&.any?
|
|
62
|
+
|
|
63
|
+
@wildcard_exclusions = []
|
|
64
|
+
@exclusion.blacklist.each do |code|
|
|
65
|
+
class_name, method_name = code.split(Contrast::Utils::ObjectShare::COLON)
|
|
66
|
+
class_pattern = build_regexp(class_name, false, true)
|
|
67
|
+
method_pattern = build_regexp(method_name)
|
|
68
|
+
next unless class_pattern && method_pattern
|
|
69
|
+
|
|
70
|
+
@wildcard_exclusions << [class_pattern, method_pattern]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def build_regexp pattern, start_anchor = false, end_anchor = false
|
|
75
|
+
pattern = Contrast::Utils::ObjectShare::CARROT + pattern if start_anchor
|
|
76
|
+
pattern += Contrast::Utils::ObjectShare::DOLLAR_SIGN if end_anchor
|
|
77
|
+
Regexp.compile(pattern)
|
|
78
|
+
rescue RegexpError => e
|
|
79
|
+
logger.error(e, "Unable to generate a pattern for #{ pattern }. It will not be used for exclusion matching.")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def protect?
|
|
83
|
+
@protect
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def assess?
|
|
87
|
+
@assess
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def url?
|
|
91
|
+
@exclusion.type == :URL
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def input?
|
|
95
|
+
@exclusion.type == :INPUT
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def code?
|
|
99
|
+
@exclusion.type == :CODE
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def name
|
|
103
|
+
@exclusion.name
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def match_all?
|
|
107
|
+
@exclusion.match_strategy == :ALL
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Determine if the given rule is excluded by this exclusion.
|
|
111
|
+
# In this case, the `protection_rules` being empty means apply to all rules,
|
|
112
|
+
# not no rules
|
|
113
|
+
#
|
|
114
|
+
# @param rule - the id of the rule which we're checking for exclusion
|
|
115
|
+
def protection_rule? rule
|
|
116
|
+
protect? &&
|
|
117
|
+
(@exclusion.protection_rules.empty? ||
|
|
118
|
+
@exclusion.protection_rules.include?(rule)
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Determine if the given rule is excluded by this exclusion.
|
|
123
|
+
# In this case, the `assessment_rules` being empty means apply to all rules,
|
|
124
|
+
# not no rules
|
|
125
|
+
#
|
|
126
|
+
# @param rule - the id of the rule which we're checking for exclusion
|
|
127
|
+
def assess_rule? rule
|
|
128
|
+
assess? &&
|
|
129
|
+
(@exclusion.assessment_rules.empty? ||
|
|
130
|
+
@exclusion.assessment_rules.include?(rule)
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def match_url? url
|
|
135
|
+
return false unless url?
|
|
136
|
+
return true if @wildcard_url
|
|
137
|
+
|
|
138
|
+
@urls.any? { |test| url.match?(test) }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def match_input? value, type
|
|
142
|
+
return false unless input?
|
|
143
|
+
|
|
144
|
+
exclusion_type = @exclusion.input_type
|
|
145
|
+
case type
|
|
146
|
+
when :PARAMETER_NAME, :PARAMETER_VALUE
|
|
147
|
+
return exclusion_type == :PARAMETER && value_match?(value)
|
|
148
|
+
when :COOKIE_NAME, :COOKIE_VALUE
|
|
149
|
+
return exclusion_type == :COOKIE && value_match?(value)
|
|
150
|
+
when :HEADER
|
|
151
|
+
return exclusion_type == :HEADER && value_match?(value, false)
|
|
152
|
+
when :BODY
|
|
153
|
+
return exclusion_type == :BODY
|
|
154
|
+
when :QUERYSTRING
|
|
155
|
+
return exclusion_type == :QUERYSTRING
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
false
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def value_match? value, case_sensitive = true
|
|
162
|
+
return true if @wildcard_input
|
|
163
|
+
|
|
164
|
+
if case_sensitive
|
|
165
|
+
value == @exclusion.input_name
|
|
166
|
+
else
|
|
167
|
+
@exclusion.input_name.casecmp(value).zero?
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def match_code? stack_trace
|
|
172
|
+
return false unless code?
|
|
173
|
+
return false if @wildcard_exclusions&.empty?
|
|
174
|
+
|
|
175
|
+
@wildcard_exclusions.each do |code|
|
|
176
|
+
class_name = code[0]
|
|
177
|
+
method_name = code[1]
|
|
178
|
+
stack_trace.each do |location|
|
|
179
|
+
next unless location.base_label.match?(method_name)
|
|
180
|
+
next unless location.path.match?(class_name)
|
|
181
|
+
|
|
182
|
+
return true
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
false
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|