Skip to content

Commit c980630

Browse files
committed
refactor: small code updates
1 parent f06567c commit c980630

File tree

6 files changed

+128
-59
lines changed

6 files changed

+128
-59
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
88

99
- The output and log file names are now automatically appended to the URL provided in `--azure-storage-sas-url` ([#389](https://github.com/tclahr/uac/issues/389)). Consequently, the `--azure-storage-sas-url-log-file` option is no longer needed and has been removed.
1010
- Introduced the `statf` tool, which leverages the `stat` system call to produce file status information in bodyfile format for FreeBSD-based systems lacking the `stat` and `perl` tools.
11+
- You can now use the `find` collector to run a specified `command` once for each matched file ([#420](https://github.com/tclahr/uac/issues/420)). Please check the [documentation](https://tclahr.github.io/uac-docs/artifacts/#field-reference-and-examples) for more information. (by [halpomeranz](https://github.com/halpomeranz))
1112

1213
### Artifacts
1314

artifacts/system/getcap.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
version: 3.0
2+
condition: command_exists "getcap"
23
output_directory: /system
4+
# abuse process capabilities
5+
# ref: https://www.elastic.co/security-labs/sequel-on-persistence-mechanisms
36
artifacts:
47
-
5-
description: List all files with Linux capabilities
8+
description: List all files with Linux capabilities.
69
supported_os: [linux]
710
collector: find
811
path: /
12+
exclude_path_pattern: ["/proc", "/sys"]
913
file_type: [f]
1014
command: getcap
11-
exclude_file_system: [proc, procfs]
1215
output_file: getcap.txt
13-
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
version: 3.0
2+
condition: command_exists "lsattr"
23
output_directory: /system
34
artifacts:
45
-
5-
description: List all immutable files
6+
description: List immutable files.
67
supported_os: [linux]
78
collector: find
89
path: /
10+
exclude_path_pattern: ["/dev", "/proc", "/run", "/sys"]
911
file_type: [f]
10-
command: lsattr | awk '$1 ~ /i/ && $1 !~ /^\\//'
11-
exclude_file_system: [proc, procfs, squashfs]
12+
command: lsattr -d | awk '$1 ~ /i/ && $1 !~ /^\\//'
1213
output_file: immutable_files.txt
13-

lib/find_based_collector.sh

Lines changed: 88 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ _find_based_collector()
3232
__fc_collector="${1:-}"
3333
shift
3434
__fc_path="${1:-}"
35-
#shift
36-
#__fc_mount_point="${1:-/}"
3735
shift
3836
__fc_is_file_list="${1:-false}"
3937
shift
@@ -63,7 +61,7 @@ _find_based_collector()
6361
shift
6462
__fc_ignore_date_range="${1:-false}"
6563
shift
66-
__fc_command_xargs_pipe="${1:-}"
64+
__fc_command="${1:-}"
6765
shift
6866
__fc_output_directory="${1:-}"
6967
shift
@@ -95,7 +93,7 @@ _find_based_collector()
9593
if ${__fc_is_file_list}; then
9694
# prepend __UAC_TEMP_DATA_DIR/collected if path does not start with /
9795
if echo "${__fc_path}" | grep -q -v -E "^/"; then
98-
__fc_path="${__UAC_TEMP_DATA_DIR}/collected/${__fc_path}"
96+
__fc_path="${__UAC_ARTIFACTS_OUTPUT_DIR}/${__fc_path}"
9997
fi
10098
__fc_path=`_sanitize_path "${__fc_path}"`
10199
if [ ! -f "${__fc_path}" ]; then
@@ -148,12 +146,10 @@ _find_based_collector()
148146
fi
149147

150148
case "${__fc_collector}" in
151-
"file"|"find")
149+
"file")
152150
if ${__fc_is_file_list}; then
153151
__fc_find_command="cat \"${__fc_path}\""
154152
else
155-
[ -n "${__fc_command_xargs_pipe}" ] && __fc_print0="true" || __fc_print0="false"
156-
157153
__fc_find_command=`_build_find_command \
158154
"${__fc_path}" \
159155
"${__fc_path_pattern}" \
@@ -167,20 +163,93 @@ _find_based_collector()
167163
"${__fc_permissions}" \
168164
"${__fc_no_group}" \
169165
"${__fc_no_user}" \
170-
"${__fc_print0}" \
166+
"" \
171167
"${__fc_start_date_days}" \
172168
"${__fc_end_date_days}"`
173169
fi
174-
if [ "${__fc_collector}" = "find" ] && [ -n "${__fc_command_xargs_pipe}" ]; then
175-
if ${__UAC_TOOL_FIND_PRINT0_SUPPORT} && ${__UAC_TOOL_XARGS_NULL_DELIMITER_SUPPORT}; then
176-
__fc_find_command="${__fc_find_command} | xargs -0 ${__fc_command_xargs_pipe}"
177-
else
178-
__fc_find_command="${__fc_find_command} | xargs ${__fc_command_xargs_pipe}"
179-
fi
180-
fi
181170
_verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__fc_find_command}"
182171
_run_command "${__fc_find_command}" \
183-
>>"${__fc_output_directory}/${__fc_output_file}"
172+
>>"${__fc_output_directory}/${__fc_output_file}"
173+
;;
174+
"find")
175+
if [ -n "${__fc_command}" ]; then
176+
if ${__fc_is_file_list}; then
177+
__fc_command="sed 's|.|\\\\&|g' \"${__fc_path}\" | xargs ${__fc_command}"
178+
elif ${__UAC_TOOL_FIND_PRINT0_SUPPORT} && ${__UAC_TOOL_XARGS_NULL_DELIMITER_SUPPORT}; then
179+
__fc_find_command=`_build_find_command \
180+
"${__fc_path}" \
181+
"${__fc_path_pattern}" \
182+
"${__fc_name_pattern}" \
183+
"${__fc_exclude_path_pattern}" \
184+
"${__fc_exclude_name_pattern}" \
185+
"${__fc_max_depth}" \
186+
"${__fc_file_type}" \
187+
"${__fc_min_file_size}" \
188+
"${__fc_max_file_size}" \
189+
"${__fc_permissions}" \
190+
"${__fc_no_group}" \
191+
"${__fc_no_user}" \
192+
"true" \
193+
"${__fc_start_date_days}" \
194+
"${__fc_end_date_days}"`
195+
if echo "${__fc_find_command}" | grep -q -E "; $"; then
196+
__fc_find_command="{ ${__fc_find_command} }"
197+
fi
198+
__fc_command="${__fc_find_command} | xargs -0 ${__fc_command}"
199+
else
200+
__fc_find_command=`_build_find_command \
201+
"${__fc_path}" \
202+
"${__fc_path_pattern}" \
203+
"${__fc_name_pattern}" \
204+
"${__fc_exclude_path_pattern}" \
205+
"${__fc_exclude_name_pattern}" \
206+
"${__fc_max_depth}" \
207+
"${__fc_file_type}" \
208+
"${__fc_min_file_size}" \
209+
"${__fc_max_file_size}" \
210+
"${__fc_permissions}" \
211+
"${__fc_no_group}" \
212+
"${__fc_no_user}" \
213+
"" \
214+
"${__fc_start_date_days}" \
215+
"${__fc_end_date_days}"`
216+
if echo "${__fc_find_command}" | grep -q -E "; $"; then
217+
__fc_find_command="{ ${__fc_find_command} }"
218+
fi
219+
__fc_command="${__fc_find_command} | sed 's|.|\\\\&|g' | xargs ${__fc_command}"
220+
fi
221+
_verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__fc_command}"
222+
_run_command "${__fc_command}" \
223+
>>"${__fc_output_directory}/${__fc_output_file}"
224+
if [ ! -s "${__fc_output_directory}/${__fc_output_file}" ]; then
225+
rm -f "${__fc_output_directory}/${__fc_output_file}" >/dev/null
226+
_log_msg DBG "Empty output file: '${__fc_output_file}'"
227+
fi
228+
else
229+
if ${__fc_is_file_list}; then
230+
__fc_find_command="cat \"${__fc_path}\""
231+
else
232+
__fc_find_command=`_build_find_command \
233+
"${__fc_path}" \
234+
"${__fc_path_pattern}" \
235+
"${__fc_name_pattern}" \
236+
"${__fc_exclude_path_pattern}" \
237+
"${__fc_exclude_name_pattern}" \
238+
"${__fc_max_depth}" \
239+
"${__fc_file_type}" \
240+
"${__fc_min_file_size}" \
241+
"${__fc_max_file_size}" \
242+
"${__fc_permissions}" \
243+
"${__fc_no_group}" \
244+
"${__fc_no_user}" \
245+
"" \
246+
"${__fc_start_date_days}" \
247+
"${__fc_end_date_days}"`
248+
fi
249+
_verbose_msg "${__UAC_VERBOSE_CMD_PREFIX}${__fc_find_command}"
250+
_run_command "${__fc_find_command}" \
251+
>>"${__fc_output_directory}/${__fc_output_file}"
252+
fi
184253
;;
185254
"hash")
186255
for __fc_algorithm in `echo "${__UAC_CONF_HASH_ALGORITHM}" | sed -e 's:|: :g'`; do
@@ -247,6 +316,9 @@ _find_based_collector()
247316
rm -f "${__fc_output_directory}/${__fc_output_file}.${__fc_algorithm}" >/dev/null
248317
_log_msg DBG "Empty output file: '${__fc_output_file}.${__fc_algorithm}'"
249318
fi
319+
else
320+
_log_msg ERR "_find_based_collector: Cannot run hash collector. Target system does not have any hashing tool available"
321+
return 1
250322
fi
251323
done
252324
;;

