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,98 @@
|
|
|
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 Utils
|
|
8
|
+
# This module keeps a background thread, initialized at startup, running. This thread is
|
|
9
|
+
# responsible for pulling a message off the queue, sending that message to SpeedRacer, and
|
|
10
|
+
# processing the response returned back from SpeedRacer. When we didn't know our config
|
|
11
|
+
# values, we may have queued assess messages to send later. This thread is also
|
|
12
|
+
# responsible for checking to see if we are now ready to send any of these assess messages
|
|
13
|
+
# to SpeedRacer.
|
|
14
|
+
module ServiceSenderUtil
|
|
15
|
+
include Contrast::Components::Interface
|
|
16
|
+
access_component :contrast_service, :logging, :analysis, :agent
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
attr_reader :assess_messages, :ready_messages_queue
|
|
20
|
+
|
|
21
|
+
def push_to_ready_queue msg
|
|
22
|
+
# Since a message may try to be pushed before sending_thread starts up, we need to initialize
|
|
23
|
+
# the queue on first message sent
|
|
24
|
+
@ready_messages_queue ||= Queue.new
|
|
25
|
+
ready_messages_queue.push msg
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def sending_thread
|
|
29
|
+
# in case we got here before a message attempted to be sent, let's make sure these are initialized
|
|
30
|
+
@ready_messages_queue ||= Queue.new
|
|
31
|
+
@assess_messages ||= []
|
|
32
|
+
|
|
33
|
+
@_sender_thread ||= Contrast::Agent::Thread.new do
|
|
34
|
+
loop do
|
|
35
|
+
check_assess_queue if assess_messages # don't bother checking if assess queue is already cleared
|
|
36
|
+
# if ready messages queue is empty, calling thread is suspended until a message is pushed onto queue
|
|
37
|
+
msg = ready_messages_queue.pop
|
|
38
|
+
begin
|
|
39
|
+
response = Contrast::Agent::FeatureState.instance.client.send_to_speedracer msg
|
|
40
|
+
Contrast::Utils::ServiceResponseUtil.process_response(response) if response
|
|
41
|
+
rescue StandardError => e
|
|
42
|
+
logger.error(e, 'Could not send message to service from service sender thread.')
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
logger.debug(nil, 'Started background sending thread.')
|
|
47
|
+
end
|
|
48
|
+
alias_method :start, :sending_thread
|
|
49
|
+
|
|
50
|
+
def stop
|
|
51
|
+
Thread.kill(@_sender_thread) if @_sender_thread&.alive?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add_to_assess_messages msg
|
|
55
|
+
# This list holds messages containing assess findings. We currently
|
|
56
|
+
# do not know if the agent is running in assess, so until we do then
|
|
57
|
+
# we must keep the messages stored here.
|
|
58
|
+
@assess_messages ||= []
|
|
59
|
+
assess_messages << msg
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def check_assess_queue
|
|
65
|
+
return unless AGENT.ready?
|
|
66
|
+
|
|
67
|
+
if ASSESS.enabled?
|
|
68
|
+
assess_messages.each do |msg|
|
|
69
|
+
update_queued_finding msg
|
|
70
|
+
ready_messages_queue.push msg # this message is ready to be sent to SR
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
@assess_messages = nil # clear out queue, we no longer need it
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# When we queued up findings, we didn't have access to a configuration
|
|
77
|
+
# object. As such, we have to make decisions now for those findings.
|
|
78
|
+
def update_queued_finding msg
|
|
79
|
+
# Findings only exist in activity messages
|
|
80
|
+
return unless msg.is_a?(Contrast::Api::Dtm::Activity)
|
|
81
|
+
|
|
82
|
+
# So set their tags
|
|
83
|
+
msg.finding_tags = Contrast::Utils::StringUtils.force_utf8(ASSESS.tags)
|
|
84
|
+
|
|
85
|
+
# and see if they're even enabled
|
|
86
|
+
check = msg.findings.dup
|
|
87
|
+
check.each do |finding|
|
|
88
|
+
msg.findings.delete(finding) if ASSESS.rule_disabled?(finding.rule_id)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
msg.findings.each do |finding|
|
|
92
|
+
finding.session_id = Contrast::Agent::FeatureState.instance.current_session_id
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
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 'singleton'
|
|
5
|
+
cs__scoped_require 'contrast/utils/object_share'
|
|
6
|
+
|
|
7
|
+
module Contrast
|
|
8
|
+
module Utils
|
|
9
|
+
# Utility methods for building and caching hashes from strings
|
|
10
|
+
class Sha256Builder
|
|
11
|
+
include Singleton
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@sha256_cache = {}
|
|
15
|
+
@gem_hash_cache = {}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Return a list of "source" files. Ignore metadata files as well as files
|
|
19
|
+
# in the spec, test or exe directories. Could potentially miss important
|
|
20
|
+
# files but good enough for the time being.
|
|
21
|
+
PATHS = '{lib,bin,ext}/**/*.{rb,c,h,c++,cpp,java,rs}'
|
|
22
|
+
def files path
|
|
23
|
+
if Dir.exist?(path)
|
|
24
|
+
Dir.glob(File.join(path, PATHS))
|
|
25
|
+
else
|
|
26
|
+
[]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Generate a SHA256 hash of the combined source code of this Gem
|
|
31
|
+
def sha256 path
|
|
32
|
+
return nil unless path
|
|
33
|
+
return nil unless File.exist?(path) && !File.directory?(path)
|
|
34
|
+
|
|
35
|
+
@sha256_cache[path] ||= Digest::SHA256.file(path).to_s
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def build_from_spec spec
|
|
39
|
+
name = spec.file_name.to_s
|
|
40
|
+
cached = @gem_hash_cache[name]
|
|
41
|
+
return cached if cached
|
|
42
|
+
|
|
43
|
+
gem_path = File.join(cache_dir(spec), name)
|
|
44
|
+
hash = sha256(gem_path)
|
|
45
|
+
|
|
46
|
+
@gem_hash_cache[name] = hash
|
|
47
|
+
hash
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def cache_dir spec
|
|
51
|
+
gems_dir = spec.gems_dir
|
|
52
|
+
parent_dir = File.dirname(gems_dir)
|
|
53
|
+
File.join(parent_dir, Contrast::Utils::ObjectShare::CACHE)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.files path
|
|
57
|
+
instance.files(path)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.sha256 path
|
|
61
|
+
instance.sha256(path)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.build_from_spec spec
|
|
65
|
+
instance.build_from_spec(spec)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Utils
|
|
6
|
+
# This module is to help perform sometimes necessary tasks specific to Sinatra
|
|
7
|
+
module SinatraHelper
|
|
8
|
+
SINATRA_VIEWS = [
|
|
9
|
+
['public/stylesheets', '*.scss', %w[SASS]],
|
|
10
|
+
['views', '*.html', %w[HTML5]],
|
|
11
|
+
['views', '*.html.erb', %w[HTML5 ERB]],
|
|
12
|
+
['views', '*.html.haml', %w[HTML5 HAML]],
|
|
13
|
+
['public', '*.html', %w[HTML5]]
|
|
14
|
+
].cs__freeze
|
|
15
|
+
|
|
16
|
+
def self.app_class
|
|
17
|
+
@_app_class ||= begin
|
|
18
|
+
return nil unless defined?(Sinatra) && defined?(Sinatra::Base)
|
|
19
|
+
|
|
20
|
+
sinatra_layers = ObjectSpace.each_object(Sinatra::Base).to_a
|
|
21
|
+
result_layer = sinatra_layers.find { |layer| layer.app.nil? }
|
|
22
|
+
result_layer
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.scannable_view_dirs
|
|
27
|
+
@_scannable_view_dirs ||= begin
|
|
28
|
+
views = SINATRA_VIEWS.dup
|
|
29
|
+
views << [view_directory, '*.erb', %w[HTML5 ERB]] if view_directory
|
|
30
|
+
views << [view_directory, '*.haml', %w[HTML5 HAML]] if view_directory
|
|
31
|
+
views << [public_directory, '*.html', %w[HTML5]] if public_directory
|
|
32
|
+
views
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.view_directory
|
|
37
|
+
@_view_directory ||= begin
|
|
38
|
+
app_class&.settings&.views
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.public_directory
|
|
43
|
+
@_public_directory ||= begin
|
|
44
|
+
app_class&.settings&.public_dir
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/utils/object_share'
|
|
5
|
+
cs__scoped_require 'contrast/api'
|
|
6
|
+
|
|
7
|
+
module Contrast
|
|
8
|
+
module Utils
|
|
9
|
+
# Utilities for converting ruby stack trace into DTMs
|
|
10
|
+
class StackTraceUtils
|
|
11
|
+
CONTRAST_MARKER = 'contrast/core_extensions'
|
|
12
|
+
MONKEYPATCH_MARKER = 'cs__'
|
|
13
|
+
|
|
14
|
+
# TODO: RUBY-532
|
|
15
|
+
CLASSNAME_CACHE = Contrast::Utils::Cache.new
|
|
16
|
+
|
|
17
|
+
# need lib here to separate from specs
|
|
18
|
+
AGENT_CLASS_MARKERS = %w[
|
|
19
|
+
/lib/contrast/
|
|
20
|
+
].cs__freeze
|
|
21
|
+
|
|
22
|
+
def self.custom_code_context?
|
|
23
|
+
stack = Kernel.caller(0, 15)
|
|
24
|
+
i = 0
|
|
25
|
+
while i < stack.length
|
|
26
|
+
stack_element = stack[i]
|
|
27
|
+
if stack_element.include?('contrast')
|
|
28
|
+
# Noop
|
|
29
|
+
elsif stack_element.include?('gems')
|
|
30
|
+
return false
|
|
31
|
+
else
|
|
32
|
+
return true
|
|
33
|
+
end
|
|
34
|
+
i += 1
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.build(
|
|
39
|
+
skip: 0,
|
|
40
|
+
depth: 10,
|
|
41
|
+
ignore: false,
|
|
42
|
+
ignore_strings: AGENT_CLASS_MARKERS,
|
|
43
|
+
class_lookup: false,
|
|
44
|
+
rasp_element: true)
|
|
45
|
+
|
|
46
|
+
stack = caller(skip.to_i, depth.to_i)
|
|
47
|
+
return [] unless stack
|
|
48
|
+
|
|
49
|
+
stack = reject_caller_entries(stack, ignore_strings) if ignore
|
|
50
|
+
stack.map! do |entry|
|
|
51
|
+
element = rasp_or_assess(rasp_element)
|
|
52
|
+
element = fill_element(element, entry, class_lookup)
|
|
53
|
+
element
|
|
54
|
+
end
|
|
55
|
+
stack.compact!
|
|
56
|
+
stack
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.reject_caller_entries stack, ignore_strings
|
|
60
|
+
return stack unless ignore_strings&.any?
|
|
61
|
+
|
|
62
|
+
stack.reject do |entry|
|
|
63
|
+
ignore_strings.any? { |marker| entry.include?(marker) } ||
|
|
64
|
+
entry.include?(MONKEYPATCH_MARKER)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.rasp_or_assess rasp_element
|
|
69
|
+
if rasp_element
|
|
70
|
+
Contrast::Api::Dtm::StackTraceElement.new
|
|
71
|
+
else
|
|
72
|
+
Contrast::Api::Dtm::TraceStack.new
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.to_dtm_stack stack_locations: nil, rasp_element: true
|
|
77
|
+
return [] unless stack_locations
|
|
78
|
+
|
|
79
|
+
stack_locations = reject_locations(stack_locations)
|
|
80
|
+
stack_locations.map! do |caller_location|
|
|
81
|
+
element = rasp_or_assess(rasp_element)
|
|
82
|
+
element = fill_loc_element(element, caller_location)
|
|
83
|
+
element
|
|
84
|
+
end
|
|
85
|
+
stack_locations.compact!
|
|
86
|
+
stack_locations
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.reject_locations stack_locations
|
|
90
|
+
stack_locations.reject do |entry|
|
|
91
|
+
class_path = entry.path
|
|
92
|
+
method = entry.label
|
|
93
|
+
AGENT_CLASS_MARKERS.any? { |marker| class_path.include?(marker) } ||
|
|
94
|
+
method.include?(MONKEYPATCH_MARKER)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# "/.rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/irb/workspace.rb:80:in `eval'"
|
|
99
|
+
def self.fill_element element, str, class_lookup
|
|
100
|
+
return element if str.nil? || str.strip.empty?
|
|
101
|
+
|
|
102
|
+
path, line, method = str.split(':')
|
|
103
|
+
element.line_number = line.to_i
|
|
104
|
+
file_name = filename_from_path(path)
|
|
105
|
+
element.file_name = Contrast::Utils::StringUtils.force_utf8(file_name)
|
|
106
|
+
declaring_class = best_classname(path, element.file_name) if class_lookup
|
|
107
|
+
element.declaring_class = Contrast::Utils::StringUtils.force_utf8(declaring_class)
|
|
108
|
+
method_name = find_method_name(method)
|
|
109
|
+
element.method_name = Contrast::Utils::StringUtils.force_utf8(method_name)
|
|
110
|
+
element
|
|
111
|
+
rescue StandardError
|
|
112
|
+
# NOOP
|
|
113
|
+
nil
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def self.best_classname path, file
|
|
117
|
+
name = first_class(path)
|
|
118
|
+
name || look_like_classname(file)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# "/.rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/irb/workspace.rb:80:in `eval'"
|
|
122
|
+
def self.fill_loc_element element, caller_location
|
|
123
|
+
return element unless caller_location
|
|
124
|
+
|
|
125
|
+
lineno = caller_location.lineno
|
|
126
|
+
element.line_number = lineno.to_i
|
|
127
|
+
path = caller_location.path
|
|
128
|
+
path = Contrast::Utils::StringUtils.force_utf8(path)
|
|
129
|
+
file_name = filename_from_path(path)
|
|
130
|
+
element.file_name = Contrast::Utils::StringUtils.force_utf8(file_name)
|
|
131
|
+
element.declaring_class = path
|
|
132
|
+
label = caller_location.label
|
|
133
|
+
element.method_name = Contrast::Utils::StringUtils.force_utf8(label)
|
|
134
|
+
element
|
|
135
|
+
rescue StandardError
|
|
136
|
+
# NOOP
|
|
137
|
+
nil
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.filename_from_path path
|
|
141
|
+
file_idx = path.rindex(Contrast::Utils::ObjectShare::SLASH)
|
|
142
|
+
if file_idx
|
|
143
|
+
txt_idx = file_idx + 1
|
|
144
|
+
path[txt_idx, path.length - txt_idx]
|
|
145
|
+
else
|
|
146
|
+
path
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Bit of a HACK: Given a path to a file, assume that the first line in the
|
|
151
|
+
# form `class Name` is the class that was loaded. True most of the time.
|
|
152
|
+
#
|
|
153
|
+
# Using regexp here is expensive b/c it creates a ton of new Strings. We're
|
|
154
|
+
# trying to avoid that, so our guess is a little more clumsy, but should
|
|
155
|
+
# still work.
|
|
156
|
+
#
|
|
157
|
+
# Note: Might need to tune end marker to include /n
|
|
158
|
+
# based on: /\s*class\s+([_[:alpha:]][_[:alnum:]]*)/m
|
|
159
|
+
CLASS_MARKER = ' class '
|
|
160
|
+
CLASS_END_MARKER = Contrast::Utils::ObjectShare::NEW_LINE
|
|
161
|
+
def self.first_class path
|
|
162
|
+
return nil if path.nil? || path.empty?
|
|
163
|
+
|
|
164
|
+
name = CLASSNAME_CACHE[path]
|
|
165
|
+
return name if name
|
|
166
|
+
|
|
167
|
+
text = File.read(path)
|
|
168
|
+
name = parse_string(text, CLASS_MARKER, CLASS_END_MARKER)
|
|
169
|
+
CLASSNAME_CACHE[path] = name if name
|
|
170
|
+
name
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
RB_MARKER = '.rb'
|
|
174
|
+
# Convert a file to look like a classname
|
|
175
|
+
# If the file ends w/ '.rb', trim that off
|
|
176
|
+
# If the file doesn't start with a capital letter,
|
|
177
|
+
# capitalize it
|
|
178
|
+
def self.look_like_classname file
|
|
179
|
+
file = file.to_s
|
|
180
|
+
file[0].capitalize + (file.end_with?(RB_MARKER) ? file.slice(1..-4) : file.slice(1..-1))
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Using regexp here is expensive b/c it creates a ton of new Strings. We're
|
|
184
|
+
# trying to avoid that, so our guess is a little more clumsy, but should
|
|
185
|
+
# still work.
|
|
186
|
+
#
|
|
187
|
+
# Note: Might need to tune end marker to include /n
|
|
188
|
+
# based on: /[`]([^']*)[']/
|
|
189
|
+
METHOD_MARKER = Contrast::Utils::ObjectShare::TICK
|
|
190
|
+
METHOD_END_MARKER = Contrast::Utils::ObjectShare::COMMA
|
|
191
|
+
def self.find_method_name method
|
|
192
|
+
parse_string(method, METHOD_MARKER, METHOD_END_MARKER)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def self.parse_string string, start_marker, end_marker
|
|
196
|
+
return nil unless string
|
|
197
|
+
|
|
198
|
+
start_idx = string.index(start_marker)
|
|
199
|
+
return nil unless start_idx
|
|
200
|
+
|
|
201
|
+
start_idx += start_marker.length # account for marker length
|
|
202
|
+
end_idx = string.index(end_marker, start_idx)
|
|
203
|
+
end_idx ||= string.length
|
|
204
|
+
len = end_idx - start_idx
|
|
205
|
+
string[start_idx, len]
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Utils
|
|
6
|
+
# Utilities for encoding and normalizing strings
|
|
7
|
+
class StringUtils
|
|
8
|
+
UTF8 = 'utf-8'
|
|
9
|
+
HTTP_PREFIX = 'HTTP-'
|
|
10
|
+
|
|
11
|
+
# Convenience method. We assume that we're working on Strings or tags
|
|
12
|
+
# String representations of things. To that end, we'll to_s anything
|
|
13
|
+
# that comes in before returning its length.
|
|
14
|
+
#
|
|
15
|
+
# But don't worry though, String.to_s just returns self. teehee
|
|
16
|
+
def self.ret_length string
|
|
17
|
+
string.nil? ? 0 : string.to_s.length
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Protobuf has a very strict typing. Nil is not a String and will throw
|
|
21
|
+
# an exception if you try to set it. Use this to be safe.
|
|
22
|
+
# Uses the object share to avoid creating several new strings per request
|
|
23
|
+
def self.protobuf_safe_string string
|
|
24
|
+
string.nil? ? Contrast::Utils::ObjectShare::EMPTY_STRING : string.to_s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Truncate a string to 255 characters max length
|
|
28
|
+
def self.truncate str, default = Contrast::Utils::ObjectShare::EMPTY_STRING
|
|
29
|
+
return default if str.nil?
|
|
30
|
+
|
|
31
|
+
str.to_s[0..255]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.force_utf8 str, logger = nil
|
|
35
|
+
return Contrast::Utils::ObjectShare::EMPTY_STRING unless str
|
|
36
|
+
|
|
37
|
+
str = str.to_s
|
|
38
|
+
if str.encoding == Encoding::UTF_8
|
|
39
|
+
str = str.encode(UTF8, invalid: :replace, undef: :replace) unless str.valid_encoding?
|
|
40
|
+
else
|
|
41
|
+
str = str.encode(UTF8, str.encoding, invalid: :replace, undef: :replace)
|
|
42
|
+
end
|
|
43
|
+
str.to_s
|
|
44
|
+
rescue StandardError => e
|
|
45
|
+
# We were unable to switch the String to a UTF-8 format.
|
|
46
|
+
# Return non-nil so as not to throw an exception later when trying
|
|
47
|
+
# to do regexp or other compares on the String
|
|
48
|
+
logger&.debug "Unable to change '#{ str }' to valid UTF-8: #{ e.message }"
|
|
49
|
+
|
|
50
|
+
Contrast::Utils::ObjectShare::EMPTY_STRING
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Given a string return a normalized version of that string.
|
|
54
|
+
# Keys are memoized so that the normalization process doesn't need
|
|
55
|
+
# to happen every time.
|
|
56
|
+
def self.normalized_key str
|
|
57
|
+
return nil unless str
|
|
58
|
+
|
|
59
|
+
str = str.to_s
|
|
60
|
+
@_normalized_keys ||= {}
|
|
61
|
+
if @_normalized_keys.key?(str)
|
|
62
|
+
@_normalized_keys[str]
|
|
63
|
+
else
|
|
64
|
+
up = str.upcase.strip
|
|
65
|
+
up = up.gsub(/[_-]/, '-')
|
|
66
|
+
up = up[5..-1] if up.start_with?(HTTP_PREFIX)
|
|
67
|
+
@_normalized_keys[str] = up
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|