Initiating a Vulnerability Scan with IP360 Rest API and PowerShell
One of the most common things I do with Tripwire's IP360 in Professional Services it automate workflows. Nearly everyone wants a way to quickly trigger a scan (be it on detection of a new machine or a request for further data in a security playbook) and it's nice and easy to do thanks to the REST API - here's an example I've put together in a PowerShell script (since a lot of sysadmins remain in the windows world!).
<#
.SYNOPSIS
This script is designed to trigger ad hoc scans of networks
.DESCRIPTION
This script is designed to trigger ad hoc scans of IP360 networks
THIS SCRIPT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
FITNESS FOR A PARTICULAR PURPOSE, AND/OR NONINFRINGEMENT.
This script is not supported under any Tripwire standard support program or service.
The script is provided AS IS without warranty of any kind. Tripwire further disclaims all
implied warranties including, without limitation, any implied warranties of merchantability
or of fitness for a particular purpose. The entire risk arising out of the use or performance
of the sample and documentation remains with you. In no event shall Tripwire, its authors,
or anyone else involved in the creation, production, or delivery of the script be liable for
any damages whatsoever (including, without limitation, damages for loss of business profits,
business interruption, loss of business information, or other pecuniary loss) arising out of
the use of or inability to use the sample or documentation, even if Tripwire has been advised
of the possibility of such damages.
WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, TRIPWIRE HAS NO OBLIGATION TO INDEMNIFY OR
DEFEND RECIPIENT AGAINST CLAIMS RELATED TO INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS.
.NOTES
Version: 1.1 - Update to add new functionality
Author: Tripwire Professional Services (Chris Hudson)
Client Name: N/A
Creation Date: Nov 2019
Currently this script DISABLES SSL validation.
This is not a recommended practice and is inherently insecure.
.EXAMPLE
Invoke-IP360-Scan -startTime "2019-11-05 11:48:21Z" -endTime "2019-11-06 11:48:21Z" -NetworkName "My
Network" -AppliancePool "DP Pool UK" -ProfileName "API Scanning Profile" -ScanName "Adhoc API Scan"
Starts a scan of the network "My Network" based on the time settings - watch your time formatting!
.EXAMPLE
$adhoctimes = Get-IP360-ScanDateForAdhoc
Invoke-IP360-Scan -startTime $adhoctimes.Starttime -endTime $adhoctimes.EndTime -NetworkName $NetworkName -
AppliancePool $AppliancePool -ProfileName $ProfileName -ScanName "Test"
.LINK
www.tripwire.com
#>
<#
=========================================
CHANGELOG:
=========================================
1.0 Initial release
1.1 Added invoke function to run immediately
#>
#--------------------------------------------------------------[Params]
------------------------------------------------------------
Param(
# VNE IP address
[Parameter(Mandatory=$true,HelpMessage="VNE IP Address or hostname")]$VNE,
# VNE Username
[Parameter(Mandatory=$true,HelpMessage="VNE username")]$username,
# VNE Password
[Parameter(Mandatory=$true,HelpMessage="VNE password")]$password,
# Accepts either $true or $false to enable or disable ssl checks
[Parameter(Mandatory=$false,HelpMessage='Set to $true or $false to enable or disable ssl
checks')]$disableSSLcheck,
#The start scan date/time in the form of 2019-11-05 11:48:21Z - ensure this is in the future!
[Parameter(Mandatory=$true,HelpMessage="The start scan date/time in the form of 2019-11-05 11:48:
21Z")]$startTime,
# The end scan date/time in the form of 2019-11-05 11:48:21Z - ensure this is after your start date!
[Parameter(Mandatory=$true,HelpMessage="The end scan date/time in the form of 2019-11-05 11:48:21Z")]$endTime,
#Network name to scan - if uncertain, try using Get-IP360-Networks first
[Parameter(Mandatory=$true,HelpMessage="Network name to scan - if uncertain, try using Get-IP360-Networks
first")]$NetworkName,
# Appliance Pool to scan with - if uncertain, try using Get-IP360-AppliancePools first
[Parameter(Mandatory=$true,HelpMessage="Appliance Pool to scan with - if uncertain, try using Get-IP360-
AppliancePools first")]$AppliancePool,
# Profile to scan with - if uncertain, try using Get-IP360-ScanProfiles first
[Parameter(Mandatory=$true,HelpMessage="Profile to scan with - if uncertain, try using Get-IP360-ScanProfiles
first")]$ProfileName,
# The name you wish to give to the created scan
[Parameter(Mandatory=$true,HelpMessage="The name you wish to give to the created scan")]$ScanName
)
#---------------------------------------------------------[Initialisations]
--------------------------------------------------------
# None
#----------------------------------------------------------[Declarations]
----------------------------------------------------------
#Script Version
$ScriptVersion = "1.0"
#-----------------------------------------------------------[Functions]
------------------------------------------------------------
################ ********************* ####################
# Turn off SSL validation. (NOT RECOMMENDED FOR PRODUCTION):
################ ********************* ####################
function Disable-SSLValidation {
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}
function Get-IP360-Network{
param($NetworkName)
$NetworkName = [System.Web.HttpUtility]::UrlEncode($NetworkName)
$r = Invoke-RestMethod -Method Get -Uri ($uri+"networks?name=$networkname") -WebSession $ip360session
if($r.count -eq 0){Write-host "Error - object not found - check name"}else{return $r.results}
}
function Get-IP360-Networks{
$r = Invoke-RestMethod -Method Get -Uri ($uri+"networks") -WebSession $ip360session
return $r.results
}
function Get-IP360-AppliancePool{
param($AppliancePool)
$AppliancePool = [System.Web.HttpUtility]::UrlEncode($AppliancePool)
$r = Invoke-RestMethod -Method Get -Uri ($uri+"appliance_pools?name=$AppliancePool") -WebSession
$ip360session
if($r.count -eq 0){Write-host "Error - object not found - check name"}else{return $r.results}
}
function Get-IP360-AppliancePools{
$r = Invoke-RestMethod -Method Get -Uri ($uri+"appliance_pools") -WebSession $ip360session
return $r.results
}
function Get-IP360-ScanProfile{
param($ProfileName)
$ProfileName = [System.Web.HttpUtility]::UrlEncode($ProfileName)
$r = Invoke-RestMethod -Method Get -Uri ($uri+"scan_profiles?name=$ProfileName") -WebSession $ip360session
if($r.count -eq 0){Write-host "Error - object not found - check name"}else{return $r.results}
}
function Get-IP360-ScanProfiles{
$r = Invoke-RestMethod -Method Get -Uri ($uri+"scan_profiles") -WebSession $ip360session
return $r.results
}
function Get-IP360-ScanDateForAdhoc{
$Temp = (Get-Date).AddMinutes(5)
$startTime = Get-Date $Temp -Format u
$Temp = (Get-date).AddDays(1)
$endTime = Get-Date $Temp -Format u
$daterange = @{'Starttime'=$startTime;'EndTime'=$endTime}
return $daterange
}
function Invoke-IP360-Scan{
param($startTime,$endTime,$NetworkName,$AppliancePool,$ProfileName,$ScanName)
if(!$ScanName){$ScanName = ("API-Invoked-Scan-" + (New-Guid))}
$appliancepooltouse = Get-IP360-AppliancePool -AppliancePool $AppliancePool
$appliancepooltouse = $appliancepooltouse.url
$networktouse = Get-IP360-Network -NetworkName $NetworkName
$networktouse = $networktouse.url
$profiletouse = Get-IP360-ScanProfile -ProfileName $ProfileName
$profiletouse = $profiletouse.url
$payload = @{name="$ScanName";scan_profile="$profiletouse";is_debug=$false;scan_end_datetime= $endTime;
scan_start_datetime= $startTime;pool="$appliancepooltouse";network= "$networktouse"
} | ConvertTo-Json
Write-debug $payload
$r = Invoke-RestMethod -Method Post -Uri ($uri+"scan_schedules") -WebSession $ip360session -ContentType
"application/json" -Body $payload
}
function Get-IP360-ScanSchedules{
param($ScanScheduleName)
$ScanScheduleName = [System.Web.HttpUtility]::UrlEncode($ScanScheduleName)
$r = Invoke-RestMethod -Method Get -Uri ($uri+"scan_schedules") -WebSession $ip360session
$r = $r | Where-Object {$_.results.name -eq $ScanScheduleName} # For some reason, search doesn't reliable
return networks, so we filter here
if($r.count -eq 0){Write-host "Error - object not found - check name"}else{return $r.results}
}
function Invoke-IP360-OnDemandScan-Now{
param($startTime,$endTime,$NetworkName,$AppliancePool,$ProfileName,$ScanName)
if(!$ScanName){$ScanName = ("API-Invoked-Scan-" + (New-Guid))}
$ScanID = Get-IP360-ScanSchedules -ScanScheduleName $ScanName
if($ScanID.results.count -gt 1){Write-host "WARNING: More than one profile found matching this scan name -
please ensure you use unique scan names";}#break}
$scanid = ($scanid.url -split '/')[-1]
$appliancepooltouse = Get-IP360-AppliancePool -AppliancePool $AppliancePool
$appliancepooltouse = $appliancepooltouse.url
$networktouse = Get-IP360-Network -NetworkName $NetworkName
$networktouse = $networktouse.url
$profiletouse = Get-IP360-ScanProfile -ProfileName $ProfileName
$profiletouse = $profiletouse.url
$payload = @{name="$ScanName";scan_profile="$profiletouse";is_debug=$false;scan_end_datetime= $endTime;
scan_start_datetime= $startTime;pool="$appliancepooltouse";network= "$networktouse"} | ConvertTo-Json
$r = Invoke-RestMethod -Method Put -Uri ($uri+"scan_schedules/$scanid") -WebSession $ip360session -
ContentType "application/json" -Body $payload
}
function Invoke-IP360-Audit{
param($NetworkName,$AppliancePool,$ProfileName,$ScanName)
$appliancepooltouse = Get-IP360-AppliancePool -AppliancePool $AppliancePool
$appliancepooltouse = $appliancepooltouse.url
$networktouse = Get-IP360-Network -NetworkName $NetworkName
$networktouse = $networktouse.url
$profiletouse = Get-IP360-ScanProfile -ProfileName $ProfileName
$profiletouse = $profiletouse.url
$payload = @{name="$ScanName";scan_profile="$profiletouse";debug=$false;pool="$appliancepooltouse";network=
"$networktouse"} | ConvertTo-Json
$r = Invoke-RestMethod -Method Post -Uri ($uri+"audits") -WebSession $ip360session -ContentType "application
/json" -Body $payload
}
#-----------------------------------------------------------[Execution]
------------------------------------------------------------
# Build connection settings
if($disableSSLcheck -eq $True){Disable-SSLValidation}
Write-host "This script gathers data about DPs"
if($Vne -eq $null)
{Write-host "Please enter a valid IP360 VNE Address"
Break
}
else
{
Write-host "Attempting to connect to $Vne"
# $testnetconnect = Test-NetConnection -Port 443 -ComputerName $Vne
if ($testnetconnect.TcpTestSucceeded -eq $True){
Write-host "Connection successfully on port 443"
}
else
{
Write-host "Unable to establish connection to $Vne on port 443- please check firewall configuration"
# Break
}
}
$uri = "https://$Vne/rest/v1/"
Write-host "Connecting to API via $uri"
# Check for credentials
if(!$password -or !$username){
# prompt for credentials
Write-host "Credentials required"
Break
}
else
{
# Connect to IP360
# Get login form
$loginform = Invoke-WebRequest -Method Get -Uri "https://$VNE/index.ice" -SessionVariable ip360session
# Use form for a login
$loginform.Forms[0].Fields.login = $username
$loginform.Forms[0].Fields.password = $password
$loginform.Forms[0].Fields.do = "auth"
$connect = Invoke-WebRequest -Method Post -Uri "https://$VNE/index.ice" -WebSession $ip360session -Body
$loginform
$ip360session.headers.Add("Referer","https://$vne")
$sid = $ip360session.Cookies.GetCookies("https://$VNE/index.ice")
$csrf = $ip360session.Cookies.GetCookies("https://$VNE/index.ice") | Where-Object {$_.name -eq "csrftoken"}
| select value
$csrf = $csrf[0].Value
$ip360session.Headers.Add('X-CSRFToken',"$csrf")
}
Invoke-IP360-Scan -startTime $startTime -endTime $endTime -NetworkName $NetworkName -AppliancePool
$AppliancePool -ProfileName $ProfileName -ScanName $ScanName
Invoke-IP360-Audit -NetworkName $NetworkName -AppliancePool $AppliancePool -ProfileName $ProfileName -ScanName
$ScanName
Remove-Variable ip360session
With that script in place (assuming the script is in the same path as you are currently located) to initiate an ad-hoc scan you can run:
.\Invoke-IP360-Scan.ps1 -VNE “192.168.1.99” -username “apiuser@tripwire.com” -password “MyPassword” -
disableSSLcheck $true -startTime "2019-11-05 11:48:21Z” -endTime "2019-11-07 11:48:21Z” -NetworkName “My
Network” -AppliancePool “My Appliance Pool” -ProfileName ”Scan Profile X” -ScanName "My Test Scan"
Note the date format - I'm not doing anything clever to force the format or validate, so be careful with use!
You could also use:
Get-help .\Invoke-IP360-Scan.ps1 –Detailed
for additional instructions on the parameters - although I suspect most will make sense from the names alone! Included in the script there are some helper functions in there that can enumerate your networks/app pools/profiles, etc which might help if you run into issues.