mirror of
https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite.git
synced 2026-02-10 06:36:36 +00:00
Compare commits
38 Commits
20250524-a
...
update_PEA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91278660b8 | ||
|
|
36001d644e | ||
|
|
fdd414f4aa | ||
|
|
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 | ||
|
|
65b98d11ac | ||
|
|
1e72dbeb76 | ||
|
|
c9282b4bdb | ||
|
|
b91334e5b3 | ||
|
|
b7bc20a027 | ||
|
|
4fbe6ffd79 |
11
.github/workflows/CI-master_tests.yml
vendored
11
.github/workflows/CI-master_tests.yml
vendored
@@ -99,6 +99,17 @@ jobs:
|
||||
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"
|
||||
}
|
||||
|
||||
# Copy the built versions
|
||||
- name: Copy all versions
|
||||
run: |
|
||||
|
||||
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
|
||||
@@ -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,103 @@
|
||||
# Title: Processes & Cron & Services & Timers - r-commands trust (rsh/rlogin/rexec)
|
||||
# ID: PR_RCommands_trust
|
||||
# Author: HT Bot
|
||||
# Last Update: 25-08-2025
|
||||
# Description: Detect hostname-based trust for Berkeley r-commands and active listeners; warn about DNS-assisted abuse.
|
||||
# License: GNU GPL
|
||||
# Version: 1.0
|
||||
# Functions Used: print_2title, print_3title, print_list, print_info, echo_no
|
||||
# Global Variables: $SEARCH_IN_FOLDER, $E, $SED_RED, $SED_RED_YELLOW
|
||||
# Initial Functions:
|
||||
# Generated Global Variables: $rhosts_found, $rsvc_listeners, $homes, $h, $f, $found
|
||||
# Fat linpeas: 0
|
||||
# Small linpeas: 1
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Berkeley r-commands trust (rsh/rlogin/rexec)"
|
||||
print_info "https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#r-commands-rlogin-rsh-rexec"
|
||||
|
||||
rhosts_found=""
|
||||
|
||||
# 1) Trust files: /etc/hosts.equiv and per-user ~/.rhosts
|
||||
print_list "Trust files (.rhosts / hosts.equiv)? ... "
|
||||
(
|
||||
# /etc/hosts.equiv
|
||||
if [ -r "/etc/hosts.equiv" ]; then
|
||||
printf "\n/etc/hosts.equiv (perm: %s)\n" "$(stat -c %a /etc/hosts.equiv 2>/dev/null || stat -f %p /etc/hosts.equiv 2>/dev/null)"
|
||||
# highlight risky entries: '+' or hosts granting any user
|
||||
sed -n "1,200p" /etc/hosts.equiv 2>/dev/null | sed -${E} "s,^\s*\+.*$,${SED_RED},; s,\s+\s*$,${SED_RED},"
|
||||
rhosts_found=1
|
||||
fi
|
||||
|
||||
# Per-user .rhosts from passwd
|
||||
# Use getent if available, else parse /etc/passwd
|
||||
homes=$( (getent passwd 2>/dev/null || cat /etc/passwd 2>/dev/null) | awk -F: '{print $6}' | sort -u )
|
||||
for h in $homes; do
|
||||
f="$h/.rhosts"
|
||||
if [ -r "$f" ]; then
|
||||
printf "\n%s (perm: %s)\n" "$f" "$(stat -c %a "$f" 2>/dev/null || stat -f %p "$f" 2>/dev/null)"
|
||||
sed -n "1,200p" "$f" 2>/dev/null | sed -${E} "s,^\s*\+.*$,${SED_RED},; s,\s+\s*$,${SED_RED},"
|
||||
rhosts_found=1
|
||||
fi
|
||||
done
|
||||
|
||||
# Common root path fallback
|
||||
if [ -r "/root/.rhosts" ] && ! echo "$homes" | grep -q "^/root$"; then
|
||||
printf "\n/root/.rhosts (perm: %s)\n" "$(stat -c %a /root/.rhosts 2>/dev/null || stat -f %p /root/.rhosts 2>/dev/null)"
|
||||
sed -n "1,200p" /root/.rhosts 2>/dev/null | sed -${E} "s,^\s*\+.*$,${SED_RED},; s,\s+\s*$,${SED_RED},"
|
||||
rhosts_found=1
|
||||
fi
|
||||
|
||||
[ "$rhosts_found" ] || echo_no
|
||||
) 2>/dev/null
|
||||
|
||||
# 2) r-commands listeners (512 exec/rexec, 513 rlogin, 514 rsh)
|
||||
print_list "Are r-commands listening? ............ "
|
||||
rsvc_listeners=""
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
ss -tlpn 2>/dev/null | awk 'NR==1 || $4 ~ /:(512|513|514)$/ {print}' | sed -n '2,200p' | sed -${E} "s,.*,${SED_RED_YELLOW}," && rsvc_listeners=1
|
||||
elif command -v netstat >/dev/null 2>&1; then
|
||||
netstat -tlpn 2>/dev/null | awk 'NR==1 || $4 ~ /:(512|513|514)$/ {print}' | sed -n '2,200p' | sed -${E} "s,.*,${SED_RED_YELLOW}," && rsvc_listeners=1
|
||||
fi
|
||||
[ "$rsvc_listeners" ] || echo_no
|
||||
|
||||
# 3) inetd/xinetd/systemd configuration hints
|
||||
print_list "rsh/rlogin/rexec enabled in inetd/xinetd? "
|
||||
(
|
||||
found=""
|
||||
[ -r /etc/inetd.conf ] && grep -E "(^|\s)(rsh|rlogin|rexec)(\s|$)" /etc/inetd.conf 2>/dev/null && found=1
|
||||
if ls /etc/xinetd.d/* >/dev/null 2>&1; then
|
||||
grep -E "(rsh|rlogin|rexec)" /etc/xinetd.d/* 2>/dev/null && found=1
|
||||
fi
|
||||
[ "$found" ] || echo_no
|
||||
)
|
||||
|
||||
print_list "rsh/rlogin/rexec sockets in systemd? .. "
|
||||
(
|
||||
found=""
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl list-unit-files --type=socket --no-pager 2>/dev/null | grep -E "(rlogin|rsh|rexec)" && found=1
|
||||
systemctl list-sockets --no-pager 2>/dev/null | grep -E "(rlogin|rsh|rexec)" && found=1
|
||||
fi
|
||||
[ "$found" ] || echo_no
|
||||
)
|
||||
|
||||
# 4) PAM rhosts trust
|
||||
print_list "PAM rhosts trust enabled? ............ "
|
||||
(
|
||||
found=""
|
||||
for p in /etc/pam.d/rlogin /etc/pam.d/rsh /etc/pam.d/rexec; do
|
||||
[ -r "$p" ] && grep -E "pam_rhosts|pam_rhosts_auth" "$p" 2>/dev/null && found=1
|
||||
done
|
||||
[ "$found" ] || echo_no
|
||||
)
|
||||
|
||||
# 5) Container-to-host hint
|
||||
if [ -f "/.dockerenv" ]; then
|
||||
print_info "Running inside a container. If host runs r-commands and root/.rhosts trusts hostnames, aligning A+PTR DNS may allow passwordless rlogin/rsh to the host."
|
||||
fi
|
||||
|
||||
# 6) Actionable guidance
|
||||
print_3title "Why risky and how to abuse"
|
||||
echo "- If a trusted entry is a hostname (not an IP) and r-services are listening, an attacker controlling DNS can set matching forward (A) and reverse (PTR) records so their IP resolves to the trusted name and reverse to the same name, passing hostname checks for passwordless access (even root if in /root/.rhosts or hosts.equiv)." | sed -${E} "s,passwordless access,${SED_RED_YELLOW},"
|
||||
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:
|
||||
|
||||
@@ -457,28 +457,35 @@ namespace winPEAS.Checks
|
||||
{ "Not Accessible", Beaprint.ansi_color_bad },
|
||||
};
|
||||
Beaprint.AnsiPrint($" HTTP (80) Access: {(connectivityInfo.HttpAccess ? "Accessible" : "Not Accessible")}", colorsBool);
|
||||
if (!string.IsNullOrEmpty(connectivityInfo.HttpError))
|
||||
if (!connectivityInfo.HttpAccess && !string.IsNullOrEmpty(connectivityInfo.HttpError))
|
||||
{
|
||||
Beaprint.PrintException($" Error: {connectivityInfo.HttpError}");
|
||||
}
|
||||
|
||||
// HTTPS Access
|
||||
Beaprint.AnsiPrint($" HTTPS (443) Access: {(connectivityInfo.HttpsAccess ? "Accessible" : "Not Accessible")}", colorsBool);
|
||||
if (!string.IsNullOrEmpty(connectivityInfo.HttpsError))
|
||||
if (!connectivityInfo.HttpsAccess && !string.IsNullOrEmpty(connectivityInfo.HttpsError))
|
||||
{
|
||||
Beaprint.PrintException($" Error: {connectivityInfo.HttpsError}");
|
||||
}
|
||||
|
||||
// HTTPS By Domain Name
|
||||
Beaprint.AnsiPrint($" HTTPS (443) Access by Domain Name: {(connectivityInfo.LambdaAccess ? "Accessible" : "Not Accessible")}", colorsBool);
|
||||
if (!connectivityInfo.LambdaAccess && !string.IsNullOrEmpty(connectivityInfo.LambdaError))
|
||||
{
|
||||
Beaprint.PrintException($" Error: {connectivityInfo.LambdaError}");
|
||||
}
|
||||
|
||||
// DNS Access
|
||||
Beaprint.AnsiPrint($" DNS (53) Access: {(connectivityInfo.DnsAccess ? "Accessible" : "Not Accessible")}", colorsBool);
|
||||
if (!string.IsNullOrEmpty(connectivityInfo.DnsError))
|
||||
if (!connectivityInfo.DnsAccess && !string.IsNullOrEmpty(connectivityInfo.DnsError))
|
||||
{
|
||||
Beaprint.PrintException($" Error: {connectivityInfo.DnsError}");
|
||||
}
|
||||
|
||||
// ICMP Access
|
||||
Beaprint.AnsiPrint($" ICMP (ping) Access: {(connectivityInfo.IcmpAccess ? "Accessible" : "Not Accessible")}", colorsBool);
|
||||
if (!string.IsNullOrEmpty(connectivityInfo.IcmpError))
|
||||
if (!connectivityInfo.IcmpAccess && !string.IsNullOrEmpty(connectivityInfo.IcmpError))
|
||||
{
|
||||
Beaprint.PrintException($" Error: {connectivityInfo.IcmpError}");
|
||||
}
|
||||
@@ -505,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;
|
||||
|
||||
@@ -1,58 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace winPEAS.Info.NetworkInfo
|
||||
{
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
// POCO returned to the UI
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
public class InternetConnectivityInfo
|
||||
{
|
||||
public bool HttpAccess { get; set; }
|
||||
public bool HttpsAccess { get; set; }
|
||||
public bool LambdaAccess { get; set; }
|
||||
public bool DnsAccess { get; set; }
|
||||
public bool IcmpAccess { get; set; }
|
||||
public string HttpError { get; set; }
|
||||
public string HttpsError { get; set; }
|
||||
public string LambdaError { get; set; }
|
||||
public string DnsError { get; set; }
|
||||
public string IcmpError { get; set; }
|
||||
public string SuccessfulHttpIp { get; set; }
|
||||
public bool HttpAccess { get; set; }
|
||||
public bool HttpsAccess { get; set; }
|
||||
public bool LambdaAccess { get; set; }
|
||||
public bool DnsAccess { get; set; }
|
||||
public bool IcmpAccess { get; set; }
|
||||
|
||||
public string HttpError { get; set; }
|
||||
public string HttpsError { get; set; }
|
||||
public string LambdaError { get; set; }
|
||||
public string DnsError { get; set; }
|
||||
public string IcmpError { get; set; }
|
||||
|
||||
public string SuccessfulHttpIp { get; set; }
|
||||
public string SuccessfulHttpsIp { get; set; }
|
||||
public string SuccessfulDnsIp { get; set; }
|
||||
public string SuccessfulIcmpIp { get; set; }
|
||||
public string SuccessfulDnsIp { get; set; }
|
||||
public string SuccessfulIcmpIp { get; set; }
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
// Connectivity tester
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
public static class InternetConnectivity
|
||||
{
|
||||
private const int HTTP_TIMEOUT = 5000; // 5 seconds
|
||||
private const int ICMP_TIMEOUT = 2000; // 2 seconds
|
||||
private static readonly string[] TEST_IPS = new[] { "1.1.1.1", "8.8.8.8" }; // Cloudflare DNS, Google DNS
|
||||
private const string LAMBDA_URL = "https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/";
|
||||
private const int HTTP_TIMEOUT_MS = 5000; // 5 s
|
||||
private const int ICMP_TIMEOUT_MS = 2000; // 2 s
|
||||
|
||||
private static bool TryHttpAccess(string ip, out string error)
|
||||
// IPs that answer on 80 & 443
|
||||
private static readonly string[] WEB_TEST_IPS =
|
||||
{ "93.184.216.34", "151.101.1.69" }; // example.com / Fastly
|
||||
|
||||
// Public DNS resolvers for DNS + ICMP checks
|
||||
private static readonly string[] DNS_ICMP_IPS =
|
||||
{ "1.1.1.1", "8.8.8.8" };
|
||||
|
||||
private const string LAMBDA_URL =
|
||||
"https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/";
|
||||
|
||||
// Shared HttpClient (kept for HTTP & Lambda checks)
|
||||
private static readonly HttpClient http = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromMilliseconds(HTTP_TIMEOUT_MS)
|
||||
};
|
||||
|
||||
// ─── Helpers ───────────────────────────────────────────────
|
||||
private static bool TryHttpAccess(string ip, out string error) =>
|
||||
TryWebRequest($"http://{ip}", out error);
|
||||
|
||||
// **NEW IMPLEMENTATION** – plain TCP connect on port 443
|
||||
private static bool TryHttpsAccess(string ip, out string error)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(HTTP_TIMEOUT));
|
||||
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(HTTP_TIMEOUT) };
|
||||
using var client = new TcpClient();
|
||||
|
||||
var resp = client.GetAsync($"http://{ip}", cts.Token)
|
||||
.GetAwaiter().GetResult();
|
||||
// Start async connect and wait up to the timeout
|
||||
var connectTask = client.ConnectAsync(ip, 443);
|
||||
bool completed = connectTask.Wait(HTTP_TIMEOUT_MS);
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
if (!completed)
|
||||
{
|
||||
error = "TCP connect timed out";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (client.Connected)
|
||||
{
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
error = $"HTTP status {(int)resp.StatusCode}";
|
||||
error = "TCP connection failed";
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -62,24 +93,16 @@ namespace winPEAS.Info.NetworkInfo
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryHttpsAccess(string ip, out string error)
|
||||
private static bool TryWebRequest(string url, out string error)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(HTTP_TIMEOUT));
|
||||
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(HTTP_TIMEOUT) };
|
||||
using var cts =
|
||||
new CancellationTokenSource(TimeSpan.FromMilliseconds(HTTP_TIMEOUT_MS));
|
||||
http.GetAsync(url, cts.Token).GetAwaiter().GetResult();
|
||||
|
||||
var resp = client.GetAsync($"https://{ip}", cts.Token)
|
||||
.GetAwaiter().GetResult();
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
error = $"HTTPS status {(int)resp.StatusCode}";
|
||||
return false;
|
||||
error = null; // any HTTP response == connectivity
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -92,24 +115,19 @@ namespace winPEAS.Info.NetworkInfo
|
||||
{
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(HTTP_TIMEOUT));
|
||||
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(HTTP_TIMEOUT) };
|
||||
using var cts =
|
||||
new CancellationTokenSource(TimeSpan.FromMilliseconds(HTTP_TIMEOUT_MS));
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, LAMBDA_URL);
|
||||
req.Headers.UserAgent.ParseAdd("winpeas");
|
||||
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
req.Headers.Accept.Add(
|
||||
new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
var resp = client.SendAsync(req, cts.Token)
|
||||
.GetAwaiter().GetResult();
|
||||
var resp = http.SendAsync(req, cts.Token).GetAwaiter().GetResult();
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
error = $"Lambda status {(int)resp.StatusCode}";
|
||||
return false;
|
||||
error = resp.IsSuccessStatusCode ? null :
|
||||
$"HTTP {(int)resp.StatusCode}";
|
||||
return error == null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -118,167 +136,132 @@ namespace winPEAS.Info.NetworkInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static bool TryDnsAccess(string ip, out string error)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var udpClient = new UdpClient())
|
||||
{
|
||||
// Set a timeout for the connection attempt
|
||||
udpClient.Client.ReceiveTimeout = HTTP_TIMEOUT;
|
||||
udpClient.Client.SendTimeout = HTTP_TIMEOUT;
|
||||
using var udp = new UdpClient();
|
||||
udp.Client.ReceiveTimeout = HTTP_TIMEOUT_MS;
|
||||
udp.Client.SendTimeout = HTTP_TIMEOUT_MS;
|
||||
|
||||
// Create DNS server endpoint
|
||||
var dnsServer = new IPEndPoint(IPAddress.Parse(ip), 53);
|
||||
var server = new IPEndPoint(IPAddress.Parse(ip), 53);
|
||||
|
||||
// Create a simple DNS query for google.com (type A record)
|
||||
byte[] dnsQuery = new byte[] {
|
||||
0x00, 0x01, // Transaction ID
|
||||
0x01, 0x00, // Flags (Standard query)
|
||||
0x00, 0x01, // Questions: 1
|
||||
0x00, 0x00, // Answer RRs: 0
|
||||
0x00, 0x00, // Authority RRs: 0
|
||||
0x00, 0x00, // Additional RRs: 0
|
||||
// google.com
|
||||
0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0x00, 0x01, // Type: A
|
||||
0x00, 0x01 // Class: IN
|
||||
};
|
||||
// minimal query for google.com A‑record
|
||||
byte[] q = {
|
||||
0x00,0x01, 0x01,0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x00,0x00,
|
||||
0x06,0x67,0x6f,0x6f,0x67,0x6c,0x65, 0x03,0x63,0x6f,0x6d, 0x00,
|
||||
0x00,0x01, 0x00,0x01
|
||||
};
|
||||
|
||||
// Send the DNS query
|
||||
udpClient.Send(dnsQuery, dnsQuery.Length, dnsServer);
|
||||
udp.Send(q, q.Length, server);
|
||||
|
||||
// Try to receive a response
|
||||
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
|
||||
byte[] response = udpClient.Receive(ref remoteEP);
|
||||
IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
|
||||
byte[] resp = udp.Receive(ref remote);
|
||||
|
||||
// If we got a response, the DNS server is reachable
|
||||
if (response != null && response.Length > 0)
|
||||
{
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
error = "No response received from DNS server";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
error = $"Socket error: {ex.Message}";
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex.Message;
|
||||
return false;
|
||||
error = resp?.Length > 0 ? null : "No DNS response";
|
||||
return error == null;
|
||||
}
|
||||
catch (SocketException ex) { error = ex.Message; return false; }
|
||||
catch (Exception ex) { error = ex.Message; return false; }
|
||||
}
|
||||
|
||||
private static bool TryIcmpAccess(string ip, out string error)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var ping = new Ping())
|
||||
{
|
||||
var reply = ping.Send(ip, ICMP_TIMEOUT);
|
||||
if (reply?.Status == IPStatus.Success)
|
||||
{
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
error = $"Ping failed with status: {reply?.Status}";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex.Message;
|
||||
return false;
|
||||
using var ping = new Ping();
|
||||
var reply = ping.Send(ip, ICMP_TIMEOUT_MS);
|
||||
|
||||
error = reply?.Status == IPStatus.Success
|
||||
? null
|
||||
: $"Ping failed: {reply?.Status}";
|
||||
return error == null;
|
||||
}
|
||||
catch (Exception ex) { error = ex.Message; return false; }
|
||||
}
|
||||
|
||||
// ─── Main entry ───────────────────────────────────────────
|
||||
public static InternetConnectivityInfo CheckConnectivity()
|
||||
{
|
||||
var result = new InternetConnectivityInfo();
|
||||
var info = new InternetConnectivityInfo();
|
||||
|
||||
// Test HTTP (port 80) on each IP until success
|
||||
foreach (var ip in TEST_IPS)
|
||||
// -------- HTTP / HTTPS --------------------------------
|
||||
foreach (var ip in WEB_TEST_IPS)
|
||||
{
|
||||
if (TryHttpAccess(ip, out string error))
|
||||
// HTTP
|
||||
if (!info.HttpAccess)
|
||||
{
|
||||
result.HttpAccess = true;
|
||||
result.SuccessfulHttpIp = ip;
|
||||
break;
|
||||
string httpErr;
|
||||
if (TryHttpAccess(ip, out httpErr))
|
||||
{
|
||||
info.HttpAccess = true;
|
||||
info.SuccessfulHttpIp = ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.HttpError = httpErr;
|
||||
}
|
||||
}
|
||||
else if (ip == TEST_IPS[TEST_IPS.Length - 1]) // Last IP
|
||||
|
||||
// HTTPS (raw TCP 443)
|
||||
if (!info.HttpsAccess)
|
||||
{
|
||||
result.HttpAccess = false;
|
||||
result.HttpError = error;
|
||||
string httpsErr;
|
||||
if (TryHttpsAccess(ip, out httpsErr))
|
||||
{
|
||||
info.HttpsAccess = true;
|
||||
info.SuccessfulHttpsIp = ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.HttpsError = httpsErr;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.HttpAccess && info.HttpsAccess) break;
|
||||
}
|
||||
|
||||
// Test HTTPS (port 443) on each IP until success
|
||||
foreach (var ip in TEST_IPS)
|
||||
// -------- Lambda --------------------------------------
|
||||
info.LambdaAccess = TryLambdaAccess(out string lambdaErr);
|
||||
if (!info.LambdaAccess) info.LambdaError = lambdaErr;
|
||||
|
||||
// -------- DNS / ICMP ----------------------------------
|
||||
foreach (var ip in DNS_ICMP_IPS)
|
||||
{
|
||||
if (TryHttpsAccess(ip, out string error))
|
||||
// DNS
|
||||
if (!info.DnsAccess)
|
||||
{
|
||||
result.HttpsAccess = true;
|
||||
result.SuccessfulHttpsIp = ip;
|
||||
break;
|
||||
string dnsErr;
|
||||
if (TryDnsAccess(ip, out dnsErr))
|
||||
{
|
||||
info.DnsAccess = true;
|
||||
info.SuccessfulDnsIp = ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.DnsError = dnsErr;
|
||||
}
|
||||
}
|
||||
else if (ip == TEST_IPS[TEST_IPS.Length - 1]) // Last IP
|
||||
|
||||
// ICMP
|
||||
if (!info.IcmpAccess)
|
||||
{
|
||||
result.HttpsAccess = false;
|
||||
result.HttpsError = error;
|
||||
string pingErr;
|
||||
if (TryIcmpAccess(ip, out pingErr))
|
||||
{
|
||||
info.IcmpAccess = true;
|
||||
info.SuccessfulIcmpIp = ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.IcmpError = pingErr;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.DnsAccess && info.IcmpAccess) break;
|
||||
}
|
||||
|
||||
// Test Lambda URL
|
||||
result.LambdaAccess = TryLambdaAccess(out string lambdaError);
|
||||
if (!result.LambdaAccess)
|
||||
{
|
||||
result.LambdaError = lambdaError;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.HttpsAccess = true;
|
||||
}
|
||||
|
||||
// Test DNS on each IP until success
|
||||
foreach (var ip in TEST_IPS)
|
||||
{
|
||||
if (TryDnsAccess(ip, out string error))
|
||||
{
|
||||
result.DnsAccess = true;
|
||||
result.SuccessfulDnsIp = ip;
|
||||
break;
|
||||
}
|
||||
else if (ip == TEST_IPS[TEST_IPS.Length - 1]) // Last IP
|
||||
{
|
||||
result.DnsAccess = false;
|
||||
result.DnsError = error;
|
||||
}
|
||||
}
|
||||
|
||||
// Test ICMP (ping) on each IP until success
|
||||
foreach (var ip in TEST_IPS)
|
||||
{
|
||||
if (TryIcmpAccess(ip, out string error))
|
||||
{
|
||||
result.IcmpAccess = true;
|
||||
result.SuccessfulIcmpIp = ip;
|
||||
break;
|
||||
}
|
||||
else if (ip == TEST_IPS[TEST_IPS.Length - 1]) // Last IP
|
||||
{
|
||||
result.IcmpAccess = false;
|
||||
result.IcmpError = error;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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