Pixie Lite PowerShell (PS) is a lightweight PS script designed to aid security analyst to look up bulk IP addresses against Abuse IP DB database using its APIv2. The script is only 92 lines long and 2.15 KB in size. This iteration of Pixie was developed to eliminate the need to install anything in Windows environments.
Get the PS script at: https://github.com/UncleSocks/pixie-defenders-automated-ip-address-workflow/blob/main/Pixie%20Powershell/pixie.ps1
Before the PowerShell Script
When I was working as an L1 SOC Analyst at an Australian Managed Service Provider (MSP), one of the challenges I encountered was manually researching large volumes of IP addresses to gather their geographic location and ISP details. This was necessary to identify IP addresses to which internal hosts were connecting to that were not part of the validated list.
For this reason, I decided to practice my Python script to automate the task. Originally, I leveraged IPInfo’s API capability to automatically pull the IP geolocation, company, and hostname informaition of bulk IP addresses, which simply displays the parsed data to the CLI using the IP_ADDRESS[COUNTRY:COMPANY:HOSTNAME]
format. I named this tool Pixie, after our Mini Pinscher, since this was my first tool and its feature is fairly straightforward (mini). Overtime, the need to also include IP address reputation in a readable format arose. The Pixie Lite for Abuse IP DB was then born, which accepts a .txt
file, communicates using Abuse IP DB API to capture the county code, ISP, abuse confidence score, total reports, and last reported date of each IP address, then exports the parsed data into a .csv
file. The tool was eventually used by my organization to automate monthly IP address reputation reports – this made me very proud.
Developing the PowerShell Script
Pixie has multiple Python 3 variants, including a feature to filter based on the company and an additional IP Cisco Talos blocklist check. I will have to refactor and update the Python codes first before writing a blog post about it. For now, this post will focus on the PS version, which is essentially a rewritten Pixie Lite for Abuse IP DB Python script. Similar with the Python version, it accepts a .txt
file, which should contain one IP address per line, then exports the parsed data to a .csv
file.
Global Parameters and Initial Setup
The script will require three global arguments: ApiKey, FilePath, and OutputPath. The ApiKey is the Abuse IP DB APIv2 Key. The FilePath is the file location of the input .txt
file, and the OutputPath is the CSV file location.
param([string]$ApiKey,
[string]$FilePath,
[string]$OutputPath
)
As part of our initial setup, we will create a blank array, where we will append each processed (parsed) IP address. Then, we will gather the contents of the .txt
input file.
$processedIpArray = @()
$fileContent = Get-Content -Path $FilePath
Connecting with Abuse IP DB APIv2
The PS script uses Abuse IP DB’s APIv2 but it requires us to specify the following HTTP parameters: URI, Method, Headers, and Body (Query) [1
]. The script sends a GET request to https://api.abuseipdb.com/api/v2/check
with the API key as the authentication, while specifying the accepted format to be JSON [2
]. The script will then query each IP address from the .txt
file using a For-Loop.
$headers = @{
'Key' = $ApiKey
'Accept' = 'application/json'
}
$body = @{
'ipAddress' = $line
'maxAgeInDays' = '90'
}
$Params = @{
Uri = 'https://api.abuseipdb.com/api/v2/check'
Method = 'GET'
Headers = $headers
Body = $body
}
We can now pass these parameters using the Invoke-RestMethod
cmdlet, which we will look at in the next subsection.
PowerShell Script Logic
The script loops through the specified .txt
file and uses the Invoke-RestMethod
cmdlet to GET the details of each IP address from the Abuse IP DB database. The script leverages hashtable splatting, where @Params
contains the key-value pairs that will be passed as a paramter when executing Invoke-RestMethod
[3
].
$lookup = Invoke-RestMethod @Params
Abuse IP DB JSON Response
When performing a Check Endpoint API GET request, Abuse IP DB will send a JSON response containing the information of the queried IP address. By default, the response is a one-liner, making it difficult to read and parse. The commented out lines below can be used to convert the JSON response to a more human-readable format.
#$lookupParsed = $lookup | ConvertTo-Json #Convert JSON to a more human-readable format.
#Write-Output $lookupParsed #Print human-readable JSON response for testing.
The $lookupParsed
uses the ConvertTo-Json
cmdlet to make the JSON response human-readable, as shown below.
{
"data": {
"ipAddress": "1.1.1.1",
"isPublic": true,
"ipVersion": 4,
"isWhitelisted": true,
"abuseConfidenceScore": 0,
"countryCode": "AU",
"usageType": "Content Delivery Network",
"isp": "APNIC and Cloudflare DNS Resolver project",
"domain": "cloudflare.com",
"hostnames": [
"one.one.one.one"
],
"isTor": false,
"totalReports": 57,
"numDistinctUsers": 13,
"lastReportedAt": "2024-11-20T16:01:14+00:00"
}
}
Please note that this is not part of the script logic but was kept for testing, especially if users want to include more information.
Abuse IP DB Lookup Logic
The script will first check whether the IP address is public. If so, it extracts and parses the country code, ISP, domain, abuse confidence score, total reports, and last reported date from the JSON response. However, if the IP address is not public, the script set the country code as PRIVATE
and the rest of the columns as N/A
explicitly.
if ($isPublic -eq $true) {
try {
$countryCode = $lookup.data.countryCode
} catch {
$countryCode = 'N/A'
}
try {
$isp = $lookup.data.isp
} catch {
$isp = 'N/A'
}
try {
$domain = $lookup.data.domain
} catch {
$domain = 'N/A'
}
$abuseConfidenceScore = $lookup.data.abuseConfidenceScore
$totalReports = $lookup.data.totalReports
$lastReportedAt = $lookup.data.lastReportedAt
} else {
$countryCode = 'N/A'
$isp = 'PRIVATE'
$abuseConfidenceScore = 'N/A'
$totalReports = 'N/A'
$lastReportedAt = 'N/A'
}
When parsing the JSON response, we can access each child value by specifying the key term, separated by a period (.). For example, if you want to check if the IP address is considered a Tor, you can access the value using $lookup.data.isTor
.
Exporting to a CSV File
Before the script can generate a CSV file, it will first create an array of PSCustomObject
to represent a collection of key-value pairs, which is useful when using the Export-Csv
cmdlet [4
]. This effectively creates the columns and the headers of the CSV file, while specifying which function to append on each column.
$processedIp = [PSCustomObject]@{
'IP Address' = $ipAddress
'Country Code' = $countryCode
'ISP' = $isp
'Domain' = $domain
'Abuse Confidence Score (%)' = $abuseConfidenceScore
'Total Reports' = $totalReports
'Last Reported At' = $lastReportedAt
}
$processedIpArray += $processedIp
Next, the script will append each processed IP address to the $processedIpArray
array that we previously created. Then it uses the Export-Csv
cmdlet to generate a CSV file to the specified $OutputPath
based on the $processedIpArray
array.
$processedIpArray | Export-Csv $OutputPath -Encoding UTF8 -NoTypeInformation
The -NoTypeInformation
will remove any unncessary metadata from the CSV contents.
PowerShell Script Usage
To use the Pixie PS script, simply execute the pixie.ps1
script and specify the API key, input text file location, and output CSV file location, for example:
pixie.ps1 -ApiKey "123456789" -FileLocation "C:\Users\Pixie\Documents\ip.txt" -OutputPath "C:\Users\Pixie\Documents\output.csv"
After the script is finished running, it should generate a CSV file on the specified -OutputPath
location, which would look like in Fig. 1 below.
Fig. 1. Sample Pixie PowerShell CSV Output
I hope you learned something useful from this blog post, and of course, I also hope that this tool will make SOC analysts’ work become a little easier.
Reference
- Microsoft, Invoke-RestMethod, -Body, microsoft.com, https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7.4 (accessed November 20, 2024)
- AbuseIPDB, CHECK Endpoint, abuseipdb.com, https://docs.abuseipdb.com/#introduction (accessed November 20, 2024)
- Microsoft, about_Splatting, microsoft.com, https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-7.4 (accessed November 20, 2024)
- Microsoft, Everything you wanted to know about PSCustomObject, microsoft.com, https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.4 (accessed November 20, 2024)