5 Days of SSHD Stats on a Public IP

Over the last 5 days my pub­licly acces­si­ble sys­tem at has had 5,092 attempted SSH logins from 8 IP Addresses.

Unsur­pris­ingly, the most com­monly attempted ssh user­name is “root”, the default admin­is­tra­tive account on Linux sys­tems.

What I did find sur­pris­ing, was that most of the IPs gave up after a rel­a­tively low num­ber of attempts.

Even more so was that for each user­name tried which wasn’t root, the num­ber of pass­words attempted was rarely more than a dozen.

Here are the IPs observed attempt­ing the unau­tho­rized logins:


All data was col­lected via syslog-ng from an Arch Linux server hosted by Rack­space sent to Splunk Storm

Tracking SSHD Login Activity in SplunkStorm

After a night out with my wife I decided to cre­ate a search for SSHD logins in Splunk Storm. See­ing that port 22 is open to the world on, I won­der how long before ran­dom bots start attempt­ing to log into it. As a secu­rity prac­ti­tioner its always inter­est­ing to see the effects of just being on the inter­net; and SplunkStorm is a great way to mon­i­tor those effects.

SSHD — Logins (Accepts and Failures)

sshd | rex field=_raw ”]: (?<sshd_action>.*) pass­word for (?<sshd_username>.*) from (?<sshd_ip>.*) port” | search sshd_action=”*” | table _time host sshd_action sshd_username sshd_ip

Here’s a look at the result:

If you’re run­ning syslog-ng, it’s super sim­ple to send your logs over to a Splunk instance. Below is what I added to my /etc/syslog-ng/syslog-ng.conf file where the X’s are val­ues pro­vided by your SplunkStorm admin console:

des­ti­na­tion d_splunk { tcp(logsX.splunkstorm.com” port(XXXXX)); };
log { source(src); destination(d_splunk); };

Splunk Query: Processes Created & Terminated

This morn­ing I installed and con­fig­ured Snare on my AWS EC2 Win­dows 2012 Server to ship logs to my SplunkStorm project.

Below is a basic query for chart­ing the top processes that have started on the sys­tem:
Even­tID 4688 — A new process has been cre­ated. (Details)

4688  | rex field=_raw “Process Name: (?<Process_Name>.*) Token Ele­va­tion Type:”  | sort Process_Name | top limit=10000 Process_Name

Here is a mod­i­fied ver­sion of the query for processes that have ter­mi­nated:
Even­tID 4689 — A process has exited. (Details)

4689  | rex field=_raw “Process Name: (?<Process_Name>.*) Exit Sta­tus:”  | sort Process_Name | top limit=10000 Process_Name

More to come.…

Auditing NTFS Permissions

Recently I’ve wanted to review the account per­mis­sions on my home server that I use for backup. It has some­times served as a sand­box of sorts; not best prac­tice, but real­ity for hardware/monetary lim­its. Rather than spend the time right-clicking and check­ing the per­mis­sions on each folder I thought it’d be nice to write a WMI script to gen­er­ate a report.

I knew this had to have been done before, and after some quick googlefu I can across this script by Amine Abdelka­der that basi­cally did every­thing I wanted.

I didn’t like the HTML out­put though, I want CSV so that it can be eas­ily sorted, fil­tered, manip­u­lated in Excel. I also wanted to con­trol the depth of the search into sub­fold­ers and the total num­ber of fold­ers it would report on.

The script, mod­i­fied for these changes, is listed below:

’ Orig­i­nal Author:  Abdelka­der, Amine
’ Orig­i­nal Date: 10/03/2006
’ Orig­i­nal Ouput: HTML File

’ Mod­i­fied by: Randy Armknecht
’ Mod­i­fied Date: 2009-11-05
’ Mod­i­fied Out­put:  CSV File, with abil­ity to con­trol depth of sub­folder search (depth)
’           and abil­ity to con­trol total num­ber of fold­ers reported on (max_seen)
Const For­Read­ing = 1, For­Writ­ing = 2, ForAp­pend­ing = 8

Const Ful­lAc­cess­Mask = 2032127, Mod­i­fy­Ac­cess­Mask = 1245631, WriteAc­cess­Mask = 118009
Const ROAc­cess­Mask = 1179817

str­Com­puter = “.“
sPar­ent­Folder = Input­Box(“Please Enter folder to gather infor­ma­tion on”, “Par­ent Folder”)

max_seen = 1000
depth = 1
count = 0

