Tag Archives: powershell

Check Logging Status of Palo Alto Firewalls

0

Posted on November 12, 2020 by

UPDATE 2020-12-28: After my initial post, I found out that the 7x and 52xx models have a different format for the ‘show logging-status’ command. I have updated the code to take those into account. In addition, I have modified the input to take a CSV value pair of firewall,apiKey.

Logs are at the heart of any firewall. So making sure that logs are available to query at all times is important.

One of the features of the Palo Alto firewalls is the ability to forward logs to a Panorama or the Cortex Data Lake service. But it’s important to confirm that the firewall is actually forwarding logs and that some error hasn’t stopped log forwarding.

The easiest way to manually check this on individual firewalls is the “show logging-status” command. It will display the last time logs were forwarded.

But this can be very tedious in an environment with many firewalls. To help automate this process, I created a Powershell script to check the results of “show logging-status” on a given list of firewalls. If any of the firewalls have not forwarded logs in 2+ hours, the list is displayed and (optionally) an email can be sent with the results.

Get-LoggingStatus Powershell script

The script below uses the Palo Alto API to query a list of firewalls. So an API key needs to be configured on the firewalls for this script to work.

See this article to configure an API key on your firewalls.

param
(
    [Parameter(Mandatory=$True,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True,
    HelpMessage='CSV file with list of Palo Alto firewalls and their API key.  Format: fw,apiKey')]
    [string]$list,
    [Parameter(Mandatory=$False,
    ValueFromPipeline=$False,
    HelpMessage='If used, email will be sent.  If excluded, no email will be sent.')]
    [switch]$sendEmail = $false
)

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

if (-Not ("TrustAllCertsPolicy" -as [type]))
{
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
}

$emailFrom = "<YourEmailAddress"
$emailTo = '<YourEmailAddress>'
$emailSubject = "Palo Alto FW Logging Issues"
$smtpServer = "<YourEmailServer>"

# How many hours the firewall's last log forward can be behind the current time.
$hourOffset = "2"

$fwLIst = Get-Content $list

$apiStem = "api/?type=op&cmd=%3Cshow%3E%3Clogging-status%3E%3C%2Flogging-status%3E%3C%2Fshow%3E"

$fwNotSendingLogs = $null

$htmlMessage = New-Object System.Text.StringBuilder
$textMessage = New-Object System.Text.StringBuilder

