diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9bf80c..fd660e1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,106 +2,10 @@ ## DEVELOPMENT VERSION -### Features +### New Artifacts Properties -- New '--enable-modifiers' command line option. Enabling this option will case UAC to run artifacts that change the current system state ([#272](https://github.com/tclahr/uac/issues/272)). -- UAC now completely skips an artifact file (YAML) that has no artifacts to be collected for the target operating system. You can use '--artifacts list [OPERATING_SYSTEM]' to display artifacts for a specific operating system only. -- New output file formats: - - none: Collected data will not be archived or compressed. Instead, it will be copied directly to an output directory ([#188](https://github.com/tclahr/uac/issues/188)). - - zip: Collected data will be archived and compressed into a zip file. Additionally, you can create a password-protected zip file using the '--output-password' option ([#149](https://github.com/tclahr/uac/issues/149)). -- You can now set a custom output file name using the '-o/--output-base-name' command line option. Variables are available to format the filename ([#179](https://github.com/tclahr/uac/issues/179)). -- Now you have the option to supply a file path to a custom profile located outside the profiles directory. -- Now you have the option to supply a file path to a custom artifact located outside the artifacts directory ([#154](https://github.com/tclahr/uac/issues/154)). -- Now you can have the option to supply a file path to a custom config file located outside the config directory using the '-c/--config' command line option. -- New remote transfer options for Amazon, Google and IBM cloud storage locations. -- UAC will now use 'wget' to transfer files to remote cloud storage locations when 'curl' is not available. -- You can now increase the verbosity level using the '-v/--verbose' command line option. Enabling a higher verbosity level will result in the display of all executed commands. -- UAC will now use the built-in function 'astrings' to extract strings from binary files when 'strings' is not available on the system. -- The message 'The strings command requires the command line developer tools.' will no longer appear on macOS systems without developer tools installed ([#171](https://github.com/tclahr/uac/issues/171)). -- Error messages generated by executed commands (stderr) are now recorded in the uac.log file ([#150](https://github.com/tclahr/uac/issues/150)). -- New '-H/--hash-collected' command line option. Enabling this option will cause UAC to hash all collected files and save the results in a hash file. To accomplish this, all collected data must first be copied to the destination directory. Therefore, ensure you have twice the free space available on the system: once for the collected data and once for the output file. Additionally, note that this process will increase the running time ([#189](https://github.com/tclahr/uac/issues/189)). -- You can now validate profiles using the '--validate-profile' command line option. +- Added the new 'redirect_stderr_to_stdout' property, an optional feature available exclusively for the command collector. When set to true, this property redirects all error messages (stderr) to standard output (stdout), ensuring they are written to the output file. -### Artifacts +### Fixes -- bodyfile/bodyfile.yaml: Updated to remove max_depth limit. -- files/applications/lesshst.yaml: Added less history file (.lesshst) collection [aix, freebsd, linux, macos, netbsd, netscaler, openbsd, solaris] ([mnrkbys](https://github.com/mnrkbys)). -- files/applications/whatsapp.yaml: Added collection of WhatsApp Desktop files [macos]. -- files/logs/additional_logs.yaml: Artifact was renamed to advanced_log_search.yaml. -- files/logs/relink.yaml: Added collection of the kernel relink log file [openbsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- files/logs/run_log.yaml: Added collection of /run/log directory. -- files/packages/pkg_contents.yaml: Updated to collect FreeBSD installed packages database [freebsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- files/system/acct.yaml: Added collection of system accounting files [freebsd, netbsd, openbsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- files/system/dev_db.yaml: Added collection of the database file used for device lookups [netbsd, openbsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- files/system/dev_shm.yaml: Updated to increase max_file_size to 10MB. -- files/system/locate_db.yaml: Added collection of the database file used by locate command, representing a snapshot of the virtual file system accessible with minimal permissions [freebsd, netbsd, openbsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- files/system/netscaler.yaml: Updated to increase max_file_size to 10MB. -- files/system/run_shm.yaml: Updated to increase max_file_size to 10MB. -- files/system/security_backups.yaml: Added collection of file backups and hashes created by the integrated security script [freebsd, netbsd, openbsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- files/system/systemd.yaml: Updated to add new locations for configuration files. -- files/system/tmp.yaml: Updated to increase max_file_size to 10MB. -- files/system/var_tmp.yaml: Updated to increase max_file_size to 10MB. -- hash_executables/hash_executables.yaml: Updated to remove max_depth and max_file_size properties. -- live_response/containers/jls.yaml: Added collection of jails used on FreeBSD systems [freebsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- live_response/hardware/dmesg.yaml: Updated collection of console message bufffer [esxi, freebsd, netscaler, openbsd, solaris] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- live_response/modifiers/revel_hidden_processes.yaml: Added command to umount filesystems mounted onto a directory that tipically corresponds to a process ID (PID) [linux] ([halpomeranz](https://github.com/halpomeranz)). -- live_response/network/procfs_information.yaml: Added collection of TCP and UDP network details from /proc/net [linux]. -- live_response/process/deleted.yaml: Collection of deleted processes will no longer use dd conv=swab. The binary file will be collected in its raw format now [linux]. -- live_response/process/deleted.yaml: Updated to fix the collection of open files of (malicious) processes [linux] ([mnrkbys](https://github.com/mnrkbys)). -- live_response/process/hash_running_processes.yaml: Updated to add support to hash running processes on FreeBSD systems that are using procfs (/proc) [freebsd]. -- live_response/process/procfs_information.yaml: Added artifact collection using cat when strings is not available. -- live_response/process/procfs_information.yaml: Updated to collect /proc/*/mount [linux] ([halpomeranz](https://github.com/halpomeranz)). -- live_response/process/procfs_information.yaml: Updated to collect /proc/*/stat [linux] ([mnrkbys](https://github.com/mnrkbys)). -- live_response/process/strings_running_processes.yaml: Added collection of strings from running processes for ESXi systems [esxi]. -- live_response/process/strings_running_processes.yaml: Added condition to check whether developer tools are installed before running strings on macOS [macos]. -- live_response/process/strings_running_processes.yaml: Added support for collecting strings even when the strings command is unavailable. In such cases, the built-in astrings command will be used instead [all]. -- live_response/storage/btrfs.yaml: Added collection of btrfs mountpoints, subvolumes and snapshots information [linux] ([mnrkbys](https://github.com/mnrkbys)). -- live_response/system/bpftool.yaml: Added eBPF programs information collection using bpftool [linux] ([mnrkbys](https://github.com/mnrkbys)). -- live_response/system/hidden_directories.yaml: Updated to remove max_depth limit. -- live_response/system/hidden_files.yaml: Updated to remove max_depth limit. -- live_response/system/kernel_tainted_state.yaml: Added collection of dmesg messages showing modules tainting the kernel [linux]. -- live_response/system/lastcomm.yaml: Added collection of the last commands executed in a reverse order based on the default and historic accounting file [freebsd, netbsd, openbsd] ([Herbert-Karl](https://github.com/Herbert-Karl)). -- live_response/system/sgid.yaml: Updated to remove max_depth limit. -- live_response/system/socket_files.yaml: Updated to remove max_depth limit. -- live_response/system/suid.yaml: Updated to remove max_depth limit. -- live_response/system/sys_modules.yaml: Removed as it is was duplicate artifact with kernel_modules.yaml. -- live_response/system/world_writable_directories.yaml: Updated to remove max_depth limit. -- live_response/system/world_writable_files.yaml: Updated to remove max_depth limit. -- live_response/system/zoneadm.yaml: Artifact was moved to live_response/containers directory ([Herbert-Karl](https://github.com/Herbert-Karl)). - -### Profiles - -- files/applications/lesshst.yaml, files/applications/viminfo.yaml, and files/applications/wget.yaml artifacts were added to the 'ir_triage' profile. - -### Command Line Option Changes - -- '--date-range-start' was renamed to '--start-date' ([#186](https://github.com/tclahr/uac/issues/186)). -- '--date-range-end' was renamed to '--end-date' ([#186](https://github.com/tclahr/uac/issues/186)). -- '--validate-artifacts-file' was renamed to '--validate-artifact'. -- '--s3-presigned-url' was renamed to '--aws-s3-presigned-url'. -- '--s3-presigned-url-log-file' was renamed to '--aws-s3-presigned-url-log-file'. -- '--ibm-cos-url', '--ibm-cos-url-log-file' and '--ibm-cloud-api-key' were removed and now transfers to IBM cloud should be done using '--s3-provider', '--s3-region', '--s3-bucket' and '--s3-token' options. - -### Artifacts Properties Changes - -- Introduced a new global 'modifier' property that ensures the artifact runs only if '--enable-modifiers' command line option is used. -- Introduced a new 'condition' property that ensures the collection runs only if the specified condition returns true. -- The 'output_directory' property is now mandatory for the following collectors: command, find, hash and stat. -- The 'file_type' property is now an array. -- The 'permissions' property is now an array. - -### uac.conf - -- Introduced a new global 'max_depth' configuration option to limit the depth of directory tree searches globally. - -### Tools - -- Statically linked 'zip' is now available for the following systems: - - linux/esxi (arm, arm64, i386 and x86_64) - - freebsd/netscaler (i386 and x86_64) -- 'avml' and 'linux_procmemdump.sh' tools were moved to the 'bin' directory. -- AVML updated to v0.14.0. - -### Deprecated - -- Android support was removed, but UAC can still be executed on Android systems using '--operating-system linux' option. +- Resolves an issue where the hash and stat collectors failed to function correctly when the %user_home% variable was included in the path property ([#289](https://github.com/tclahr/uac/issues/289)). diff --git a/artifacts/files/applications/git.yaml b/artifacts/files/applications/git.yaml new file mode 100644 index 00000000..2f1f05fd --- /dev/null +++ b/artifacts/files/applications/git.yaml @@ -0,0 +1,28 @@ +version: 1.0 +artifacts: +# Git hooks/Git pager can be used to run persistence. +# ref: https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms + - + description: Collect Git hooks under .git/hooks directory. + supported_os: [linux, macos] + collector: file + path: / + path_pattern: ["*/.git/hooks/*"] + file_type: [f] + - + description: Collect /etc/gitconfig file. + supported_os: [linux, macos] + collector: file + path: /etc/gitconfig + - + description: Collect ~/.gitconfig file. + supported_os: [linux, macos] + collector: file + path: /%user_home%/.gitconfig + exclude_nologin_users: true + - + description: Collect ~/.config/git/gitconfig file. + supported_os: [linux, macos] + collector: file + path: /%user_home%/.config/git/config + exclude_nologin_users: true diff --git a/artifacts/files/packages/apt.yaml b/artifacts/files/packages/apt.yaml new file mode 100644 index 00000000..3efa6593 --- /dev/null +++ b/artifacts/files/packages/apt.yaml @@ -0,0 +1,9 @@ +version: 1.0 +# APT can be used to run persistence. +# ref: https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms +artifacts: + - + description: Collect script files under /etc/apt/apt.conf.d/ directory. + supported_os: [linux] + collector: file + path: /etc/apt/apt.conf.d diff --git a/artifacts/files/packages/dnf.yaml b/artifacts/files/packages/dnf.yaml new file mode 100644 index 00000000..a68e3afd --- /dev/null +++ b/artifacts/files/packages/dnf.yaml @@ -0,0 +1,16 @@ +version: 1.0 +# DNF can be used to run persistence. +# ref: https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms +artifacts: + - + description: Collect configuration files under /etc/dnf/pluginconf.d/ directory. + supported_os: [linux] + collector: file + path: /etc/dnf/pluginconf.d + - + description: Collect script files under dnf-plugins directories. + supported_os: [linux] + collector: file + path: / + name_pattern: ["dnf-plugins"] + file_type: [d] diff --git a/artifacts/files/packages/yum.yaml b/artifacts/files/packages/yum.yaml new file mode 100644 index 00000000..42fb96c1 --- /dev/null +++ b/artifacts/files/packages/yum.yaml @@ -0,0 +1,14 @@ +version: 1.0 +# YUM can be used to run persistence. +# ref: https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms +artifacts: + - + description: Collect configuration files under /etc/yum/pluginconf.d/ directory. + supported_os: [linux] + collector: file + path: /etc/yum/pluginconf.d + - + description: Collect script files under /usr/lib/yum-plugins/ directory. + supported_os: [linux] + collector: file + path: /usr/lib/yum-plugins diff --git a/artifacts/files/system/acct.yaml b/artifacts/files/system/acct.yaml index a9150cae..c1319f5b 100644 --- a/artifacts/files/system/acct.yaml +++ b/artifacts/files/system/acct.yaml @@ -1,7 +1,7 @@ -version: 1.0 +version: 2.0 artifacts: # system accounting files, covering processes that terminated on the system, allowing one to see past program executions - # this is deactivated by default, but quite usefull when active + # this is deactivated by default, but quite useful when active - description: Collect system accounting files. supported_os: [freebsd, netbsd, openbsd] @@ -19,4 +19,24 @@ artifacts: supported_os: [freebsd, netbsd, openbsd] collector: file path: /var/account/savacct + ignore_date_range: true + - + description: Collect system accounting files. + supported_os: [solaris] + collector: file + path: /var/adm/pacct* + ignore_date_range: true + - + description: Collect system accounting summary files. + supported_os: [solaris] + collector: file + path: /var/adm/acct + max_file_size: 1073741824 # 1GB + ignore_date_range: true + - + description: Collect extended system accounting files from default location. + supported_os: [solaris] + collector: file + path: /var/adm/exacct + max_file_size: 1073741824 # 1GB ignore_date_range: true \ No newline at end of file diff --git a/artifacts/files/system/udev.yaml b/artifacts/files/system/udev.yaml new file mode 100644 index 00000000..75530873 --- /dev/null +++ b/artifacts/files/system/udev.yaml @@ -0,0 +1,12 @@ +version: 1.0 +# udev rules can be abused to run persistence. +# ref 1: https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms +# ref 2: https://ch4ik0.github.io/en/posts/leveraging-Linux-udev-for-persistence/ +artifacts: + - + description: Collect udev rule files. + supported_os: [linux] + collector: file + path: / + path_pattern: ["*/udev/rules.d/*"] + file_type: [f] diff --git a/artifacts/live_response/system/acctadm.yaml b/artifacts/live_response/system/acctadm.yaml new file mode 100644 index 00000000..07f99b38 --- /dev/null +++ b/artifacts/live_response/system/acctadm.yaml @@ -0,0 +1,10 @@ +version: 1.0 +condition: command_exists "acctadm" +output_directory: /live_response/system +artifacts: + - + description: Shows the configuration for extended accounting. + supported_os: [solaris] + collector: command + command: acctadm + output_file: acctadm.txt \ No newline at end of file diff --git a/artifacts/live_response/system/acctcom.yaml b/artifacts/live_response/system/acctcom.yaml new file mode 100644 index 00000000..4cc8fa39 --- /dev/null +++ b/artifacts/live_response/system/acctcom.yaml @@ -0,0 +1,17 @@ +version: 1.0 +condition: command_exists "acctcom" +output_directory: /live_response/system +artifacts: + - + description: Shows the last commands executed in a reverse order based on the default accounting file. + supported_os: [solaris] + collector: command + command: acctcom -f -i -t /var/adm/pacct + output_file: acctcom_-f_-i_-t.txt + - + description: Shows the last commands executed in a reverse order from the historic accounting files. + supported_os: [solaris] + collector: command + foreach: ls /var/adm/pacct* + command: acctcom -f -i -t %line% + output_file: acctcom_-f_-i_-t_%line%.txt \ No newline at end of file diff --git a/artifacts/live_response/system/lastcomm.yaml b/artifacts/live_response/system/lastcomm.yaml index fc70e634..c5e0e737 100644 --- a/artifacts/live_response/system/lastcomm.yaml +++ b/artifacts/live_response/system/lastcomm.yaml @@ -1,10 +1,10 @@ -version: 1.0 +version: 2.0 condition: command_exists "lastcomm" output_directory: /live_response/system artifacts: - description: Shows the last commands executed in a reverse order based on the default accounting file. - supported_os: [freebsd, netbsd, openbsd] + supported_os: [freebsd, netbsd, openbsd, solaris] collector: command command: lastcomm output_file: lastcomm.txt @@ -14,4 +14,10 @@ artifacts: collector: command foreach: ls /var/account/acct* command: lastcomm -f %line% - output_file: lastcomm_%line%.txt \ No newline at end of file + output_file: lastcomm_%line%.txt + - + description: Shows the last commands executed in a reverse order based on the extended accounting file. + supported_os: [solaris] + collector: command + command: lastcomm -x + output_file: lastcomm_-x.txt \ No newline at end of file diff --git a/lib/command_collector.sh b/lib/command_collector.sh index a443d8c6..0b5bf962 100644 --- a/lib/command_collector.sh +++ b/lib/command_collector.sh @@ -9,6 +9,7 @@ # string output_directory: ful path to the output directory # string output_file: output file name (optional) # boolean compress_output_file: compress output file (optional) (default: false) +# boolean redirect_stderr_to_stdout: redirect stderr to stdout (optional) (default: false) # Returns: # none _command_collector() @@ -18,6 +19,7 @@ _command_collector() __cc_output_directory="${3:-}" __cc_output_file="${4:-}" __cc_compress_output_file="${5:-false}" + __cc_redirect_stderr_to_stdout="${6:-false}" if [ -z "${__cc_command}" ]; then _log_msg ERR "_command_collector: empty command parameter" @@ -59,7 +61,7 @@ _command_collector() fi _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__cc_new_command}" - _run_command "${__cc_new_command}" \ + _run_command "${__cc_new_command}" "${__cc_redirect_stderr_to_stdout}" \ >>"${__cc_new_output_directory}/${__cc_new_output_file}" # remove output file if it is empty @@ -77,7 +79,7 @@ _command_collector() _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__cc_new_command}" ( cd "${__cc_new_output_directory}" \ - && _run_command "${__cc_new_command}" + && _run_command "${__cc_new_command}" "${__cc_redirect_stderr_to_stdout}" ) fi done @@ -96,7 +98,7 @@ _command_collector() __cc_command="${__cc_command} | gzip - | cat -" fi _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__cc_command}" - _run_command "${__cc_command}" \ + _run_command "${__cc_command}" "${__cc_redirect_stderr_to_stdout}" \ >>"${__cc_output_directory}/${__cc_output_file}" # remove output file if it is empty @@ -114,7 +116,7 @@ _command_collector() _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__cc_command}" ( cd "${__cc_output_directory}" \ - && _run_command "${__cc_command}" + && _run_command "${__cc_command}" "${__cc_redirect_stderr_to_stdout}" ) fi diff --git a/lib/find_based_collector.sh b/lib/find_based_collector.sh index 9c07f78d..75d80d0d 100644 --- a/lib/find_based_collector.sh +++ b/lib/find_based_collector.sh @@ -185,6 +185,9 @@ _find_based_collector() "true" \ "${__fc_start_date_days}" \ "${__fc_end_date_days}"` + if echo "${__fc_find_command}" | grep -q -E "; $"; then + __fc_find_command="{ ${__fc_find_command} }" + fi __fc_hash_command="${__fc_find_command} | xargs -0 ${__fc_hashing_tool}" else __fc_find_command=`_build_find_command \ @@ -201,11 +204,18 @@ _find_based_collector() "" \ "${__fc_start_date_days}" \ "${__fc_end_date_days}"` + if echo "${__fc_find_command}" | grep -q -E "; $"; then + __fc_find_command="{ ${__fc_find_command} }" + fi __fc_hash_command="${__fc_find_command} | sed 's|.|\\\\&|g' | xargs ${__fc_hashing_tool}" fi _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__fc_hash_command}" _run_command "${__fc_hash_command}" \ >>"${__fc_output_directory}/${__fc_output_file}.${__fc_algorithm}" + if [ ! -s "${__fc_output_directory}/${__fc_output_file}.${__fc_algorithm}" ]; then + rm -f "${__fc_output_directory}/${__fc_output_file}.${__fc_algorithm}" >/dev/null + _log_msg DBG "Empty output file '${__fc_output_file}.${__fc_algorithm}'" + fi fi done ;; @@ -228,6 +238,9 @@ _find_based_collector() "true" \ "${__fc_start_date_days}" \ "${__fc_end_date_days}"` + if echo "${__fc_find_command}" | grep -q -E "; $"; then + __fc_find_command="{ ${__fc_find_command} }" + fi __fc_stat_command="${__fc_find_command} | xargs -0 ${__UAC_TOOL_STAT_BIN}${__UAC_TOOL_STAT_PARAMS:+ }${__UAC_TOOL_STAT_PARAMS}" else __fc_find_command=`_build_find_command \ @@ -244,6 +257,9 @@ _find_based_collector() "" \ "${__fc_start_date_days}" \ "${__fc_end_date_days}"` + if echo "${__fc_find_command}" | grep -q -E "; $"; then + __fc_find_command="{ ${__fc_find_command} }" + fi __fc_stat_command="${__fc_find_command} | sed 's|.|\\\\&|g' | xargs ${__UAC_TOOL_STAT_BIN}${__UAC_TOOL_STAT_PARAMS:+ }${__UAC_TOOL_STAT_PARAMS}" fi _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__fc_stat_command}" @@ -257,6 +273,10 @@ _find_based_collector() -e "s:\`::g" \ -e "s:|.\{1,4\}$:|0:" \ >>"${__fc_output_directory}/${__fc_output_file}" + if [ ! -s "${__fc_output_directory}/${__fc_output_file}" ]; then + rm -f "${__fc_output_directory}/${__fc_output_file}" >/dev/null + _log_msg DBG "Empty output file '${__fc_output_file}'" + fi else _log_msg ERR "_find_based_collector: cannot run stat collector. Target system has neither 'stat', 'statx' nor 'perl' tool available" return 1 diff --git a/lib/parse_artifact.sh b/lib/parse_artifact.sh index 390e49a5..fbc64dab 100644 --- a/lib/parse_artifact.sh +++ b/lib/parse_artifact.sh @@ -40,6 +40,7 @@ _parse_artifact() __pa_path_pattern="" __pa_path="" __pa_permissions="" + __pa_redirect_stderr_to_stdout=false __pa_supported_os="" } _cleanup_local_vars @@ -93,14 +94,14 @@ _parse_artifact() # run global condition command and skip collection if exit code is greater than 0 if echo "${__pa_condition}" | grep -q -E "^!"; then __pa_condition=`echo "${__pa_condition}" | sed -e 's|^! *||' 2>/dev/null` - if _run_command "${__pa_condition}" >/dev/null; then + if _run_command "${__pa_condition}" true >/dev/null; then _log_msg DBG "Global condition '${__pa_condition}' not satisfied. Skipping..." return 1 else _log_msg DBG "Global condition '${__pa_condition}' satisfied" fi else - if _run_command "${__pa_condition}" >/dev/null; then + if _run_command "${__pa_condition}" true >/dev/null; then _log_msg DBG "Global condition '${__pa_condition}' satisfied" else _log_msg DBG "Global condition '${__pa_condition}' not satisfied. Skipping..." @@ -201,6 +202,9 @@ _parse_artifact() "permissions:") __pa_permissions=`echo "${__pa_value}" | _array_to_psv 2>/dev/null` ;; + "redirect_stderr_to_stdout:") + __pa_redirect_stderr_to_stdout="${__pa_value}" + ;; "supported_os:") __pa_supported_os=`echo "${__pa_value}" | _array_to_psv 2>/dev/null` ;; @@ -232,7 +236,7 @@ _parse_artifact() # run local condition command and skip collection if exit code greater than 0 if echo "${__pa_condition}" | grep -q -E "^!"; then __pa_condition=`echo "${__pa_condition}" | sed -e 's|^! *||' 2>/dev/null` - if _run_command "${__pa_condition}" false >/dev/null; then + if _run_command "${__pa_condition}" true >/dev/null; then _log_msg DBG "Condition '${__pa_condition}' not satisfied. Skipping..." _cleanup_local_vars continue @@ -240,7 +244,7 @@ _parse_artifact() _log_msg DBG "Condition '${__pa_condition}' satisfied" fi else - if _run_command "${__pa_condition}" false >/dev/null; then + if _run_command "${__pa_condition}" true >/dev/null; then _log_msg DBG "Condition '${__pa_condition}' satisfied" else _log_msg DBG "Condition '${__pa_condition}' not satisfied. Skipping..." @@ -326,7 +330,8 @@ _parse_artifact() "${__pa_new_command}" \ "${__pa_new_output_directory}" \ "${__pa_new_output_file}" \ - "${__pa_compress_output_file}" + "${__pa_compress_output_file}" \ + "${__pa_redirect_stderr_to_stdout}" elif [ "${__pa_collector}" = "file" ]; then _find_based_collector \ "file" \ @@ -364,7 +369,7 @@ _parse_artifact() "${__pa_new_output_directory}" \ "${__pa_new_output_file}" elif [ "${__pa_collector}" = "hash" ]; then - _file_collector \ + _find_based_collector \ "hash" \ "${__pa_new_path}" \ "${__pa_is_file_list}" \ @@ -382,7 +387,7 @@ _parse_artifact() "${__pa_new_output_directory}" \ "${__pa_new_output_file}" elif [ "${__pa_collector}" = "stat" ]; then - _file_collector \ + _find_based_collector \ "stat" \ "${__pa_new_path}" \ "${__pa_is_file_list}" \ @@ -408,7 +413,8 @@ _parse_artifact() "${__pa_command}" \ "${__pa_output_directory}" \ "${__pa_output_file}" \ - "${__pa_compress_output_file}" + "${__pa_compress_output_file}" \ + "${__pa_redirect_stderr_to_stdout}" elif [ "${__pa_collector}" = "file" ]; then _find_based_collector \ "file" \ diff --git a/lib/presigned_url_transfer.sh b/lib/presigned_url_transfer.sh deleted file mode 100644 index e74757db..00000000 --- a/lib/presigned_url_transfer.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: Apache-2.0 - -# Transfer file to a presigned URL. -# Arguments: -# string source: source file path -# string url: presigned URL -# Returns: -# boolean: true on success -# false on fail -presigned_url_transfer() -{ - __pu_source="${1:-}" - __pu_url="${2:-}" - - if command_exists "curl"; then - __pu_command="curl \ ---fail \ ---insecure \ ---request PUT \ ---header \"x-ms-blob-type: BlockBlob\" \ ---header \"Content-Type: application/octet-stream\" \ ---header \"Accept: */*\" \ ---header \"Expect: 100-continue\" \ ---upload-file \"${__pu_source}\" \ -\"${__pu_url}\"" - else - __pu_command="wget \ --O - \ ---quiet \ ---no-check-certificate \ ---method PUT \ ---header \"x-ms-blob-type: BlockBlob\" \ ---header \"Content-Type: application/octet-stream\" \ ---header \"Accept: */*\" \ ---header \"Expect: 100-continue\" \ ---body-file \"${__pu_source}\" \ -\"${__pu_url}\"" - fi - - _verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__pu_command}" - _run_command "${__pu_command}" - -} \ No newline at end of file diff --git a/lib/run_command.sh b/lib/run_command.sh index 4d7f6f78..0d8dd05c 100644 --- a/lib/run_command.sh +++ b/lib/run_command.sh @@ -5,13 +5,14 @@ # Run command. # Arguments: # string command: command (including arguments) -# boolean log_stderr: send stderr to uac.log (optional) (default: true) +# boolean redirect_stderr_to_stdout: redirect stderr to stdout (optional) (default: false) # Returns: # integer: command exit code _run_command() { __rc_command="${1:-}" - __rc_log_stderr="${2:-true}" + __rc_redirect_stderr_to_stdout="${2:-false}" + __rc_stderr_file="${__UAC_TEMP_DATA_DIR}/run_command.stderr.txt" if [ -z "${__rc_command}" ]; then _log_msg ERR "_run_command: empty command parameter" @@ -22,24 +23,23 @@ _run_command() return 1 fi - __rc_stderr_file="/dev/null" - if ${__rc_log_stderr}; then - __rc_stderr_file="${__UAC_TEMP_DATA_DIR}/run_command.stderr.txt" - fi + if ${__rc_redirect_stderr_to_stdout}; then + eval "${__rc_command}" 2>&1 + __rc_exit_code="$?" + else + eval "${__rc_command}" 2>"${__rc_stderr_file}" + __rc_exit_code="$?" - eval "${__rc_command}" \ - 2>"${__rc_stderr_file}" - __rc_exit_code="$?" + __rc_stderr="" + if [ -s "${__rc_stderr_file}" ]; then + __rc_stderr=`awk 'BEGIN {ORS="/n"} {print $0}' "${__rc_stderr_file}" | sed -e 's|/n$||' 2>/dev/null` + __rc_stderr=" 2> ${__rc_stderr}" + fi - __rc_stderr="" - if [ -s "${__UAC_TEMP_DATA_DIR}/run_command.stderr.txt" ] && ${__rc_log_stderr}; then - __rc_stderr=`awk 'BEGIN {ORS="/n"} {print $0}' "${__UAC_TEMP_DATA_DIR}/run_command.stderr.txt" | sed -e 's|/n$||' 2>/dev/null` - __rc_stderr=" 2> ${__rc_stderr}" + __rc_command=`echo "${__rc_command}" | awk 'BEGIN {ORS="/n"} {print $0}' | sed -e 's| *| |g' -e 's|/n$||' 2>/dev/null` + _log_msg CMD "${__rc_command}${__rc_stderr}" fi - __rc_command=`echo "${__rc_command}" | awk 'BEGIN {ORS="/n"} {print $0}' | sed -e 's| *| |g' -e 's|/n$||' 2>/dev/null` - _log_msg CMD "${__rc_command}${__rc_stderr}" - return "${__rc_exit_code}" } \ No newline at end of file diff --git a/lib/validate_artifact.sh b/lib/validate_artifact.sh index 3eb22287..cfd70574 100644 --- a/lib/validate_artifact.sh +++ b/lib/validate_artifact.sh @@ -42,6 +42,7 @@ _validate_artifact() __va_path_pattern="" __va_path="" __va_permissions="" + __va_redirect_stderr_to_stdout="" __va_supported_os="" } _cleanup_local_vars @@ -336,6 +337,13 @@ _validate_artifact() done __va_permissions="${__va_value}" ;; + "redirect_stderr_to_stdout:") + if [ "${__va_value}" != true ] && [ "${__va_value}" != false ]; then + _error_msg "artifact: 'redirect_stderr_to_stdout' must be 'true' or 'false'." + return 1 + fi + __va_redirect_stderr_to_stdout="${__va_value}" + ;; "supported_os:") if echo "${__va_value}" | grep -q -v -E "^\[.*\]$"; then _error_msg "artifact: 'supported_os' must be an array/list." @@ -465,6 +473,10 @@ _validate_artifact() _error_msg "artifact: invalid 'compress_output_file' property for '${__va_collector}' collector." return 1 fi + if [ -n "${__va_redirect_stderr_to_stdout}" ]; then + _error_msg "artifact: invalid 'redirect_stderr_to_stdout' property for '${__va_collector}' collector." + return 1 + fi if [ -n "${__va_foreach}" ]; then _error_msg "artifact: invalid 'foreach' property for '${__va_collector}' collector." return 1 diff --git a/profiles/ir_triage.yaml b/profiles/ir_triage.yaml index 8e258f8f..69f0a3e2 100644 --- a/profiles/ir_triage.yaml +++ b/profiles/ir_triage.yaml @@ -25,6 +25,7 @@ artifacts: - live_response/vms/* - chkrootkit/* - hash_executables/hash_executables.yaml + - files/applications/git.yaml - files/applications/lesshst.yaml - files/applications/viminfo.yaml - files/applications/wget.yaml