lib/parse_artifact.sh

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,6 @@ _parse_artifact()
4949

5050
__pa_global_output_directory=""
5151

52-
_replace_exposed_variables()
53-
{
54-
__re_value="${1:-}"
55-
56-
if [ -n "${__UAC_START_DATE}" ]; then
57-
__re_value=`printf "%s" "${__re_value}" \
58-
| sed -e "s|%start_date%|${__UAC_START_DATE}|g" \
59-
-e "s|%start_date_epoch%|${__UAC_START_DATE_EPOCH}|g" 2>/dev/null`
60-
fi
61-
if [ -n "${__UAC_END_DATE}" ]; then
62-
__re_value=`printf "%s" "${__re_value}" \
63-
| sed -e "s|%end_date%|${__UAC_END_DATE}|g" \
64-
-e "s|%end_date_epoch%|${__UAC_END_DATE_EPOCH}|g" 2>/dev/null`
65-
fi
66-
printf "%s" "${__re_value}" \
67-
| sed -e "s|%uac_directory%|${__UAC_DIR}|g" \
68-
-e "s|%mount_point%|${__UAC_MOUNT_POINT}|g" \
69-
-e "s:%non_local_mount_points%:${__UAC_EXCLUDE_MOUNT_POINTS}:g" \
70-
-e "s|%temp_directory%|${__UAC_TEMP_DATA_DIR}/tmp|g" 2>/dev/null
71-
}
72-
7352
# remove lines starting with # (comments) and any inline comments
7453
# remove leading and trailing space characters
7554
# remove blank lines
@@ -125,7 +104,10 @@ _parse_artifact()
125104
"
126105
done
127106
fi
128-
__pa_command=`_replace_exposed_variables "${__pa_value}"`
107+
__pa_command="${__pa_value}"
108+
if printf "%s" "${__pa_command}" | grep -q -E "%[a-zA-Z_]"; then
109+
__pa_command=`_replace_runtime_user_defined_variables "${__pa_command}"`
110+
fi
129111
;;
130112
"compress_output_file:")
131113
__pa_compress_output_file="${__pa_value}"
@@ -138,7 +120,10 @@ _parse_artifact()
138120
"
139121
done
140122
fi
141-
__pa_condition=`_replace_exposed_variables "${__pa_value}"`
123+
__pa_condition="${__pa_value}"
124+
if printf "%s" "${__pa_condition}" | grep -q -E "%[a-zA-Z_]"; then
125+
__pa_condition=`_replace_runtime_user_defined_variables "${__pa_condition}"`
126+
fi
142127
;;
143128
"description:")
144129
__pa_description="${__pa_value}"
@@ -166,7 +151,10 @@ _parse_artifact()
166151
"
167152
done
168153
fi
169-
__pa_foreach=`_replace_exposed_variables "${__pa_value}"`
154+
__pa_foreach="${__pa_value}"
155+
if printf "%s" "${__pa_foreach}" | grep -q -E "%[a-zA-Z_]"; then
156+
__pa_foreach=`_replace_runtime_user_defined_variables "${__pa_foreach}"`
157+
fi
170158
;;
171159
"ignore_date_range:")
172160
__pa_ignore_date_range="${__pa_value}"
@@ -196,14 +184,20 @@ _parse_artifact()
196184
if echo "${__pa_value}" | grep -q -E "%temp_directory%"; then
197185
__pa_output_directory=`echo "${__pa_value}" | sed -e "s|%temp_directory%|${__UAC_TEMP_DATA_DIR}/tmp|g" 2>/dev/null`
198186
else
199-
__pa_output_directory="${__UAC_TEMP_DATA_DIR}/collected/${__pa_value}"
187+
__pa_output_directory="${__UAC_ARTIFACTS_OUTPUT_DIR}/${__pa_value}"
200188
fi
201189
;;
202190
"output_file:")
203191
__pa_output_file="${__pa_value}"
192+
if printf "%s" "${__pa_output_file}" | grep -q -E "%[a-zA-Z_]"; then
193+
__pa_output_file=`_replace_runtime_user_defined_variables "${__pa_output_file}"`
194+
fi
204195
;;
205196
"path:")
206-
__pa_path=`_replace_exposed_variables "${__pa_value}"`
197+
__pa_path="${__pa_value}"
198+
if printf "%s" "${__pa_path}" | grep -q -E "%[a-zA-Z_]"; then
199+
__pa_path=`_replace_runtime_user_defined_variables "${__pa_path}"`
200+
fi
207201
;;
208202
"path_pattern:")
209203
__pa_path_pattern=`echo "${__pa_value}" | _array_to_psv 2>/dev/null`
@@ -362,7 +356,7 @@ _parse_artifact()
362356
"${__pa_no_group}" \
363357
"${__pa_no_user}" \
364358
"${__pa_ignore_date_range}" \
365-
"" \
359+
"" \
366360
"${__UAC_TEMP_DATA_DIR}" \
367361
"file_collector.tmp"
368362
elif [ "${__pa_collector}" = "find" ]; then
@@ -383,7 +377,7 @@ _parse_artifact()
383377
"${__pa_no_group}" \
384378
"${__pa_no_user}" \
385379
"${__pa_ignore_date_range}" \
386-
"${__pa_command}" \
380+
"${__pa_new_command}" \
387381
"${__pa_new_output_directory}" \
388382
"${__pa_new_output_file}"
389383
elif [ "${__pa_collector}" = "hash" ]; then
@@ -404,7 +398,7 @@ _parse_artifact()
404398
"${__pa_no_group}" \
405399
"${__pa_no_user}" \
406400
"${__pa_ignore_date_range}" \
407-
"" \
401+
"" \
408402
"${__pa_new_output_directory}" \
409403
"${__pa_new_output_file}"
410404
elif [ "${__pa_collector}" = "stat" ]; then
@@ -425,7 +419,7 @@ _parse_artifact()
425419
"${__pa_no_group}" \
426420
"${__pa_no_user}" \
427421
"${__pa_ignore_date_range}" \
428-
"" \
422+
"" \
429423
"${__pa_new_output_directory}" \
430424
"${__pa_new_output_file}"
431425
fi
@@ -457,7 +451,7 @@ _parse_artifact()
457451
"${__pa_no_group}" \
458452
"${__pa_no_user}" \
459453
"${__pa_ignore_date_range}" \
460-
"" \
454+
"" \
461455
"${__UAC_TEMP_DATA_DIR}" \
462456
"file_collector.tmp"
463457
elif [ "${__pa_collector}" = "find" ]; then
@@ -478,7 +472,7 @@ _parse_artifact()
478472
"${__pa_no_group}" \
479473
"${__pa_no_user}" \
480474
"${__pa_ignore_date_range}" \
481-
"${__pa_command}" \
475+
"${__pa_command}" \
482476
"${__pa_output_directory}" \
483477
"${__pa_output_file}"
484478
elif [ "${__pa_collector}" = "hash" ]; then
@@ -499,7 +493,7 @@ _parse_artifact()
499493
"${__pa_no_group}" \
500494
"${__pa_no_user}" \
501495
"${__pa_ignore_date_range}" \
502-
"" \
496+
"" \
503497
"${__pa_output_directory}" \
504498
"${__pa_output_file}"
505499
elif [ "${__pa_collector}" = "stat" ]; then
@@ -520,7 +514,7 @@ _parse_artifact()
520514
"${__pa_no_group}" \
521515
"${__pa_no_user}" \
522516
"${__pa_ignore_date_range}" \
523-
"" \
517+
"" \
524518
"${__pa_output_directory}" \
525519
"${__pa_output_file}"
526520
fi
@@ -531,4 +525,4 @@ _parse_artifact()
531525
esac
532526
done
533527

534-
}
528+
}

lib/validate_artifact.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,4 +566,4 @@ _validate_artifact()
566566
esac
567567

568568
done
569-
}
569+
}

0 commit comments

Comments
 (0)