Thoughts about security, beer, music and stuff

Check Logging Status of Palo Alto Firewalls


Posted on November 12, 2020 by

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.

    HelpMessage='Text file with list of Palo Alto firewalls.')]
    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

$apiKey = "Your API Key"

$emailFrom = ""
$emailTo = ''
$emailSubject = "Palo Alto FW Logging Issues"
$smtpServer = ""

# 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"


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

foreach ($fw in $fwLIst){
    $url = "https://$fw/$apiStem&key=$apiKey"

    $WebRequestContent = $null
    $ErrResp = $null

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

    if ($WebRequestContent -ne $null)
        $JsonFromResponse = $WebRequestContent.Content

    if (($ErrResp) -or ($JsonFromResponse -eq $null))
        Write-Host "There was an error!" -ForegroundColor Red
        Write-Host $ErrResp -ForegroundColor Yellow
    elseif($JsonFromResponse.response.status -ne "success")
        Write-Host "There was an error!" -ForegroundColor Red
        Write-Host $JsonFromResponse.response.result -ForegroundColor Yellow
        Write-Host $JsonFromResponse.response.status -ForegroundColor Yellow
        #$trafficString = Select-String -InputObject $($JsonFromResponse.response.result) -SimpleMatch "traffic" | %{$_.Values}

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

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

#        Write-Host "Log Type: $logType"
#        Write-Host "Last Log Created: $logLastCreated"
#        Write-Host "Last Log Forwarded: $logLastFwd"

        # Add 12 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>
                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;}
      {background: #FF2626; color: #ffffff;}
      {background: #85D4FF;}
				tr:hover {background-color: #85D4FF}
                <p>The following Palo Alto firewalls have stopped forwarding logs:</p>
                <tr><th>Firewall</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
    Write-Host "All firewalls are forwarding logs."

Make sure to edit the highlighted lines to add your API key and 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 “-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.

Comparing InsightVM and Tenable.SC


Posted on August 14, 2020 by

Over the years, I’ve had the opportunity to work with both Rapid7’s InsightVM and Tenable’s Tenable.SC.  At the core of these products is their vulnerability scanners, Nexpose and Nessus respectively.  I wanted to compare these two vulnerability management products and document some of the pros and cons of each one.


While both products scan your network and report on vulnerabilities, they report them in different ways.  Ideologically, InsightVM is more vulnerability focused while Tenable.SC is more remediation focused.


Detecting WINS Service Status With PowerShell


Posted on July 19, 2020 by

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


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)"
        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:

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)


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.


Little to no budget? Improve security through effective communication


Posted on May 2, 2020 by

Many security professionals face the same challenge – improve security and reduce risk with a fixed or reduced budget.  There is a lot of information on the internet about using Open Source software to build systems that can help you reduce risk.

But I propose that we, as security professionals, must be teachers as well as technicians.  Yes, we can do the work.  But how much better would it be if the entire IT department or even the entire organization understood basic security principles and could apply them in their day to day activities?  It’s like the old adage.  You can give a man a fish and feed him for a day or you can teach a man to fish and feed him for a lifetime.  Let’s teach people to be secure so they can apply security principles at work and in their day-to-day lives.

This article’s focus will be slightly different than a formalized Security Awareness Program (see Securing the Human for details on that).  Instead, we will look at ways any security professional can more effectively communicate with others so that security concepts become a more prominent topic in people’s day to day life.

Be Approachable

I’m sure all of us know about an “angry security guy”.  Maybe we are that guy.  But the first step to effectively communicating security concepts to others is to be approachable.  Staff need to feel free to come to us with questions and concerns.  In particular, they need to feel free to bring any possible risks to us.


Using the Tenable.SC API to list Asset Groups for a list of IPs


Posted on May 1, 2020 by

I recently needed to pull all of the asset groups associated with a list of IPs from Tenable.SC. It’s easy enough to filter assets in Tenable.SC by Asset Group and get all of the assets in a group. And the full list of Asset Groups can be viewed in the Web UI by looking at the information for a single asset. But there was no report or query within the Web UI that would list all Asset Groups for list of IPs/assets.

Enter the Tenable.SC API. Within the API, there is a method called “assetintersections” that will list all Asset Groups associated with a given IP.{id}/assetIntersections

With a little scripting in your favorite language, a list of IPs and their associated Asset Groups can be created.

Using Powershell and the Nexpose API to create Exceptions


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.


Two Practical Lessons from the Equifax Breach Report


Posted on December 20, 2018 by

Last week, Congress released the full Equifax Breach Report.

To briefly recap the breach, attackers exploited an Apache Struts vulnerability on the Equifax ACIS web servers (accessed at  They then pivoted from these servers to gain further access and query multiple databases within Equifax. As a result, the personal information of 148 million US Citizens was stolen.

It’s a fantastic document that not only explains HOW the breach happened, but WHY it happened.  It’s a document that everyone in IT, from the new Service Desk Tech to the seasoned CIO, should read.

The report explains that the breach was the result of many contributing factors that will be familiar to anyone who has worked in IT.  Let’s go through the list. (more…)

Auditing Passwords with Active Directory Properties


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…)

Let’s Talk about Succession Planning


Posted on July 12, 2015 by

Last week I received an email from my web host.  It said that all customers needed to backup and move their data because their hosting services would be shutting down immediately.  It was a strange email.  After some digging, I found out that the reason for the shut down was that the CEO had just died.  There was evidently no one who could step in and take over the business.  So the decision was make to close.

Why would the unfortunate death of one employee, even a very high level employee, cause a business to shut down?  Simply put, it is the lack of succession planning.  What is succession planning and why is it important? (more…)