foreach ($listItem in $fwLIst)
{
    $fw,$apiKey = $listItem -split ","

    $url = "https://$($fw.trim())/$apiStem&key=$($apiKey.trim())"

    $WebRequestContent = $null
    $ErrResp = $null
    [xml]$WebResponse = $null

    try
    {
        $WebRequestContent = Invoke-WebRequest -Uri "$url" -Method Get
    }
    catch
    {
        $streamReader = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
        $ErrResp = $streamReader.ReadToEnd() | ConvertFrom-Json
        $streamReader.Close()
    }

    if ($WebRequestContent -ne $null)
    {
        [xml]$WebResponse = $WebRequestContent.Content
    }

    if (($ErrResp) -or ($WebResponse -eq $null))
    {
        Write-Host "There was an error!" -ForegroundColor Red
        Write-Host $ErrResp -ForegroundColor Yellow
    }
    elseif($WebResponse.response.status -ne "success")
    {
        Write-Host "There was an error!" -ForegroundColor Red
        Write-Host $WebResponse.response.result -ForegroundColor Yellow
        Write-Host $WebResponse.response.status -ForegroundColor Yellow
    }
    else
    {

        $ConnStatus = $WebResponse.response.result | Select-String -Pattern 'Connection Status.*' -AllMatches | ForEach-Object{$_.Matches}

        $LogCollectors = $WebResponse.response.result | Select-String -Pattern 'Log Collector.*' -AllMatches | ForEach-Object{$_.Matches}
        
        $trafficString = $WebResponse.response.result | Select-String -Pattern 'traffic.*' -AllMatches | ForEach-Object{$_.Matches}

        $i=0
        
        if ($ConnStatus)
        {
            foreach ($ConnStringMatch in $ConnStatus)
            {                                                                                                       
                if ($ConnStringMatch -match "lr - Active")
                {

                    $logType,$logLastCreated,$logLastFwd,$seqNumFwd,$seqNumAck,$totalLogsFwd = $trafficString[$i] -split "\s{2,}"
                    $lcLabel,$lcValue = $LogCollectors[$i] -split ":"
                    $lcValue = $lcValue.Trim()

                    # Add offset hours to the Last Log Fwred datetime.  If this is less than the current datetime, logs are not being fowarded.  Add the firewall to the list.
                    if ($logLastFwd -as [DateTime])
                    {
                        if ((Get-Date $logLastFwd).AddHours($hourOffset) -lt (Get-Date))
                        {
                            $fwNotSendingLogs += $fw
                            $null = $htmlMessage.AppendLine("<tr><td>$fw</td><td>$lcValue</td><td>$logLastFwd</td></tr>")
                            $null = $textMessage.AppendLine("$fw using Log Collector $lcValue last forwarded logs on $logLastFwd")
                        }
                    }
                    else
                    {
                        $fwNotSendingLogs += $fw
                        $null = $htmlMessage.AppendLine("<tr><td>$fw</td><td>$lcValue</td><td>$logLastFwd</td></tr>")
                        $null = $textMessage.AppendLine("$fw using Log Collector $lcValue last forwarded logs on $logLastFwd")
                    }
                }
            
                $i++
            }
        }
        elseif ($trafficString)
        {

            $trafficString = $WebResponse.response.result | Where {$_ -match "traffic.*"} | Foreach {$Matches[0]}

            $logType,$logLastCreated,$logLastFwd,$seqNumFwd,$seqNumAck,$totalLogsFwd = $trafficString -split "\s{2,}"

            # Add offset hours to the Last Log Fwred datetime.  If this is less than the current datetime, logs are not being fowarded.  Add the firewall to the list.
            if ((Get-Date $logLastFwd).AddHours($hourOffset) -lt (Get-Date))
            {
                $fwNotSendingLogs += $fw
                $null = $htmlMessage.AppendLine("<tr><td>$fw</td><td>$logLastFwd</td></tr>")
                $null = $textMessage.AppendLine("$fw last forwarded logs on $logLastFwd")
            }
        }
    }
}

