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,82 @@
|
|
|
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/module'
|
|
6
|
+
cs__scoped_require 'contrast/utils/object_share'
|
|
7
|
+
|
|
8
|
+
module Contrast
|
|
9
|
+
module Agent
|
|
10
|
+
module Assess
|
|
11
|
+
# This is used to revert, or undo, the patches that we've placed into
|
|
12
|
+
# modules. This is necessary for those cases where the original method
|
|
13
|
+
# was supposed to be removed, but wasn't b/c we had renamed it -- looking
|
|
14
|
+
# at you, FactoryBot
|
|
15
|
+
class ClassReverter
|
|
16
|
+
include Contrast::Components::Interface
|
|
17
|
+
access_component :logging, :scope
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def unpatch!
|
|
21
|
+
Contrast::Agent::FeatureState.instance.uninstrument_namespaces.
|
|
22
|
+
each { |mod_sym| revert_module mod_sym }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def revert_module mod
|
|
28
|
+
with_contrast_scope do
|
|
29
|
+
revert_child_modules(mod, [])
|
|
30
|
+
end
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
logger.error(e, "Unable to remove patches from the module #{ mod }")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def revert_child_modules mod, reverted_modules, parent_mod = nil
|
|
36
|
+
return if parent_mod == mod
|
|
37
|
+
return if reverted_modules.include?(mod)
|
|
38
|
+
|
|
39
|
+
reverted_modules << mod
|
|
40
|
+
|
|
41
|
+
immediate_constants = mod.cs__constants(false).collect! { |k| mod.cs__const_get(k) }
|
|
42
|
+
immediate_constants.select! { |k| k.is_a?(Module) }
|
|
43
|
+
immediate_constants.flatten!
|
|
44
|
+
if immediate_constants.any?
|
|
45
|
+
immediate_constants.each do |const|
|
|
46
|
+
revert_aliases(const)
|
|
47
|
+
revert_child_modules(const, reverted_modules, mod)
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
revert_aliases(mod)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# in order to fully uninstrument classes we must use true when getting the singleton/instance methods
|
|
55
|
+
# that way if a class makes use of instance_eval for instance(defined on Kernel) we are able to revert this
|
|
56
|
+
# specific instance of that method to use the default behavior while leaving the remainder of
|
|
57
|
+
# objects using the patched behavior
|
|
58
|
+
def revert_aliases clazz
|
|
59
|
+
marker = Contrast::Utils::ObjectShare::CONTRAST_PATCHED_METHOD_START
|
|
60
|
+
instance_methods = (clazz.instance_methods(true) + clazz.private_instance_methods(true)).select { |method| method.to_s.start_with?(marker) }
|
|
61
|
+
singleton_methods = clazz.cs__singleton_class.instance_methods(true).select { |method| method.to_s.start_with?(marker) }
|
|
62
|
+
instance_methods.each { |i_method| revert_alias(clazz, i_method, instance_methods) }
|
|
63
|
+
singleton_methods.each { |s_method| revert_alias(clazz.cs__singleton_class, s_method, singleton_methods) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def revert_alias clazz, current_method_name, methods
|
|
67
|
+
original_method_name = clazz.instance_method(current_method_name).original_name
|
|
68
|
+
|
|
69
|
+
is_private = clazz.private_method_defined?(original_method_name)
|
|
70
|
+
|
|
71
|
+
# revert aliasing only for those methods currently defined on the original
|
|
72
|
+
if is_private || clazz.method_defined?(original_method_name)
|
|
73
|
+
clazz.send(:alias_method, original_method_name, current_method_name)
|
|
74
|
+
clazz.send(:private, original_method_name) if is_private
|
|
75
|
+
end
|
|
76
|
+
clazz.send(:undef_method, current_method_name) if methods.include?(current_method_name)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,398 @@
|
|
|
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/prevent_serialization'
|
|
5
|
+
|
|
6
|
+
module Contrast
|
|
7
|
+
module Agent
|
|
8
|
+
module Assess
|
|
9
|
+
# This class holds the data about an event in the application
|
|
10
|
+
# We'll use it to build an event that TeamServer can consume if
|
|
11
|
+
# the object to which this event belongs ends in a trigger.
|
|
12
|
+
class ContrastEvent
|
|
13
|
+
include Contrast::Utils::PreventSerialization
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
def safe_args_representation args
|
|
17
|
+
return nil unless args
|
|
18
|
+
return Contrast::Utils::ObjectShare::EMPTY_ARRAY if args.empty?
|
|
19
|
+
|
|
20
|
+
rep = []
|
|
21
|
+
args.each do |arg|
|
|
22
|
+
# We have to handle named args
|
|
23
|
+
rep << if arg.is_a?(Hash)
|
|
24
|
+
safe_arg_hash_representation(arg)
|
|
25
|
+
else
|
|
26
|
+
arg.cs__inspect
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
rep
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def safe_arg_hash_representation hash
|
|
33
|
+
# since this is the named hash for arguments, only the value is
|
|
34
|
+
# suspect here
|
|
35
|
+
hash.transform_values(&:cs__inspect)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# if given an object that can be duped, duplicate it. otherwise just
|
|
39
|
+
# return the original object. swallow all exceptions from
|
|
40
|
+
# non-duplicable things.
|
|
41
|
+
#
|
|
42
|
+
# we can't just check respond_to? though b/c dup exists on the
|
|
43
|
+
# base Object class
|
|
44
|
+
def safe_dup original
|
|
45
|
+
return nil unless original
|
|
46
|
+
|
|
47
|
+
begin
|
|
48
|
+
original.dup
|
|
49
|
+
rescue StandardError
|
|
50
|
+
original
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
attr_accessor :source_name
|
|
56
|
+
attr_reader :event_id, :source_type, :parent_ids
|
|
57
|
+
|
|
58
|
+
# We need this to track the parent id's of events to build up a flow
|
|
59
|
+
# chart of the finding
|
|
60
|
+
@atomic_id = 0
|
|
61
|
+
@atomic_mutex = Mutex.new
|
|
62
|
+
def self.next_atomic_id
|
|
63
|
+
@atomic_mutex.synchronize do
|
|
64
|
+
begin
|
|
65
|
+
@atomic_id += 1
|
|
66
|
+
# Rollover things
|
|
67
|
+
rescue StandardError
|
|
68
|
+
@atomic_id = 1
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def initialize policy_node, tagged, object, ret, args, invoked = 0, source_type = nil, source_name = nil
|
|
74
|
+
@caller = caller_locations(get_call_start(policy_node, invoked), 10)
|
|
75
|
+
@policy_node = policy_node
|
|
76
|
+
@time = Contrast::Utils::Timer.now_ms
|
|
77
|
+
@thread = Thread.current.object_id
|
|
78
|
+
@source_type = source_type
|
|
79
|
+
@source_name = source_name
|
|
80
|
+
|
|
81
|
+
# These methods rely on the above being set. Don't move them!
|
|
82
|
+
@event_id = Contrast::Agent::Assess::ContrastEvent.next_atomic_id
|
|
83
|
+
@parent_ids = find_parent_ids(policy_node, object, ret, args)
|
|
84
|
+
snapshot(tagged, object, ret, args)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Parent IDs are the event ids of all the sources of this event which
|
|
88
|
+
# were tracked prior to this event occurring
|
|
89
|
+
def find_parent_ids policy_node, object, ret, args
|
|
90
|
+
return if policy_node.is_a?(Contrast::Agent::Assess::Policy::SourceNode)
|
|
91
|
+
|
|
92
|
+
mapped = policy_node.sources.map do |source|
|
|
93
|
+
value_of_source(source, object, ret, args)
|
|
94
|
+
end
|
|
95
|
+
selected = mapped.select do |source|
|
|
96
|
+
source &&
|
|
97
|
+
Contrast::Utils::DuckUtils.quacks_to?(source, :cs__properties) &&
|
|
98
|
+
source.cs__properties.events &&
|
|
99
|
+
source.cs__properties.events.last
|
|
100
|
+
end
|
|
101
|
+
selected.map do |source|
|
|
102
|
+
source.cs__properties.events.last.event_id
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def snapshot tagged, object, ret, args
|
|
107
|
+
target = @policy_node.target
|
|
108
|
+
case target
|
|
109
|
+
# If the target is nil, this rule was violated simply by a method
|
|
110
|
+
# being called. We'll save all the information, but nothing will be
|
|
111
|
+
# marked up, as nothing need be tracked
|
|
112
|
+
when nil
|
|
113
|
+
@object = object.cs__inspect
|
|
114
|
+
@args = cs__class.safe_args_representation(args)
|
|
115
|
+
@ret = ret.cs__inspect
|
|
116
|
+
# If the target is O, then we dup the O and safely represent the rest
|
|
117
|
+
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
|
118
|
+
@object = cs__class.safe_dup(tagged)
|
|
119
|
+
@args = cs__class.safe_args_representation(args)
|
|
120
|
+
@ret = ret.cs__inspect
|
|
121
|
+
# If the target is R, then we dup the R and safely represent the rest
|
|
122
|
+
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
123
|
+
@object = object.cs__inspect
|
|
124
|
+
@args = cs__class.safe_args_representation(args)
|
|
125
|
+
@ret = cs__class.safe_dup(tagged)
|
|
126
|
+
# If the target is P*, then we need to dup things a differently. We
|
|
127
|
+
# need to find the true target inside so that we can mark it up
|
|
128
|
+
# later, but the other args should be represented as their safe form.
|
|
129
|
+
else
|
|
130
|
+
@object = object.cs__inspect
|
|
131
|
+
@args = cs__class.safe_args_representation(args)
|
|
132
|
+
@ret = ret.cs__inspect
|
|
133
|
+
save_target_arg(target, tagged)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# I know we're creating an extra string here since we replace the safe
|
|
138
|
+
# one w/ a dup, but good enough for now. Trying not to make this too
|
|
139
|
+
# complicated. - HM 8/8/19
|
|
140
|
+
def save_target_arg target, tagged
|
|
141
|
+
if target.is_a?(Integer)
|
|
142
|
+
@args[target] = cs__class.safe_dup(tagged)
|
|
143
|
+
return
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
@args.each_with_index do |search, index|
|
|
147
|
+
next unless search.is_a?(Hash)
|
|
148
|
+
next unless search[target]
|
|
149
|
+
|
|
150
|
+
search[target] = cs__class.safe_dup(tagged)
|
|
151
|
+
@highlight = index
|
|
152
|
+
break
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def value_of_source source, object, ret, args
|
|
157
|
+
case source
|
|
158
|
+
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
|
159
|
+
object
|
|
160
|
+
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
161
|
+
ret
|
|
162
|
+
else
|
|
163
|
+
if source.is_a?(Integer)
|
|
164
|
+
args[source]
|
|
165
|
+
else
|
|
166
|
+
args.each do |search|
|
|
167
|
+
next unless search.is_a?(Hash)
|
|
168
|
+
|
|
169
|
+
s = search[source]
|
|
170
|
+
return s if s
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# each policy_node has a certain number of levels down it calls
|
|
177
|
+
# before getting here. since we know them, we can skip
|
|
178
|
+
# right to the part of the stack we care about.
|
|
179
|
+
#
|
|
180
|
+
# Note: if our callstack changes, this number has to change
|
|
181
|
+
def get_call_start policy_node, invoked
|
|
182
|
+
# TODO: RUBY-440 audit these numbers to get stacktraces to render
|
|
183
|
+
# properly
|
|
184
|
+
base = case policy_node
|
|
185
|
+
when Contrast::Agent::Assess::Policy::SourceNode
|
|
186
|
+
6
|
|
187
|
+
when Contrast::Agent::Assess::Policy::PropagationNode
|
|
188
|
+
7
|
|
189
|
+
when Contrast::Agent::Assess::Policy::TriggerNode
|
|
190
|
+
7
|
|
191
|
+
else
|
|
192
|
+
2
|
|
193
|
+
end
|
|
194
|
+
base + invoked
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Convert this event into a DTM that TeamServer can consume
|
|
198
|
+
def to_dtm_event
|
|
199
|
+
event = Contrast::Api::Dtm::TraceEvent.new
|
|
200
|
+
|
|
201
|
+
# Figure out what the target of this event was. It's a little
|
|
202
|
+
# annoying for us since P can be named (thanks, Ruby) where
|
|
203
|
+
# as for everyone else it is idx based.
|
|
204
|
+
taint_target = determine_taint_target(event)
|
|
205
|
+
|
|
206
|
+
event.type = @policy_node.node_type
|
|
207
|
+
event.action = @policy_node.build_action
|
|
208
|
+
event.timestamp_ms = @time.to_i
|
|
209
|
+
event.thread = Contrast::Utils::StringUtils.force_utf8(@thread)
|
|
210
|
+
truncate_obj = Contrast::Utils::ObjectShare::OBJECT_KEY != taint_target
|
|
211
|
+
event.object = build_event_object(@object, truncate_obj)
|
|
212
|
+
truncate_ret = Contrast::Utils::ObjectShare::RETURN_KEY != taint_target
|
|
213
|
+
event.ret = build_event_object(@ret, truncate_ret)
|
|
214
|
+
built_args = build_event_args(taint_target)
|
|
215
|
+
built_args.each do |arg|
|
|
216
|
+
event.args << arg
|
|
217
|
+
end
|
|
218
|
+
taint_ranges = find_taint_ranges(@object, @args, @ret, taint_target)
|
|
219
|
+
taint_ranges.each do |range|
|
|
220
|
+
event.taint_ranges << range
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# We delayed doing this as long as possible b/c it's expensive
|
|
224
|
+
stack = Contrast::Utils::StackTraceUtils.to_dtm_stack(
|
|
225
|
+
stack_locations: @caller,
|
|
226
|
+
rasp_element: false)
|
|
227
|
+
stack.each do |frame|
|
|
228
|
+
event.stack << frame
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
event.field_name = Contrast::Utils::StringUtils.force_utf8(source_name)
|
|
232
|
+
|
|
233
|
+
event_source_dtm = build_event_source_dtm
|
|
234
|
+
event.event_sources << event_source_dtm if event_source_dtm
|
|
235
|
+
|
|
236
|
+
event.object_id = event_id.to_i
|
|
237
|
+
@parent_ids&.each do |id|
|
|
238
|
+
parent = Contrast::Api::Dtm::ParentObjectId.new
|
|
239
|
+
parent.id = id.to_i
|
|
240
|
+
event.parent_object_ids << parent
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# not to be confused w/ the partial signature
|
|
244
|
+
build_complete_signature(event)
|
|
245
|
+
|
|
246
|
+
event
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def forced_source_type
|
|
250
|
+
@_forced_source_type ||= Contrast::Utils::StringUtils.force_utf8(source_type)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def forced_source_name
|
|
254
|
+
@_forced_source_name ||= Contrast::Utils::StringUtils.force_utf8(source_name)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Probably only for source events, but we'll go
|
|
258
|
+
# with source_type instead. java & .net support source_type
|
|
259
|
+
# in propagation events, so we'll future proof this
|
|
260
|
+
def build_event_source_dtm
|
|
261
|
+
# You can have a source w/o a name, but not w/o a type
|
|
262
|
+
return unless source_type
|
|
263
|
+
|
|
264
|
+
dtm = Contrast::Api::Dtm::TraceEventSource.new
|
|
265
|
+
dtm.type = forced_source_type
|
|
266
|
+
dtm.name = forced_source_name
|
|
267
|
+
dtm
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# We're not going to build the signature string here, b/c we have all
|
|
271
|
+
# the composite pieces of it. Instead, we're going to let TeamServer
|
|
272
|
+
# render this for us.
|
|
273
|
+
def build_complete_signature event
|
|
274
|
+
signature = Contrast::Api::Dtm::TraceEventSignature.new
|
|
275
|
+
event.signature = signature
|
|
276
|
+
return_type = @ret ? @ret.cs__class.name : Contrast::Utils::ObjectShare::NIL_STRING
|
|
277
|
+
signature.return_type = Contrast::Utils::StringUtils.force_utf8(return_type)
|
|
278
|
+
signature.class_name = Contrast::Utils::StringUtils.force_utf8(@policy_node.class_name)
|
|
279
|
+
signature.method_name = Contrast::Utils::StringUtils.force_utf8(@policy_node.method_name)
|
|
280
|
+
if @args
|
|
281
|
+
@args&.each do |arg|
|
|
282
|
+
arg_type = arg ? arg.cs__class.name : Contrast::Utils::ObjectShare::NIL_STRING
|
|
283
|
+
signature.arg_types << Contrast::Utils::StringUtils.force_utf8(arg_type)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
signature.constructor = @policy_node.method_name == :new
|
|
287
|
+
# if there's a ret, then this method isn't nil. not 100% full proof since you can
|
|
288
|
+
# return nil, but this is the best we've got currently.
|
|
289
|
+
signature.void_method = @ret.nil?
|
|
290
|
+
# 8 is STATIC in Java... we have to placate them for now
|
|
291
|
+
# it has been requested that flags be removed since it isn't used
|
|
292
|
+
signature.flags = 8 unless @policy_node.instance_method?
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Wrapper around build_event_object for the args array. Handles
|
|
296
|
+
# tainting the correct argument.
|
|
297
|
+
def build_event_args taint_target
|
|
298
|
+
event_args = []
|
|
299
|
+
@args.each_index do |idx|
|
|
300
|
+
truncate_arg = taint_target != idx
|
|
301
|
+
event_arg = build_event_object(@args[idx], truncate_arg)
|
|
302
|
+
event_args << event_arg
|
|
303
|
+
end
|
|
304
|
+
event_args
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Build the event object. We were originally going to include taint on
|
|
308
|
+
# each one, but TS doesn't accept / use that, so it is a waste of time.
|
|
309
|
+
#
|
|
310
|
+
# We'll truncate any object that isn't important to the taint ranges of
|
|
311
|
+
# this event, so that we don't murder TeamServer by, for instance,
|
|
312
|
+
# hypothetically sending the entire rendered HTML page >_> <_< >_>
|
|
313
|
+
ELLIPSIS = '...'
|
|
314
|
+
UNTRUNCATED_PORTION_LENGTH = 25
|
|
315
|
+
TRUNCATION_LENGTH = (UNTRUNCATED_PORTION_LENGTH * 2) + 3 # ELLIPSIS length
|
|
316
|
+
def build_event_object object, truncate
|
|
317
|
+
event_object = Contrast::Api::Dtm::TraceEventObject.new
|
|
318
|
+
obj_string = Contrast::Utils::StringUtils.force_utf8(object)
|
|
319
|
+
if truncate && Contrast::Utils::StringUtils.ret_length(obj_string) > TRUNCATION_LENGTH
|
|
320
|
+
tmp = []
|
|
321
|
+
tmp << obj_string[0, UNTRUNCATED_PORTION_LENGTH]
|
|
322
|
+
tmp << ELLIPSIS
|
|
323
|
+
tmp << obj_string[
|
|
324
|
+
obj_string.length - UNTRUNCATED_PORTION_LENGTH,
|
|
325
|
+
UNTRUNCATED_PORTION_LENGTH]
|
|
326
|
+
obj_string = tmp.join
|
|
327
|
+
end
|
|
328
|
+
event_object.value = Base64.encode64(obj_string)
|
|
329
|
+
event_object.tracked = Contrast::Utils::Assess::TrackingUtil.tracked?(object)
|
|
330
|
+
event_object
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# We have to do a little work to figure out what our TS appropriate
|
|
334
|
+
# target is. To break this down, the logic is as follows:
|
|
335
|
+
# 1) If my policy_node has a target, work on targets. Else, work on sources.
|
|
336
|
+
# Per TS law, each policy_node must have at least a source or a target.
|
|
337
|
+
# The only type of policy_node w/o targets is a Trigger, but that may
|
|
338
|
+
# change.
|
|
339
|
+
# 2) If I have a highlight, it means that I have a P target that is
|
|
340
|
+
# not in integer form (it was a named / keyword type for which I had
|
|
341
|
+
# to find the index). I need to address this so that TS can process
|
|
342
|
+
# it.
|
|
343
|
+
# 3) I'll set the event's source and target to TS values.
|
|
344
|
+
# 4) Return the highlight or the first source/target as the taint
|
|
345
|
+
# target.
|
|
346
|
+
def determine_taint_target event
|
|
347
|
+
if @policy_node&.targets&.any?
|
|
348
|
+
event.source = @policy_node.source_string if @policy_node.source_string
|
|
349
|
+
event.target = if @highlight
|
|
350
|
+
"P#{ @highlight }"
|
|
351
|
+
else
|
|
352
|
+
@policy_node.target_string
|
|
353
|
+
end
|
|
354
|
+
@highlight || @policy_node.targets[0]
|
|
355
|
+
elsif @policy_node&.sources&.any?
|
|
356
|
+
event.source = if @highlight
|
|
357
|
+
"P#{ @highlight }"
|
|
358
|
+
else
|
|
359
|
+
@policy_node.source_string
|
|
360
|
+
end
|
|
361
|
+
event.target = @policy_node.target_string if @policy_node.target_string
|
|
362
|
+
@highlight || @policy_node.sources[0]
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# TeamServer only supports one object's taint ranges at a time.
|
|
367
|
+
# We'll find the taint ranges for the target and return those
|
|
368
|
+
def find_taint_ranges object, args, ret, taint_target
|
|
369
|
+
# If there's no taint_target, this isn't a dataflow trace, but a
|
|
370
|
+
# trigger one
|
|
371
|
+
return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless taint_target
|
|
372
|
+
|
|
373
|
+
properties = case taint_target
|
|
374
|
+
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
|
375
|
+
object.cs__properties
|
|
376
|
+
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
377
|
+
ret.cs__properties
|
|
378
|
+
else
|
|
379
|
+
target = args[taint_target]
|
|
380
|
+
if target.is_a?(Hash)
|
|
381
|
+
if @policy_node&.targets&.any?
|
|
382
|
+
target[@policy_node.targets[0]].cs__properties
|
|
383
|
+
else
|
|
384
|
+
target[@policy_node.sources[0]].cs__properties
|
|
385
|
+
end
|
|
386
|
+
else
|
|
387
|
+
target.cs__properties
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless properties.tracked?
|
|
392
|
+
|
|
393
|
+
properties.tags_to_dtm
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
end
|