Compare commits

..

1 Commits

Author SHA1 Message Date
HackTricks PEASS Autoimprover
93614a2986 autoimprover: simplify linpeas checks 2026-01-18 22:28:18 +00:00
45 changed files with 119 additions and 819 deletions

View File

@@ -1,18 +0,0 @@
{
"type": "object",
"additionalProperties": false,
"properties": {
"decision": {
"type": "string",
"enum": ["merge", "comment"]
},
"message": {
"type": "string"
},
"confidence": {
"type": "string",
"enum": ["low", "medium", "high"]
}
},
"required": ["decision", "message", "confidence"]
}

26
.github/workflows/CI-PR_from_dev.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: CI-PR_from_dev
on:
push:
branches:
- winpeas_dev
- linpeas_dev
workflow_dispatch:
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
# checkout
- name: Checkout
uses: actions/checkout@v2
# PR
- name: Pull Request
uses: repo-sync/pull-request@v2
with:
destination_branch: "master"
github_token: ${{ secrets.PULL_REQUEST_TOKEN }}

View File

@@ -48,23 +48,23 @@ jobs:
# build
- name: run MSBuild
run: msbuild $env:Solution_Path /p:Configuration=$env:Configuration /p:UseSharedCompilation=false
run: msbuild $env:Solution_Path
# Execute all unit tests in the solution
- name: Execute unit tests
run: dotnet test $env:Solution_Path --configuration $env:Configuration
#- name: Execute unit tests
# run: dotnet test $env:Solution_Path
# Build & update all versions
- name: Build all versions
run: |
echo "build x64"
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="x64" /p:UseSharedCompilation=false
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" /p:UseSharedCompilation=false
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" /p:UseSharedCompilation=false
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU"
- name: Execute winPEAS -h
shell: pwsh
@@ -230,9 +230,6 @@ jobs:
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
- name: Run linPEAS builder tests
run: python3 -m unittest discover -s linPEAS/tests -p "test_*.py"
# Build linpeas binaries
- name: Build linpeas binaries

View File

@@ -42,23 +42,19 @@ jobs:
# build
- name: run MSBuild
run: msbuild $env:Solution_Path /p:Configuration=$env:Configuration /p:UseSharedCompilation=false
# Execute unit tests in the solution
- name: Execute unit tests
run: dotnet test $env:Solution_Path --configuration $env:Configuration
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" /p:UseSharedCompilation=false
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" /p:UseSharedCompilation=false
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" /p:UseSharedCompilation=false
msbuild -m $env:Solution_Path /t:Rebuild /p:Configuration=$env:Configuration /p:Platform="Any CPU"
- name: Execute winPEAS -h
shell: pwsh
@@ -127,9 +123,6 @@ jobs:
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
- name: Run linPEAS builder tests
run: python3 -m unittest discover -s linPEAS/tests -p "test_*.py"
# Run linpeas help as quick test
- name: Run linpeas help

View File

@@ -1,167 +0,0 @@
name: Codex PR Triage
on:
workflow_run:
workflows: ["PR-tests"]
types: [completed]
jobs:
codex_triage:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
should_run: ${{ steps.gate.outputs.should_run }}
pr_number: ${{ steps.gate.outputs.pr_number }}
pr_title: ${{ steps.gate.outputs.pr_title }}
pr_body: ${{ steps.gate.outputs.pr_body }}
base_ref: ${{ steps.gate.outputs.base_ref }}
head_ref: ${{ steps.gate.outputs.head_ref }}
base_sha: ${{ steps.gate.outputs.base_sha }}
head_sha: ${{ steps.gate.outputs.head_sha }}
decision: ${{ steps.parse.outputs.decision }}
message: ${{ steps.parse.outputs.message }}
steps:
- name: Resolve PR context
id: gate
env:
GH_TOKEN: ${{ github.token }}
run: |
pr_number="${{ github.event.workflow_run.pull_requests[0].number }}"
if [ -z "$pr_number" ]; then
echo "No pull request found for this workflow_run; skipping."
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "pr_number=" >> "$GITHUB_OUTPUT"
exit 0
fi
author="$(gh pr view "$pr_number" --json author --jq .author.login)"
if [ "$author" != "carlospolop" ]; then
echo "PR author is $author; skipping."
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
exit 0
fi
pr_title="$(gh pr view "$pr_number" --json title --jq .title)"
pr_body="$(gh pr view "$pr_number" --json body --jq .body)"
base_ref="$(gh pr view "$pr_number" --json baseRefName --jq .baseRefName)"
head_ref="$(gh pr view "$pr_number" --json headRefName --jq .headRefName)"
base_sha="$(gh pr view "$pr_number" --json baseRefOid --jq .baseRefOid)"
head_sha="$(gh pr view "$pr_number" --json headRefOid --jq .headRefOid)"
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
echo "pr_title<<EOF" >> "$GITHUB_OUTPUT"
echo "$pr_title" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
echo "pr_body<<EOF" >> "$GITHUB_OUTPUT"
echo "$pr_body" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
echo "base_ref=$base_ref" >> "$GITHUB_OUTPUT"
echo "head_ref=$head_ref" >> "$GITHUB_OUTPUT"
echo "base_sha=$base_sha" >> "$GITHUB_OUTPUT"
echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT"
- name: Checkout PR merge ref
uses: actions/checkout@v5
with:
ref: refs/pull/${{ steps.gate.outputs.pr_number }}/merge
if: ${{ steps.gate.outputs.should_run == 'true' }}
- name: Pre-fetch base and head refs
if: ${{ steps.gate.outputs.should_run == 'true' }}
run: |
git fetch --no-tags origin \
${{ steps.gate.outputs.base_ref }} \
+refs/pull/${{ steps.gate.outputs.pr_number }}/head
- name: Run Codex
id: run_codex
if: ${{ steps.gate.outputs.should_run == 'true' }}
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
output-schema-file: .github/codex/pr-merge-schema.json
model: gpt-5.2-codex
prompt: |
You are reviewing PR #${{ steps.gate.outputs.pr_number }} for ${{ github.repository }}.
Decide whether to merge or comment. Merge only if all of the following are true:
- Changes are simple and safe (no DoS, no long operations, no backdoors).
- Changes follow common PEASS syntax and style without breaking anything and add useful checks or value.
- Changes simplify code or add new useful checks without breaking anything.
If you don't have any doubts, and all the previous conditions are met, decide to merge.
If you have serious doubts, choose "comment" and include your doubts or questions.
If you decide to merge, include a short rationale.
Pull request title and body:
----
${{ steps.gate.outputs.pr_title }}
${{ steps.gate.outputs.pr_body }}
Review ONLY the changes introduced by the PR:
git log --oneline ${{ steps.gate.outputs.base_sha }}...${{ steps.gate.outputs.head_sha }}
Output JSON only, following the provided schema.
- name: Parse Codex decision
id: parse
if: ${{ steps.gate.outputs.should_run == 'true' }}
env:
CODEX_MESSAGE: ${{ steps.run_codex.outputs.final-message }}
run: |
python3 - <<'PY'
import json
import os
data = json.loads(os.environ.get('CODEX_MESSAGE', '') or '{}')
decision = data.get('decision', 'comment')
message = data.get('message', '').strip() or 'Codex did not provide details.'
with open(os.environ['GITHUB_OUTPUT'], 'a') as handle:
handle.write(f"decision={decision}\n")
handle.write("message<<EOF\n")
handle.write(message + "\n")
handle.write("EOF\n")
PY
merge_or_comment:
runs-on: ubuntu-latest
needs: codex_triage
if: ${{ github.event.workflow_run.conclusion == 'success' && needs.codex_triage.outputs.should_run == 'true' && needs.codex_triage.outputs.decision != '' }}
permissions:
contents: write
pull-requests: write
steps:
- name: Merge PR when approved
if: ${{ needs.codex_triage.outputs.decision == 'merge' }}
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ needs.codex_triage.outputs.pr_number }}
run: |
gh api \
-X PUT \
-H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/pulls/${PR_NUMBER}/merge \
-f merge_method=squash \
-f commit_title="Auto-merge PR #${PR_NUMBER} (Codex)"
- name: Comment with doubts
if: ${{ needs.codex_triage.outputs.decision == 'comment' }}
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.codex_triage.outputs.pr_number }}
CODEX_MESSAGE: ${{ needs.codex_triage.outputs.message }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: Number(process.env.PR_NUMBER),
body: process.env.CODEX_MESSAGE,
});

