Meet Moss: The Helper

The word "MOSS" rendered in bright green rectangular blocks against a dark blue background, in a pixelated or digital font style.

Hello, meet Moss! Moss stands for nothing, it’s just a cool name I think from the British TV show named IT Crowd. You can check other versions or more about the project by visiting here.

This tool helps me at work. I decided to share some of it with the hopes it could make other people’s jobs easier as well.

It will take input and generated different queries that I can search on the Firewall. I am not going to name the firewall we use for opsec reasons.

After inputting an IP address, it will use AD API to get all the groups that the user is in.

Often I need to lookup a site’s IP, we use nslookup very often. The code will take a site and perform a Nslookup request and take the IP(s) that shown and put them in a format that allows me to easily search the firewall for requests made to that site. It will save the query to the clipboard buffer.

What It Looks Like

MOSS menu for querying data, managing groups, and performing lookups.

Nslookup

After it displays and copy the IP query into the clipboard, the code will go back to the main page of Moss.

MOSS system command-line menu for michaelmeade.org, including IP address lookup and options for Queries, Get Groups, and Nslookup.

Getting Groups

The get groups is the same code that I mentioned in my other article Using PowerShell: At Work. The script is a little different than the one given in that article because for a unknown reason my permissions or something was changed that caused this part of the script to not work anymore.

But during the summer I found a new way of getting the user’s groups. I am not going to show it in action for privacy reasons. I don’t want to accidentally expose something that I am not supposed to.

Turning data to queries

After inputting a site the following menu will show which currently has 15 different ways to create queries that can be used to query the firewall. During work I usually mostly use the url contains ( 4 ) option since it will rarely match the exact URL given.

Command-line interface showing a URL input for 'google.com' and a numbered menu of 15 options for filtering or querying data, including Referer, URL, Category, Email & DST address, App, User & URL, and destination address.

After picking an option it will generate the query and copy it to the clipboard buffer so all you have to do is paste it into the Firewall to search. It will also display the query it generates in yellow.

The Log File

Before copying the generated query to the clipboard, the script will save the generated query in a log file. This is so the user can have a record of what query that they can re-use at a later time. The log file can be changed but the output looks like this: query --> date & Time as seen in the image below.

The Delimiter between the query and the date / time is -->.

The Code

$Host.UI.RawUI.ForegroundColor = 'green'

function Read-Host($prompt) {
    Write-Host "$prompt " -NoNewline -ForegroundColor Red
    Microsoft.PowerShell.Utility\Read-Host
}

function Log-Query {
param(
    [string] $q
)

    $filePath = "C:\Users\MMeade1\OneDrive - New York State Office of Information Technology Services\Desktop\fun\logs\logs.txt"
    $date = Get-Date -Format "MM-dd-yyyy HH:mm:ss"
    $write = $q + " --> " + $date
    Write-Output $write | Out-File $filePath -append

}


function Save-Query {
param(
    # Writes the query in console and also sets it in clipboard buffer
        [string] $query
    )
    Write-Host `n`n`n`n
    Write-Host $query -NoNewline -ForegroundColor yellow
    Set-Clipboard $query
    Log-Query $query


}

function Create-Email-By-Name {
param( 
[string] $name
)
    # turns name to email
    $email_host = $name.replace(" ", ".")
    $agency = Read-Host "Enter Agency>"
    $email = $email_host + "@" + $agency + ".ny.gov"
return $email 
}

