diff --git a/linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/16_Crontab_UI_misconfig.sh b/linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/16_Crontab_UI_misconfig.sh index 0512577..49e9049 100644 --- a/linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/16_Crontab_UI_misconfig.sh +++ b/linPEAS/builder/linpeas_parts/4_procs_crons_timers_srvcs_sockets/16_Crontab_UI_misconfig.sh @@ -51,77 +51,76 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then fi # If no candidates detected, exit quietly - if [ -z "$candidates" ]; then - exit 0 - fi + if [ "$candidates" ]; then - # Iterate candidates and extract interesting data - printf "%s\n" "$candidates" | while read -r svc; do - [ -n "$svc" ] || continue - # Ensure suffix .service if missing - case "$svc" in - *.service) : ;; - *) svc="$svc.service" ;; - esac + # Iterate candidates and extract interesting data + printf "%s\n" "$candidates" | while read -r svc; do + [ -n "$svc" ] || continue + # Ensure suffix .service if missing + case "$svc" in + *.service) : ;; + *) svc="$svc.service" ;; + esac - state="" - user="" - if command -v systemctl >/dev/null 2>&1; then - state=$(systemctl is-active "$svc" 2>/dev/null) - user=$(systemctl show "$svc" -p User 2>/dev/null | cut -d= -f2) - fi - - [ -z "$state" ] && state="unknown" - [ -z "$user" ] && user="unknown" - - echo "Service: $svc (state: $state, User: $user)" | sed -${E} "s,root,${SED_RED},g" - - # Read Environment from systemd (works even if file unreadable in many setups) - envvals=$(systemctl show "$svc" -p Environment 2>/dev/null | cut -d= -f2-) - if [ -n "$envvals" ]; then - basic_user=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^BASIC_AUTH_USER=' | head -n1 | cut -d= -f2-) - basic_pwd=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^BASIC_AUTH_PWD=' | head -n1 | cut -d= -f2-) - dbpath=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^CRON_DB_PATH=' | head -n1 | cut -d= -f2-) - port=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^PORT=' | head -n1 | cut -d= -f2-) - - if [ -n "$basic_user" ] || [ -n "$basic_pwd" ]; then - uprint="$basic_user" - pprint="$basic_pwd" - [ -n "$basic_pwd" ] && pprint="$basic_pwd" - echo " └─ Basic-Auth credentials in Environment: user='${uprint}' pwd='${pprint}'" | sed -${E} "s,pwd='[^']*',${SED_RED_YELLOW},g" + state="" + user="" + if command -v systemctl >/dev/null 2>&1; then + state=$(systemctl is-active "$svc" 2>/dev/null) + user=$(systemctl show "$svc" -p User 2>/dev/null | cut -d= -f2) fi - if [ -n "$dbpath" ]; then - echo " └─ CRON_DB_PATH: $dbpath" - fi + [ -z "$state" ] && state="unknown" + [ -z "$user" ] && user="unknown" - # Check listener bound to localhost - [ -z "$port" ] && port=8000 - if command -v ss >/dev/null 2>&1; then - if ss -ltn 2>/dev/null | grep -qE "127\.0\.0\.1:${port}[[:space:]]"; then - echo " └─ Listener detected on 127.0.0.1:${port} (likely Crontab UI)." + echo "Service: $svc (state: $state, User: $user)" | sed -${E} "s,root,${SED_RED},g" + + # Read Environment from systemd (works even if file unreadable in many setups) + envvals=$(systemctl show "$svc" -p Environment 2>/dev/null | cut -d= -f2-) + if [ -n "$envvals" ]; then + basic_user=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^BASIC_AUTH_USER=' | head -n1 | cut -d= -f2-) + basic_pwd=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^BASIC_AUTH_PWD=' | head -n1 | cut -d= -f2-) + dbpath=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^CRON_DB_PATH=' | head -n1 | cut -d= -f2-) + port=$(printf "%s\n" "$envvals" | tr ' ' '\n' | grep -E '^PORT=' | head -n1 | cut -d= -f2-) + + if [ -n "$basic_user" ] || [ -n "$basic_pwd" ]; then + uprint="$basic_user" + pprint="$basic_pwd" + [ -n "$basic_pwd" ] && pprint="$basic_pwd" + echo " └─ Basic-Auth credentials in Environment: user='${uprint}' pwd='${pprint}'" | sed -${E} "s,pwd='[^']*',${SED_RED_YELLOW},g" fi - else - if netstat -tnl 2>/dev/null | grep -qE "127\.0\.0\.1:${port}[[:space:]]"; then - echo " └─ Listener detected on 127.0.0.1:${port} (likely Crontab UI)." - fi - fi - # If we know DB path, try to read crontab.db for obvious secrets and check perms - if [ -n "$dbpath" ] && [ -d "$dbpath" ] && [ -r "$dbpath" ]; then - dbfile="$dbpath/crontab.db" - if [ -f "$dbfile" ]; then - perms=$(ls -ld "$dbpath" 2>/dev/null | awk '{print $1, $3, $4}') - echo " └─ DB dir perms: $perms" - if [ -w "$dbpath" ] || [ -w "$dbfile" ]; then - echo " └─ Writable by current user -> potential job injection!" | sed -${E} "s,.*,${SED_RED},g" + if [ -n "$dbpath" ]; then + echo " └─ CRON_DB_PATH: $dbpath" + fi + + # Check listener bound to localhost + [ -z "$port" ] && port=8000 + if command -v ss >/dev/null 2>&1; then + if ss -ltn 2>/dev/null | grep -qE "127\.0\.0\.1:${port}[[:space:]]"; then + echo " └─ Listener detected on 127.0.0.1:${port} (likely Crontab UI)." + fi + else + if netstat -tnl 2>/dev/null | grep -qE "127\.0\.0\.1:${port}[[:space:]]"; then + echo " └─ Listener detected on 127.0.0.1:${port} (likely Crontab UI)." + fi + fi + + # If we know DB path, try to read crontab.db for obvious secrets and check perms + if [ -n "$dbpath" ] && [ -d "$dbpath" ] && [ -r "$dbpath" ]; then + dbfile="$dbpath/crontab.db" + if [ -f "$dbfile" ]; then + perms=$(ls -ld "$dbpath" 2>/dev/null | awk '{print $1, $3, $4}') + echo " └─ DB dir perms: $perms" + if [ -w "$dbpath" ] || [ -w "$dbfile" ]; then + echo " └─ Writable by current user -> potential job injection!" | sed -${E} "s,.*,${SED_RED},g" + fi + echo " └─ Inspecting $dbfile for embedded secrets in commands (zip -P / --password / pass/token/secret)..." + grep -E "-P[[:space:]]+\S+|--password[[:space:]]+\S+|[Pp]ass(word)?|[Tt]oken|[Ss]ecret" "$dbfile" 2>/dev/null | head -n 20 | sed -${E} "s,(${SED_RED_YELLOW}),\1,g" fi - echo " └─ Inspecting $dbfile for embedded secrets in commands (zip -P / --password / pass/token/secret)..." - grep -E "-P[[:space:]]+\S+|--password[[:space:]]+\S+|[Pp]ass(word)?|[Tt]oken|[Ss]ecret" "$dbfile" 2>/dev/null | head -n 20 | sed -${E} "s,(${SED_RED_YELLOW}),\1,g" fi fi - fi - echo "" - done + echo "" + done + fi fi