mirror of
https://github.com/rvrsh3ll/Misc-Powershell-Scripts
synced 2026-06-21 14:09:04 +00:00
586 lines
19 KiB
PowerShell
586 lines
19 KiB
PowerShell
function Invoke-ThreadedFunction
|
|
{
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Position = 0, Mandatory = $false)]
|
|
[String[]]$ComputerName,
|
|
[String[]]$VulnLinks,
|
|
[Parameter(Position = 1, Mandatory = $True)]
|
|
[System.Management.Automation.ScriptBlock]$ScriptBlock,
|
|
[Parameter(Position = 2)]
|
|
[Hashtable]$ScriptParameters,
|
|
[Int]$Threads = 20,
|
|
[Int]$Timeout = 100,
|
|
[Int]$Hostcount
|
|
)
|
|
|
|
begin
|
|
{
|
|
|
|
if ($PSBoundParameters['Debug'])
|
|
{
|
|
$DebugPreference = 'Continue'
|
|
}
|
|
if ($ComputerName)
|
|
{
|
|
Write-Verbose "[*] Total number of hosts: $($ComputerName.count)"
|
|
}
|
|
elseif ($VulnLinks)
|
|
{
|
|
Write-Verbose "[*] Total number of URL's: $($VulnLinks.count*$Hostcount)"
|
|
}
|
|
|
|
|
|
# Adapted from:
|
|
# http://powershell.org/wp/forums/topic/invpke-parallel-need-help-to-clone-the-current-runspace/
|
|
$SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
|
|
$SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState()
|
|
|
|
# threading adapted from
|
|
# https://github.com/darkoperator/Posh-SecMod/blob/master/Discovery/Discovery.psm1#L407
|
|
# Thanks Carlos!
|
|
# create a pool of maxThread runspaces
|
|
$Pool = [runspacefactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host)
|
|
$Pool.Open()
|
|
|
|
$Jobs = @()
|
|
$PS = @()
|
|
$Wait = @()
|
|
|
|
$Counter = 0
|
|
}
|
|
|
|
process
|
|
{
|
|
|
|
if ($ComputerName)
|
|
{
|
|
ForEach ($Computer in $ComputerName)
|
|
{
|
|
|
|
# make sure we get a server name
|
|
if ($Computer -ne '')
|
|
{
|
|
|
|
While ($($Pool.GetAvailableRunspaces()) -le 0)
|
|
{
|
|
Start-Sleep -MilliSeconds $Timeout
|
|
}
|
|
|
|
# create a "powershell pipeline runner"
|
|
$PS += [powershell]::create()
|
|
$PS[$Counter].runspacepool = $Pool
|
|
|
|
# add the script block + arguments
|
|
$Null = $PS[$Counter].AddScript($ScriptBlock).AddParameter('ComputerName', $Computer)
|
|
if ($ScriptParameters)
|
|
{
|
|
ForEach ($Param in $ScriptParameters.GetEnumerator())
|
|
{
|
|
$Null = $PS[$Counter].AddParameter($Param.Name, $Param.Value)
|
|
}
|
|
}
|
|
|
|
# start job
|
|
$Jobs += $PS[$Counter].BeginInvoke();
|
|
|
|
# store wait handles for WaitForAll call
|
|
$Wait += $Jobs[$Counter].AsyncWaitHandle
|
|
}
|
|
$Counter = $Counter + 1
|
|
}
|
|
}
|
|
elseif ($VulnLinks)
|
|
{
|
|
ForEach ($testlink in $VulnLinks)
|
|
{
|
|
# make sure we get a server name
|
|
if ($testlink -ne '')
|
|
{
|
|
|
|
While ($($Pool.GetAvailableRunspaces()) -le 0)
|
|
{
|
|
Start-Sleep -MilliSeconds $Timeout
|
|
}
|
|
|
|
# create a "powershell pipeline runner"
|
|
$PS += [powershell]::create()
|
|
$PS[$Counter].runspacepool = $Pool
|
|
|
|
# add the script block + arguments
|
|
$Null = $PS[$Counter].AddScript($ScriptBlock).AddParameter('VulnLinks', $testlink)
|
|
if ($ScriptParameters)
|
|
{
|
|
ForEach ($Param in $ScriptParameters.GetEnumerator())
|
|
{
|
|
$Null = $PS[$Counter].AddParameter($Param.Name, $Param.Value)
|
|
}
|
|
}
|
|
|
|
# start job
|
|
$Jobs += $PS[$Counter].BeginInvoke();
|
|
|
|
# store wait handles for WaitForAll call
|
|
$Wait += $Jobs[$Counter].AsyncWaitHandle
|
|
}
|
|
$Counter = $Counter + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
end
|
|
{
|
|
|
|
Write-Verbose "Waiting for scanning threads to finish..."
|
|
$WaitTimeout = Get-Date
|
|
|
|
# set a 60 second timeout for the scanning threads
|
|
while ($($Jobs | Where-Object { $_.IsCompleted -eq $False }).count -gt 0 -or $($($(Get-Date) - $WaitTimeout).totalSeconds) -gt 60)
|
|
{
|
|
Start-Sleep -MilliSeconds $Timeout
|
|
}
|
|
|
|
# end async call
|
|
for ($y = 0; $y -lt $Counter; $y++)
|
|
{
|
|
|
|
try
|
|
{
|
|
# complete async job
|
|
$PS[$y].EndInvoke($Jobs[$y])
|
|
|
|
}
|
|
catch
|
|
{
|
|
Write-Warning "error: $_"
|
|
}
|
|
finally
|
|
{
|
|
$PS[$y].Dispose()
|
|
}
|
|
}
|
|
|
|
$Pool.Dispose()
|
|
Write-Verbose "All threads completed!"
|
|
}
|
|
}
|
|
|
|
function Find-Fruit
|
|
|
|
{
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
|
|
Search for "low hanging fruit".
|
|
.DESCRIPTION
|
|
|
|
A script to find potentially easily exploitable web servers on a target network.
|
|
|
|
.PARAMETER Rhosts
|
|
|
|
Targets in CIDR or comma separated format.
|
|
|
|
.PARAMETER Port
|
|
|
|
Specifies the port to connect to.
|
|
|
|
.PARAMETER Path
|
|
|
|
Path to custom dictionary.
|
|
|
|
.PARAMETER Timeout
|
|
|
|
Timeout for each connection in milliseconds.
|
|
|
|
.PARAMETER UseSSL
|
|
|
|
Use an SSL connection.
|
|
|
|
.PARAMETER Threads
|
|
|
|
The maximum concurrent threads to execute..
|
|
|
|
.PARAMETER WebProxy
|
|
|
|
Specify an http proxy
|
|
|
|
.PARAMETER ProxyPort
|
|
|
|
Specify the http proxy port
|
|
|
|
|
|
.EXAMPLE
|
|
|
|
C:\PS> Find-Fruit -Rhosts 192.168.1.0/24 -Port 8080
|
|
C:\PS> Find-Fruit -Rhosts 192.168.1.0/24 -Path dictionary.txt -Port 8443 -UseSSL
|
|
C:\PS> Find-Fruit -Rhosts 192.168.1.0/24 -Port 8080 -WebProxy 127.0.0.1 -ProxyPort 8080
|
|
|
|
|
|
.NOTES
|
|
Credits to mattifestation for Get-HttpStatus
|
|
HTTP Status Codes: 100 - Informational * 200 - Success * 300 - Redirection * 400 - Client Error * 500 - Server Error
|
|
|
|
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
|
|
param (
|
|
[Parameter(Mandatory = $True)]
|
|
[String]$Rhosts,
|
|
[Parameter(Mandatory=$False)]
|
|
[Int]$Port,
|
|
[Parameter(Mandatory=$False)]
|
|
[String]$Path,
|
|
[Parameter(Mandatory=$False)]
|
|
[Int]$Timeout = 110,
|
|
[Parameter(Mandatory=$False)]
|
|
[Switch]$UseSSL,
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateRange(1, 100)]
|
|
[Int]$Threads,
|
|
[Parameter(Mandatory=$False)]
|
|
[String]$WebProxy,
|
|
[Parameter(Mandatory=$False)]
|
|
[String]$ProxyPort
|
|
)
|
|
|
|
begin {
|
|
$hostList = New-Object System.Collections.ArrayList
|
|
|
|
$iHosts = $Rhosts -split ","
|
|
|
|
foreach ($iHost in $iHosts) {
|
|
$iHost = $iHost.Replace(" ", "")
|
|
|
|
if (!$iHost) {
|
|
continue
|
|
}
|
|
|
|
if ($iHost.contains("/")) {
|
|
$netPart = $iHost.split("/")[0]
|
|
[uint32]$maskPart = $iHost.split("/")[1]
|
|
|
|
$address = [System.Net.IPAddress]::Parse($netPart)
|
|
if ($maskPart -ge $address.GetAddressBytes().Length * 8) {
|
|
throw "Bad host mask"
|
|
}
|
|
|
|
$numhosts = [System.math]::Pow(2, (($address.GetAddressBytes().Length * 8) - $maskPart))
|
|
|
|
$startaddress = $address.GetAddressBytes()
|
|
[array]::Reverse($startaddress)
|
|
|
|
$startaddress = [System.BitConverter]::ToUInt32($startaddress, 0)
|
|
[uint32]$startMask = ([System.math]::Pow(2, $maskPart) - 1) * ([System.Math]::Pow(2, (32 - $maskPart)))
|
|
$startAddress = $startAddress -band $startMask
|
|
#in powershell 2.0 there are 4 0 bytes padded, so the [0..3] is necessary
|
|
$startAddress = [System.BitConverter]::GetBytes($startaddress)[0..3]
|
|
[array]::Reverse($startaddress)
|
|
$address = [System.Net.IPAddress][byte[]]$startAddress
|
|
|
|
$Null = $hostList.Add($address.IPAddressToString)
|
|
|
|
for ($i = 0; $i -lt $numhosts - 1; $i++) {
|
|
$nextAddress = $address.GetAddressBytes()
|
|
[array]::Reverse($nextAddress)
|
|
$nextAddress = [System.BitConverter]::ToUInt32($nextAddress, 0)
|
|
$nextAddress++
|
|
$nextAddress = [System.BitConverter]::GetBytes($nextAddress)[0..3]
|
|
[array]::Reverse($nextAddress)
|
|
$address = [System.Net.IPAddress][byte[]]$nextAddress
|
|
$Null = $hostList.Add($address.IPAddressToString)
|
|
}
|
|
|
|
}
|
|
else {
|
|
$Null = $hostList.Add($iHost)
|
|
}
|
|
}
|
|
|
|
$HostEnumBlock = {
|
|
param($ComputerName, $UseSSL, $Port, $Path, $Timeout)
|
|
|
|
if ($UseSSL -and $Port -eq 0) {
|
|
# Default to 443 if SSL is specified but no port is specified
|
|
$Port = 443
|
|
}
|
|
elseif ($Port -eq 0) {
|
|
# Default to port 80 if no port is specified
|
|
$Port = 80
|
|
}
|
|
|
|
|
|
if ($UseSSL) {
|
|
$SSL = 's'
|
|
# Ignore invalid SSL certificates
|
|
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
|
|
}
|
|
else {
|
|
$SSL = ''
|
|
}
|
|
|
|
if (($Port -eq 80) -or ($Port -eq 443)) {
|
|
$PortNum = ''
|
|
}
|
|
else {
|
|
$PortNum = ":$Port"
|
|
}
|
|
|
|
if ($Path) {
|
|
if (!(Test-Path -Path $Path)) { Throw "File doesnt exist" }
|
|
$VulnLinks = @()
|
|
foreach ($Link in Get-Content $Path) {
|
|
$VulnLinks = $VulnLinks + $Link
|
|
}
|
|
}
|
|
else {
|
|
$VulnLinks = @()
|
|
$VulnLinks = $VulnLinks + "jmx-console/" # Jboss
|
|
$VulnLinks = $VulnLinks + "web-console/ServerInfo.jsp" # Jboss
|
|
$VulnLinks = $VulnLinks + "invoker/JMXInvokerServlet" # Jboss
|
|
$VulnLinks = $VulnLinks + "system/console" # OSGi console
|
|
$VulnLinks = $VulnLinks + "axis2/axis2-admin/" # Apache Axis2
|
|
$VulnLinks = $VulnLinks + "manager/html/" # Tomcat
|
|
$VulnLinks = $VulnLinks + "tomcat/manager/html/" # Tomcat
|
|
$VulnLinks = $VulnLinks + "wp-admin" # Wordpress
|
|
$VulnLinks = $VulnLinks + "workorder/FileDownload.jsp" #Manage Engine
|
|
$VulnLinks = $VulnLinks + "ibm/console/logon.jsp?action=OK" # WebSphere
|
|
$VulnLinks = $VulnLinks + "data/login" # Dell iDrac
|
|
$VulnLinks = $VulnLinks + "script/" # Jenkins Script Conosle
|
|
$VulnLinks = $VulnLinks + "opennms/" # OpenNMS
|
|
$VulnLinks = $VulnLinks + "RDWeb/Pages/en-US/Default.aspx" #RDS Remote Desktop
|
|
$VulnLinks = $VulnLinks + "securityRealm/user/admin/" #Jenkins Vuln Check
|
|
}
|
|
|
|
# Check Http status for each entry in the host
|
|
foreach ($Target in $ComputerName) {
|
|
|
|
|
|
foreach ($Item in $Vulnlinks) {
|
|
$WebTarget = "http$($SSL)://$($Target)$($PortNum)/$($Item)"
|
|
$URI = New-Object Uri($WebTarget)
|
|
|
|
try {
|
|
$WebRequest = [System.Net.WebRequest]::Create($URI)
|
|
$WebRequest.Headers.Add('UserAgent', $UserAgent)
|
|
$ProxyAddress = New-Object System.Net.WebProxy("http://$($WebProxy):$($ProxyPort)",$true)
|
|
$WebRequest.Proxy = $ProxyAddress
|
|
$WebResponse = $WebRequest.Timeout = $Timeout
|
|
$WebResponse = $WebRequest.GetResponse()
|
|
$WebStatus = $WebResponse.StatusCode
|
|
$ResultObject += $ScanObject
|
|
$WebResponse.Close()
|
|
}
|
|
catch {
|
|
$WebStatus = $Error[0].Exception.InnerException.Response.StatusCode
|
|
if ($WebStatus -eq $null) {
|
|
# Not every exception returns a StatusCode.
|
|
# If that is the case, return the Status.
|
|
$WebStatus = $Error[0].Exception.InnerException.Status
|
|
}
|
|
}
|
|
|
|
$Result = @{
|
|
Status = $WebStatus;
|
|
URL = $WebTarget
|
|
}
|
|
|
|
New-Object -TypeName PSObject -Property $Result | Where-Object {$_.Status -eq 'OK'}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
process {
|
|
|
|
if($Threads) {
|
|
Write-Verbose "Using threading with threads = $Threads"
|
|
|
|
# if we're using threading, kick off the script block with Invoke-ThreadedFunction
|
|
$ScriptParams = @{
|
|
'UseSSL' = $UseSSL
|
|
'Port' = $Port
|
|
'Path' = $Path
|
|
'Timeout' = $Timeout
|
|
'UserAgent' = $UserAgent
|
|
'WebProxy' = $WebProxy
|
|
'ProxyPort' = $ProxyPort
|
|
}
|
|
|
|
# kick off the threaded script block + arguments
|
|
Invoke-ThreadedFunction -ComputerName $hostList -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams
|
|
}
|
|
|
|
else {
|
|
Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $HostList, $UseSSL, $Port, $Path, $Timeout, $UserAgent
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function Brute-Fruit
|
|
|
|
{
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Search for web directories and files at scale across multiple web servers. Think "Dirbusting across a broad range of hosts".
|
|
|
|
.DESCRIPTION
|
|
A script to find directories and files across multiple web servers.
|
|
|
|
.PARAMETER Dictionary
|
|
Path to custom dictionary of files or directories.
|
|
Here's a good place to start:
|
|
https://github.com/danielmiessler/SecLists/tree/master/Discovery/Web-Content
|
|
https://github.com/DanMcInerney/pentest-machine/blob/master/wordlists/dirs-files-6000.list
|
|
|
|
.PARAMATER UrlList
|
|
List of URL's to scan. These should be one per line in the format of "http://domain.com", "https://domain.com:8443", etc...
|
|
|
|
.PARAMETER Timeout
|
|
Timeout for each connection in milliseconds.
|
|
|
|
.PARAMETER Threads
|
|
The maximum concurrent threads to execute.
|
|
|
|
.PARAMETER FoundOnly
|
|
Only display found URI's
|
|
|
|
|
|
.EXAMPLE
|
|
C:\PS> Brute-Fruit -Dictionary C:\temp\dictionary-of-files-to-test.txt -UrlList C:\temp\list-of-hosts.txt -Timeout 3000
|
|
|
|
C:\PS> Brute-Fruit -Dictionary C:\temp\dictionary-of-files-to-test.txt -UrlList C:\temp\list-of-hosts.txt -Timeout 3000 -Threads 10 -FoundOnly -Verbose
|
|
|
|
.NOTES
|
|
Credits to mattifestation for Get-HttpStatus
|
|
HTTP Status Codes: 100 - Informational * 200 - Success * 300 - Redirection * 400 - Client Error * 500 - Server Error
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
|
|
param (
|
|
[Parameter(Mandatory = $false)]
|
|
[String]$Dictionary,
|
|
[Parameter(Mandatory=$False)]
|
|
[Int]$Timeout = 110,
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateRange(1, 100)]
|
|
[Int]$Threads,
|
|
[Parameter(Mandatory=$False)]
|
|
[Switch]$FoundOnly,
|
|
[Parameter(Mandatory=$False)]
|
|
[String]$UrlList
|
|
)
|
|
|
|
begin
|
|
{
|
|
if (!(Test-Path -Path $UrlList)) { Throw "File doesn't exist" }
|
|
$hostlist = @()
|
|
$hostlist
|
|
foreach ($hostobject in Get-Content $UrlList)
|
|
{
|
|
$hostlist += $hostobject
|
|
}
|
|
|
|
if (!(Test-Path -Path $Dictionary)) { Throw "Dictionary file doesn't exist" }
|
|
$VulnLinks = @()
|
|
foreach ($Link in Get-Content $Dictionary)
|
|
{
|
|
$VulnLinks = $VulnLinks + $Link
|
|
}
|
|
|
|
|
|
$HostEnumBlock = {
|
|
param($ComputerName, $Dictionary, $Timeout, $FoundOnly, $VulnLinks)
|
|
|
|
foreach ($Item in $Vulnlinks)
|
|
{
|
|
|
|
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
|
|
foreach ($Target in $ComputerName)
|
|
{
|
|
|
|
$WebTarget = "$Target/$Item"
|
|
$URI = New-Object Uri($WebTarget)
|
|
|
|
try
|
|
{
|
|
$WebRequest = [System.Net.WebRequest]::Create($URI)
|
|
$ProxyAddress = New-Object System.Net.WebProxy("http://$($WebProxy):$($ProxyPort)",$true)
|
|
$WebRequest.Proxy = $ProxyAddress
|
|
$WebResponse = $WebRequest.Timeout = $Timeout
|
|
$WebResponse = $WebRequest.GetResponse()
|
|
$WebStatus = $WebResponse.StatusCode
|
|
$Stream = $WebResponse.GetResponseStream()
|
|
$Reader = New-Object IO.StreamReader($Stream)
|
|
$html = $reader.ReadToEnd()
|
|
$WebSize = $html.Length
|
|
$ResultObject += $ScanObject
|
|
$WebResponse.Close()
|
|
}
|
|
catch
|
|
{
|
|
$WebStatus = $Error[0].Exception.InnerException.Response.StatusCode
|
|
|
|
if ($WebStatus -eq $null)
|
|
{
|
|
# Not every exception returns a StatusCode.
|
|
# If that is the case, return the Status.
|
|
$WebStatus = $Error[0].Exception.InnerException.Status
|
|
}
|
|
}
|
|
|
|
$Result = @{
|
|
Status = $WebStatus;
|
|
URL = $WebTarget
|
|
Size = $WebSize
|
|
}
|
|
|
|
if ($FoundOnly) {
|
|
New-Object -TypeName PSObject -Property $Result | Where-Object {$_.Status -eq 'OK'}
|
|
|
|
} else {
|
|
New-Object -TypeName PSObject -Property $Result
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
process {
|
|
|
|
if($Threads) {
|
|
Write-Verbose "Using threading with threads = $Threads"
|
|
|
|
# if we're using threading, kick off the script block with Invoke-ThreadedFunction
|
|
$ScriptParams = @{
|
|
'UseSSL' = $UseSSL
|
|
'Port' = $Port
|
|
'Dictionary' = $Dictionary
|
|
'Timeout' = $Timeout
|
|
'FoundOnly' = $FoundOnly
|
|
'ComputerName' = $hostlist
|
|
'WebProxy' = $WebProxy
|
|
'ProxyPort' = $ProxyPort
|
|
|
|
|
|
}
|
|
|
|
# kick off the threaded script block + arguments
|
|
$Hostcount = $hostlist.count
|
|
Invoke-ThreadedFunction -VulnLinks $VulnLinks -HostCount $Hostcount -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams
|
|
}
|
|
|
|
else {
|
|
Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $HostList, $Dictionary, $Timeout, $FoundOnly, $VulnLinks
|
|
}
|
|
}
|
|
}
|