function Get-Groups {
param(
    [string] $email
)
    # Gets a user AD groups
    $user_name = Get-aduser -Filter {UserPrincipalName -eq $email -and Enabled -eq $true } -Properties Enabled, UserPrincipalName, SamAccountName, mail | select SamAccountName
    $user = $user_name.SamAccountName;


    $user_groups = Get-ADUser -Identity $user -Properties MemberOf | Select -ExpandProperty MemberOf

    foreach ($group in $user_groups) {
        $name = $group.Split(',')[0].split("=")[1]
        Write-Host $name -ForegroundColor yellow
    }
    Write-Host `n`n`n
}

function Query-Menu {
    # Used to create query for palo

    Clear-Host
    
    $url = Read-Host "Enter URL>"


    Write-Host "`n`n`t`t1) Referer eq`n`t
    `t2) Refferer contains`n
    `t3) Url eq`n
    `t4) Url contains`n
    `t5) Category eq`n
    `t6) Email & DST address`n
    `t7) App`n
    `t8) User & URL`n
    `t9) URL contains & Not Equal Alert`n
    `t10) URL Contains ^ Not Equal & User`n
    `t11) App Id & User`n
    `t12) Source user & src IP`n
    `t13) URL eq & zone`n
    `t14) URL contains & zone`n
    `t15) dest address`n"

    Write-host `n`n`n
    $option = Read-Host "Enter Option>"
    Write-host `n`n
    if ($option -eq 1) {
        # Referer equals URL
        Save-Query "( referer eq '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 2) {
        # Referer contains URL
        Save-Query "( referer contains '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 3) {
        # URL is equal
        Save-Query "( url eq '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 4) {
        # URL contains
        Save-Query "( url contains '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 5) {
        # Category contains URL 
        Save-Query "( category contains '$url' )"
        Write-host `n`n

    }
    elseif ($option -eq 6) {
        # url & dest addr
        Write-Host `n`n`n`
        $email = Read-Host "Enter username>"
        Save-Query "( addr.dst in '$url' ) and ( user.src eq '$email' )"
        Write-host `n`n

    } 
    elseif ($option -eq 7) {
        # App equal URL
        Save-Query "( app eq '$url' )"
        Write-host `n`n

    }
    elseif ($option -eq 8) {
        # User and URL equal
        Write-Host `n`n`n`
        $email = Read-Host "Enter emails>"
        Save-Query "( user.src eq '$email' ) and ( url eq '$url' ) "
        Write-host `n`n

    }
    elseif ($option -eq 9){
        # URL contains & not equal alert
        Save-Query "( url contains '$url' ) and ( action neq 'alert' )"
        Write-host `n`n

    }
    elseif ($option -eq 10){
        # URL contains & not equal & user
        Write-Host `n`n`n`
        $email = Read-Host "Enter emails>"
        Save-Query "( url contains '$url' ) and ( action neq 'alert' ) and ( user.src eq '$user' )"
        Write-host `n`n

    }
    elseif ($option -eq 11) {
        # app id & user
        Write-Host `n`n`n`
        $email = Read-Host "Enter emails>"
        Save-Query "( app eq '$url' ) and ( user.src eq '$email' )"
        Write-host `n`n

    }
    elseif ($option -eq 12) {
        # Email & Source IP
        Write-Host `n`n`n`
        $email = Read-Host "Enter emails>"
        Save-Query " ( user.src eq '$email' ) and ( addr.src in '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 13) {
        # Search by zone & URL eq
        Write-Host `n`n`n`
        $zone = Read-Host "Enter zone>"
        Save-Query "( zone.src eq '$zone' ) and ( url eq '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 14) {
        # Search by zone & URL contains
        Write-Host `n`n`n`
        $zone = Read-Host "Enter zone>"
        Save-Query "( zone.src eq '$zone' ) and ( url contains '$url' )"
        Write-host `n`n
    }
    elseif ($option -eq 15) {
        #dest address
        Write-Host `n`n`n`
        Save-Query "( addr.dst in '$url' )"
        Write-host `n`n
    }
}


function Get-Ip-Query {
    param (
        $site
    )
    $ips   = [System.Net.Dns]::GetHostAddresses($site)
    $count = $ips.count
    $out = ""
    $i =0
    Foreach($item in $ips) {
        $i += 1
        If ($i -eq $count) {
            $out += "( addr.dst in '$item' ) "
        } 
        else {
            $out += "( addr.dst in '$item' ) or "
        }
    }

    Write-Host "(" $out ")" -ForegroundColor yellow
    $clip = "(" + $out + ")"
    Set-Clipboard -Value $clip
    Write-Host `n`n`n`n
}


$bye = "

    ########  ##    ## ########                 
    ##     ##  ##  ##  ##                       
    ##     ##   ####   ##                       
    ########     ##    ######                   
    ##     ##    ##    ##                       
    ##     ##    ##    ##       ### ### ### ### 
    ########     ##    ######## ### ### ### ### 
                                             

"

$banner = "`t`t
           `t`t         ███    ███  ██████  ███████ ███████ 
           `t`t         ████  ████ ██    ██ ██      ██      
           `t`t         ██ ████ ██ ██    ██ ███████ ███████ 
           `t`t         ██  ██  ██ ██    ██      ██      ██ 
           `t`t         ██      ██  ██████  ███████ ███████ 
                                    
                                                         
"

while ($true) {
    Write-Host `n`n
    Write-Host $banner
    Write-Host `n`n
    Write-Host "`t`t`t`t===================================================`n"
    Write-Host "`t`t`t`n`t`t`t`t`t`t`t`t1) Queries`n`t
    `t`t`t`n`t`t`t`t`t`t`t`t2) Get Groups`n`t
    `t`t`t`n`t`t`t`t`t`t`t`t3) Nslookup to Query`n`t
    `t`t`t`n`t`t`t`t`t`t`t`t4) Exit`n`t"
    Write-Host "`t`t`t`t`===================================================`n"
    Write-Host `n`n`n
    $options = Read-Host "menu> "
    if ($options -eq 1) {
        Query-Menu
    }
    elseif ($options -eq 2) {
        # get groups
        Clear-Host
        $input_email = Read-Host "email> " -NoNewline -ForegroundColor red
        if ($input_email -match " ") { 
            $email = Create-Email-By-Name $input_email
        }

        Write-Host `n`n`n`n 
        
        Get-Groups $email
    }
    elseif ($options -eq 3) {
        Clear-Host
     
        $site = Read-Host "site> "
        Write-Host `n`n`n
        Get-Ip-Query $site
        Write-Host `n`n
    }
    elseif ($options -eq 4) {
        Clear-Host
        Write-Host $bye
        exit
    }
}

Notes

Some of the file paths have been changed to protect my privacy and opsec at my job.

Another new feature that I added that is that after generating the query it will save the newly created query into a txt file. This acts as a log where I can see the date and time, and the query that was generated at a later time.

A new feature I added recently is that when it creates the query, it will save the newly created query in a text file. This is so that in the future you can look back and find the query to re-use or maybe even see the most common query you use during a period of time.