Add opt-in online package vulnerability lookup

This commit is contained in:
Carlos Polop
2026-06-29 13:50:25 +02:00
parent 4c0c55fa99
commit aef2b84f33
5 changed files with 142 additions and 17 deletions
@@ -20,7 +20,7 @@
# Functions Used: print_2title, print_3title, print_info, echo_not_found
# Global Variables:
# Initial Functions:
# Generated Global Variables: $pk_full, $pk_version, $pk_pkg_manager, $pk_distro_id, $pk_distro_codename, $pk_fixed_version, $pk_fixed_label, $pk_min_vuln, $pk_max_vuln, $pk_lower, $pk_higher, $pk_vulnerable, $pk_ioc_count
# Generated Global Variables: $pk_full, $pk_version, $pk_pkg_manager, $pk_distro_id, $pk_distro_codename, $pk_fixed_version, $pk_fixed_label, $pk_min_vuln, $pk_max_vuln, $pk_lower, $pk_higher, $pk_vulnerable, $pk_ioc_count, $VERSION_CODENAME, $Version
# Fat linpeas: 0
# Small linpeas: 1
@@ -10,7 +10,7 @@
# Functions Used:
# Global Variables: $E, $SED_GREEN, $SED_YELLOW, $SED_RED_YELLOW
# Initial Functions:
# Generated Global Variables: $DF43_KERNEL_OS, $DF43_KERNEL_RELEASE, $DF43_KERNEL_VERSION, $DF43_KBUILD, $DF43_VERSION_KNOWN, $DF43_ESP_AFFECTED, $DF43_RXRPC_AFFECTED, $DF43_ESP_MODS, $DF43_RXRPC_MODS, $DF43_LOADED_ESP, $DF43_LOADED_RXRPC, $DF43_AUTO_ESP, $DF43_AUTO_RXRPC, $DF43_MODDEP, $DF43_MOD, $DF43_BUILTIN_ESP, $DF43_BUILTIN_RXRPC, $DF43_KCFG, $DF43_KCAT, $DF43_C, $DF43_MITIG_ESP, $DF43_MITIG_RXRPC, $DF43_USERNS_OFF, $DF43_CAP_NET_ADMIN, $DF43_CAPEFF, $DF43_CAPLO, $DF43_OLDBUILD, $DF43_BDATE, $DF43_BE, $DF43_FE, $DF43_ESP_REACH, $DF43_RXRPC_REACH, $DF43_RC
# Generated Global Variables: $DF43_KERNEL_OS, $DF43_KERNEL_RELEASE, $DF43_KERNEL_VERSION, $DF43_KBUILD, $DF43_VERSION_KNOWN, $DF43_ESP_AFFECTED, $DF43_RXRPC_AFFECTED, $DF43_ESP_MODS, $DF43_RXRPC_MODS, $DF43_LOADED_ESP, $DF43_LOADED_RXRPC, $DF43_AUTO_ESP, $DF43_AUTO_RXRPC, $DF43_MODDEP, $DF43_MOD, $DF43_BUILTIN_ESP, $DF43_BUILTIN_RXRPC, $DF43_KCFG, $DF43_KCAT, $DF43_C, $DF43_MITIG_ESP, $DF43_MITIG_RXRPC, $DF43_USERNS_OFF, $DF43_CAP_NET_ADMIN, $DF43_CAPEFF, $DF43_CAPLO, $DF43_OLDBUILD, $DF43_BDATE, $DF43_BE, $DF43_FE, $DF43_ESP_REACH, $DF43_RXRPC_REACH, $DF43_RC, $DF43_CURVER, $DF43_REQVER, $DF43_OP, $DF43_CMP
# Fat linpeas: 0
# Small linpeas: 1
@@ -6,20 +6,146 @@
# License: GNU GPL
# Version: 1.0
# Functions Used:
# Global Variables:
# Global Variables: $VERSION, $ONLINE_VULN_CHECKS
# Initial Functions:
# Generated Global Variables: $$INTERNET_SEARCH_TIMEOUT
# Generated Global Variables: $$INTERNET_SEARCH_TIMEOUT, $HACKTRICKS_HOST_CHECKER_URL, $HACKTRICKS_PACKAGE_LIMIT, $_os_id, $_os_version_id, $_os_version_major, $_ecosystem, $_pkg_name, $_pkg_line, $_pkg_version, $_limit, $_os_name, $_os_codename, $_hostname, $_hacktricks_host_checker_url, $_hacktricks_payload, $source, $binary, $Version
# Fat linpeas: 0
# Small linpeas: 1
linpeas_json_escape(){
printf "%s" "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/ / /g'
}
linpeas_os_release_field(){
[ -r /etc/os-release ] || return
awk -F= -v key="$1" '
$1 == key {
value=$0
sub(/^[^=]*=/, "", value)
gsub(/^"/, "", value)
gsub(/"$/, "", value)
print value
exit
}
' /etc/os-release 2>/dev/null
}
linpeas_os_package_ecosystem(){
_os_id="$(linpeas_os_release_field ID)"
_os_version_id="$(linpeas_os_release_field VERSION_ID)"
_os_version_major="$(printf "%s" "$_os_version_id" | cut -d. -f1)"
case "$_os_id" in
debian) [ "$_os_version_major" ] && printf "Debian:%s" "$_os_version_major" ;;
ubuntu) [ "$_os_version_id" ] && printf "Ubuntu:%s" "$_os_version_id" ;;
alpine) [ "$_os_version_id" ] && printf "Alpine:v%s" "$_os_version_id" ;;
fedora) [ "$_os_version_id" ] && printf "Fedora:%s" "$_os_version_id" ;;
amzn) [ "$_os_version_id" ] && printf "Amazon Linux:%s" "$_os_version_id" ;;
rhel) [ "$_os_version_major" ] && printf "Red Hat:%s" "$_os_version_major" ;;
centos) [ "$_os_version_major" ] && printf "CentOS:%s" "$_os_version_major" ;;
rocky) [ "$_os_version_major" ] && printf "Rocky Linux:%s" "$_os_version_major" ;;
almalinux) [ "$_os_version_major" ] && printf "AlmaLinux:%s" "$_os_version_major" ;;
esac
}
linpeas_print_package_json_lines(){
_ecosystem="$(linpeas_os_package_ecosystem)"
if command -v dpkg-query >/dev/null 2>&1; then
dpkg-query -W -f='${source:Package}\t${source:Version}\t${binary:Package}\t${Version}\n' 2>/dev/null | awk -F '\t' -v ecosystem="$_ecosystem" '
function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); gsub(/\r/," ",s); return s }
{
name=$1; version=$2
if (name == "" || name == "-") { name=$3; version=$4 }
if (version == "" || version == "-") { version=$4 }
sub(/^src:/, "", name)
if (name == "" || version == "") next
key=name "|" version
if (seen[key]++) next
printf "{\"name\":\"%s\",\"version\":\"%s\",\"ecosystem\":\"%s\",\"manager\":\"dpkg\"}\n", esc(name), esc(version), esc(ecosystem)
}'
elif command -v rpm >/dev/null 2>&1; then
rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\n' 2>/dev/null | awk -F '\t' -v ecosystem="$_ecosystem" '
function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); gsub(/\r/," ",s); return s }
$1 != "" && $2 != "" {
key=$1 "|" $2
if (seen[key]++) next
printf "{\"name\":\"%s\",\"version\":\"%s\",\"ecosystem\":\"%s\",\"manager\":\"rpm\"}\n", esc($1), esc($2), esc(ecosystem)
}'
elif command -v apk >/dev/null 2>&1; then
apk info 2>/dev/null | while IFS= read -r _pkg_name; do
[ "$_pkg_name" ] || continue
_pkg_line="$(apk info -e -v "$_pkg_name" 2>/dev/null | head -n 1)"
_pkg_version="$(printf "%s" "$_pkg_line" | awk -v n="$_pkg_name" 'index($0, n "-") == 1 { print substr($0, length(n) + 2); exit }')"
[ "$_pkg_version" ] || continue
printf '{"name":"%s","version":"%s","ecosystem":"%s","manager":"apk"}\n' \
"$(linpeas_json_escape "$_pkg_name")" "$(linpeas_json_escape "$_pkg_version")" "$(linpeas_json_escape "$_ecosystem")"
done
elif command -v pacman >/dev/null 2>&1; then
pacman -Q 2>/dev/null | awk -v ecosystem="$_ecosystem" '
function esc(s) { gsub(/\\/,"\\\\",s); gsub(/"/,"\\\"",s); gsub(/\r/," ",s); return s }
$1 != "" && $2 != "" {
key=$1 "|" $2
if (seen[key]++) next
printf "{\"name\":\"%s\",\"version\":\"%s\",\"ecosystem\":\"%s\",\"manager\":\"pacman\"}\n", esc($1), esc($2), esc(ecosystem)
}'
fi
}
linpeas_packages_json(){
_limit="${HACKTRICKS_PACKAGE_LIMIT:-300}"
linpeas_print_package_json_lines | awk -v max="$_limit" '
BEGIN { first=1; printf "[" }
NF {
if (count >= max) next
if (!first) printf ","
printf "%s", $0
first=0
count++
}
END { printf "]" }'
}
linpeas_os_json(){
_os_id="$(linpeas_os_release_field ID)"
_os_name="$(linpeas_os_release_field PRETTY_NAME)"
_os_version_id="$(linpeas_os_release_field VERSION_ID)"
_os_codename="$(linpeas_os_release_field VERSION_CODENAME)"
printf '{"id":"%s","name":"%s","version_id":"%s","codename":"%s","kernel":{"release":"%s","version":"%s","arch":"%s"}}' \
"$(linpeas_json_escape "$_os_id")" \
"$(linpeas_json_escape "$_os_name")" \
"$(linpeas_json_escape "$_os_version_id")" \
"$(linpeas_json_escape "$_os_codename")" \
"$(linpeas_json_escape "$(uname -r 2>/dev/null)")" \
"$(linpeas_json_escape "$(uname -v 2>/dev/null)")" \
"$(linpeas_json_escape "$(uname -m 2>/dev/null)")"
}
linpeas_host_checker_payload(){
_hostname="$(hostname 2>/dev/null)"
if [ "$ONLINE_VULN_CHECKS" ]; then
printf '{"hostname":"%s","source":"linpeas","version":"%s","online_package_check":true,"os":%s,"packages":%s}' \
"$(linpeas_json_escape "$_hostname")" \
"$(linpeas_json_escape "$VERSION")" \
"$(linpeas_os_json)" \
"$(linpeas_packages_json)"
else
printf '{"hostname":"%s","source":"linpeas","version":"%s"}' \
"$(linpeas_json_escape "$_hostname")" \
"$(linpeas_json_escape "$VERSION")"
fi
}
check_external_hostname(){
INTERNET_SEARCH_TIMEOUT=15
_hacktricks_host_checker_url="${HACKTRICKS_HOST_CHECKER_URL:-https://tools.hacktricks.wiki/api/host-checker}"
_hacktricks_payload="$(linpeas_host_checker_payload)"
# wget or curl?
if command -v curl >/dev/null 2>&1; then
curl "https://tools.hacktricks.wiki/api/host-checker" -H "User-Agent: linpeas" -d "{\"hostname\":\"$(hostname)\"}" -H "Content-Type: application/json" --max-time "$INTERNET_SEARCH_TIMEOUT"
curl -s "$_hacktricks_host_checker_url" -H "User-Agent: linpeas" --data-binary "$_hacktricks_payload" -H "Content-Type: application/json" --max-time "$INTERNET_SEARCH_TIMEOUT"
elif command -v wget >/dev/null 2>&1; then
wget -q -O - "https://tools.hacktricks.wiki/api/host-checker" --header "User-Agent: linpeas" --post-data "{\"hostname\":\"$(hostname)\"}" -H "Content-Type: application/json" --timeout "$INTERNET_SEARCH_TIMEOUT"
wget -q -O - "$_hacktricks_host_checker_url" --header "User-Agent: linpeas" --header "Content-Type: application/json" --post-data "$_hacktricks_payload" --timeout "$INTERNET_SEARCH_TIMEOUT"
else
echo "wget or curl not found"
fi
@@ -8,19 +8,17 @@
# Functions Used:
# Global Variables:
# Initial Functions:
# Generated Global Variables: $url_lambda, $TIMEOUT_INTERNET_SECONDS_443_BIN
# Generated Global Variables: $url_443, $TIMEOUT_INTERNET_SECONDS_443_BIN
# Fat linpeas: 0
# Small linpeas: 1
check_tcp_443_bin () {
local TIMEOUT_INTERNET_SECONDS_443_BIN=$1
local url_lambda="https://tools.hacktricks.wiki/api/host-checker"
local url_443="https://1.1.1.1"
if command -v curl >/dev/null 2>&1; then
if curl -s --connect-timeout $TIMEOUT_INTERNET_SECONDS_443_BIN "$url_lambda" \
-H "User-Agent: linpeas" -H "Content-Type: application/json" \
-d "{\"hostname\":\"$(hostname)\"}" >/dev/null 2>&1
if curl -s -k --connect-timeout "$TIMEOUT_INTERNET_SECONDS_443_BIN" "$url_443" >/dev/null 2>&1
then
echo "Port 443 is accessible with curl"
return 0 # ✅ success
@@ -30,9 +28,7 @@ check_tcp_443_bin () {
fi
elif command -v wget >/dev/null 2>&1; then
if wget -q --timeout=$TIMEOUT_INTERNET_SECONDS_443_BIN -O - "$url_lambda" \
--header "User-Agent: linpeas" -H "Content-Type: application/json" \
--post-data "{\"hostname\":\"$(hostname)\"}" >/dev/null 2>&1
if wget -q --no-check-certificate --timeout="$TIMEOUT_INTERNET_SECONDS_443_BIN" -O - "$url_443" >/dev/null 2>&1
then
echo "Port 443 is accessible with wget"
return 0
@@ -8,7 +8,7 @@
# Functions Used:
# Global Variables:
# Initial Functions:
# Generated Global Variables: $VERSION, $ADVISORY, $IAMROOT, $MAXPATH_FIND_W, $C, $RED, $SED_RED, $GREEN, $SED_GREEN, $YELLOW, $SED_YELLOW, $RED_YELLOW, $SED_RED_YELLOW, $BLUE, $SED_BLUE, $ITALIC_BLUE, $LIGHT_MAGENTA, $SED_LIGHT_MAGENTA, $LIGHT_CYAN, $SED_LIGHT_CYAN, $LG, $SED_LG, $DG, $SED_DG, $NC, $UNDERLINED, $ITALIC, $MACPEAS, $FAST, $SUPERFAST, $DISCOVERY, $PORTS, $QUIET, $CHECKS, $MITRE_FILTER, $SEARCH_IN_FOLDER, $ROOT_FOLDER, $WAIT, $PASSWORD, $NOCOLOR, $DEBUG, $AUTO_NETWORK_SCAN, $EXTRA_CHECKS, $REGEXES, $PORT_FORWARD, $E, $PING, $FPING, $DISCOVER_BAN_BAD, $DISCOVER_BAN_GOOD, $SCAN_BAN_GOOD, $NMAP_GOOD, $SCRIPTNAME, $FOUND_BASH, $FOUND_NC, $HOMESEARCH, $GREPHOMESEARCH, $SCAN_BAN_BAD, $HOME, $THREADS, $opt, $HELP, $USER, $TOTAL_T1_TIME, $END_T1_TIME, $START_T1_TIME, $title, $title_len, $max_title_len, $rest_len, $CONT_THREADS, $wgroups, $SEDOVERFLOW, $Wfolders, $Wfolder, $grp, $END_T2_TIME, $TOTAL_T2_TIME, $START_T2_TIME, $_mitre_tag, $_mitre_filter, $_mitre_base, $_mitre_tags_left, $_mitre_filters_left
# Generated Global Variables: $VERSION, $ADVISORY, $IAMROOT, $MAXPATH_FIND_W, $C, $RED, $SED_RED, $GREEN, $SED_GREEN, $YELLOW, $SED_YELLOW, $RED_YELLOW, $SED_RED_YELLOW, $BLUE, $SED_BLUE, $ITALIC_BLUE, $LIGHT_MAGENTA, $SED_LIGHT_MAGENTA, $LIGHT_CYAN, $SED_LIGHT_CYAN, $LG, $SED_LG, $DG, $SED_DG, $NC, $UNDERLINED, $ITALIC, $MACPEAS, $FAST, $SUPERFAST, $DISCOVERY, $PORTS, $QUIET, $CHECKS, $MITRE_FILTER, $SEARCH_IN_FOLDER, $ROOT_FOLDER, $WAIT, $PASSWORD, $NOCOLOR, $DEBUG, $AUTO_NETWORK_SCAN, $EXTRA_CHECKS, $REGEXES, $PORT_FORWARD, $NOT_CHECK_EXTERNAL_HOSTNAME, $ONLINE_VULN_CHECKS, $E, $PING, $FPING, $DISCOVER_BAN_BAD, $DISCOVER_BAN_GOOD, $SCAN_BAN_GOOD, $NMAP_GOOD, $SCRIPTNAME, $FOUND_BASH, $FOUND_NC, $HOMESEARCH, $GREPHOMESEARCH, $SCAN_BAN_BAD, $HOME, $THREADS, $opt, $HELP, $USER, $TOTAL_T1_TIME, $END_T1_TIME, $START_T1_TIME, $title, $title_len, $max_title_len, $rest_len, $CONT_THREADS, $wgroups, $SEDOVERFLOW, $Wfolders, $Wfolder, $grp, $END_T2_TIME, $TOTAL_T2_TIME, $START_T2_TIME, $_mitre_tag, $_mitre_filter, $_mitre_base, $_mitre_tags_left, $_mitre_filters_left
# Fat linpeas: 0
# Small linpeas: 1
@@ -85,6 +85,7 @@ EXTRA_CHECKS=""
REGEXES=""
PORT_FORWARD=""
NOT_CHECK_EXTERNAL_HOSTNAME=""
ONLINE_VULN_CHECKS=""
THREADS="$( ( (grep -c processor /proc/cpuinfo 2>/dev/null) || ( (command -v lscpu >/dev/null 2>&1) && (lscpu | grep '^CPU(s):' | awk '{print $2}')) || echo -n 2) | tr -d "\n")"
[ "$THREADS" -eq "$THREADS" ] 2>/dev/null && : || THREADS="2" #If THREADS is not a number, put number 2
[ "$THREADS" -lt 1 ] 2>/dev/null && THREADS="2" #If THREADS is 0 or negative, put number 2 (avoids division-by-zero in eval_bckgrd)
@@ -97,6 +98,7 @@ ${NC}This tool enum and search possible misconfigurations$DG (known vulns, user,
${YELLOW} -s${BLUE} Stealth & faster (don't check some time consuming checks)
${YELLOW} -e${BLUE} Perform extra enumeration
${YELLOW} -r${BLUE} Enable Regexes (this can take from some mins to hours)
${YELLOW} -V${BLUE} Send package/kernel inventory to HackTricks for online vulnerability lookup
${YELLOW} -P${BLUE} Indicate a password that will be used to run 'sudo -l' and to bruteforce other users accounts via 'su'
${YELLOW} -n${BLUE} Do not check hostname & IP in known malicious lists and leaks
${YELLOW} -D${BLUE} Debug mode
@@ -123,10 +125,10 @@ ${NC}This tool enum and search possible misconfigurations$DG (known vulns, user,
${YELLOW} -N${BLUE} Do not use colours
${YELLOW} -z <N>${BLUE} Set number of threads for background checks (default: auto-detected CPU count, fallback: 2; must be >= 1)$NC"
while getopts ":h?asd:p:i:P:qo:T:LMwNDterf:F:z:" opt; do
while getopts ":h?asd:p:i:P:qo:T:LMwNDterVf:F:z:" opt; do
case "$opt" in
h|\?) printf "%s\n\n" "$HELP$NC"; exit 0;;
a) FAST="";EXTRA_CHECKS="1";;
a) FAST="";EXTRA_CHECKS="1";ONLINE_VULN_CHECKS="1";;
s) SUPERFAST=1;;
d) DISCOVERY=$OPTARG;;
p) PORTS=$OPTARG;;
@@ -144,6 +146,7 @@ while getopts ":h?asd:p:i:P:qo:T:LMwNDterf:F:z:" opt; do
t) AUTO_NETWORK_SCAN="1";;
e) EXTRA_CHECKS="1";;
r) REGEXES="1";;
V) ONLINE_VULN_CHECKS="1";;
f) SEARCH_IN_FOLDER=$OPTARG;
if ! [ "$(echo -n $SEARCH_IN_FOLDER | tail -c 1)" = "/" ]; then #Make sure firmware folder ends with "/"
SEARCH_IN_FOLDER="${SEARCH_IN_FOLDER}/";