Set fso = Cre­ateOb­ject(“Scripting.FileSystemObject”)
’File name Same As Folder Name with­out spe­cial Car­ac­teres
’WScript.echo full­file­name

Set fsOut = fso.OpenTextFile(fullfilename, ForAp­pend­ing, True)

On Error Resume Next

    fsOut.Writeline “Folder, User Name, Per­mis­sion“


Show­Sub­Fold­ers FSO.GetFolder(sParentFolder),fullfilename

Out­put­Folder­Info sPar­ent­Folder, full­file­name

Set fsOut = fso.OpenTextFile(fullfilename, ForAp­pend­ing, True)
fsOut.Writeline strTable­Foot
Msg­Box “Done “

Pub­lic Sub OutputFolderInfo(FolderName , sOut­file)
    Const Ful­lAc­cess­Mask = 2032127, Mod­i­fy­Ac­cess­Mask = 1245631, WriteAc­cess­Mask = 1180095
    Const ROAc­cess­Mask = 1179817
    Const For­Read­ing = 1, For­Writ­ing = 2, ForAp­pend­ing = 8
    str­Com­puter = “.“

    ‘Build the path to the folder because it requites 2 back­slashes
    fold­er­path = Replace(FolderName, “\”, “\\”)

    object­path = “winmgmts:Win32_LogicalFileSecuritySetting.path=’” & fold­er­path & “‘“

    ‘Get the secu­rity set for the object
    Set wmi­FileSec­Set­ting = GetO­b­ject(object­path)

    ‘ver­ify that the get was suc­cess­ful
    Ret­Val = wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor)
    If Err Then
        ‘Msg­Box (“Get­Se­cu­ri­ty­De­scrip­tor failed” & vbCrLf & Err.Number & vbCrLf & Err.Description)
    End If

    Set objWMIS­er­vice = GetO­b­ject(“win­mgmts:” & “{impersonationLevel=impersonate}!\\” & str­Com­puter & “\root\cimv2”)
    Set col­Fold­ers = objWMIService.ExecQuery(“SELECT * FROM Win32_Directory WHERE Name =’” & fold­er­path & “‘”)

    For Each obj­Folder In col­Fold­ers
        ’ Retrieve the DACL array of Win32_ACE objects.
        DACL = wmiSecurityDescriptor.DACL

        Set fso = Cre­ateOb­ject(“Scripting.FileSystemObject”)
        Set fsOut = fso.OpenTextFile(sOutfile, ForAp­pend­ing, True)

        For Each wmi­Ace In DACL
            ’ Get Win32_Trustee object from ACE
            Set Trustee = wmiAce.Trustee
            fsOut.Write objFolder.Name&”,”&Trustee.Domain&”\”&Trustee.Name&”,“

            FoundAc­cess­Mask = False
            Cus­tom­Ac­cess­Mask = Flase
            While Not FoundAc­cess­Mask And Not Cus­tom­Ac­cess­Mask
                If wmiAce.AccessMask = Ful­lAc­cess­Mask Then
                    AccessType = “Full Con­trol“
                    FoundAc­cess­Mask = True
                End If
                If wmiAce.AccessMask = Mod­i­fy­Ac­cess­Mask Then
                    AccessType = “Mod­ify“
                    FoundAc­cess­Mask = True
                End If
                If wmiAce.AccessMask = WriteAc­cess­Mask Then
                    AccessType = “Read/Write Con­trol“
                    FoundAc­cess­Mask = True
                End If
                If wmiAce.AccessMask = ROAc­cess­Mask Then
                    AccessType = “Read Only“
                    FoundAc­cess­Mask = True
                    Cus­tom­Ac­cess­Mask = True
                End If
            If FoundAc­cess­Mask Then
                fsOut.Write AccessType&vbCrLf
                fsOut.Write “Cus­tom”&vbCrLf
            End If

        Set fsOut = Noth­ing
        Set fso = Noth­ing

    Set fsOut = Noth­ing
    Set fso = Noth­ing
end Sub

Sub Show­Sub­Fold­ers (Folder,fname)
    On Error Resume Next
        If count < depth then
            count = count + 1
            total_seen = 0
            For Each Sub­folder in Folder.SubFolders
            if total_seen < max_seen then
                total_seen = total_seen + 1
                Call OutputFolderInfo(Subfolder.Path,fname)
                ‘Wscript.Echo Subfolder.Path
                call Show­Sub­Fold­ers (Subfolder,fname)
            end if
        end if
End Sub