mirror of
https://github.com/peass-ng/PEASS-ng.git
synced 2026-01-06 01:58:07 -08:00
Compare commits
34 Commits
20250525-b
...
update_PEA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f46172fab2 | ||
|
|
cc5ab76991 | ||
|
|
36001d644e | ||
|
|
fdd414f4aa | ||
|
|
c3e50dbdbf | ||
|
|
41128808a6 | ||
|
|
6fd96f4bdb | ||
|
|
a745f00dd7 | ||
|
|
933e12d7f1 | ||
|
|
4061cef7e8 | ||
|
|
b66ced3c63 | ||
|
|
cde725dacc | ||
|
|
f0f829890c | ||
|
|
99c36b8562 | ||
|
|
a74c6c820f | ||
|
|
53fd4d8dc8 | ||
|
|
9b37fd4ef4 | ||
|
|
f27b1d4816 | ||
|
|
d335b9254f | ||
|
|
d5e3c2a885 | ||
|
|
4af321d138 | ||
|
|
4e556fd594 | ||
|
|
39066f6867 | ||
|
|
c3a93a57fe | ||
|
|
f62d9fc550 | ||
|
|
11e9b8dde6 | ||
|
|
b9a9ad5ddf | ||
|
|
88f08a405e | ||
|
|
322792c4ec | ||
|
|
c150e63b52 | ||
|
|
7b8dcfbe8d | ||
|
|
aac3667247 | ||
|
|
64ab193d25 | ||
|
|
aab8241ede |
201
.github/workflows/PR-tests.yml
vendored
Normal file
201
.github/workflows/PR-tests.yml
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
name: PR-tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
|
||||
jobs:
|
||||
Build_and_test_winpeas_pr:
|
||||
runs-on: windows-latest
|
||||
|
||||
# environment variables
|
||||
env:
|
||||
Solution_Path: 'winPEAS\winPEASexe\winPEAS.sln'
|
||||
Configuration: 'Release'
|
||||
|
||||
steps:
|
||||
# checkout
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Download regexes
|
||||
run: |
|
||||
powershell.exe -ExecutionPolicy Bypass -File build_lists/download_regexes.ps1
|
||||
|
||||
# Add MSBuild to the PATH
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
|
||||
# Setup NuGet
|
||||
- name: Setup NuGet.exe
|
||||
uses: nuget/setup-nuget@v1
|
||||
|
||||
# Restore the packages for testing
|
||||
- name: Restore the application
|
||||
run: nuget restore $env:Solution_Path
|
||||
|
||||
# build
|
||||
- name: run MSBuild
|
||||
run: msbuild $env:Solution_Path
|
||||
|
||||
# Build all versions
|
||||
- name: Build all versions
|
||||
run: |
|
||||
echo "build x64"
|
||||
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x64"
|
||||
|
||||
echo "build x86"
|
||||
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x86"
|
||||
|
||||
echo "build Any CPU"
|
||||
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU"
|
||||
|
||||
- name: Execute winPEAS -h
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Configuration = "Release"
|
||||
$exePath = "winPEAS/winPEASexe/winPEAS/bin/$Configuration/winPEAS.exe"
|
||||
if (Test-Path $exePath) {
|
||||
& $exePath -h
|
||||
} else {
|
||||
Write-Error "winPEAS.exe not found at $exePath"
|
||||
}
|
||||
|
||||
- name: Execute winPEAS cloudinfo
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Configuration = "Release"
|
||||
$exePath = "winPEAS/winPEASexe/winPEAS/bin/$Configuration/winPEAS.exe"
|
||||
if (Test-Path $exePath) {
|
||||
& $exePath cloudinfo
|
||||
} else {
|
||||
Write-Error "winPEAS.exe not found at $exePath"
|
||||
}
|
||||
|
||||
- name: Execute winPEAS systeminfo
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Configuration = "Release"
|
||||
$exePath = "winPEAS/winPEASexe/winPEAS/bin/$Configuration/winPEAS.exe"
|
||||
if (Test-Path $exePath) {
|
||||
& $exePath systeminfo
|
||||
} else {
|
||||
Write-Error "winPEAS.exe not found at $exePath"
|
||||
}
|
||||
|
||||
- name: Execute winPEAS networkinfo
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Configuration = "Release"
|
||||
$exePath = "winPEAS/winPEASexe/winPEAS/bin/$Configuration/winPEAS.exe"
|
||||
if (Test-Path $exePath) {
|
||||
& $exePath networkinfo
|
||||
} else {
|
||||
Write-Error "winPEAS.exe not found at $exePath"
|
||||
}
|
||||
|
||||
Build_and_test_linpeas_pr:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Download repo
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
# Setup go
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17.0-rc1
|
||||
stable: false
|
||||
- run: go version
|
||||
|
||||
# Build linpeas
|
||||
- name: Build linpeas
|
||||
run: |
|
||||
python3 -m pip install PyYAML
|
||||
cd linPEAS
|
||||
python3 -m builder.linpeas_builder --all --output linpeas_fat.sh
|
||||
python3 -m builder.linpeas_builder --all-no-fat --output linpeas.sh
|
||||
python3 -m builder.linpeas_builder --small --output linpeas_small.sh
|
||||
|
||||
# Run linpeas help as quick test
|
||||
- name: Run linpeas help
|
||||
run: linPEAS/linpeas_fat.sh -h && linPEAS/linpeas.sh -h && linPEAS/linpeas_small.sh -h
|
||||
|
||||
# Run linpeas as a test
|
||||
- name: Run linpeas system_information
|
||||
run: linPEAS/linpeas_fat.sh -o system_information -a
|
||||
|
||||
- name: Run linpeas container
|
||||
run: linPEAS/linpeas_fat.sh -o container -a
|
||||
|
||||
- name: Run linpeas cloud
|
||||
run: linPEAS/linpeas_fat.sh -o cloud -a
|
||||
|
||||
- name: Run linpeas procs_crons_timers_srvcs_sockets
|
||||
run: linPEAS/linpeas_fat.sh -o procs_crons_timers_srvcs_sockets -a
|
||||
|
||||
- name: Run linpeas network_information
|
||||
run: linPEAS/linpeas_fat.sh -o network_information -t -a
|
||||
|
||||
- name: Run linpeas users_information
|
||||
run: linPEAS/linpeas_fat.sh -o users_information -a
|
||||
|
||||
- name: Run linpeas software_information
|
||||
run: linPEAS/linpeas_fat.sh -o software_information -a
|
||||
|
||||
- name: Run linpeas interesting_perms_files
|
||||
run: linPEAS/linpeas_fat.sh -o interesting_perms_files -a
|
||||
|
||||
- name: Run linpeas interesting_files
|
||||
run: linPEAS/linpeas_fat.sh -o interesting_files -a
|
||||
|
||||
Build_and_test_macpeas_pr:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
# Download repo
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
# Build linpeas (macpeas)
|
||||
- name: Build macpeas
|
||||
run: |
|
||||
python3 -m pip install PyYAML --break-system-packages
|
||||
python3 -m pip install requests --break-system-packages
|
||||
cd linPEAS
|
||||
python3 -m builder.linpeas_builder --all --output linpeas_fat.sh
|
||||
|
||||
# Run linpeas help as quick test
|
||||
- name: Run macpeas help
|
||||
run: linPEAS/linpeas_fat.sh -h
|
||||
|
||||
# Run macpeas parts to test it
|
||||
- name: Run macpeas system_information
|
||||
run: linPEAS/linpeas_fat.sh -o system_information -a
|
||||
|
||||
- name: Run macpeas container
|
||||
run: linPEAS/linpeas_fat.sh -o container -a
|
||||
|
||||
- name: Run macpeas cloud
|
||||
run: linPEAS/linpeas_fat.sh -o cloud -a
|
||||
|
||||
- name: Run macpeas procs_crons_timers_srvcs_sockets
|
||||
run: linPEAS/linpeas_fat.sh -o procs_crons_timers_srvcs_sockets -a
|
||||
|
||||
- name: Run macpeas network_information
|
||||
run: linPEAS/linpeas_fat.sh -o network_information -t -a
|
||||
|
||||
- name: Run macpeas users_information
|
||||
run: linPEAS/linpeas_fat.sh -o users_information -a
|
||||
|
||||
- name: Run macpeas software_information
|
||||
run: linPEAS/linpeas_fat.sh -o software_information -a
|
||||
@@ -96,7 +96,7 @@ bash /path/to/linpeas.sh -f /path/to/folder
|
||||
|
||||
The goal of this script is to search for possible **Privilege Escalation Paths** (tested in Debian, CentOS, FreeBSD, OpenBSD and MacOS).
|
||||
|
||||
This script doesn't have any dependency.
|
||||
This script doesn't have any dependency. It also detects unsafe patterns in privileged cron/systemd scripts that read process command lines (pgrep/ps), transform them into a command string, and execute it (for example, apache2ctl -t built from pgrep -lfa output), which can lead to root code execution.
|
||||
|
||||
It uses **/bin/sh** syntax, so can run in anything supporting `sh` (and the binaries and parameters used).
|
||||
|
||||
@@ -170,7 +170,7 @@ LinPEAS uses colors to indicate where does each section begin. But **it also use
|
||||
|
||||
- The  **Red** color is used for identifing suspicious configurations that could lead to privilege escalation.
|
||||
|
||||
- The  **Green** color is used for known good configurations (based on the name not on the conten!)
|
||||
- The  **Green** color is used for known good configurations (based on the name not on the content!)
|
||||
|
||||
- The  **Blue** color is used for: Users without shell & Mounted devices
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument('--small', action='store_true', help='Build small version of linpeas.')
|
||||
parser.add_argument('--include', type=str, help='Build linpeas only with the modules indicated you can indicate section names or module IDs).')
|
||||
parser.add_argument('--exclude', type=str, help='Exclude the given modules (you can indicate section names or module IDs).')
|
||||
parser.add_argument('--output', required=True, type=str, help='Parth to write the final linpeas file to.')
|
||||
parser.add_argument('--output', required=True, type=str, help='Path to write the final linpeas file to.')
|
||||
args = parser.parse_args()
|
||||
|
||||
all_modules = args.all
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# License: GNU GPL
|
||||
# Version: 1.0
|
||||
# Functions Used: echo_not_found, print_2title, print_info
|
||||
# Global Variables:
|
||||
# Global Variables: $NoEnvVars, $EnvVarsRed
|
||||
# Initial Functions:
|
||||
# Generated Global Variables:
|
||||
# Fat linpeas: 0
|
||||
@@ -35,5 +35,5 @@
|
||||
|
||||
print_2title "Environment"
|
||||
print_info "Any private information inside environment variables?"
|
||||
(env || printenv || set) 2>/dev/null | grep -v "RELEVANT*|FIND*|^VERSION=|dbuslistG|mygroups|ldsoconfdG|pwd_inside_history|kernelDCW_Ubuntu_Precise|kernelDCW_Ubuntu_Trusty|kernelDCW_Ubuntu_Xenial|kernelDCW_Rhel|^sudovB=|^rootcommon=|^mounted=|^mountG=|^notmounted=|^mountpermsB=|^mountpermsG=|^kernelB=|^C=|^RED=|^GREEN=|^Y=|^B=|^NC=|TIMEOUT=|groupsB=|groupsVB=|knw_grps=|sidG|sidB=|sidVB=|sidVB2=|sudoB=|sudoG=|sudoVB=|timersG=|capsB=|notExtensions=|Wfolders=|writeB=|writeVB=|_usrs=|compiler=|LS_COLORS=|pathshG=|notBackup=|processesDump|processesB|commonrootdirs|USEFUL_SOFTWARE|PSTORAGE_" | sed -${E} "s,[pP][aA][sS][sS][wW]|[aA][pP][iI][kK][eE][yY]|[aA][pP][iI][_][kK][eE][yY]|KRB5CCNAME,${SED_RED},g" || echo_not_found "env || set"
|
||||
(env || printenv || set) 2>/dev/null | grep -Eiv "$NoEnvVars" | sed -${E} "s,$EnvVarsRed,${SED_RED},g" || echo_not_found "env || set"
|
||||
echo ""
|
||||
@@ -0,0 +1,121 @@
|
||||
# Title: Processes & Cron & Services & Timers - Unsafe pgrep/ps → command execution
|
||||
# ID: PR_Unsafe_processlist_cmd_exec
|
||||
# Author: HT Bot
|
||||
# Last Update: 2025-08-27
|
||||
# Description: Detect privileged cron/systemd scripts that read process command lines (pgrep/ps),
|
||||
# transform them into a command string and execute it (e.g., cmd var / eval). This
|
||||
# catches patterns like the apache2ctl -t injection from pgrep -lfa found in HTB Zero.
|
||||
# License: GNU GPL
|
||||
# Version: 1.0
|
||||
# Functions Used: print_2title, print_info
|
||||
# Global Variables: $SEARCH_IN_FOLDER
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $candfile, $line, $file, $svc, $user, $exec, $pgrep_lines, $ps_lines, $exec_lines, $hint, $pattern_dollar
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Unsafe process-list command execution in privileged jobs"
|
||||
print_info "Looks for root cron/systemd scripts that build commands from pgrep/ps output and execute them (e.g., pgrep -lfa → var 'cmd' → exec/eval). If found, try forging a matching process argv to get code run as root."
|
||||
|
||||
candfile=$(mktemp 2>/dev/null || echo "/tmp/linpeas.candidates.$$")
|
||||
|
||||
# 1) Collect candidates from cron
|
||||
for f in /etc/crontab /etc/anacrontab /var/spool/cron/crontabs/root; do
|
||||
[ -r "$f" ] && cat "$f" 2>/dev/null | grep -vE '^[[:space:]]*#' | awk '{print $0}' || true
|
||||
done |
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
case "$line" in
|
||||
""|\#*) continue ;;
|
||||
esac
|
||||
# Extract absolute paths from the line
|
||||
echo "$line" | grep -oE '/[A-Za-z0-9_./-]+' 2>/dev/null | while IFS= read -r file; do
|
||||
[ -e "$file" ] && printf '%s\n' "$file" >>"$candfile"
|
||||
# Expand run-parts directories
|
||||
if echo "$line" | grep -qE '\brun-parts\b' && [ -d "$file" ]; then
|
||||
ls -1 "$file" 2>/dev/null | while IFS= read -r x; do
|
||||
[ -f "$file/$x" ] && printf '%s\n' "$file/$x" >>"$candfile"
|
||||
done
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Include files inside cron directories
|
||||
for d in /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly; do
|
||||
[ -d "$d" ] || continue
|
||||
find "$d" -maxdepth 1 -type f -readable 2>/dev/null >>"$candfile"
|
||||
done
|
||||
|
||||
# 2) Collect candidates from systemd (services running as root)
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl list-units --type=service --all 2>/dev/null | awk '{print $1}' | grep -E '\.service$' | while IFS= read -r svc; do
|
||||
user=$(systemctl show "$svc" -p User 2>/dev/null | cut -d= -f2)
|
||||
# Default user is root when empty; consider both empty and 'root'
|
||||
if [ -z "$user" ] || [ "$user" = "root" ]; then
|
||||
exec=$(systemctl show "$svc" -p ExecStart 2>/dev/null | cut -d= -f2-)
|
||||
# Extract absolute paths referenced in ExecStart
|
||||
printf '%s' "$exec" | grep -oE '/[A-Za-z0-9_./-]+' 2>/dev/null | while IFS= read -r file; do
|
||||
[ -e "$file" ] && printf '%s\n' "$file" >>"$candfile"
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# De-duplicate and trim to a reasonable number
|
||||
if [ -s "$candfile" ]; then
|
||||
sort -u "$candfile" | head -n 150 | while IFS= read -r file; do
|
||||
# Only plain text, readable files <= 500KB
|
||||
[ -r "$file" ] || continue
|
||||
[ -f "$file" ] || continue
|
||||
# Skip obvious binaries
|
||||
case "$(head -c 4 "$file" 2>/dev/null | od -An -t x1 | tr -d ' \n')" in
|
||||
7f454c46|cafebabe|feedface|feedfacf) continue;;
|
||||
esac
|
||||
[ $(wc -c <"$file" 2>/dev/null) -le 512000 ] || continue
|
||||
|
||||
# Look for pgrep/ps grabbing command lines
|
||||
pgrep_lines=$(grep -nE '\bpgrep\b[^\n]*\-(f|\-\-full)' "$file" 2>/dev/null)
|
||||
ps_lines=$(grep -nE '\bps\b[^\n]*\-o[[:space:]]*(pid,(cmd|args)|command)|\bps\b[^\n]*\-ef' "$file" 2>/dev/null)
|
||||
|
||||
[ -z "$pgrep_lines$ps_lines" ] && continue
|
||||
|
||||
# Look for building a command string and executing it
|
||||
exec_lines=""
|
||||
# variable execution via a variable named "cmd"
|
||||
pattern_dollar="\$"
|
||||
if grep -nE '^[[:space:]]*cmd *=.*' "$file" 2>/dev/null | grep -q '.'; then
|
||||
exec_lines=$(grep -nE "(^|[;&|][[:space:]]*)${pattern_dollar}cmd(\b|[[:space:]])" "$file" 2>/dev/null)
|
||||
fi
|
||||
# eval/bash -c patterns
|
||||
exec_lines=${exec_lines}
|
||||
exec_lines=$(printf '%s\n' "$exec_lines"; grep -nE '\beval\b[[:space:]]+"?\$?[A-Za-z_][A-Za-z0-9_]*' "$file" 2>/dev/null)
|
||||
exec_lines=$(printf '%s\n' "$exec_lines"; grep -nE '\b(bash|sh)\b[[:space:]]+\-c[[:space:]]+"?\$?[A-Za-z_][A-Za-z0-9_]*' "$file" 2>/dev/null)
|
||||
|
||||
[ -z "$exec_lines" ] && continue
|
||||
|
||||
echo "[!] Potentially vulnerable privileged script: $file"
|
||||
[ -n "$pgrep_lines" ] && echo "$pgrep_lines" | sed 's/^/ pgrep: /'
|
||||
[ -n "$ps_lines" ] && echo "$ps_lines" | sed 's/^/ ps: /'
|
||||
echo "$exec_lines" | sed 's/^/ exec: /'
|
||||
|
||||
# Extra hint if apache2ctl -t appears
|
||||
if grep -qE 'apache2ctl' "$file" 2>/dev/null && grep -qE '\-t(\b|[[:space:]])' "$file" 2>/dev/null; then
|
||||
hint=" hint: script references 'apache2ctl -t' — try forging argv via a fake process name to load attacker-controlled config (e.g., -d/-f)."
|
||||
echo "$hint"
|
||||
fi
|
||||
|
||||
echo
|
||||
done
|
||||
fi
|
||||
|
||||
rm -f "$candfile" 2>/dev/null
|
||||
else
|
||||
# Folder mode: best-effort regex scan within the provided directory (bounded)
|
||||
print_2title "Unsafe process-list command execution (folder scan)"
|
||||
print_info "Searching for scripts that read pgrep/ps output and execute a constructed command."
|
||||
find "${SEARCH_IN_FOLDER}" -type f -maxdepth 5 -size -512k 2>/dev/null \
|
||||
| xargs -I{} sh -c 'grep -qE "\\bpgrep\\b.*-(f|--full)|\\bps\\b.*-o[[:space:]]*(pid,(cmd|args)|command)|\\bps\\b.*-ef" "{}" 2>/dev/null && \
|
||||
grep -qE "(^|[;&|][[:space:]]*)\(\$[cC][mM][dD])(\\b|[[:space:]])|\\beval\\b|\\b(bash|sh)\\b[[:space:]]+-c" "{}" 2>/dev/null && echo "[!] Potential match: {}"' \
|
||||
| head -n 50
|
||||
echo
|
||||
fi
|
||||
@@ -8,7 +8,7 @@
|
||||
# Functions Used: check_dns, check_icmp, check_tcp_443, check_tcp_443_bin, check_tcp_80, print_2title, check_external_hostname
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $pid4, $pid2, $pid1, $pid3, $pid5, $NOT_CHECK_EXTERNAL_HOSTNAME, $TIMEOUT_INTERNET_SECONDS
|
||||
# Generated Global Variables: $pid4, $pid2, $pid1, $pid3, $$tcp443_bin_status, $NOT_CHECK_EXTERNAL_HOSTNAME, $TIMEOUT_INTERNET_SECONDS
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 0
|
||||
|
||||
@@ -19,24 +19,30 @@ print_2title "Internet Access?"
|
||||
TIMEOUT_INTERNET_SECONDS=5
|
||||
|
||||
if [ "$SUPERFAST" ]; then
|
||||
TIMEOUT_INTERNET_SECONDS=2
|
||||
TIMEOUT_INTERNET_SECONDS=2.5
|
||||
fi
|
||||
|
||||
|
||||
# Run all checks in background
|
||||
check_tcp_80 2>/dev/null & pid1=$!
|
||||
check_tcp_443 2>/dev/null & pid2=$!
|
||||
check_tcp_443_bin 2>/dev/null & pid3=$!
|
||||
check_icmp 2>/dev/null & pid4=$!
|
||||
check_dns 2>/dev/null & pid5=$!
|
||||
check_tcp_80 "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid1=$!
|
||||
check_tcp_443 "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid2=$!
|
||||
check_icmp "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid3=$!
|
||||
check_dns "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid4=$!
|
||||
|
||||
# Kill all after 10 seconds
|
||||
(sleep $TIMEOUT_INTERNET_SECONDS && kill -9 $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null) &
|
||||
(sleep $(( $TIMEOUT_INTERNET_SECONDS + 1 )) && kill -9 $pid1 $pid2 $pid3 $pid4 2>/dev/null) &
|
||||
|
||||
check_tcp_443_bin $TIMEOUT_INTERNET_SECONDS 2>/dev/null
|
||||
tcp443_bin_status=$?
|
||||
|
||||
wait $pid1 $pid2 $pid3 $pid4 2>/dev/null
|
||||
|
||||
|
||||
# Wait for all to finish
|
||||
wait $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
|
||||
wait 2>/dev/null
|
||||
|
||||
if ! [ "$SUPERFAST" ] && ! [ "$NOT_CHECK_EXTERNAL_HOSTNAME" ]; then
|
||||
if [ "$tcp443_bin_status" -eq 0 ] && \
|
||||
[ -z "$SUPERFAST" ] && [ -z "$NOT_CHECK_EXTERNAL_HOSTNAME" ]; then
|
||||
echo ""
|
||||
print_2title "Is hostname malicious or leaked?"
|
||||
print_info "This will check the public IP and hostname in known malicious lists and leaks to find any relevant information about the host."
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# Functions Used: print_2title
|
||||
# Global Variables: $DEBUG, $knw_usrs, $nosh_usrs, $sh_usrs, $DEBUG, $USER, $STRINGS
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $mysqluser, $mysqlexec, $mysqlconnect, $mysqlconnectnopass
|
||||
# Generated Global Variables: $mysqluser, $mysqlexec, $mysqlconnect, $mysqlconnectnopass, $mysqluser, $version_output, $major_version, $version, $process_info
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
@@ -102,4 +102,42 @@ if [ "$(command -v mysql || echo -n '')" ] || [ "$(command -v mysqladmin || echo
|
||||
else echo_no
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
### This section checks if MySQL (mysqld) is running as root and if its version is 4.x or 5.x to refer a known local privilege escalation exploit! ###
|
||||
|
||||
# Find the mysqld process
|
||||
process_info=$(ps aux | grep '[m]ysqld' | head -n1)
|
||||
|
||||
if [ -z "$process_info" ]; then
|
||||
echo "MySQL process not found." | sed -${E} "s,.*,${SED_GREEN},"
|
||||
else
|
||||
|
||||
# Extract the process user
|
||||
mysqluser=$(echo "$process_info" | awk '{print $1}')
|
||||
|
||||
# Get the MySQL version string
|
||||
version_output=$(mysqld --version 2>&1)
|
||||
|
||||
# Extract the version number (expects format like X.Y.Z)
|
||||
version=$(echo "$version_output" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
echo "Unable to determine MySQL version." | sed -${E} "s,.*,${SED_GREEN},"
|
||||
else
|
||||
|
||||
# Extract the major version number (X from X.Y.Z)
|
||||
major_version=$(echo "$version" | cut -d. -f1)
|
||||
|
||||
# Check if MySQL is running as root and if the version is either 4.x or 5.x
|
||||
if [ "$mysqluser" = "root" ] && { [ "$major_version" -eq 4 ] || [ "$major_version" -eq 5 ]; }; then
|
||||
echo "MySQL is running as root with version $version. This is a potential local privilege escalation vulnerability!" | sed -${E} "s,.*,${SED_RED},"
|
||||
echo "\tRefer to: https://www.exploit-db.com/exploits/1518" | sed -${E} "s,.*,${SED_YELLOW},"
|
||||
echo "\tRefer to: https://medium.com/r3d-buck3t/privilege-escalation-with-mysql-user-defined-functions-996ef7d5ceaf" | sed -${E} "s,.*,${SED_YELLOW},"
|
||||
else
|
||||
echo "MySQL is running as user '$mysqluser' with version $version." | sed -${E} "s,.*,${SED_GREEN},"
|
||||
fi
|
||||
### ------------------------------------------------------------------------------------------------------------------------------------------------ ###
|
||||
|
||||
fi
|
||||
fi
|
||||
@@ -0,0 +1,22 @@
|
||||
# Title: Interesting Files - Interesting Environment Variables
|
||||
# ID: IF_Interesting_environment_variables
|
||||
# Author: Jack Vaughn
|
||||
# Last Update: 25-05-2025
|
||||
# Description: Searching possible sensitive environment variables inside of /proc/*/environ
|
||||
# License: GNU GPL
|
||||
# Version: 1.0
|
||||
# Functions Used: print_2title
|
||||
# Global Variables: $MACPEAS, $NoEnvVars, $EnvVarsRed
|
||||
# Initial Functions:
|
||||
# Generated Global Variables:
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
if [ -z "$MACPEAS" ]; then
|
||||
print_2title "Checking all env variables in /proc/*/environ removing duplicates and filtering out useless env vars"
|
||||
cat /proc/[0-9]*/environ 2>/dev/null | \
|
||||
tr '\0' '\n' | \
|
||||
grep -Eiv "$NoEnvVars" | \
|
||||
sort -u | \
|
||||
sed -${E} "s,$EnvVarsRed,${SED_RED},g"
|
||||
fi
|
||||
@@ -8,25 +8,19 @@
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $pid, $pids
|
||||
# Generated Global Variables: $TIMEOUT_INTERNET_SECONDS_DNS, $local_pid
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
|
||||
check_dns(){
|
||||
local TIMEOUT_INTERNET_SECONDS_DNS=$1
|
||||
if ! [ -f "/bin/bash" ]; then
|
||||
echo " /bin/bash not found"
|
||||
return
|
||||
fi
|
||||
|
||||
/bin/bash -c '
|
||||
for ip in 1.1.1.1 8.8.8.8 ; do
|
||||
(( echo cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001 | xxd -p -r >&3; dd bs=9000 count=1 <&3 2>/dev/null | xxd ) 3>/dev/udp/$ip/53 && echo "DNS available" && exit 0) &
|
||||
pids+=($!)
|
||||
done
|
||||
for pid in ${pids[@]}; do
|
||||
wait $pid && exit 0
|
||||
done
|
||||
echo "DNS not available"
|
||||
' 2>/dev/null | grep "available" || echo "DNS not available"
|
||||
# example.com
|
||||
(bash -c '((( echo cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001 | xxd -p -r >&3; dd bs=9000 count=1 <&3 2>/dev/null | xxd ) 3>/dev/udp/1.1.1.1/53 && echo "DNS accessible") | grep "accessible" && exit 0 ) 2>/dev/null || echo "DNS is not accessible"') & local_pid=$!
|
||||
|
||||
sleep $TIMEOUT_INTERNET_SECONDS_DNS && kill -9 $local_pid 2>/dev/null && echo "DNS is not accessible"
|
||||
}
|
||||
@@ -8,11 +8,20 @@
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables:
|
||||
# Generated Global Variables: $TIMEOUT_INTERNET_SECONDS_ICMP, $local_pid
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
|
||||
check_icmp(){
|
||||
(ping -c 1 1.1.1.1 | grep -E "1 received|1 packets received" && echo "Ping is available" || echo "Ping is not available" 2>/dev/null) | grep -i "available"
|
||||
local TIMEOUT_INTERNET_SECONDS_ICMP=$1
|
||||
if ! [ "$(command -v ping 2>/dev/null || echo -n '')" ]; then
|
||||
echo " ping not found"
|
||||
return
|
||||
fi
|
||||
|
||||
# example.com
|
||||
((ping -c 1 1.1.1.1 2>/dev/null | grep -Ei "1 received|1 packets received" && echo "ICMP is accessible" || echo "ICMP is not accessible" 2>/dev/null) | grep "accessible" && exit 0 ) 2>/dev/null || echo "ICMP is not accessible" & local_pid=$!
|
||||
|
||||
sleep $TIMEOUT_INTERNET_SECONDS_ICMP && kill -9 $local_pid 2>/dev/null && echo "ICMP is not accessible"
|
||||
}
|
||||
@@ -8,30 +8,21 @@
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $pid, $pids
|
||||
# Generated Global Variables: $local_pid, $TIMEOUT_INTERNET_SECONDS_443
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
|
||||
|
||||
check_tcp_443(){
|
||||
local TIMEOUT_INTERNET_SECONDS_443=$1
|
||||
if ! [ -f "/bin/bash" ]; then
|
||||
echo " /bin/bash not found"
|
||||
return
|
||||
fi
|
||||
|
||||
/bin/bash -c '
|
||||
for ip in 1.1.1.1 8.8.8.8; do
|
||||
(echo >/dev/tcp/$ip/443 && echo "Port 443 is accessible" && exit 0) &
|
||||
pids+=($!)
|
||||
done
|
||||
for pid in ${pids[@]}; do
|
||||
wait $pid && exit 0
|
||||
done
|
||||
echo "Port 80 is not accessible"
|
||||
' 2>/dev/null | grep "accessible" || echo "Port 80 is not accessible"
|
||||
# example.com
|
||||
(bash -c '(echo >/dev/tcp/104.18.74.230/443 2>/dev/null && echo "Port 443 is accessible" && exit 0) 2>/dev/null || echo "Port 443 is not accessible"') & local_pid=$!
|
||||
|
||||
sleep $TIMEOUT_INTERNET_SECONDS_443 && kill -9 $local_pid 2>/dev/null && echo "Port 443 is not accessible"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,16 +8,39 @@
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables:
|
||||
# Generated Global Variables: $url_lambda, $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://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/"
|
||||
|
||||
check_tcp_443_bin(){
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -s "https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/" -H "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1 && echo "Port 443 is accessible with curl" || echo "Port 443 is not accessible with curl"
|
||||
if curl -s --connect-timeout $TIMEOUT_INTERNET_SECONDS_443_BIN "$url_lambda" \
|
||||
-H "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1
|
||||
then
|
||||
echo "Port 443 is accessible with curl"
|
||||
return 0 # ✅ success
|
||||
else
|
||||
echo "Port 443 is not accessible with curl"
|
||||
return 1
|
||||
fi
|
||||
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O - "https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/" --header "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1 && echo "Port 443 is accessible with wget" || echo "Port 443 is not accessible with wget"
|
||||
if wget -q --timeout=$TIMEOUT_INTERNET_SECONDS_443_BIN -O - "$url_lambda" \
|
||||
--header "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1
|
||||
then
|
||||
echo "Port 443 is accessible with wget"
|
||||
return 0
|
||||
else
|
||||
echo "Port 443 is not accessible with wget"
|
||||
return 1
|
||||
fi
|
||||
|
||||
else
|
||||
echo "Neither curl nor wget available"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,25 +8,21 @@
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $pid, $pids
|
||||
# Generated Global Variables: $local_pid, $TIMEOUT_INTERNET_SECONDS_80
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
|
||||
|
||||
check_tcp_80(){
|
||||
local TIMEOUT_INTERNET_SECONDS_80=$1
|
||||
if ! [ -f "/bin/bash" ]; then
|
||||
echo " /bin/bash not found"
|
||||
return
|
||||
fi
|
||||
|
||||
/bin/bash -c '
|
||||
for ip in 1.1.1.1 8.8.8.8; do
|
||||
(echo >/dev/tcp/$ip/80 && echo "Port 80 is accessible" && exit 0) &
|
||||
pids+=($!)
|
||||
done
|
||||
for pid in ${pids[@]}; do
|
||||
wait $pid && exit 0
|
||||
done
|
||||
echo "Port 80 is not accessible"
|
||||
' 2>/dev/null | grep "accessible"
|
||||
# example.com
|
||||
(bash -c '(echo >/dev/tcp/104.18.74.230/80 2>/dev/null && echo "Port 80 is accessible" && exit 0) 2>/dev/null || echo "Port 80 is not accessible"') & local_pid=$!
|
||||
|
||||
sleep $TIMEOUT_INTERNET_SECONDS_80 && kill -9 $local_pid 2>/dev/null && echo "Port 80 is not accessible"
|
||||
}
|
||||
18
linPEAS/builder/linpeas_parts/variables/EnvVarsRed.sh
Normal file
18
linPEAS/builder/linpeas_parts/variables/EnvVarsRed.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
# Title: Variables - EnvVarsRed
|
||||
# ID: EnvVarsRed
|
||||
# Author: Carlos Polop
|
||||
# Last Update: 26-05-2025
|
||||
# Description: Useless env vars
|
||||
# License: GNU GPL
|
||||
# Version: 1.0
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $EnvVarsRed
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
|
||||
EnvVarsRed="[pP][aA][sS][sS][wW]|[aA][pP][iI][kK][eE][yY]|[aA][pP][iI][_][kK][eE][yY]|KRB5CCNAME|[aA][pP][iI][_][kK][eE][yY]|[aA][wW][sS]|[aA][zZ][uU][rR][eE]|[gG][cC][pP]|[aA][pP][iI]|[sS][eE][cC][rR][eE][tT]|[sS][qQ][lL]|[dD][aA][tT][aA][bB][aA][sS][eE]|[tT][oO][kK][eE][nN]"
|
||||
|
||||
|
||||
16
linPEAS/builder/linpeas_parts/variables/NoEnvVars.sh
Normal file
16
linPEAS/builder/linpeas_parts/variables/NoEnvVars.sh
Normal file
@@ -0,0 +1,16 @@
|
||||
# Title: Variables - NoEnvVars
|
||||
# ID: NoEnvVars
|
||||
# Author: Carlos Polop
|
||||
# Last Update: 26-05-2025
|
||||
# Description: Useless env vars
|
||||
# License: GNU GPL
|
||||
# Version: 1.0
|
||||
# Functions Used:
|
||||
# Global Variables:
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $NoEnvVars
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
|
||||
NoEnvVars="LESS_TERMCAP|JOURNAL_STREAM|XDG_SESSION|DBUS_SESSION|systemd\/sessions|systemd_exec|MEMORY_PRESSURE_WATCH|RELEVANT*|FIND*|^VERSION=|dbuslistG|mygroups|ldsoconfdG|pwd_inside_history|kernelDCW_Ubuntu_Precise|kernelDCW_Ubuntu_Trusty|kernelDCW_Ubuntu_Xenial|kernelDCW_Rhel|^sudovB=|^rootcommon=|^mounted=|^mountG=|^notmounted=|^mountpermsB=|^mountpermsG=|^kernelB=|^C=|^RED=|^GREEN=|^Y=|^B=|^NC=|TIMEOUT=|groupsB=|groupsVB=|knw_grps=|sidG|sidB=|sidVB=|sidVB2=|sudoB=|sudoG=|sudoVB=|timersG=|capsB=|notExtensions=|Wfolders=|writeB=|writeVB=|_usrs=|compiler=|LS_COLORS=|pathshG=|notBackup=|processesDump|processesB|commonrootdirs|USEFUL_SOFTWARE|PSTORAGE_|^PATH=|^INVOCATION_ID=|^WATCHDOG_PID=|^LISTEN_PID="
|
||||
@@ -292,9 +292,12 @@ class LinpeasBaseBuilder:
|
||||
all_module_paths += self.enumerate_directory(LINPEAS_PARTS["variables"])
|
||||
|
||||
for module in LINPEAS_PARTS["modules"]:
|
||||
exclude = False
|
||||
for ex_module in exclude_modules:
|
||||
if ex_module in module["folder_path"] or ex_module in [module["name"], module["name_check"]]:
|
||||
continue
|
||||
exclude = True
|
||||
break
|
||||
if exclude: continue
|
||||
all_module_paths += self.enumerate_directory(module["folder_path"])
|
||||
|
||||
for module in all_module_paths:
|
||||
|
||||
@@ -97,7 +97,7 @@ class LinpeasBuilder:
|
||||
for orig_url in urls:
|
||||
tar_gz_bin_name = ""
|
||||
if ",,," in orig_url:
|
||||
tar_gz_bin_name = url.split(",,,")[1]
|
||||
tar_gz_bin_name = orig_url.split(",,,")[1]
|
||||
url = orig_url.split(",,,")[0]
|
||||
else:
|
||||
url = orig_url
|
||||
@@ -402,9 +402,9 @@ class LinpeasBuilder:
|
||||
|
||||
|
||||
def __replace_mark(self, mark: str, find_calls: list, join_char: str):
|
||||
"""Substitude the markup with the actual code"""
|
||||
|
||||
self.linpeas_sh = self.linpeas_sh.replace(mark, join_char.join(find_calls)) #New line char is't needed
|
||||
"""Substitute the markup with the actual code"""
|
||||
|
||||
self.linpeas_sh = self.linpeas_sh.replace(mark, join_char.join(find_calls)) #New line char isn't needed
|
||||
|
||||
def write_linpeas(self, path):
|
||||
"""Write on disk the final linpeas"""
|
||||
|
||||
@@ -106,8 +106,6 @@ def parse_line(line: str):
|
||||
|
||||
global FINAL_JSON, C_SECTION, C_MAIN_SECTION, C_2_SECTION, C_3_SECTION
|
||||
|
||||
if "Cron jobs" in line:
|
||||
a=1
|
||||
|
||||
if is_section(line, TITLE1_PATTERN):
|
||||
title = parse_title(line)
|
||||
@@ -145,17 +143,26 @@ def parse_line(line: str):
|
||||
|
||||
|
||||
def parse_peass(outputpath: str, jsonpath: str = ""):
|
||||
global OUTPUT_PATH, JSON_PATH
|
||||
global OUTPUT_PATH, JSON_PATH, FINAL_JSON, C_SECTION, C_MAIN_SECTION, C_2_SECTION, C_3_SECTION
|
||||
|
||||
OUTPUT_PATH = outputpath
|
||||
JSON_PATH = jsonpath
|
||||
|
||||
for line in open(OUTPUT_PATH, 'r', encoding="utf8").readlines():
|
||||
line = line.strip()
|
||||
if not line or not clean_colors(line): #Remove empty lines or lines just with colors hex
|
||||
continue
|
||||
# Reset globals to avoid data leaking between executions
|
||||
FINAL_JSON = {}
|
||||
C_SECTION = FINAL_JSON
|
||||
C_MAIN_SECTION = FINAL_JSON
|
||||
C_2_SECTION = FINAL_JSON
|
||||
C_3_SECTION = FINAL_JSON
|
||||
|
||||
parse_line(line)
|
||||
with open(OUTPUT_PATH, 'r', encoding="utf8") as f:
|
||||
for line in f.readlines():
|
||||
line = line.strip()
|
||||
# Remove empty lines or lines containing only color codes
|
||||
if not line or not clean_colors(line):
|
||||
continue
|
||||
|
||||
parse_line(line)
|
||||
|
||||
if JSON_PATH:
|
||||
with open(JSON_PATH, "w") as f:
|
||||
|
||||
@@ -512,7 +512,7 @@ namespace winPEAS.Checks
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(resolutionInfo.Error))
|
||||
{
|
||||
Beaprint.BadPrint($" {resolutionInfo.Error}");
|
||||
Beaprint.PrintException($" {resolutionInfo.Error}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -102,17 +102,15 @@ namespace winPEAS.Checks
|
||||
{
|
||||
vulnHandlers = ProcessesInfo.GetVulnHandlers(progress);
|
||||
}
|
||||
Dictionary<string, string> colors = new Dictionary<string, string>();
|
||||
colors[Checks.CurrentUserName] = Beaprint.ansi_color_bad;
|
||||
colors[HandlesHelper.elevatedProcess] = Beaprint.ansi_color_bad;
|
||||
|
||||
foreach (Dictionary<string, string> handler in vulnHandlers)
|
||||
{
|
||||
Dictionary<string, string> colors = new Dictionary<string, string>()
|
||||
{
|
||||
{ Checks.CurrentUserName, Beaprint.ansi_color_bad },
|
||||
{ handler["Reason"], Beaprint.ansi_color_bad },
|
||||
};
|
||||
|
||||
Beaprint.DictPrint(vulnHandlers, colors, true);
|
||||
colors[handler["Reason"]] = Beaprint.ansi_color_bad;
|
||||
}
|
||||
Beaprint.DictPrint(vulnHandlers, colors, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace winPEAS.Helpers
|
||||
public static string ansi_current_user = MAGENTA;
|
||||
|
||||
private static string Advisory =
|
||||
"winpeas should be used for authorized penetration testing and/or educational purposes only." +
|
||||
"winpeas should be used for authorized penetration testing and/or educational purposes only. " +
|
||||
"Any misuse of this software will not be the responsibility of the author or of any other collaborator. " +
|
||||
"Use it at your own devices and/or with the device owner's permission.";
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace winPEAS.Helpers
|
||||
/---------------------------------------------------------------------------------\
|
||||
| {1}Do you like PEASS?{0} |
|
||||
|---------------------------------------------------------------------------------|
|
||||
| {3}Learn Cloud Hacking{0} : {2}training.hacktricks.xyz {0} |
|
||||
| {3}Learn Cloud Hacking{0} : {2}training.hacktricks.xyz {0} |
|
||||
| {3}Follow on Twitter{0} : {2}@hacktricks_live{0} |
|
||||
| {3}Respect on HTB{0} : {2}SirBroccoli {0} |
|
||||
|---------------------------------------------------------------------------------|
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace winPEAS.Helpers
|
||||
private const int CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64;
|
||||
public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
|
||||
public const int DUPLICATE_SAME_ACCESS = 0x2;
|
||||
public const string elevatedProcess = "Access denied, process is probably elevated";
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct FILE_NAME_INFO
|
||||
@@ -171,7 +172,7 @@ namespace winPEAS.Helpers
|
||||
// Hex perms from https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights and https://github.com/buffer/maltracer/blob/master/defines.py
|
||||
|
||||
//PROCESS_ALL_ACCESS
|
||||
if ((h.GrantedAccess & 0x001F0FFF) == h.GrantedAccess)
|
||||
if ((h.GrantedAccess & 0x001F0FFF) == h.GrantedAccess || (h.GrantedAccess & 0x1FFFFF) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "PROCESS_ALL_ACCESS";
|
||||
@@ -454,6 +455,8 @@ namespace winPEAS.Helpers
|
||||
}
|
||||
catch
|
||||
{
|
||||
data["name"] = elevatedProcess;
|
||||
data["sid"] = elevatedProcess;
|
||||
return data;
|
||||
}
|
||||
finally
|
||||
@@ -469,12 +472,32 @@ namespace winPEAS.Helpers
|
||||
public static PT_RELEVANT_INFO getProcInfoById(int pid)
|
||||
{
|
||||
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||
Process proc;
|
||||
|
||||
Process proc = Process.GetProcessById(pid);
|
||||
try
|
||||
{
|
||||
proc = Process.GetProcessById(pid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
pri.pid = pid;
|
||||
pri.name = "Error, process may not exist";
|
||||
pri.userName = "Error, process may not exist";
|
||||
pri.userSid = "Error, process may not exist";
|
||||
pri.imagePath = "Error, process may not exist";
|
||||
return pri;
|
||||
}
|
||||
Dictionary<string, string> user = GetProcU(proc);
|
||||
|
||||
StringBuilder fileName = new StringBuilder(2000);
|
||||
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
|
||||
|
||||
try
|
||||
{
|
||||
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
|
||||
}
|
||||
catch
|
||||
{
|
||||
fileName = new StringBuilder(elevatedProcess);
|
||||
}
|
||||
|
||||
pri.pid = pid;
|
||||
pri.name = proc.ProcessName;
|
||||
|
||||
@@ -195,11 +195,11 @@ namespace winPEAS.Info.ProcessInfo
|
||||
continue;
|
||||
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(sFilePath, Checks.Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||
IdentityReference sid = null;
|
||||
try
|
||||
{
|
||||
System.Security.AccessControl.FileSecurity fs = System.IO.File.GetAccessControl(sFilePath);
|
||||
IdentityReference sid = fs.GetOwner(typeof(SecurityIdentifier));
|
||||
string ownerName = sid.Translate(typeof(NTAccount)).ToString();
|
||||
sid = fs.GetOwner(typeof(SecurityIdentifier));
|
||||
|
||||
// If current user already have permissions over that file or the proc belongs to the owner of the file,
|
||||
// handler not interesting to elevate privs
|
||||
@@ -207,6 +207,8 @@ namespace winPEAS.Info.ProcessInfo
|
||||
continue;
|
||||
|
||||
to_add["File Path"] = sFilePath;
|
||||
|
||||
string ownerName = sid.Translate(typeof(NTAccount)).ToString();
|
||||
to_add["File Owner"] = ownerName;
|
||||
}
|
||||
catch (System.IO.FileNotFoundException)
|
||||
@@ -218,7 +220,10 @@ namespace winPEAS.Info.ProcessInfo
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
catch (System.Security.Principal.IdentityNotMappedException)
|
||||
{
|
||||
to_add["File Owner"] = sid.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "key")
|
||||
|
||||
Reference in New Issue
Block a user