if ($fwNotSendingLogs)
{
    $htmlhead = "<html>
                <style>
                BODY{font-family: Consolas; font-size: 10pt;}
                H1{font-size: 22px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
                H2{font-size: 18px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
                H3{font-size: 16px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
                TABLE{border: 1px solid black; border-collapse: collapse; font-size: 9pt;}
                TH{border: 1px solid #969595; background: #dddddd; padding: 5px; color: #000000;}
                TD{border: 1px solid #969595; padding: 5px; }
                td.pass{background: #B7EB83;}
                td.warn{background: #FFF275;}
                td.fail{background: #FF2626; color: #ffffff;}
                td.info{background: #85D4FF;}
				tr:hover {background-color: #85D4FF}
                </style>
                <body>
                <p>The following Palo Alto firewalls have stopped forwarding logs:</p>
                <table>
                <tr><th>Firewall</th><th>Log Collector Name</th><th>Last Log Fowarded</th></tr>"
    
    $htmltail = "</table></body></html>"

    $body = $htmlhead + $htmlMessage + $htmltail

    If ($sendEmail)
    {
        Send-MailMessage -To $emailTo -body $body -BodyAsHtml -From $emailFrom -Subject $emailSubject -Priority High -smtpServer $smtpServer
    }

    Write-Host $textMessage -ForegroundColor Yellow
}
else
{
    Write-Host "All firewalls are forwarding logs."
}



Make sure to edit the highlighted lines to add your email settings.

To use the script, save it as “Get-LoggingStatus.ps1” and run it with these command line parameters.

Get-LoggingStatus.ps1 -list "C:\PathTo\firewall.txt" [-sendEmail]

The “-list” parameter takes a CSV formatted file with the list of firewalls and their associated API key.

The “-sendEmail” parameter is optional. If used and any firewalls are not sending logs, it will send an email.

The variable “$hourOffset” sets a threshold on how many hours the firewall can be behind for log forwarding.

If you want to test the functionality of the script, set the “$hourOffset” variable to a negative number, like -2. The script will think that all firewalls are failing to forward logs and cause the script to display a list of results similar to the following.

firewall01 last forwarded logs on YYYY/MM/DD HH:MM:SS
firewall02 last forwarded logs on YYYY/MM/DD HH:MM:SS
...

Just make sure to change the variable back to 2 or whatever threshold you want to set before using the script.

If one or more firewalls are NOT forwarding logs, the best solution is probably to open a case with support. But at least the problem can be detected quickly before logs are lost.

Detecting WINS Service Status With PowerShell

0

Posted on July 19, 2020 by

To slightly modify something that Edwin Starr sang in the 1970 hit “War

WINS!

What is it good for?

Absolutely NOTHING!

In most environments, the WINS service is no longer necessary as the Netbios protocol is no longer needed for name lookups (now handled by DNS).

Netbios can (and should) be disabled on all endpoints (servers and workstations). Windows OS Hub has a great article on how to do that. But that still might leave the WINS service running on servers in the environment.

To detect the state of the WINS service on all Domain Controllers, I created the PowerShell script below. It gets a list of all DCs, then determines if the WINS service is installed or not, then gets the state of the WINS service.

$Servers = @(Get-ADDomainController -filter *).name

Foreach ($Server in $Servers)
{
    $WINSService = Get-Service -ComputerName $Server -Name WINS -ErrorAction SilentlyContinue

    if ($WINSService)
    {
        Write-Host "$Server,installed,$($WINSService.status)"
    }
    else
    {
        Write-Host "$Server,not installed,"
    }
}

This script needs to be run as a user with the ability to query services on Domain Controllers.

It will write its output is CSV format similar to what is below:

SERVER1,installed,running
SERVER2,installed,stopped
SERVER3,not installed,

This should help identify Domain Controllers that are still running WINs or that have the service installed, but stopped.

Tenable.SC – Adding an email alert when a ticket is assigned (manually and PowerShell)

0

Posted on May 17, 2020 by

Tenable.SC has a basic ticketing system built into their product.  But, by default, there’s no way to notify someone that a ticket has been assigned to them.  To notify someone that a ticket has been assigned to them, an alert needs to be generated that is based on a query.

The first step is to configure a query. Within Tenable.SC, navigate to Analysis Queries and Add a query.  In the Query Builder section, select “Ticket” for Type and “Ticket List” for Tool.

(more…)

Using Powershell and the Nexpose API to create Exceptions

0

Posted on February 15, 2019 by

Nexpose, like other vulnerability management platforms, has the ability to create exceptions for the vulnerabilities it finds. You might need to issue exceptions because the vulnerability is a false positive, a compensating control is in place, or the risk is acceptable to the business.

Unfortunately, you sometimes have to create exceptions for hundreds, if not thousands, of vulnerabilities within Nexpose. It’s far too time consuming to create those manually.

The good news is that Nexpose has a well documented API. I’ve used this API to create a Powershell module that can help automate the submission of vulnerability exceptions.

(more…)

Auditing Passwords with Active Directory Properties

0

Posted on August 28, 2015 by

Have you ever been looking through Active Directory and notice something strange in one of the fields?  Maybe the Organization or Description field has a weird string of letters, numbers, and characters.  You think, “Huh, that kind of looks like a password.”

Ding! Ding! Ding!

Yes, it happens.  Either through lack of understanding or just laziness, sometimes passwords get put into the plain text fields in AD.  This is dangerous because those fields are readable by everyone on the domain.

So how do you know if any of these fields are being used to store passwords?  I managed to cobble together a PowerShell script that can help. (more…)

PowerShell script to alert for changes in NS records

2

Posted on October 17, 2013 by

UPDATE: A newer version of this script is here.

Last week, Johannes Ullrich shared a Bash script that would check for changes in NS records.  This was in a blog post about the google.com.my DNS hijack.  I wanted to create a version of the this script that would be usable on Windows machines.  So I created the PowerShell script below that does pretty much the same thing as the Bash script.  The script runs nslookup.exe instead of DIG and queries the DNS server for all NS records for a domain.  This is saved in file named domain.new and compared with a previous query of the NS records stored in domain.old.  If there are any differences, an email is sent and an entry is made in the Application Event Log. (more…)