View File

@@ -1,193 +0,0 @@
name: PR Failure Codex Dispatch
on:
workflow_run:
workflows: ["PR-tests"]
types: [completed]
jobs:
resolve_pr_context:
if: >
${{ github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.pull_requests &&
github.event.workflow_run.pull_requests[0] &&
!startsWith(github.event.workflow_run.head_commit.message, 'Fix CI failures for PR #') }}
runs-on: ubuntu-latest
permissions:
pull-requests: read
issues: read
outputs:
number: ${{ steps.pr_context.outputs.number }}
author: ${{ steps.pr_context.outputs.author }}
head_repo: ${{ steps.pr_context.outputs.head_repo }}
head_branch: ${{ steps.pr_context.outputs.head_branch }}
should_run: ${{ steps.pr_context.outputs.should_run }}
steps:
- name: Resolve PR context
id: pr_context
env:
PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
GH_TOKEN: ${{ github.token }}
run: |
pr_author=$(gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/pulls/${PR_NUMBER} \
--jq '.user.login')
pr_head_repo=$(gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/pulls/${PR_NUMBER} \
--jq '.head.repo.full_name')
pr_head_branch=$(gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/pulls/${PR_NUMBER} \
--jq '.head.ref')
pr_labels=$(gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/issues/${PR_NUMBER} \
--jq '.labels[].name')
if echo "$pr_labels" | grep -q "^codex-fix-attempted$"; then
echo "codex fix already attempted for PR #${PR_NUMBER}; skipping."
should_run=false
else
should_run=true
fi
{
echo "number=${PR_NUMBER}"
echo "author=${pr_author}"
echo "head_repo=${pr_head_repo}"
echo "head_branch=${pr_head_branch}"
echo "should_run=${should_run}"
} >> "$GITHUB_OUTPUT"
codex_on_failure:
needs: resolve_pr_context
if: ${{ needs.resolve_pr_context.outputs.author == 'carlospolop' && needs.resolve_pr_context.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
actions: read
steps:
- name: Comment on PR with failure info
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
WORKFLOW_NAME: ${{ github.event.workflow_run.name }}
with:
github-token: ${{ github.token }}
script: |
const prNumber = Number(process.env.PR_NUMBER);
const body = `PR #${prNumber} had a failing workflow "${process.env.WORKFLOW_NAME}".\n\nRun: ${process.env.RUN_URL}\n\nLaunching Codex to attempt a fix.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
- name: Mark fix attempt
env:
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
GH_TOKEN: ${{ github.token }}
run: |
gh api -X POST -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/issues/${PR_NUMBER}/labels \
-f labels='["codex-fix-attempted"]'
- name: Checkout PR head
uses: actions/checkout@v5
with:
repository: ${{ needs.resolve_pr_context.outputs.head_repo }}
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
persist-credentials: true
token: ${{ secrets.CODEX_FIXER_TOKEN }}
- name: Configure git author
run: |
git config user.name "codex-action"
git config user.email "codex-action@users.noreply.github.com"
- name: Fetch failure summary
env:
GH_TOKEN: ${{ github.token }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
gh api -H "Accept: application/vnd.github+json" \
/repos/${{ github.repository }}/actions/runs/$RUN_ID/jobs \
--paginate > /tmp/jobs.json
python3 - <<'PY'
import json
data = json.load(open('/tmp/jobs.json'))
lines = []
for job in data.get('jobs', []):
if job.get('conclusion') == 'failure':
lines.append(f"Job: {job.get('name')} (id {job.get('id')})")
lines.append(f"URL: {job.get('html_url')}")
for step in job.get('steps', []):
if step.get('conclusion') == 'failure':
lines.append(f" Step: {step.get('name')}")
lines.append("")
summary = "\n".join(lines).strip() or "No failing job details found."
with open('codex_failure_summary.txt', 'w') as handle:
handle.write(summary)
PY
- name: Create Codex prompt
env:
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
HEAD_BRANCH: ${{ needs.resolve_pr_context.outputs.head_branch }}
run: |
{
echo "You are fixing CI failures for PR #${PR_NUMBER} in ${{ github.repository }}."
echo "The failing workflow run is: ${RUN_URL}"
echo "The PR branch is: ${HEAD_BRANCH}"
echo ""
echo "Failure summary:"
cat codex_failure_summary.txt
echo ""
echo "Please identify the cause, apply a easy, simple and minimal fix, and update files accordingly."
echo "Run any fast checks you can locally (no network)."
echo "Leave the repo in a state ready to commit as when you finish, it'll be automatically committed and pushed."
} > codex_prompt.txt
- name: Run Codex
id: run_codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt-file: codex_prompt.txt
sandbox: workspace-write
model: gpt-5.2-codex
- name: Commit and push if changed
env:
TARGET_BRANCH: ${{ needs.resolve_pr_context.outputs.head_branch }}
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
run: |
if git diff --quiet; then
echo "No changes to commit."
exit 0
fi
rm -f codex_failure_summary.txt codex_prompt.txt
git add -A
git reset -- codex_failure_summary.txt codex_prompt.txt
git commit -m "Fix CI failures for PR #${PR_NUMBER}"
git push origin HEAD:${TARGET_BRANCH}
- name: Comment with Codex result
if: ${{ steps.run_codex.outputs.final-message != '' }}
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.resolve_pr_context.outputs.number }}
CODEX_MESSAGE: ${{ steps.run_codex.outputs.final-message }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: Number(process.env.PR_NUMBER),
body: process.env.CODEX_MESSAGE,
});

0
LICENSE Normal file → Executable file
View File

3
README.md Normal file → Executable file
View File

@@ -28,7 +28,7 @@ Check the **[parsers](./parsers/)** directory to **transform PEASS outputs to JS
If you are a **PEASS & Hacktricks enthusiast**, you can get your hands now on **our [custom swag](https://peass.creator-spring.com/) and show how much you like our projects!**
You can also, join the 💬 [Discord group](https://discord.gg/hRep4RUj7f) or the [telegram group](https://t.me/peass) to learn about the latest news in cybersecurity and meet other cybersecurity enthusiasts, or follow me on Twitter 🐦 [@hacktricks_live](https://twitter.com/hacktricks_live).
You can also, join the 💬 [Discord group](https://discord.gg/hRep4RUj7f) or the [telegram group](https://t.me/peass) to learn about latest news in cybersecurity and meet other cybersecurity enthusiasts, or follow me on Twitter 🐦 [@hacktricks_live](https://twitter.com/hacktricks_live).
## Let's improve PEASS together
@@ -37,3 +37,4 @@ If you want to **add something** and have **any cool idea** related to this proj
## Advisory
All the scripts/binaries of the PEAS suite 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 machines and/or with the owner's permission.

View File

@@ -1705,7 +1705,7 @@ search:
auto_check: True
exec:
- '( redis-server --version || echo_not_found "redis-server") 2>/dev/null'
- redis_info="$(if [ "$TIMEOUT" ]; then $TIMEOUT 2 redis-cli INFO 2>/dev/null; else redis-cli INFO 2>/dev/null; fi)"; if [ "$redis_info" ] && ! echo "$redis_info" | grep -i NOAUTH; then echo "Redis isn't password protected" | sed -${E} "s,.*,${SED_RED},"; fi
- if [ "`redis-cli INFO 2>/dev/null`" ] && ! [ "`redis-cli INFO 2>/dev/null | grep -i NOAUTH`" ]; then echo "Redis isn't password protected" | sed -${E} "s,.*,${SED_RED},"; fi
files:
- name: "redis.conf"
@@ -3352,7 +3352,7 @@ search:
- name: "credentials.xml"
value:
bad_regex: "secret.*|password.*|token.*|SecretKey.*|credentialId.*"
bad_regex: "secret.*|password.*"
remove_empty_lines: True
type: f
search_in:
@@ -3360,7 +3360,7 @@ search:
- name: "config.xml"
value:
bad_regex: "secret.*|password.*|token.*|SecretKey.*|credentialId.*"
bad_regex: "secret.*|password.*"
only_bad_lines: True
type: f
search_in:

View File

@@ -30,9 +30,10 @@
# Fat linpeas: 0
# Small linpeas: 0
if apt list --installed 2>/dev/null | grep -E 'polkit.*0\.105-26' | grep -qEv 'ubuntu1\.[1-9]' || \
yum list installed 2>/dev/null | grep -qE 'polkit.*\(0\.117-2\|0\.115-6\|0\.11[3-9]\)' || \
rpm -qa 2>/dev/null | grep -qE 'polkit.*\(0\.117-2\|0\.115-6\|0\.11[3-9]\)'; then
if apt list --installed 2>/dev/null | grep -q 'polkit.*0\.105-26' || \
yum list installed 2>/dev/null | grep -q 'polkit.*\(0\.117-2\|0\.115-6\)' || \
rpm -qa 2>/dev/null | grep -q 'polkit.*\(0\.117-2\|0\.115-6\)'; then
echo "Vulnerable to CVE-2021-3560" | sed -${E} "s,.*,${SED_RED_YELLOW},"
echo ""
fi

View File

@@ -30,7 +30,7 @@
# Functions Used: echo_not_found, print_2title, print_list, warn_exec
# Global Variables:
# Initial Functions:
# Generated Global Variables: $ASLR, $hypervisorflag, $detectedvirt, $unpriv_userns_clone, $perf_event_paranoid, $mmap_min_addr, $ptrace_scope, $dmesg_restrict, $kptr_restrict, $unpriv_bpf_disabled, $protected_symlinks, $protected_hardlinks
# Generated Global Variables: $ASLR, $hypervisorflag, $detectedvirt, $unpriv_userns_clone, $perf_event_paranoid, $mmap_min_addr, $ptrace_scope, $dmesg_restrict, $kptr_restrict, $unpriv_bpf_disabled
# Fat linpeas: 0
# Small linpeas: 0
@@ -127,22 +127,6 @@ else
if [ "$ptrace_scope" -eq 0 ]; then echo "0" | sed -${E} "s,0,${SED_RED},"; else echo "$ptrace_scope" | sed -${E} "s,.*,${SED_GREEN},g"; fi
fi
print_list "protected_symlinks? ............ "$NC
protected_symlinks=$(cat /proc/sys/fs/protected_symlinks 2>/dev/null)
if [ -z "$protected_symlinks" ]; then
echo_not_found "/proc/sys/fs/protected_symlinks"
else
if [ "$protected_symlinks" -eq 0 ]; then echo "0" | sed -${E} "s,0,${SED_RED},"; else echo "$protected_symlinks" | sed -${E} "s,.*,${SED_GREEN},g"; fi
fi
print_list "protected_hardlinks? ........... "$NC
protected_hardlinks=$(cat /proc/sys/fs/protected_hardlinks 2>/dev/null)
if [ -z "$protected_hardlinks" ]; then
echo_not_found "/proc/sys/fs/protected_hardlinks"
else
if [ "$protected_hardlinks" -eq 0 ]; then echo "0" | sed -${E} "s,0,${SED_RED},"; else echo "$protected_hardlinks" | sed -${E} "s,.*,${SED_GREEN},g"; fi
fi
print_list "perf_event_paranoid? ........... "$NC
perf_event_paranoid=$(cat /proc/sys/kernel/perf_event_paranoid 2>/dev/null)
if [ -z "$perf_event_paranoid" ]; then

View File

@@ -4,7 +4,6 @@
# Last Update: 07-03-2024
# Description: Check for additional disk information and system resources relevant to privilege escalation:
# - Disk utilization
# - Inode usage
# - System resources
# - Storage statistics
# - Common vulnerable scenarios:
@@ -45,8 +44,4 @@ if [ "$EXTRA_CHECKS" ] || [ "$DEBUG" ]; then
(df -h || lsblk) 2>/dev/null || echo_not_found "df and lsblk"
warn_exec free 2>/dev/null
echo ""
print_2title "Inode usage"
warn_exec df -i 2>/dev/null
echo ""
fi
fi

View File

@@ -5,7 +5,7 @@
# Description: Azure Automation Account Service Enumeration
# License: GNU GPL
# Version: 1.0
# Functions Used: check_az_automation_acc, exec_with_jq, print_2title, print_3title
# Functions Used: check_az_automation_acc, exec_with_jq, print_2title, print_3title, set_metadata_req_cmd
# Global Variables: $is_az_automation_acc,
# Initial Functions: check_az_automation_acc
# Generated Global Variables: $API_VERSION, $HEADER, $az_req
@@ -21,13 +21,7 @@ if [ "$is_az_automation_acc" = "Yes" ]; then
HEADER="X-IDENTITY-HEADER:$IDENTITY_HEADER"
az_req=""
if [ "$(command -v curl || echo -n '')" ]; then
az_req="curl -s -f -L -H '$HEADER'"
elif [ "$(command -v wget || echo -n '')" ]; then
az_req="wget -q -O - --header '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi
set_metadata_req_cmd az_req "$HEADER"
if [ "$az_req" ]; then
print_3title "Management token"

View File

@@ -5,7 +5,7 @@
# Description: Azure VM Enumeration
# License: GNU GPL
# Version: 1.0
# Functions Used: check_az_vm, exec_with_jq, print_2title, print_3title
# Functions Used: check_az_vm, exec_with_jq, print_2title, print_3title, set_metadata_req_cmd
# Global Variables: $is_az_vm
# Initial Functions: check_az_vm
# Generated Global Variables: $API_VERSION, $HEADER, $az_req, $URL
@@ -21,13 +21,7 @@ if [ "$is_az_vm" = "Yes" ]; then
API_VERSION="2021-12-13" #https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=linux#supported-api-versions
az_req=""
if [ "$(command -v curl || echo -n '')" ]; then
az_req="curl -s -f -L -H '$HEADER'"
elif [ "$(command -v wget || echo -n '')" ]; then
az_req="wget -q -O - --header '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi
set_metadata_req_cmd az_req "$HEADER"
if [ "$az_req" ]; then
print_3title "Instance details"

View File

@@ -5,7 +5,7 @@
# Description: Azure App Service Enumeration
# License: GNU GPL
# Version: 1.0
# Functions Used: check_az_app, exec_with_jq, print_2title, print_3title
# Functions Used: check_az_app, exec_with_jq, print_2title, print_3title, set_metadata_req_cmd
# Global Variables: $is_az_app,
# Initial Functions: check_az_app
# Generated Global Variables: $API_VERSION, $HEADER, $az_req
@@ -21,13 +21,7 @@ if [ "$is_az_app" = "Yes" ]; then
HEADER="X-IDENTITY-HEADER:$IDENTITY_HEADER"
az_req=""
if [ "$(command -v curl || echo -n '')" ]; then
az_req="curl -s -f -L -H '$HEADER'"
elif [ "$(command -v wget || echo -n '')" ]; then
az_req="wget -q -O - --header '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi
set_metadata_req_cmd az_req "$HEADER"
if [ "$az_req" ]; then
print_3title "Management token"

View File

@@ -6,7 +6,7 @@
# License: GNU GPL
# Version: 1.2
# Functions Used: echo_not_found, print_2title, print_info, print_3title
# Global Variables: $EXTRA_CHECKS, $IAMROOT, $SEARCH_IN_FOLDER, $TIMEOUT, $WRITABLESYSTEMDPATH
# Global Variables: $EXTRA_CHECKS, $SEARCH_IN_FOLDER, $IAMROOT, $WRITABLESYSTEMDPATH
# Initial Functions:
# Generated Global Variables: $service_unit, $service_path, $service_content, $finding, $findings, $service_file, $exec_path, $exec_paths, $service, $line, $target_file, $target_exec, $relpath1, $relpath2
# Fat linpeas: 0
@@ -178,11 +178,7 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then
if [ "$EXTRA_CHECKS" ]; then
echo ""
print_3title "Service versions and status:"
if [ "$TIMEOUT" ]; then
$TIMEOUT 30 sh -c "(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null" || echo_not_found "service|chkconfig|rc-status|launchctl"
else
(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null || echo_not_found "service|chkconfig|rc-status|launchctl"
fi
(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null || echo_not_found "service|chkconfig|rc-status|launchctl"
fi
# Check systemd path writability
@@ -194,4 +190,4 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then
fi
echo ""
fi
fi

View File

@@ -1,25 +0,0 @@
# Title: Processes & Cron & Services & Timers - Deleted open files
# ID: PR_Deleted_open_files
# Author: Carlos Polop
# Last Update: 2025-01-07
# Description: Identify deleted files still held open by running processes
# License: GNU GPL
# Version: 1.0
# Functions Used: print_2title, print_info
# Global Variables: $DEBUG, $EXTRA_CHECKS, $E, $SED_RED
# Initial Functions:
# Generated Global Variables:
# Fat linpeas: 0
# Small linpeas: 1
if [ "$(command -v lsof 2>/dev/null || echo -n '')" ] || [ "$DEBUG" ]; then
print_2title "Deleted files still open"
print_info "Open deleted files can hide tools and still consume disk space"
lsof +L1 2>/dev/null | sed -${E} "s,\\(deleted\\),${SED_RED},g"
echo ""
elif [ "$EXTRA_CHECKS" ] || [ "$DEBUG" ]; then
print_2title "Deleted files still open"
print_info "lsof not found, scanning /proc for deleted file descriptors"
ls -l /proc/[0-9]*/fd 2>/dev/null | grep "(deleted)" | sed -${E} "s,\\(deleted\\),${SED_RED},g" | head -n 200
echo ""
fi

View File

@@ -23,7 +23,6 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then
incrontab -l 2>/dev/null
ls -alR /etc/cron* /var/spool/cron/crontabs /var/spool/anacron 2>/dev/null | sed -${E} "s,$cronjobsG,${SED_GREEN},g" | sed "s,$cronjobsB,${SED_RED},g"
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/* /etc/incron.d/* /var/spool/incron/* 2>/dev/null | tr -d "\r" | grep -v "^#" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
grep -Hn '^PATH=' /etc/crontab /etc/cron.d/* 2>/dev/null | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
crontab -l -u "$USER" 2>/dev/null | tr -d "\r"
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /var/at/tabs/ /etc/periodic/ 2>/dev/null | sed -${E} "s,$cronjobsG,${SED_GREEN},g" | sed "s,$cronjobsB,${SED_RED},g" #MacOS paths
atq 2>/dev/null
@@ -248,4 +247,4 @@ else
print_info "https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#scheduledcron-jobs"
find "$SEARCH_IN_FOLDER" '(' -type d -or -type f ')' '(' -name "cron*" -or -name "anacron" -or -name "anacrontab" -or -name "incron.d" -or -name "incron" -or -name "at" -or -name "periodic" ')' -exec echo {} \; -exec ls -lR {} \;
fi
echo ""
echo ""

View File

@@ -8,7 +8,7 @@
# Functions Used: print_2title, print_info
# Global Variables: $Groups, $groupsB, $groupsVB, $nosh_usrs, $sh_usrs, $USER
# Initial Functions:
# Generated Global Variables: $pkexec_bin, $pkexec_version, $policy_dir, $policy_file
# Generated Global Variables: $pkexec_bin, $policy_dir, $policy_file
# Fat linpeas: 0
# Small linpeas: 1
@@ -30,10 +30,6 @@ if [ -n "$pkexec_bin" ]; then
# Check polkit version for known vulnerabilities
if command -v pkexec >/dev/null 2>&1; then
pkexec --version 2>/dev/null
pkexec_version="$(pkexec --version 2>/dev/null | grep -oE '[0-9]+(\\.[0-9]+)+')"
if [ "$pkexec_version" ] && [ "$(printf '%s\n' "$pkexec_version" "0.120" | sort -V | head -n1)" = "$pkexec_version" ] && [ "$pkexec_version" != "0.120" ]; then
echo "Potentially vulnerable to CVE-2021-4034 (PwnKit) - check distro patches" | sed -${E} "s,.*,${SED_RED_YELLOW},"
fi
fi
fi

View File

@@ -6,7 +6,7 @@
# License: GNU GPL
# Version: 1.0
# Functions Used: print_2title
# Global Variables: $MACPEAS, $sh_usrs, $TIMEOUT, $USER
# Global Variables: $MACPEAS, $sh_usrs, $USER
# Initial Functions:
# Generated Global Variables: $ushell, $no_shells, $unexpected_shells
# Fat linpeas: 0
@@ -26,16 +26,8 @@ else
no_shells=$(grep -Ev "sh$" /etc/passwd 2>/dev/null | cut -d ':' -f 7 | sort | uniq)
unexpected_shells=""
printf "%s\n" "$no_shells" | while read f; do
if [ -x "$f" ]; then
if [ "$TIMEOUT" ]; then
if $TIMEOUT 1 "$f" -c 'whoami' 2>/dev/null | grep -q "$USER"; then
unexpected_shells="$f\n$unexpected_shells"
fi
else
if "$f" -c 'whoami' 2>/dev/null | grep -q "$USER"; then
unexpected_shells="$f\n$unexpected_shells"
fi
fi
if $f -c 'whoami' 2>/dev/null | grep -q "$USER"; then
unexpected_shells="$f\n$unexpected_shells"
fi
done
grep "sh$" /etc/passwd 2>/dev/null | sort | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},"
@@ -49,4 +41,4 @@ else
done
fi
fi
echo ""
echo ""

View File

@@ -8,7 +8,7 @@
# Functions Used: echo_not_found, print_2title, print_info
# Global Variables:$IAMROOT, $PASSWORD, $sudoB, $sudoG, $sudoVB1, $sudoVB2
# Initial Functions:
# Generated Global Variables: $secure_path_line
# Generated Global Variables:
# Fat linpeas: 0
# Small linpeas: 1
@@ -19,16 +19,6 @@ print_info "https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation
if [ "$PASSWORD" ]; then
(echo "$PASSWORD" | timeout 1 sudo -S -l | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW}," | sed -${E} "s,$sudoB,${SED_RED},g") 2>/dev/null || echo_not_found "sudo"
fi
(sudo -n -l 2>/dev/null | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW}," | sed -${E} "s,$sudoB,${SED_RED},g" | sed "s,\!root,${SED_RED},") 2>/dev/null || echo "No cached sudo token (sudo -n -l)"
secure_path_line=$(sudo -l 2>/dev/null | grep -o "secure_path=[^,]*" | head -n 1 | cut -d= -f2)
if [ "$secure_path_line" ]; then
for p in $(echo "$secure_path_line" | tr ':' ' '); do
if [ -w "$p" ]; then
echo "Writable secure_path entry: $p" | sed -${E} "s,.*,${SED_RED},g"
fi
done
fi
( grep -Iv "^$" cat /etc/sudoers | grep -v "#" | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW}," | sed -${E} "s,$sudoB,${SED_RED},g" | sed "s,pwfeedback,${SED_RED},g" ) 2>/dev/null || echo_not_found "/etc/sudoers"
if ! [ "$IAMROOT" ] && [ -w '/etc/sudoers.d/' ]; then
echo "You can create a file in /etc/sudoers.d/ and escalate privileges" | sed -${E} "s,.*,${SED_RED_YELLOW},"
@@ -39,4 +29,4 @@ for f in /etc/sudoers.d/*; do
grep -Iv "^$" "$f" | grep -v "#" | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW}," | sed -${E} "s,$sudoB,${SED_RED},g" | sed "s,pwfeedback,${SED_RED},g"
fi
done
echo ""
echo ""

View File

@@ -40,18 +40,4 @@ else
echo "ptrace protection is enabled ($ptrace_scope)" | sed "s,is enabled,${SED_GREEN},g";
fi
if [ -d "/var/run/sudo/ts" ]; then
echo "Sudo token directory perms:" | sed -${E} "s,.*,${SED_LIGHT_CYAN},g"
ls -ld /var/run/sudo/ts 2>/dev/null
if [ -w "/var/run/sudo/ts" ]; then
echo "/var/run/sudo/ts is writable" | sed -${E} "s,.*,${SED_RED},g"
fi
if [ -f "/var/run/sudo/ts/$USER" ]; then
ls -l "/var/run/sudo/ts/$USER" 2>/dev/null
if [ -w "/var/run/sudo/ts/$USER" ]; then
echo "User sudo token file is writable" | sed -${E} "s,.*,${SED_RED},g"
fi
fi
fi
echo ""

View File

@@ -1,64 +0,0 @@
# Title: Software Information - Browser Profiles
# ID: SW_Browser_profiles
# Author: Carlos Polop
# Last Update: 10-03-2025
# Description: List browser profiles that may store credentials/cookies
# License: GNU GPL
# Version: 1.0
# Functions Used: print_2title, print_3title, print_info
# Global Variables: $HOMESEARCH, $SED_RED
# Initial Functions:
# Generated Global Variables: $h, $firefox_ini, $chrome_base, $profiles
# Fat linpeas: 0
# Small linpeas: 1
print_2title "Browser Profiles"
print_info "https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#browser-data"
echo ""
for h in $HOMESEARCH; do
[ -d "$h" ] || continue
firefox_ini="$h/.mozilla/firefox/profiles.ini"
if [ -f "$firefox_ini" ]; then
print_3title "Firefox profiles ($h)"
awk -F= '
/^\[Profile/ { in_profile=1 }
/^Path=/ { path=$2 }
/^IsRelative=/ { isrel=$2 }
/^$/ {
if (path != "") {
if (isrel == "1") {
print base "/.mozilla/firefox/" path
} else {
print path
}
}
path=""; isrel=""
}
END {
if (path != "") {
if (isrel == "1") {
print base "/.mozilla/firefox/" path
} else {
print path
}
}
}
' base="$h" "$firefox_ini" 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
echo ""
fi
for chrome_base in "$h/.config/google-chrome" "$h/.config/chromium" "$h/.config/BraveSoftware/Brave-Browser" "$h/.config/microsoft-edge" "$h/.config/microsoft-edge-beta" "$h/.config/microsoft-edge-dev"; do
if [ -d "$chrome_base" ]; then
profiles=$(find "$chrome_base" -maxdepth 1 -type d \( -name "Default" -o -name "Profile *" \) 2>/dev/null)
if [ "$profiles" ]; then
print_3title "Chromium profiles ($chrome_base)"
printf "%s\n" "$profiles" | sed -${E} "s,.*,${SED_RED},"
echo ""
fi
fi
done
done

View File

@@ -37,14 +37,14 @@ printf "%s\n" "$suids_files" | while read s; do
else
c="a"
for b in $sidB; do
if echo "$sname" | grep -q $(echo $b | cut -d % -f 1); then
if echo $s | grep -q $(echo $b | cut -d % -f 1); then
echo "$s" | sed -${E} "s,$(echo $b | cut -d % -f 1),${C}[1;31m& ---> $(echo $b | cut -d % -f 2)${C}[0m,"
c=""
break;
fi
done;
if [ "$c" ]; then
if echo "$sname" | grep -qE "$sidG1" || echo "$sname" | grep -qE "$sidG2" || echo "$sname" | grep -qE "$sidG3" || echo "$sname" | grep -qE "$sidG4" || echo "$sname" | grep -qE "$sidVB" || echo "$sname" | grep -qE "$sidVB2"; then
if echo "$s" | grep -qE "$sidG1" || echo "$s" | grep -qE "$sidG2" || echo "$s" | grep -qE "$sidG3" || echo "$s" | grep -qE "$sidG4" || echo "$s" | grep -qE "$sidVB" || echo "$s" | grep -qE "$sidVB2"; then
echo "$s" | sed -${E} "s,$sidG1,${SED_GREEN}," | sed -${E} "s,$sidG2,${SED_GREEN}," | sed -${E} "s,$sidG3,${SED_GREEN}," | sed -${E} "s,$sidG4,${SED_GREEN}," | sed -${E} "s,$sidVB,${SED_RED_YELLOW}," | sed -${E} "s,$sidVB2,${SED_RED_YELLOW},"
else
echo "$s (Unknown SUID binary!)" | sed -${E} "s,/.*,${SED_RED},"
@@ -96,4 +96,4 @@ printf "%s\n" "$suids_files" | while read s; do
fi
fi
done;
echo ""
echo ""

View File

@@ -17,10 +17,10 @@ check_external_hostname(){
INTERNET_SEARCH_TIMEOUT=15
# wget or curl?
if command -v curl >/dev/null 2>&1; then
curl "https://tools.hacktricks.wiki/api/host-checker" -H "User-Agent: linpeas" -d "{\"hostname\":\"$(hostname)\"}" -H "Content-Type: application/json" --max-time "$INTERNET_SEARCH_TIMEOUT"
curl "https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/" -H "User-Agent: linpeas" -d "{\"hostname\":\"$(hostname)\"}" -H "Content-Type: application/json" --max-time "$INTERNET_SEARCH_TIMEOUT"
elif command -v wget >/dev/null 2>&1; then
wget -q -O - "https://tools.hacktricks.wiki/api/host-checker" --header "User-Agent: linpeas" --post-data "{\"hostname\":\"$(hostname)\"}" -H "Content-Type: application/json" --timeout "$INTERNET_SEARCH_TIMEOUT"
wget -q -O - "https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/" --header "User-Agent: linpeas" --post-data "{\"hostname\":\"$(hostname)\"}" -H "Content-Type: application/json" --timeout "$INTERNET_SEARCH_TIMEOUT"
else
echo "wget or curl not found"
fi
}
}

View File

@@ -15,12 +15,11 @@
check_tcp_443_bin () {
local TIMEOUT_INTERNET_SECONDS_443_BIN=$1
local url_lambda="https://tools.hacktricks.wiki/api/host-checker"
local url_lambda="https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/"
if command -v curl >/dev/null 2>&1; then
if curl -s --connect-timeout $TIMEOUT_INTERNET_SECONDS_443_BIN "$url_lambda" \
-H "User-Agent: linpeas" -H "Content-Type: application/json" \
-d "{\"hostname\":\"$(hostname)\"}" >/dev/null 2>&1
-H "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1
then
echo "Port 443 is accessible with curl"
return 0 # ✅ success
@@ -31,8 +30,7 @@ check_tcp_443_bin () {
elif command -v wget >/dev/null 2>&1; then
if wget -q --timeout=$TIMEOUT_INTERNET_SECONDS_443_BIN -O - "$url_lambda" \
--header "User-Agent: linpeas" -H "Content-Type: application/json" \
--post-data "{\"hostname\":\"$(hostname)\"}" >/dev/null 2>&1
--header "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1
then
echo "Port 443 is accessible with wget"
return 0

View File

@@ -0,0 +1,29 @@
# Title: Cloud - set_metadata_req_cmd
# ID: set_metadata_req_cmd
# Author: Carlos Polop
# Last Update: 22-08-2023
# Description: Set a metadata service request command based on curl/wget availability
# License: GNU GPL
# Version: 1.0
# Functions Used:
# Global Variables:
# Initial Functions:
# Generated Global Variables:
# Fat linpeas: 0
# Small linpeas: 1
set_metadata_req_cmd(){
local req_var="$1"
local header="$2"
if command -v curl >/dev/null 2>&1; then
printf -v "$req_var" "curl -s -f -L -H '%s'" "$header"
elif command -v wget >/dev/null 2>&1; then
printf -v "$req_var" "wget -q -O - --header '%s'" "$header"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
printf -v "$req_var" ""
return 1
fi
}

View File

@@ -15,5 +15,6 @@
sidG1="/abuild-sudo$|/accton$|/allocate$|/ARDAgent$|/arping$|/atq$|/atrm$|/authpf$|/authpf-noip$|/authopen$|/batch$|/bbsuid$|/bsd-write$|/btsockstat$|/bwrap$|/cacaocsc$|/camel-lock-helper-1.2$|/ccreds_validate$|/cdrw$|/chage$|/check-foreground-console$|/chrome-sandbox$|/chsh$|/cons.saver$|/crontab$|/ct$|/cu$|/dbus-daemon-launch-helper$|/deallocate$|/desktop-create-kmenu$|/dma$|/dma-mbox-create$|/dmcrypt-get-device$|/doas$|/dotlockfile$|/dotlock.mailutils$|/dtaction$|/dtfile$|/eject$|/execabrt-action-install-debuginfo-to-abrt-cache$|/execdbus-daemon-launch-helper$|/execdma-mbox-create$|/execlockspool$|/execlogin_chpass$|/execlogin_lchpass$|/execlogin_passwd$|/execssh-keysign$|/execulog-helper$|/exim4|/expiry$|/fdformat$|/fstat$|/fusermount$|/fusermount3$"
sidG2="/gnome-pty-helper$|/glines$|/gnibbles$|/gnobots2$|/gnome-suspend$|/gnometris$|/gnomine$|/gnotski$|/gnotravex$|/gpasswd$|/gpg$|/gpio$|/gtali|/.hal-mtab-lock$|/helper$|/imapd$|/inndstart$|/kismet_cap_nrf_51822$|/kismet_cap_nxp_kw41z$|/kismet_cap_ti_cc_2531$|/kismet_cap_ti_cc_2540$|/kismet_cap_ubertooth_one$|/kismet_capture$|/kismet_cap_linux_bluetooth$|/kismet_cap_linux_wifi$|/kismet_cap_nrf_mousejack$|/ksu$|/list_devices$|/load_osxfuse$|/locate$|/lock$|/lockdev$|/lockfile$|/login_activ$|/login_crypto$|/login_radius$|/login_skey$|/login_snk$|/login_token$|/login_yubikey$|/lpc$|/lpd$|/lpd-port$|/lppasswd$|/lpq$|/lpr$|/lprm$|/lpset$|/lxc-user-nic$|/mahjongg$|/mail-lock$|/mailq$|/mail-touchlock$|/mail-unlock$|/mksnap_ffs$|/mlocate$|/mlock$|/mount$|/mount.cifs$|/mount.ecryptfs_private$|/mount.nfs$|/mount.nfs4$|/mount_osxfuse$|/mtr$|/mutt_dotlock$"
sidG3="/ncsa_auth$|/netpr$|/netkit-rcp$|/netkit-rlogin$|/netkit-rsh$|/netreport$|/netstat$|/newgidmap$|/newtask$|/newuidmap$|/nvmmctl$|/opieinfo$|/opiepasswd$|/pam_auth$|/pam_extrausers_chkpwd$|/pam_timestamp_check$|/pamverifier$|/pfexec$|/hping3$|/ping$|/ping6$|/pmconfig$|/pmap$|/polkit-agent-helper-1$|/polkit-explicit-grant-helper$|/polkit-grant-helper$|/polkit-grant-helper-pam$|/polkit-read-auth-helper$|/polkit-resolve-exe-helper$|/polkit-revoke-helper$|/polkit-set-default-helper$|/postdrop$|/postqueue$|/poweroff$|/ppp$|/procmail$|/pstat$|/pt_chmod$|/pwdb_chkpwd$|/quota$|/rcmd|/remote.unknown$|/rlogin$|/rmformat$|/rnews$|/run-mailcap$|/sacadm$|/same-gnome$|screen.real$|/security_authtrampoline$|/sendmail.sendmail$|/shutdown$|/skeyaudit$|/skeyinfo$|/skeyinit$|/sliplogin|/slocate$|/smbmnt$|/smbumount$|/smpatch$|/smtpctl$|/sperl5.8.8$|/ssh-agent$|/ssh-keysign$|/staprun$|/startinnfeed$|/stclient$|/su$|/suexec$|/sys-suspend$|/sysstat$|/systat$"
sidG3="/ncsa_auth$|/netpr$|/netkit-rcp$|/netkit-rlogin$|/netkit-rsh$|/netreport$|/netstat$|/newgidmap$|/newtask$|/newuidmap$|/nvmmctl$|/opieinfo$|/opiepasswd$|/pam_auth$|/pam_extrausers_chkpwd$|/pam_timestamp_check$|/pamverifier$|/pfexec$|/ping$|/ping6$|/pmconfig$|/pmap$|/polkit-agent-helper-1$|/polkit-explicit-grant-helper$|/polkit-grant-helper$|/polkit-grant-helper-pam$|/polkit-read-auth-helper$|/polkit-resolve-exe-helper$|/polkit-revoke-helper$|/polkit-set-default-helper$|/postdrop$|/postqueue$|/poweroff$|/ppp$|/procmail$|/pstat$|/pt_chmod$|/pwdb_chkpwd$|/quota$|/rcmd|/remote.unknown$|/rlogin$|/rmformat$|/rnews$|/run-mailcap$|/sacadm$|/same-gnome$|screen.real$|/security_authtrampoline$|/sendmail.sendmail$|/shutdown$|/skeyaudit$|/skeyinfo$|/skeyinit$|/sliplogin|/slocate$|/smbmnt$|/smbumount$|/smpatch$|/smtpctl$|/sperl5.8.8$|/ssh-agent$|/ssh-keysign$|/staprun$|/startinnfeed$|/stclient$|/su$|/suexec$|/sys-suspend$|/sysstat$|/systat$"
sidG4="/telnetlogin$|/timedc$|/tip$|/top$|/traceroute6$|/traceroute6.iputils$|/trpt$|/tsoldtlabel$|/tsoljdslabel$|/tsolxagent$|/ufsdump$|/ufsrestore$|/ulog-helper$|/umount.cifs$|/umount.nfs$|/umount.nfs4$|/unix_chkpwd$|/uptime$|/userhelper$|/userisdnctl$|/usernetctl$|/utempter$|/utmp_update$|/uucico$|/uuglist$|/uuidd$|/uuname$|/uusched$|/uustat$|/uux$|/uuxqt$|/VBoxHeadless$|/VBoxNetAdpCtl$|/VBoxNetDHCP$|/VBoxNetNAT$|/VBoxSDL$|/VBoxVolInfo$|/VirtualBoxVM$|/vmstat$|/vmware-authd$|/vmware-user-suid-wrapper$|/vmware-vmx$|/vmware-vmx-debug$|/vmware-vmx-stats$|/vncserver-x11$|/volrmmount$|/w$|/wall$|/whodo$|/write$|/X$|/Xorg.wrap$|/Xsun$|/Xvnc$|/yppasswd$"

View File

@@ -13,5 +13,5 @@
# Small linpeas: 1
sudoVB1=" \*|env_keep\W*\+=.*LD_PRELOAD|env_keep\W*\+=.*LD_LIBRARY_PATH|env_keep\W*\+=.*BASH_ENV|env_keep\W*\+=.* ENV|env_keep\W*\+=.*PATH|!env_reset|!requiretty|peass{SUDOVB1_HERE}"
sudoVB1=" \*|env_keep\W*\+=.*LD_PRELOAD|env_keep\W*\+=.*LD_LIBRARY_PATH|env_keep\W*\+=.*BASH_ENV|env_keep\W*\+=.* ENV|peass{SUDOVB1_HERE}"
sudoVB2="peass{SUDOVB2_HERE}"

View File

@@ -405,7 +405,7 @@ class LinpeasBuilder:
name = entry["name"]
caseinsensitive = entry.get("caseinsensitive", False)
regex = entry["regex"]
regex = regex.replace("\\", "\\\\").replace('"', '\\"').strip()
regex = regex.replace('"', '\\"').strip()
falsePositives = entry.get("falsePositives", False)
if falsePositives:

View File

@@ -1,40 +0,0 @@
import os
import stat
import subprocess
import tempfile
import unittest
from pathlib import Path
class LinpeasBuilderTests(unittest.TestCase):
def setUp(self):
self.repo_root = Path(__file__).resolve().parents[2]
self.linpeas_dir = self.repo_root / "linPEAS"
def _run_builder(self, args, output_path):
cmd = ["python3", "-m", "builder.linpeas_builder"] + args + ["--output", str(output_path)]
result = subprocess.run(cmd, cwd=str(self.linpeas_dir), capture_output=True, text=True)
if result.returncode != 0:
raise AssertionError(
f"linpeas_builder failed:\nstdout:\n{result.stdout}\nstderr:\n{result.stderr}"
)
def test_small_build_creates_executable(self):
with tempfile.TemporaryDirectory() as tmpdir:
output_path = Path(tmpdir) / "linpeas_small.sh"
self._run_builder(["--small"], output_path)
self.assertTrue(output_path.exists(), "linpeas_small.sh was not created.")
mode = output_path.stat().st_mode
self.assertTrue(mode & stat.S_IXUSR, "linpeas_small.sh is not executable.")
def test_include_exclude_modules(self):
with tempfile.TemporaryDirectory() as tmpdir:
output_path = Path(tmpdir) / "linpeas_include.sh"
self._run_builder(["--include", "system_information,container", "--exclude", "container"], output_path)
content = output_path.read_text(encoding="utf-8", errors="ignore")
self.assertIn("Operative system", content)
self.assertNotIn("Am I Containered?", content)
if __name__ == "__main__":
unittest.main()

View File

@@ -127,9 +127,7 @@ def parse_line(line: str):
elif is_section(line, INFO_PATTERN):
title = parse_title(line)
if C_SECTION == {}:
return
C_SECTION.setdefault("infos", []).append(title)
C_SECTION["infos"].append(title)
#If here, then it's text
else:

View File

@@ -71,7 +71,7 @@ CALL :T_Progress 2
:ListHotFixes
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic qfe get Caption,Description,HotFixID,InstalledOn
wmic qfe get Caption,Description,HotFixID,InstalledOn | more
) else (
powershell -command "Get-HotFix | Format-Table -AutoSize"
)
@@ -204,7 +204,7 @@ CALL :T_Progress 1
CALL :ColorLine " %E%33m[+]%E%97m Registered Anti-Virus(AV)"
where wmic >nul 2>&1
if %errorlevel% equ 0 (
WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List
WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List | more
) else (
powershell -command "Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct | Select-Object -ExpandProperty displayName"
)
@@ -238,7 +238,7 @@ CALL :ColorLine " %E%33m[+]%E%97m MOUNTED DISKS"
ECHO. [i] Maybe you find something interesting
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic logicaldisk get caption
wmic logicaldisk get caption | more
) else (
fsutil fsinfo drives
)
@@ -670,7 +670,7 @@ if "%long%" == "true" (
ECHO.
where wmic >nul 2>&1
if !errorlevel! equ 0 (
for /f %%x in ('wmic logicaldisk get name') do (
for /f %%x in ('wmic logicaldisk get name ^| more') do (
set tdrive=%%x
if "!tdrive:~1,2!" == ":" (
%%x

View File

@@ -1,26 +0,0 @@
cmake_minimum_required(VERSION 3.16)
project(winPEAS_dotnet NONE)
set(PROJECT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/winPEAS.csproj")
find_program(DOTNET_EXECUTABLE dotnet)
find_program(MSBUILD_EXECUTABLE msbuild)
find_program(XBUILD_EXECUTABLE xbuild)
if(DOTNET_EXECUTABLE)
set(BUILD_TOOL "${DOTNET_EXECUTABLE}")
set(BUILD_ARGS build "${PROJECT_FILE}" -c Release)
elseif(MSBUILD_EXECUTABLE)
set(BUILD_TOOL "${MSBUILD_EXECUTABLE}")
set(BUILD_ARGS "${PROJECT_FILE}" /p:Configuration=Release)
elseif(XBUILD_EXECUTABLE)
set(BUILD_TOOL "${XBUILD_EXECUTABLE}")
set(BUILD_ARGS "${PROJECT_FILE}" /p:Configuration=Release)
else()
message(FATAL_ERROR "dotnet, msbuild, or xbuild is required to build winPEAS")
endif()
add_custom_target(winpeas ALL
COMMAND ${BUILD_TOOL} ${BUILD_ARGS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)

View File

@@ -128,7 +128,7 @@ Once you have installed and activated it you need to:
- **System Information**
- [x] Basic System info information
- [x] Use WES-NG to search for vulnerabilities
- [x] Use Watson to search for vulnerabilities
- [x] Enumerate Microsoft updates
- [x] PS, Audit, WEF and LAPS Settings
- [x] LSA protection
@@ -262,7 +262,7 @@ Once you have installed and activated it you need to:
## TODO
- Add more checks
- Maintain updated WES-NG
- Mantain updated Watson (last JAN 2021)
If you want to help with any of this, you can do it using **[github issues](https://github.com/peass-ng/PEASS-ng/issues)** or you can submit a pull request.

View File

@@ -1,36 +0,0 @@
using System;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using winPEAS.Checks;
namespace winPEAS.Tests
{
[TestClass]
public class ArgumentParsingTests
{
private static bool InvokeIsNetworkTypeValid(string arg)
{
var method = typeof(Checks).GetMethod("IsNetworkTypeValid", BindingFlags.NonPublic | BindingFlags.Static);
Assert.IsNotNull(method, "IsNetworkTypeValid method not found.");
return (bool)method.Invoke(null, new object[] { arg });
}
[TestMethod]
public void ShouldAcceptValidNetworkTypes()
{
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=auto"));
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=10.10.10.10"));
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=10.10.10.10/24"));
Assert.IsTrue(InvokeIsNetworkTypeValid("-network=10.10.10.10,10.10.10.20"));
}
[TestMethod]
public void ShouldRejectInvalidNetworkTypes()
{
Assert.IsFalse(InvokeIsNetworkTypeValid("-network="));
Assert.IsFalse(InvokeIsNetworkTypeValid("-network=10.10.10.999"));
Assert.IsFalse(InvokeIsNetworkTypeValid("-network=10.10.10.10/64"));
Assert.IsFalse(InvokeIsNetworkTypeValid("-network=not-an-ip"));
}
}
}

View File

@@ -95,7 +95,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArgumentParsingTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SmokeTests.cs" />
</ItemGroup>
@@ -134,4 +133,4 @@
<Import Project="..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net451\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net451\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<Import Project="..\packages\Fody.6.5.5\build\Fody.targets" Condition="Exists('..\packages\Fody.6.5.5\build\Fody.targets')" />
<Import Project="..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" />
</Project>
</Project>

View File

@@ -392,7 +392,7 @@ namespace winPEAS.Checks
foreach (string regHkcu in passRegHkcu)
{
Beaprint.DictPrint(RegistryHelper.GetRegValues("HKCU", regHkcu), false);
Beaprint.DictPrint(RegistryHelper.GetRegValues("HKLM", regHkcu), false);
}
foreach (string regHklm in passRegHklm)

View File

@@ -88,7 +88,6 @@ namespace winPEAS.Checks
PrintLocalGroupPolicy,
PrintPotentialGPOAbuse,
AppLockerHelper.PrintAppLockerPolicy,
PrintPrintNightmarePointAndPrint,
PrintPrintersWMIInfo,
PrintNamedPipes,
PrintNamedPipeAbuseCandidates,
@@ -837,39 +836,6 @@ namespace winPEAS.Checks
}
}
private static void PrintPrintNightmarePointAndPrint()
{
Beaprint.MainPrint("PrintNightmare PointAndPrint Policies");
Beaprint.LinkPrint("https://itm4n.github.io/printnightmare-exploitation/", "Check PointAndPrint policy hardening");
try
{
string key = @"Software\\Policies\\Microsoft\\Windows NT\\Printers\\PointAndPrint";
var restrict = RegistryHelper.GetDwordValue("HKLM", key, "RestrictDriverInstallationToAdministrators");
var noWarn = RegistryHelper.GetDwordValue("HKLM", key, "NoWarningNoElevationOnInstall");
var updatePrompt = RegistryHelper.GetDwordValue("HKLM", key, "UpdatePromptSettings");
if (restrict == null && noWarn == null && updatePrompt == null)
{
Beaprint.NotFoundPrint();
return;
}
Beaprint.NoColorPrint($" RestrictDriverInstallationToAdministrators: {restrict}\n" +
$" NoWarningNoElevationOnInstall: {noWarn}\n" +
$" UpdatePromptSettings: {updatePrompt}");
if (restrict == 0 && noWarn == 1 && updatePrompt == 2)
{
Beaprint.BadPrint(" [!] Potentially vulnerable to PrintNightmare misconfiguration");
}
}
catch (Exception ex)
{
Beaprint.PrintException(ex.Message);
}
}
private static void PrintPrintersWMIInfo()
{
Beaprint.MainPrint("Enumerating Printers (WMI)");

View File

@@ -46,7 +46,7 @@ namespace winPEAS.Info.NetworkInfo
// 4. Call external checker
var resp = httpClient
.PostAsync("https://tools.hacktricks.wiki/api/host-checker", payload)
.PostAsync("https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/", payload)
.GetAwaiter().GetResult();
if (resp.IsSuccessStatusCode)

View File

@@ -4,8 +4,6 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Threading;
namespace winPEAS.Info.NetworkInfo
@@ -50,7 +48,7 @@ namespace winPEAS.Info.NetworkInfo
{ "1.1.1.1", "8.8.8.8" };
private const string LAMBDA_URL =
"https://tools.hacktricks.wiki/api/host-checker";
"https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/";
// Shared HttpClient (kept for HTTP & Lambda checks)
private static readonly HttpClient http = new HttpClient
@@ -120,12 +118,7 @@ namespace winPEAS.Info.NetworkInfo
using var cts =
new CancellationTokenSource(TimeSpan.FromMilliseconds(HTTP_TIMEOUT_MS));
var payload = new StringContent(
JsonSerializer.Serialize(new { hostname = Environment.MachineName }),
Encoding.UTF8,
"application/json");
var req = new HttpRequestMessage(HttpMethod.Post, LAMBDA_URL);
req.Content = payload;
var req = new HttpRequestMessage(HttpMethod.Get, LAMBDA_URL);
req.Headers.UserAgent.ParseAdd("winpeas");
req.Headers.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));

View File

@@ -16,10 +16,6 @@ namespace winPEAS.Info.UserInfo.SAM
{
get
{
if (_maxPasswordAge == long.MinValue)
{
return TimeSpan.MinValue;
}
return -new TimeSpan(_maxPasswordAge);
}
set
@@ -32,10 +28,6 @@ namespace winPEAS.Info.UserInfo.SAM
{
get
{
if (_minPasswordAge == long.MinValue)
{
return TimeSpan.MinValue;
}
return -new TimeSpan(_minPasswordAge);
}
set

View File

@@ -88,10 +88,6 @@ namespace winPEAS.KnownFileCreds
if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes"))
{
string[] subKeys = RegistryHelper.GetRegSubkeys("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions\\", SID));
if (subKeys.Length == 0)
{
subKeys = RegistryHelper.GetRegSubkeys("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\Sessions", SID));
}
foreach (string sessionName in subKeys)
{
@@ -133,10 +129,6 @@ namespace winPEAS.KnownFileCreds
else
{
string[] subKeys = RegistryHelper.GetRegSubkeys("HKCU", "Software\\SimonTatham\\PuTTY\\Sessions\\");
if (subKeys.Length == 0)
{
subKeys = RegistryHelper.GetRegSubkeys("HKCU", "Software\\SimonTatham\\PuTTY\\Sessions");
}
RegistryKey selfKey = Registry.CurrentUser.OpenSubKey(@"Software\\SimonTatham\\PuTTY\\Sessions"); // extract own Sessions registry keys
if (selfKey != null)
@@ -206,10 +198,6 @@ namespace winPEAS.KnownFileCreds
if (SID.StartsWith("S-1-5") && !SID.EndsWith("_Classes"))
{
Dictionary<string, object> hostKeys = RegistryHelper.GetRegValues("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\SshHostKeys\\", SID));
if ((hostKeys == null) || (hostKeys.Count == 0))
{
hostKeys = RegistryHelper.GetRegValues("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\SshHostKeys", SID));
}
if ((hostKeys != null) && (hostKeys.Count != 0))
{
Dictionary<string, string> putty_ssh = new Dictionary<string, string>
@@ -228,10 +216,6 @@ namespace winPEAS.KnownFileCreds
else
{
Dictionary<string, object> hostKeys = RegistryHelper.GetRegValues("HKCU", "Software\\SimonTatham\\PuTTY\\SshHostKeys\\");
if ((hostKeys == null) || (hostKeys.Count == 0))
{
hostKeys = RegistryHelper.GetRegValues("HKCU", "Software\\SimonTatham\\PuTTY\\SshHostKeys");
}
if ((hostKeys != null) && (hostKeys.Count != 0))
{
Dictionary<string, string> putty_ssh = new Dictionary<string, string>();

View File

@@ -11,7 +11,6 @@ namespace winPEAS
[STAThread]
public static void Main(string[] args)
{
// TODO: keep Main minimal; this line was an intentional break in test PR.
Checks.Checks.Run(args);
}
}

View File

@@ -815,40 +815,12 @@ systeminfo.exe
Write-Host ""
if ($TimeStamp) { TimeElapsed }
Write-Host -ForegroundColor Blue "=========|| WINDOWS HOTFIXES"
Write-Host "=| Check missing patches with WES-NG https://github.com/bitsadmin/wesng" -ForegroundColor Yellow
Write-Host "=| Check if windows is vulnerable with Watson https://github.com/rasta-mouse/Watson" -ForegroundColor Yellow
Write-Host "Possible exploits (https://github.com/codingo/OSCP-2/blob/master/Windows/WinPrivCheck.bat)" -ForegroundColor Yellow
$Hotfix = Get-HotFix | Sort-Object -Descending -Property InstalledOn -ErrorAction SilentlyContinue | Select-Object HotfixID, Description, InstalledBy, InstalledOn
$Hotfix | Format-Table -AutoSize
# PrintNightmare PointAndPrint policy checks
Write-Host ""
if ($TimeStamp) { TimeElapsed }
Write-Host -ForegroundColor Blue "=========|| PRINTNIGHTMARE POINTANDPRINT POLICY"
$pnKey = "HKLM:\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
if (Test-Path $pnKey) {
$pn = Get-ItemProperty -Path $pnKey -ErrorAction SilentlyContinue
$restrict = $pn.RestrictDriverInstallationToAdministrators
$noWarn = $pn.NoWarningNoElevationOnInstall
$updatePrompt = $pn.UpdatePromptSettings
Write-Host "RestrictDriverInstallationToAdministrators: $restrict"
Write-Host "NoWarningNoElevationOnInstall: $noWarn"
Write-Host "UpdatePromptSettings: $updatePrompt"
$hasAllValues = ($null -ne $restrict) -and ($null -ne $noWarn) -and ($null -ne $updatePrompt)
if (-not $hasAllValues) {
Write-Host "PointAndPrint policy values are missing or not configured" -ForegroundColor Gray
} elseif (($restrict -eq 0) -and ($noWarn -eq 1) -and ($updatePrompt -eq 2)) {
Write-Host "Potentially vulnerable to PrintNightmare misconfiguration" -ForegroundColor Red
} else {
Write-Host "PointAndPrint policy is not in the known risky configuration" -ForegroundColor Green
}
} else {
Write-Host "PointAndPrint policy key not found" -ForegroundColor Gray
}
#Show all unique updates installed
Write-Host ""
if ($TimeStamp) { TimeElapsed }