Published: 2023-09-20

What's Normal? DNS TTL Values

I am trying to start a series of brief diaries about "what's normal." Analysts often only look at the network when they suspect something is wrong. But to find the anomaly, someone must first know what's normal. So, I am trying to collect data from my home network to show what to consider. The values I am presenting here are normal for my home network and will likely differ for your network. So, instead of just copying/pasting, run the experiment yourself :)

For this first installment, I am looking at the DNS TTL values. Each DNS response includes a "Time to Live" (TTL). This is the time the answer is good for; your host or recursive DNS server will cache the answer for that many seconds. An answer retrieved from a recursive server will use the TTL remaining for the recursive server. A recursive server that 20 seconds ago received an answer with a TTL of 60 seconds will report a TTL of 40 seconds. The TTLs you observe may depend on the traffic you are collecting. You will see a more diverse set of TTLs if the answers are received from a recursive server. Answers from an authoritative server are likely clustered around common values like 60, 3600 (one hour), or 86400 (one day). 

So, what are the median TTLs for each record type? (I am using the median. A few outliers were throwing off the average too much).

Query Type Rounded Median TTL
NS 500,000
MX 1800
PTR 1800
TXT 300
A 60
SOA 60

"NS" and "MX" records being long-lived is no surprise. You will not change your DNS and Mail servers all the time, and MX records poing to hostnames. If you intend to fail over an MX record, you update the A/AAAA records for the hostname. It is interesting that AAAA records are slightly longer lived than A records. But in line with the fact that "mobile IP" for IPv6 is a myth and operationally, IPv6 is treated just like IPv4. SOA records must be updated whenever any other records are updated. Keeping it's TTL small makes sense.

What about the distribution of records? A and AAAA records are remarkably similar (as expected from the similar median?). I sued a logarithmic x-axis to display the smaller TTL values properly.

(click on the image for the full resolution)



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


Published: 2023-09-19

Obfuscated Scans for Older Adobe Experience Manager Vulnerabilities

Adobe Experience Manager (AEM) is a complex enterprise-level content management system built around open-source products like Apache Sling, Jackrabbit/Oak, and Felix. Just last week, Adobe patched another XSS vulnerability in AEM. But the scans we see now target older vulnerabilities, likely a vulnerability 2-3 years old.

AEM includes "Dispatcher," which is responsible for load balancing but also has some web application firewall functionality. One of the "tricks" in exploiting AEM is to bypass this layer, and I think this is what may have been seen here.

For example, we do see in yesterday's and today's "First Seen" list two attempts:


They match common AEM exploits, but the /bin/wcm/...;/../; prefix may be meant to obfuscate the attack. Right now, I cannot pinpoint the particular vulnerability being exploited. If someone can help, please let me know. :)

Usually, the exploit URL looks like this:


Queries for querybuilder.json.css are not very common. We have seen this so far in the last couple of years. There is certainly an increased interest in these vulnerabilities lately:


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


Published: 2023-09-18

Internet Wide Multi VPN Search From Single /24 Network

Brute-forcing passwords for VPN access has become a standard technique for various actors to access corporate networks to exfiltrate data later or deploy ransomware. After identifying the VPN, an attacker may use simple brute forcing, credential stuffing, or social engineering in some very public cases to obtain access.

Today, I noticed in one of my honeypots new "most commonly hit" URLs:

GET /remote/login HTTP/1.1
GET /dana-na/auth/url_default/welcome.cgi HTTP/1.1
GET /global-protect/login.esp HTTP/1.1
GET /vpn/index.html HTTP/1.1

These URLs have one thing in common: They are used by VPN and remote access solutions. The first one is a bit generic, making it difficult to identify the exact product they are looking for.

The second URL, '/dana-na/' appears to be associated with Pulse Connect Security, a VPN solution with a rich history of vulnerabilities in the past. I do not see any exploit attempts as part of these scans, just simple requests for the URL. Some of our handlers suggested Juniper may also use it.

'/global-protect/login.esp' is associated with Palo Alto's Global Protect solution. It also had a few vulnerabilities in the past. 

Finally, '/vpn/index.html' appears to be related to a Netscaler remote access product.

Another interesting property of these scans is that they all originate from A different IP address in this subnet scans for each URL; the IPs have not been used before the last couple of days.

Whois data for this network:

role:           Aeza Network
address:        350001, Krasnodar, st. im. Mayakovskogo, b. 160, office 2.4
nic-hdl:        AN32749-RIPE
mnt-by:         aeza-group-mnt
created:        2021-11-24T09:55:02Z
last-modified:  2021-11-24T09:55:02Z
source:         RIPE # Filtered

The scanning IP addresses have no services exposed, but other IPs in this /24 do have simple default web pages. This appears to be typical for a hosting provider like Aeza Networks. It is possible that the originator of these scans compromised or just rented a few servers in this subnet. Low-cost virtual servers offered by providers like Aeza, are always popular as "throw-away" systems to conduct scans like this.

What should you do?

First, ensure your remote access software is up to date. This should not just include these web-based VPN solutions. Include console servers or other remote access methods.

Secondly, use multi-factor authentication. If supported, opt for a phishing-resistant solution. Note that simple one-time passwords like Google Authenticator are not phishing-resistant. A phishing-resistant solution does not allow the user to select the credentials for a particular website. Possible solutions are FIDO2 or Passkeys, which are sadly not much seen yet for these types of remote access systems.

You should probably implement country-based blocking for critical gateways or a limited allow list. But quite often, you will need these VPN gateways to be accessible from dynamic home IPs, and country-based block lists are not only hard to get right, but they are simple to bypass. Blocking may be a good start :)

And a bit of "security through obscurity" can help: Try to run these gateways on an unusual port.

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


Published: 2023-09-14

DShield and qemu Sitting in a Tree: L-O-G-G-I-N-G

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



Setting up and configuring the DShield Honeypot is an important component of contributing to the SANS Internet Storm Center (ISC) [1]. The recommended OS and hardware for hosting the installation is Raspberry Pi OS Lite [2] on any of the Raspberry Pi hardware versions [3]. That said, for development work and experimentation, constantly re-installing the OS on the physical hardware isn’t the most convenient process and an additional expense for more Raspberry Pi’s isn’t exactly appealing either. Similarly, someone interested in dipping their toe in the honeypot waters might not want to commit to purchasing the Raspberry Pi hardware right away.

So, what is a cost effective and time-efficient solution that doesn’t require any additional hardware that takes advantage of native Windows functionality? This blog post details how to use qemu to accomplish exactly that.

Why the DShield Honeypot?

The DShield honeypot serves as a data collection point for the SANS ISC. In doing so, DShield deployments support the ISC’s aim to crowdsource monitoring of malicious activities online. However, as with many code repositories, issues crop up from time to time [4]. A few of the issues personally encountered include:

  • Minor issues with the install.sh setup script.
  • Data retention issues in the isc-agent/web honeypot.
  • Inability to access full web honeypot logs on the local system.
  • Compatibility quirks with Ubuntu Server 22.04.2 LTS.

Contributing to the DShield project serves not only the project itself but also the broader information security community. qemu, an open-source hardware emulator, provides a comprehensive solution for this, from the deployment of a DShield honeypot to troubleshooting and testing. Although qemu is most often associated with Linux environments, it can be seamlessly operated within Windows through the Windows Subsystem for Linux (WSL), making it a versatile tool for facilitating DShield honeypot deployment.

Getting Setup on Windows Subsystem for Linux (WSL)

For myself, the most pressing problem for troubleshooting encountered issues is overcoming limited hardware availability: having only a single Raspberry Pi 4B 8 GB, a time and cost-effective solution is needed. One such solution is to use WSL. WSL allows Linux applications and utilities to be run directly on Windows. In this case, it can also be used as the base for qemu installation. The online documentation can guide how to configure Ubuntu 22.04 LTS on WSL. [5] It can also be installed from the Microsoft Store. [6]

Figure 1: Ubuntu 22.04 LTS running on Windows 11 WSL

Upgrading and Configuring Ubuntu 22.04 LTS on WSL for qemu Support

Once Ubuntu 22.04 LTS is installed on the WSL, the operating system will need to be updated and specific packages installed to facilitate qemu operations, as well as prepare for subsequent setup tasks. Execute the following commands to achieve this:

sudo apt update -y && sudo apt upgrade -y # update the OS
sudo apt install -y qemu openssl qemu-utils fdisk qemu-system-arm bc # install packages

Executing these commands serves dual purposes: it updates the Ubuntu installation to the latest version, improving security, and it equips the system with essential tools for deploying and managing a DShield honeypot via qemu.

Investigating a qemu Solution

Already aware that qemu could provide hardware emulation but not certain if it would accomplish the task or how to implement it, research was initiated to see if this trail had already been blazed.

Early research identified two major leads:

  1. Raspberry Pi 3B qemu Built-in Support: qemu has a built-in machine configuration for a variety of Raspberry Pi boards up to 3B. [7]
  2. Raspberry Pi 3B qemu Configuration: Radu Zaharia has an excellent post detailing some of the configuration options when implementing qemu to emulate Raspberry Pi 3B hardware. [8]

Obtaining the Latest Raspberry Pi OS Lite (ARM) Disk Image

Equipped with this information, the next step is to download the latest version of Raspberry Pi OS Lite:

Commands Notes
mkdir ~/rpi && cd ~/rpi
create a directory named ‘rpi’ and change to it
wget -q --show-progress https://downloads.raspberrypi.org/raspios_lite_armhf_latest -O raspios_lite_armhf_latest.img.xz
download the latest Raspberry Pi OS Lite image for arm architectures
xz --decompress ./ raspios_lite_armhf_latest.img.xz
decompress the image
cp raspios_lite_armhf_latest.img.xz rpi-16g.img
make a working copy

Command Table 1: Download & extract Raspberry Pi OS Lite (armhf)


Figure 2: Downloading with 'wget'


Resizing and Mounting the Disk Image with a Calculated Offset

Next, the image file must be resized and mounted. The offset of the first partition in the image file will also need to be calculated in order to mount the image correctly.

Commands Notes
qemu-img resize ./rpi-16g.img 16G
resize the .img file
fdisk -l ./rpi-16g.img
calculate the offset based on the start of the first partition
sudo mkdir /mnt/rpi 
create a directory to mount to
sudo mount -o loop,offset=4194304 ./rpi-16g.img /mnt/rpi 
mount the .img using the offset we calculated

Command Table 2: Resize and mount the .img file


Figure 3: Calculating the offset with ‘bc’


Creating a ‘userconf’ File to Enable Login

To log in after booting, a ‘userconf’ file should be created in the appropriate directory on the mounted image.

Commands Notes
echo 'pi' | openssl passwd -6 -stdin
generates a SHA-512 hashed password out of ‘pi’
sudo nano /mnt/rpi/userconf 
creates the userconf file

Command Table 3: Generate a 'userconf' file and populate it with credentials

The following string, when placed in the ‘userconf’ file, will create the user ‘pi’ with password ‘pi’


Note: The use of the username ‘pi’ and password ‘pi’ is for demonstration purposes only. These credentials are commonly targeted by attackers and should not be used in a production environment. [9]

First Boot!

With that done, it’s time for the first boot by executing the following:

qemu-system-aarch64 \
   -machine raspi3b \
   -cpu cortex-a72 \
   -dtb /mnt/rpi/bcm2710-rpi-3-b-plus.dtb \
   -m 1G -smp 4 \
   -kernel /mnt/rpi/kernel8.img \
   -sd ~/rpi/rpi-16g.img \
   -nographic \
   -device usb-net,netdev=net0 \
   -netdev user,id=net0,hostfwd=tcp::2222-:2222,hostfwd=tcp::2223-:2223,hostfwd=tcp::8000-:8000 \
   -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootdelay=1"


Option Explanation
-machine raspi3b 
Sets the emulated machine to Raspberry Pi 3 Model B.
-cpu cortex-a72
Sets the CPU model to Cortex-A72.
-dtb /mnt/rpi/bcm2710-rpi-3-b-plus.dtb
Path to the Device Tree Blob (DTB) file (part of the mounted image)
-m 1G
Allocates 1 GB of RAM to the machine.
-smp 4
Sets the number of CPU cores to 4.
-kernel /mnt/rpi/kernel8.img
Path to the kernel image.
-sd ./rpi-16g.img
Specifies the SD card image to be used.
Disables graphical output, uses terminal instead.
-device usb-net,netdev=net0
Adds a USB network device with the specified netdev backend.
-netdev user,id=net0,hostfwd=tcp::2222-:2222,hostfwd=tcp::2223-:2223,hostfwd=tcp::8000-:8000
Creates a user-mode network backend with port forwarding from our host (Windows) to our guest (DShield) through qemu for the specified ports: 2222, 2223, and 8000 (needed for DShield).
-append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootdelay=1" 
Kernel command line options. (Needed to boot at all)

Command Table 4: Explanation of qemu options


Resize the Raspberry Pi Disk and File System

Recall that the size of the image file has already been changed to 16GB, but now the OS will need to update its disk and file system to take advantage of the additional space. This requires rebooting the emulated device but it is recommended to shut it down instead. Issuing a reboot to the Raspberry Pi OS tends cause qemu to hang.

Commands Notes
df -h  check the size of /dev/root
sudo fdisk -l  get the starting offset of the second partition (532480)
sudo fdisk /dev/mmcblk0 enter the fdisk utility
# d, 2
# c, n, p, 2, 532480, <enter>, n
# w    
options to enter into the fdisk utility
sudo shutdown now shut down the emulated device
# You are now back at the WSL prompt. Up arrow until at the qemu command previously used to launch your emulated Raspberry Pi device and execute it to boot again.
df -h; sudo resize2fs /dev/mmcblk0p2; df -h command sequence to check, resize, and verify the filesystem
sudo shutdown now shut down the emulated device
# You are now back at the WSL prompt. Up arrow until at the qemu command previously used to launch your emulated Raspberry Pi device and execute it to boot again.

Command Table 5: Resize the Raspberry Pi OS Lite disk & update the file system to show the full 16GB

After successfully executing the commands above, the device should have a configuration similar to this:


Figure 4: After updating the disk and file system, /dev/root shows 16G as the size


Update the Raspberry Pi and Check the Kernel Version

At this point, there is plenty of disk space to update the device and upgrade it, if needed. Use the following one-liner to accomplish this:

Commands Description
sudo apt update -y && sudo apt dist-upgrade -y && sudo apt autoremove -y && sudo apt clean -y && sudo apt autoclean -y
Update, upgrade, and clean the system

Command Table 6: Commands to update the Raspberry Pi OS



The qemu command used to initiate the emulated Raspberry Pi specifies a kernel image file with the “-kernel /mnt/rpi/kernel8.img” option. When updating and upgrading the installation, the kernel image located at “/mnt/rpi/kernel8.img” will not be updated automatically. This can result in issues with the emulated Raspberry Pi's functionality.

Execute the following on your emulated Raspberry Pi BEFORE shutting down to provide a URL for downloading an updated kernel8.img file. Copy the URL and then shutdown the Raspberry Pi device.

# On the Raspberry Pi BEFORE Shutting Down
KVER=$(dpkg -s raspberrypi-kernel | grep Version | awk '{print $2}' | cut -d':' -f2 | cut -d'-' -f1); \
echo "https://github.com/raspberrypi/firmware/raw/$KVER/boot/kernel8.img"


Figure 5: Copy the URL to download the correct kernel8.img directly from the Raspberry Pi repo


# Copy the URL echoed out and shut down the Raspberry Pi
sudo shutdown now

# Back on your WSL prompt
sudo wget -q --show-progress <COPIED URL GOES HERE> -O /mnt/rpi/kernel8.img


Install DShield

DShield can now be installed by following the guidance on the official GitHub repository for Raspberry Pi [10] or using the commands below. Be sure to obtain an API key by creating an account at the Internet Storm Center [11]. It is needed during installation and, later, to contribute logs to the DShield project.

# Enable SSH
sudo systemctl enable ssh; sudo systemctl start ssh

# Install DShield
sudo apt -y install git
git clone https://github.com/DShield-ISC/dshield
cd dshield/bin
sudo ./install.sh



At this stage, the qemu-emulated Raspberry Pi is operational with the DShield Honeypot installed and it is nearly to the point of aggregating logs. The next critical step involves enabling external access to the honeypot. This requires strategically configuring the network perimeter device, be it a router, firewall, or other security appliance, to route inbound traffic from your public IP address to the relevant listening ports on the Windows host machine.

Before diving into the specifics of configuring the Windows Firewall, lets first discuss the path that incoming malicious traffic will follow. Using the "hostfwd" parameter in the qemu command string, wslrelay.exe (on WSL) will create corresponding listeners on the Windows host, setting the stage for the subsequent forwarding of traffic.


Figure 6: Attack SSH traffic forwarded to port 2222, through the Windows Firewall, and on to the wslrelay.exe listeners


Any traffic that hits those ports will be forwarded via wslrelay.exe from the Windows host (Ubuntu on WSL) to the Raspberry Pi OS guest (DShield on Raspberry Pi OS).


Figure 7: Inside the wsl environment, qemu forwards the SSH traffic from host to guest where DShield is listening


In the example depicted above, the qemu configuration implemented is based on the following "hostfwd" parameter:


From here, the Cowrie SSH honeypot will take over and log the malicious traffic in the Cowrie logs.

If that seems complicated, no worries! These processes are automated through the initial execution of the qemu command string and the establishment of corresponding Windows Firewall rules that permit incoming traffic on the specified ports.

Configure the Windows Firewall – Adding Rules

Before configuring the Windows Firewall, take stock of what is about to happen. This will intentionally poke a hole in the Windows host’s firewall to allow malicious traffic in. The firewall rules below will remain up until intentionally taken back down.

If this is an acceptable risk, then let’s carry on!

The following must be run in a command prompt with Administrator privileges:

netsh advfirewall firewall add rule name="DShield SSH" dir=in action=allow protocol=TCP localport=2222
netsh advfirewall firewall add rule name="DShield Telnet" dir=in action=allow protocol=TCP localport=2223
netsh advfirewall firewall add rule name="DShield Web" dir=in action=allow protocol=TCP localport=8000

These rules will allow traffic through the Windows firewall where qemu should already be running and wslrelay.exe will be listening.


Figure 8: wslrelay.exe listening on the same ports that are now exposed


It will then be picked up by the corresponding ports on your DShield honeypot.


Figure 9: The DShield honeypot listening on those ports inside the qemu environment


Configure the Windows Firewall – Removing Rules

To remove the firewall rules, the following must be run in a command prompt with Administrator privileges:

netsh advfirewall firewall delete rule name="DShield SSH" protocol=TCP localport=2222
netsh advfirewall firewall delete rule name="DShield Telnet" protocol=TCP localport=2223
netsh advfirewall firewall delete rule name="DShield Web" protocol=TCP localport=8000

These rules should be removed before you shut down your honeypot.

Security Considerations

For a more robust and secure DShield honeypot setup, the following best practices are recommended. Compatibility with specific hardware, BIOS, and system configurations should be verified through testing.

  • QEMU Sandboxing: Utilize the ‘-sandbox on’ flag in qemu to restrict system calls and enhance security.
  • Resource Limitation: Set CPU and memory limits for the guest VM to mitigate resource exhaustion attacks.
    • This configuration sets ‘-smp 4 -m 1G’ to allocate four CPU cores and 1 GB of RAM.
  • Port Forwarding: Forward only essential ports required for DShield functionality.
  • Network Segmentation: Place the host machine on a separate network or VLAN to isolate it.
  • Software Updates: Apply updates to both Windows and Ubuntu and use the latest DShield version.
  • SSH Security for DShield: Enable key-based authentication and disable root login when using SSH to access DShield honeypot logs.

At the end of the day, there will always be risk when running a honeypot on any network, much less poking a hole in the firewall. Ensure these risks fit well within the risk profile used for operating on any personally owned devices or networks.

Alternatives for Accomplishing Similar Results

This isn’t the only means of virtualizing a DShield honeypot. The following alternatives were explored, and some were even implemented, but running it locally, inside qemu, has proven to be the most representative of the recommend installation without additional Raspberry Pi hardware.

  • Virtual Machines: These offer a convenient option for running a DShield honeypot on Ubuntu 22.04 LTS [12] but lacks support for the recommended Raspberry Pi OS Lite or the ability to emulate ARM-based hardware.


Figure 10: DShield on Ubuntu 22.04 LTS running in a VM


  • WSL: The Windows Subsystem for Linux is an easier option for using Ubuntu 22.04 LTS to set up a DShield honeypot but suffers from the same lack of support for testing and troubleshooting Raspberry Pi OS Lite on emulated ARM-based hardware. [13]


Figure 11: Ubuntu 22.04 LTS running in WSL


  • qemu: Offers hardware emulation and supports running the latest versions of the recommended operating system. [14]
  • Docker Containers: Containers can replicate the software environment needed for DShield but lack hardware emulation capabilities. Additionally, existing solutions are dated. [15]
  • Cloud-based Virtualization: Some cloud services offer ARM-based virtual machines. However, the additional costs can still be a drawback. [16]

What Is the Question Being Answered?

  • What is a cost effective and time-efficient way to set up additional DShield honeypots without requiring any additional physical hardware?

Who Would Benefit from This Information and Why?

  • Cybersecurity Researchers: Students and professionals focused on cybersecurity could utilize this information to effectively set up virtual honeypots. This provides them with a budget-friendly, scalable alternative to physical honeypots, thereby accelerating their research efforts.
  • Software Developers: Those constrained by hardware limitations can benefit immensely from leveraging qemu. This tool allows them to emulate the specific hardware features of multiple Raspberry Pi devices by aiding in testing and development without hardware limitations or supply concerns. [17]
  • SANS BACS Interns: Students participating in the SANS BACS internship program would find this information invaluable. It offers a way to rapidly deploy a honeypot without the need for purchasing and configuring hardware, allowing them to focus more on the core elements of their internship tasks.


This blog post provides an in-depth guide on how to deploy a DShield Honeypot using qemu on a Windows system with the Windows Subsystem for Linux (WSL). This approach offers a cost-effective and time-efficient way to contribute to the SANS ISC without needing to invest in additional hardware like a Raspberry Pi. By leveraging qemu's hardware emulation capabilities, this guide details the entire process, from setting up the initial environment, to resolving issues with kernel updates, and even configuring the Windows Firewall for data collection.

This strategy makes it easier to test, troubleshoot, and deploy DShield honeypots, and, in doing so, aid the broader cybersecurity community in gathering essential data about online threats. Whether you are a seasoned cybersecurity professional or a beginner interested in honing your skills, this qemu-based DShield honeypot deployment strategy offers an accessible pathway to contributing valuable data to the SANS ISC.


[1] https://www.dshield.org/tools/honeypot/
[2] https://github.com/DShield-ISC/dshield/blob/main/docs/install-instructions/Raspbian.md
[3] https://isc.sans.edu/diary/22680/
[4] https://github.com/DShield-ISC/dshield/issues
[5] https://learn.microsoft.com/en-us/windows/wsl/install
[6] https://apps.microsoft.com/store/detail/ubuntu-22042-lts/9PN20MSR04DW
[7] https://www.qemu.org/docs/master/system/arm/raspi.html
[8] https://raduzaharia.medium.com/system-emulation-using-qemu-raspberry-pi-3-4973260ffb3e
[9] https://tehtris.com/en/blog/our-selection-of-alerts-on-honeypots-report-9-may-2023
[10] https://github.com/DShield-ISC/dshield
[11] https://isc.sans.edu/register.html
[12] https://github.com/DShield-ISC/dshield/blob/main/docs/install-instructions/Ubuntu.md
[13] https://raspberrypi.stackexchange.com/questions/135262/how-to-install-raspberrypios-on-wsl
[14] https://www.qemu.org/docs/master/system/arm/raspi.html
[15] https://github.com/xme/dshield-docker
[16] https://www.mythic-beasts.com/order/rpi
[17] https://www.tomshardware.com/news/raspberry-pi-4-supply-issues


Published: 2023-09-12

Microsoft September 2023 Patch Tuesday

This month we got patches for 66 vulnerabilities. Of these, 5 are critical, and 2 are already being exploited, according to Microsoft.

One of the exploited vulnerabilities is a Microsoft Streaming Service Proxy Elevation of Privilege Vulnerability (CVE-2023-36802). According to the advisory, an attacker who successfully exploited this vulnerability could gain SYSTEM privileges. The CVSS for this vulnerability is 6.8.

The second one is a Microsoft Word Information Disclosure Vulnerability (CVE-2023-36761). According to the advisory, the Preview Pane is an attack vector and exploiting this vulnerability could allow the disclosure of NTLM hashes. 

Regarding critical vulnerabilities, one of them is a Remote Code Execution (RCE) vulnerability on Internet Connection Sharing (ICS) (CVE-2023-38148). According to the advisory, an unauthorized attacker could exploit this Internet Connection Sharing (ICS) vulnerability by sending a specially crafted network packet to the Internet Connection Sharing (ICS) Service. This vulnerability requires no user interaction and no privileges. The CVSS is 8.8 -  the highest for this month.

The second highest CVSS this month is associated to a RCE affecting Visual Studio (CVE-2023-36793). To exploit this vulnerability an attacker would have to convince a user to open a maliciously crafted package file in Visual Studio. The CVSS is 7.8.

See my dashboard for a more detailed breakout: https://patchtuesdaydashboard.com/

September 2023 Security Updates

CVE Disclosed Exploited Exploitability (old versions) current version Severity CVSS Base (AVG) CVSS Temporal (AVG)
.NET Core and Visual Studio Denial of Service Vulnerability
%%cve:2023-36799%% No No - - Important 6.5 5.7
.NET Framework Remote Code Execution Vulnerability
%%cve:2023-36788%% No No - - Important 7.8 6.8
3D Builder Remote Code Execution Vulnerability
%%cve:2023-36773%% No No - - Important 7.8 6.8
%%cve:2023-36772%% No No - - Important 7.8 6.8
%%cve:2023-36771%% No No - - Important 7.8 6.8
%%cve:2023-36770%% No No - - Important 7.8 6.8
3D Viewer Remote Code Execution Vulnerability
%%cve:2023-36760%% No No - - Important 7.8 6.8
%%cve:2023-36740%% No No - - Important 7.8 6.8
%%cve:2023-36739%% No No - - Important 7.8 6.8
AutoDesk: CVE-2022-41303 use-after-free vulnerability in Autodesk® FBX® SDK 2020 or prior
%%cve:2022-41303%% No No Less Likely Less Likely Important    
Azure DevOps Server Remote Code Execution Vulnerability
%%cve:2023-33136%% No No - - Important 8.8 7.7
%%cve:2023-38155%% No No - - Important 7.0 6.3
Azure HDInsight Apache Ambari Elevation of Privilege Vulnerability
%%cve:2023-38156%% No No - - Important 7.2 6.3
Chromium: CVE-2023-4761 Out of bounds memory access in FedCM
%%cve:2023-4761%% No No - - -    
Chromium: CVE-2023-4762 Type Confusion in V8
%%cve:2023-4762%% No No - - -    
Chromium: CVE-2023-4763 Use after free in Networks
%%cve:2023-4763%% No No - - -    
Chromium: CVE-2023-4764 Incorrect security UI in BFCache
%%cve:2023-4764%% No No - - -    
Chromium: CVE-2023-4863 Heap buffer overflow in WebP
%%cve:2023-4863%% No No - - -    
DHCP Server Service Denial of Service Vulnerability
%%cve:2023-38162%% No No - - Important 7.5 6.5
DHCP Server Service Information Disclosure Vulnerability
%%cve:2023-38152%% No No - - Important 5.3 4.6
%%cve:2023-36801%% No No - - Important 5.3 4.6
Dynamics Finance and Operations Cross-site Scripting Vulnerability
%%cve:2023-36800%% No No - - Important 7.6 6.6
Electron: CVE-2023-39956 -Visual Studio Code Remote Code Execution Vulnerability
%%cve:2023-39956%% No No - - Important    
Internet Connection Sharing (ICS) Remote Code Execution Vulnerability
%%cve:2023-38148%% No No - - Critical 8.8 7.7
Microsoft Azure Kubernetes Service Elevation of Privilege Vulnerability
%%cve:2023-29332%% No No - - Critical 7.5 6.5
Microsoft Dynamics 365 (on-premises) Cross-site Scripting Vulnerability
%%cve:2023-36886%% No No - - Important 7.6 6.6
%%cve:2023-38164%% No No - - Important 7.6 6.6
Microsoft Excel Information Disclosure Vulnerability
%%cve:2023-36766%% No No - - Important 7.8 6.8
Microsoft Exchange Server Information Disclosure Vulnerability
%%cve:2023-36777%% No No - - Important 5.7 5.0
Microsoft Exchange Server Remote Code Execution Vulnerability
%%cve:2023-36756%% No No - - Important 8.0 7.0
%%cve:2023-36745%% No No - - Important 8.0 7.0
%%cve:2023-36744%% No No - - Important 8.0 7.0
Microsoft Exchange Server Spoofing Vulnerability
%%cve:2023-36757%% No No - - Important 8.0 7.0
Microsoft Identity Linux Broker Remote Code Execution Vulnerability
%%cve:2023-36736%% No No - - Important 4.4 3.9
Microsoft Office Elevation of Privilege Vulnerability
%%cve:2023-36765%% No No - - Important 7.8 6.8
Microsoft Office Security Feature Bypass Vulnerability
%%cve:2023-36767%% No No - - Important 4.3 3.8
Microsoft Office Spoofing Vulnerability
%%cve:2023-41764%% No No - - Moderate 5.5 4.8
Microsoft Outlook Information Disclosure Vulnerability
%%cve:2023-36763%% No No - - Important 7.5 6.5
Microsoft SharePoint Server Elevation of Privilege Vulnerability
%%cve:2023-36764%% No No - - Important 8.8 7.7
Microsoft Streaming Service Proxy Elevation of Privilege Vulnerability
%%cve:2023-36802%% No Yes - - Important 7.8 6.8
Microsoft Word Information Disclosure Vulnerability
%%cve:2023-36761%% Yes Yes - - Important 6.2 5.6
Microsoft Word Remote Code Execution Vulnerability
%%cve:2023-36762%% No No - - Important 7.3 6.4
Visual Studio Code Remote Code Execution Vulnerability
%%cve:2023-36742%% No No - - Important 7.8 6.8
Visual Studio Elevation of Privilege Vulnerability
%%cve:2023-36759%% No No - - Important 6.7 5.8
%%cve:2023-36758%% No No - - Important 7.8 6.8
Visual Studio Remote Code Execution Vulnerability
%%cve:2023-36796%% No No - - Critical 7.8 6.8
%%cve:2023-36794%% No No - - Important 7.8 6.8
%%cve:2023-36793%% No No - - Critical 7.8 6.8
%%cve:2023-36792%% No No - - Critical 7.8 6.8
Windows Cloud Files Mini Filter Driver Elevation of Privilege Vulnerability
%%cve:2023-35355%% No No - - Important 7.8 6.8
Windows Common Log File System Driver Elevation of Privilege Vulnerability
%%cve:2023-38144%% No No - - Important 7.8 6.8
%%cve:2023-38143%% No No - - Important 7.8 6.8
Windows Defender Attack Surface Reduction Security Feature Bypass
%%cve:2023-38163%% No No - - Important 7.8 6.8
Windows GDI Elevation of Privilege Vulnerability
%%cve:2023-38161%% No No - - Important 7.8 6.8
%%cve:2023-36804%% No No - - Important 7.8 6.8
Windows Kernel Elevation of Privilege Vulnerability
%%cve:2023-38150%% No No - - Important 7.8 7.0
%%cve:2023-38142%% No No - - Important 7.8 6.8
%%cve:2023-38141%% No No - - Important 7.8 6.8
%%cve:2023-38139%% No No - - Important 7.8 6.8
Windows Kernel Information Disclosure Vulnerability
%%cve:2023-38140%% No No - - Important 5.5 4.8
%%cve:2023-36803%% No No - - Important 5.5 4.8
Windows MSHTML Platform Security Feature Bypass Vulnerability
%%cve:2023-36805%% No No Less Likely Less Likely Important 7.0 6.1
Windows Miracast Wireless Display Remote Code Execution Vulnerability
%%cve:2023-38147%% No No - - Important 8.8 7.7
Windows TCP/IP Denial of Service Vulnerability
%%cve:2023-38149%% No No - - Important 7.5 6.5
Windows TCP/IP Information Disclosure Vulnerability
%%cve:2023-38160%% No No - - Important 5.5 4.8
Windows Themes Remote Code Execution Vulnerability
%%cve:2023-38146%% No No - - Important 8.8 7.7

Renato Marinho
Morphus Labs| LinkedIn|Twitter


Published: 2023-09-11

Apple fixes 0-Day Vulnerability in Older Operating Systems

This update fixes the ImageIO vulnerability Apple patched for current operating systems last week. Now, Apple follows up with a patch for its older, but still supported, operating system versions.

According to Citizen Lab, this vulnerability is already being exploited. Exploitation took advantage of the ImageIO vulnerability and a vulnerability in the Apple wallet "PassKit" API to send a "Pass" to the victim, including the malicious image. These older operating systems support PassKit, but it needs to be clarified if they are vulnerable to the PassKit issue.

More details: Apple: https://support.apple.com/en-us/HT201222

Citizen Lab: https://citizenlab.ca/2023/09/blastpass-nso-group-iphone-zero-click-zero-day-exploit-captured-in-the-wild/


iOS 15.7.9 and iPadOS 15.7.9 macOS Monterey 12.6.9 macOS Big Sur 11.7.10
CVE-2023-41064 [critical] ChatGPT-CVSS: 9 *** EXPLOITED *** ImageIO
A buffer overflow issue was addressed with improved memory handling.
Processing a maliciously crafted image may lead to arbitrary code execution. Apple is aware of a report that this issue may have been actively exploited.
x x x

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


Published: 2023-09-10

Quickie: Generating a YARA Rule to Detect Obfuscated Strings

In diary entry "Creating a YARA Rule to Detect Obfuscated Strings" I explain how to tune a YARA rule with regular expressions for performance.

I'm sharing here a Python script I wrote to generate regular expressions. The script takes one argument: the string to BASE64 encode and generate regexes for (string "ActiveMime" in my previous diary entry):

import base64
import itertools
import sys

def GenerateRegex(word):
    strings = []
    whitespace = [' ', '\\t', '\\r', '\\n']
    detect = word[:len(word) // 3 * 3]
    print(f'String to search: {word}')
    print(f'String to search (* 3): {detect}')
    detectBASE64 = base64.standard_b64encode(detect.encode('utf8')).decode('latin')
    print(f'BASE64 string to search: {detectBASE64}')
    whitespaceregex = '[' + ''.join(whitespace) + ']*'
    print(f'Whitespace characters: {whitespaceregex}')

    detectBASE64 = [char for char in detectBASE64]


    for ws in itertools.product(whitespace, whitespace):
        strings.append(detectBASE64[0] + ''.join(ws) + whitespaceregex.join([''] + detectBASE64[1:]))
    for ws1 in whitespace:
        strings.append(''.join(detectBASE64[0:2]) + ws1 + whitespaceregex.join([''] + detectBASE64[2:]))
    strings.append(''.join(detectBASE64[0:3]) + whitespaceregex.join([''] + detectBASE64[3:]))

    return strings, detect

def Main():
    regexStrings, detect = GenerateRegex(sys.argv[1])

    print('        $base64_%s%d = /%s/' % (detect, 0, regexStrings[0]))
    for index, regex in enumerate(regexStrings[1:]):
        print('        $base64_%s%d = /%s/' % (detect, index + 1, regex))

if __name__ == '__main__':

Didier Stevens
Senior handler
Microsoft MVP


Published: 2023-09-09

?Anyone get the ASN of the Truck that Hit Me?!?: Creating a PowerShell Function to Make 3rd Party API Calls for Extending Honeypot Information [Guest Diary]

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


For this blog post, after a mid-point conversation with the SANS team and mentors, I’ve decided to show how I go about creating a function in PowerShell to assist in sorting wheat from chaff in the process of rationalizing honeypot attackers, by modeling API calls in Postman.

What’s an API and how do I use it?

First off, I’d like to touch on the application Postman [2]. Postman is a wonderful tool that can be used to rationalize and share API calls for platforms, and also to publish and collaborate with other members of a team. 

As a security professional, you’ll often have use for integrating services\platforms into processes, and APIs are key to understanding a platform’s capabilities and ultimately automating them. There are other platforms that can aid in this process, Postman is simply my preferred tool and I’ll demo some of the reasons here.

Where do I get started?

When creating a module it is good to start off with an understanding of the moving pieces in the API, as these elements will be molded into the functions for the module as “variables”. The API we’ll be working with is the AlienVault OTX platform, which allows for free sign-up and API access. 

On this page there are a list of different areas of focus for the platform (domains, URLs, IP addresses, etc.) via the API and you should look over the API endpoints to come up with a series of functions that would benefit a threat hunter\security analyst via scripting.

In some cases – the service\platform provider offers a directly importable collection for Postman, which details out all of the API elements for you. This is the case with the Atlassian product Jira [4], where both the Postman collection and the OpenAPI specification are available via the documentation site:

(Note: Importing collections to Postman is documented here)

How does Postman help us to use PowerShell??

Postman offers us the ability to craft the calls that we’d like to make, based off the specifications of the API, and generate code for a litany of different coding standards (PowerShell, Python, Perl, C#, etc.) – and create a wrapper in our chosen scripting language to modularize it!

To start creating a collection & call from scratch – we’re going to the AVOTX call for looking up IP addresses (/api/v1/indicators/IPv4/{ip}/{section})

(Note: Creating an account for AVOTX is recommended, but it is not necessary to follow the concepts). Here we can see the fields that will become variables in our function for Postman (and ultimately PowerShell):

We are going to create a new API collection in Postman:

  • Click “New”
  • Click “Collection”

  • Name the collection “AlienVault OTX”
  • On the left hand side, you should see the collection – Expand it using the carat at the side and click “Add a request”

  • Name the request “IP Address Lookup” and hit Enter

You should now have a blank canvas to start crafting your query for IP addresses!

Now we’re going to set some variables both for the environment and also for the URL that we’re submitting. Click “New” -> “Environment”, name the new environment “AlienVault OTX”. We’ll need to set the following variables:

(Note: You will need to sign up for an account in order to obtain an API key, which will be visible here, and replace the “apikey” value listed above)

Click “Save”, and we can now select “AlienVault OTX” from the environment dropdown menu in the top right corner of the interface, making the variables that we set available in our requests. Creating an environment allows you to share queries without hardcoding your credentials into the collection, and also allows you to switch between DEV\PROD instances when working with APIs that might have different uses.

To place these variables we’ve created into the calls – we’ll bring our tab for “IP Address Lookup” back to the forefront, and put the following into the “Enter URL or paste text” field at the top:


This will do a number of things. If you hover over the {{baseURL}} (case sensitive) you should see that the Postman interface recognizes it as your environment variable. The two in URL or “path variables) (ip and section) are also stubbed out below:

We need to set the values and descriptions for the variables now (IP address taken from my attack observation #3 during SANS ISC internship):

We also need to set the authentication for the call to use our API key by clicking on the “Authorization” tab, choosing the type of "Bearer Token", and setting the token value to {{apikey}} (which we set in the environment variables earlier):

We should be all set to click on the “Send” button, and the data for the call should populate at the bottom of the screen in a JSON format (if it isn’t colorized as seen – ensure that "JSON" is selected from the depicted field:

NOW we get to the PowerShell bit. After making that call – there’s an icon on the right side of the interface for “Code” that we need to click…

… which then brings up an interface with a dropdown menu, allowing you to select the coding model that you would like to see the call set against in a code snippet!

(MAJOR NOTE: We will not be going into this, as it is multiple blog posts in-and-of itself, but you will want to choose a secure way to manage and implement credentials in your scripting. Some blog posts to get you started (parts 1 & 2), and you may also want to look into secret vaulting)

I was told there would be PowerShell…

Now that we can see the formatting for how the call works against the API, we just need to craft the function and export it to a module. The API call has two functions which will be accounted for in the parameters, and an environment variable which will be called for the API key. Long term, you will want to choose a path forward for how you set this value ($avotx_apikey).

I’ve crafted the following (extremely basic\no frills) PowerShell function to wrap up the API call: https://github.com/WhatInTheShell/PublicShare/blob/main/README.md

The "IPAddress" parameter accepts an array of strings to attempt to query, and returns data associated to the submitted IPv4 addresses. A more elaborate error handling could be created for this function, taking into account elements such as…

  • API call limit exhaustion
  • Service being unreachable
  • API key not being set (check before call)
  • Etc.

… but for brevity I’m simply adding the very basics of “if not success, throw error”.

Cool… but now what do I use it for?

In the Cowrie logs folder for the DShield Honeypot (/srv/cowrie/var/log/cowrie), there are JSON formatted files for traffic that can be extracted from the device (or processed directly w\PowerShell Core) and used to find IP addresses that are attacking. For this you would use a combination of Get-Content & ConvertFrom-JSON:

Based off of the function that we have, the “src_ip” field is going to be of most interest to us, and we only want to submit an IP address once, so we will want to employ the Select-Object with -ExpandProperty & -Unique options set – and store the returned values as an array called $attackers:

$attackers = Get-Content "$local_folder_path\CowrieLogs\cowrie.json.2023-08-19" | ConvertFrom-Json | Select-Object -ExpandProperty src_ip -Unique

Once those values are collected and stored, gathering information on the IP addresses that are hitting your honeypot is as easy as running this oneliner:

$otx_research_data = Get-OTXIPv4Data -IPAddress $attackers -Sections general -APIKey $avotx_apikey

You can now use the $otx_research_data object to group the entries by reputation, country code, recognized trends, etc. – allowing an analyst\threat researcher to prioritize what to look into. This process can be repeated and stacked with other services that are either free consumption or services your organization subscribes to.


Python is great, and this exact same process can be used in creating a Python function to get the same result. What I wanted to do was step away from the security standard go-to for scripting and show how similar goals can be achieved in an alternative fashion. 

When crafting a solution, it is better to have a tool and not need it, than to need a tool and not have it. You may have associates joining your team, or working in tandem with the security department, that don’t have as much exposure\experience with one language versus another.

If you are able to show examples of something that they are familiar with, it lowers the bar of entry in adopting new approaches, implementing new automations, and increases the extensibility of solutions and partnerships.

[1] https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-7.3
[2] https://www.postman.com
[3] https://otx.alienvault.com/api
[4] https://www.atlassian.com/software/jira
[5] https://developer.atlassian.com/cloud/jira/platform/rest/v3/intro/#about
[6] https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-and-exporting-overview/
[7] https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-1/
[8] https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-2/
[9] https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/how-to/manage-secretstore?view=ps-modules
[10] https://learn.microsoft.com/en-us/powershell/scripting/install/install-ubuntu?view=powershell-7.3
[11] 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


Published: 2023-09-07

Apple Releases iOS/iPadOS 16.6.1, macOS 13.5.2, watchOS 9.6.2 fixing two zeroday vulnerabilities

macOS Ventura 13.5.2 iOS 16.6.1 and iPadOS 16.6.1 watchOS 9.6.2
CVE-2023-41064 [critical] ChatGPT-CVSS: 9.8 *** EXPLOITED *** ImageIO
A buffer overflow issue was addressed with improved memory handling.
Processing a maliciously crafted image may lead to arbitrary code execution. Apple is aware of a report that this issue may have been actively exploited.
x x  
CVE-2023-41061 [moderate] ChatGPT-CVSS: 9.8 *** EXPLOITED *** Wallet
A validation issue was addressed with improved logic.
A maliciously crafted attachment may result in arbitrary code execution. Apple is aware of a report that this issue may have been actively exploited.
  x x


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


Published: 2023-09-07

Fleezeware/Scareware Advertised via Facebook Tags; Available in Apple App Store

Scareware, software advertised via fake malware messages, or Fleezeware, software providing questionable subscription services, keeps ending up in Apple's app store, bypassing various controls Apple uses to restrict software available to its users. Part of the difficulty in proactively recognizing this type of software is that these apps are often benign. The issue with this software is that it doesn't do much, if anything at all. The program becomes more obvious in how the software is advertised. 

The latest example is "Synapse Security," published by Pas Borisa UAB. The software's main feature appears to be a VPN service. The software is advertised via Facebook by "tagging" users. Once a user has been "tagged", the post may also be visible in the feed of friends of the tagged user. The posts used have deceptive clickbait content:

Interestingly, the link results in a TLS error if it is clicked on in a desktop browser. The server appears to perform some TLS fingerprinting. Curl is also not allowed:

% openssl s_client --connect ffm.link:443
00074457F87F0000:error:0A0003E8:SSL routines:ssl3_read_bytes:reason(1000):ssl/record/rec_layer_s3.c:1586:SSL alert number 0

But my iPad was able to connect without problem, and received the typical "scareware" page:

Clicking on OK leads to the Apple Appstore page for "Synape Security", which describes itself as "The pulse of online protection." The app is luckily not popular enough to have received sufficient reviews. It offers a number of subscription options, starting with a one-week option for $8.99. Overall, the price appears to be higher than other VPN offers from well-known companies. In addition to the VPN service, the application offers ad blocking.

I briefly installed the application without paying for premium services. It configured an IPSEC VPN and appeared to work, but I have not had the time to check its effectiveness. Given the deceptive advertising, I do not expect anything useful.

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


Published: 2023-09-06

Security Relevant DNS Records

DNS has a big security impact. DNS is partly responsible for your traffic reaching the correct host on the internet. But there is more to DNS than name resolution. I am going to mention a few security-relevant record types here, in no particular order:

I did add some records mentioned by@hquest on Twitter.

DNSSEC (DNSKEY, RRSIG, DS, NSEC3, and others...)

That is probably the most obvious security-related feature. DNSSEC is used to digitally sign DNS records. It protects the integrity of DNS responses. Note that DNSSEC does nothing to protect the confidentiality of the data. DNS requests are not affected by DNSSEC either. There are a few different records related to DNSSEC:

  • DNSKEY: DNS records used to retrieve the public key used to verify the DNS signatures.
  • RRSIG: Signature for a particular DNS records
  • DS: Hash of a key used to verify the key integrity.


While there was at one point a proposal for a dedicated SPF record type, these email security features all use TXT records. SPF designates authorized mail servers allowed to send email for a particular domain. DKIM offers public keys that can be used to verify DKIM signatures, and DMARC  records will indicate what to do with email that does not pass DKIM and/or SPF verification.


These TXT records are part of MTA-STS (Strict Transport Security). They are used to indicate that a mail server will support STARTTLS. Together with TLSRPT for reporting, the goal is to prevent downgrade attacks.


The "Certificate Authorization Authority" record will list certificate authorities that may issue certificates for a particular domain. Certificate authorities check this record before issuing a certificate. TLS clients, like browsers, will not verify this record. The CAA record may also include an email address to notify if a certificate request was rejected due to the CAA record.


This record type can assist in setting up an HTTPS connection. It may indicate supported HTTP versions. For security, it will indicate support for encrypted client hellos (ECH). But this feature has not been used much so far.


Used to advertise the fingerprint of TLS certificates. This record requires DNSSEC.

Any other record types I missed?

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


Published: 2023-09-05

Common usernames submitted to honeypots

Based on reader feedback, I decided to take a look at usernames submitted to honeypots. The usernames that are seen on a daily basis look very familiar. They tend to come from default user accounts, such as "administrator" on Windows systems or "root" on Linux systems. The knowledge of a default user account can help in brute force attacks. If the username is already known, only the password needs to be guessed. This shouldn't be too much of a problem to users as long as strong passwords are chosen or other authentication methods such as public key authentication is used. Setting up public key authentication is also referenced in our DShield setup instructions for a Raspberry Pi [2]. 

I exported the username data from my honeypot, which is a little over 16 months of data, using JQ. 

# output data from all local cowrie logs
# cat /logs/cowrie.json.* 
# select data with the username key present
# jq 'select(.username)' 
# output raw username vales (without quotes) and store in a text file
# jq -r .username > 2023-09-04_all_usernames_raw.txt

cat /logs/cowrie.json.* | jq 'select(.username)' | jq -r .username > 2023-09-04_all_usernames_raw.txt


Total number of usernames submitted: 3,668,336
Number of unique passwords submitted: 105,022 (2.86% of passwords submitted were unique)

The most common username, "root", accounted for almost 50% of the total username submissions. This is not surprising since SSH is a common attack protocol that the honeypots collect this data from and is commonly used in Linux systems. This may change over time as newer Windows operating systems which include SSH options, become more common [3].

Username Count Percentage
root 1,778,938 48.49%
admin 137,971 3.76%
user 58,942 1.61%
test 48,086 1.31%
ubuntu 44,230 1.21%
345gs5662d34 36,473 0.99%
nproc 33,269 0.91%
postgres 17,700 0.48%
oracle 17,384 0.47%
ftpuser 13,404 0.37%
TOTAL 2,186,397 59.60%

Figure 1: Top 10 usernames submitted to my honeypot and overall counts


Almost 60% of all usernames come from the top 10 list. Let's take a look at some of the most frequently used passwords for some of these usernames. This data can also be extracted with JQ.

# output all cowrie data in /logs directory
# cat /logs/cowrie.json.*
# select all data with the username of "root"
# jq 'select(.username=="root")'
# output raw password data (no quotes)
# jq -r .password
# sort data alphabetically
# sort
# give unique password values with frequency counts
# uniq -c
# sort data by frequency count, reverse sorted (descending, most frequent hits on top)
# and save results to text file
# sort -rn > passwords_submitted_with_root_user_count.txt

cat /logs/cowrie.json.* | jq 'select(.username=="root")' | jq -r .password | sort | uniq -c | sort -rn > passwords_submitted_with_root_user_count.txt

Figure 2: Honeypot passwords associated with most common usernames


In the honeypot data, there are some deviations with the most common passwords used. The most commonly submitted password with the "root" user account was noted in my previous diary [4]. This also highlights another unusual finding with a username of the same value ("345gs5662d34"). This username only has one password associated with it, unlike the other top findings. If you know something about this particular value, please add a comment.

It's very common to see the login for a new device or service to have a default password that is the same as the built-in default user account. Attacking these default values can be very successful if users do not change the default password. Also, if a device is reset during troubleshooting, these default credentials may not be addressed after the reset. 

Figure 3: 20 Most frequently used usernames for one honeypot over the last 16 months


The most commonly submitted usernames and passwords with the same values can also be easily retrieved with JQ. 

# read json logs in /logs directory
# cat /logs/cowrie.json.*
# select values with the username key present
# jq 'select(.username)'
# select data where the values in the username and password keys are equal
# jq 'select(.username==.password)'
# select and output username and password values in CSV format
# jq -r '[.username, .password] | @csv'
# sort data alphabetically
# sort 
# display unique values with the number of instances of the value
# uniq -c
# sort the data by number of instances, reverse sorted (descending order)
# sort -nr
# display the first 30 items
# head -n 30

cat /logs/cowrie.json.* | jq 'select(.username)' | jq 'select(.username==.password)' | \
jq -r '[.username, .password] | @csv' | sort | uniq -c | sort -nr | head -n 30

Figure 4: 30 most commonly seen matching username and psasword values from honeypot


Make sure to use unique passwords and when possible, avoid using the default account with your device or service [5]. If possible, disable that account and when it's not possible, set a very strong password with limited rights. 

[1] https://community.ui.com/questions/user-name-and-password/68e13798-d7b8-41e2-9e8e-cec3d92b0c4e
[2] https://isc.sans.edu/honeypotinstall.pdf
[3] https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui
[4] https://isc.sans.edu/diary/What+is+the+origin+of+passwords+submitted+to+honeypots/30182/
[5] https://www.raspberrypi.com/news/raspberry-pi-bullseye-update-april-2022/

Jesse La Grew


Published: 2023-09-04

Creating a YARA Rule to Detect Obfuscated Strings

I wrote a blog post "Quickpost: Analysis of PDF/ActiveMime Polyglot Maldocs" on how to analyse PDF/ActiveMime polyglot malicious document files and also developed a YARA rule to detect them.

These polyglot files are PDF files into which an Office document (for example, a Single File Web Page Word document) has been embedded (in various ways).

When a Word document with VBA code is saved as a Single File Web Page, the ole file with the VBA code is stored inside an ActiveMime file. That file starts with binary sequence ActiveMime.

A Single File Web Page is a MIME file, the ActiveMime file is stored as a BASE64 encoded part.

To detect PDF/ActiveMime maldocs, I developed a YARA rule that looks for a PDF header at the start of the file and contains the string "ActiveMime" in BASE64.

A simple rule to implement this looks like this:

rule pdfactivemime1 {
        $pdf = "%PDF-"
        $activemime = "ActiveMime" base64
        $pdf at 0 and $activemime

A simple rule like that is able to detect the simple PoC file I made, but is not able to detect the maldocs found in the wild. That's because of obfuscation.

The BASE64 encoded part in the MIME file can be obfuscated by adding extra whitespace characters between the individual characters that compose the BASE64 string.

Here is a simple example. ActiveMim in BASE64 is QWN0aXZlTWlt. I added an extra line break between Q and WN0aXZlTWlt:

This simple change breaks the simple YARA rule, but does not hinder the Word parser: it is still able to read the document.

In the maldocs found in-the-wild, much more whitespace characters were added. So we need a YARA rule to take this into account, and the solution is to use a regular expression that looks for the characters QWN0aXZlTWlt (potentialy) interspersed with whitespace characters (I selected 4 whitespace characters: space, tab, carriage-return and newline).

Like this rule:

rule pdfactivemime2 {
        $pdf = "%PDF-"
        $activemime = /Q[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $pdf at 0 and $activemime

The rule works, however, YARA issues a warning, that the rule may slow down scanning.

So you can use this rule for ad-hoc detection, but not for intensive scanning.

The problem is the following: one of the first steps of a YARA scan, is to search for so called "atoms". Atoms are short, fixed substrings of the strings you provide in your rules.

The fixed substrings in string $activemime in rule pdfactivemime2 are all individual characters, e.g., they are one byte long. And that is too short to execute a performant Aho-Corasick search (the search algorithm used by the YARA engine).

The solution I implemented is the following: I made a set of regular expressions that all start with 3 fixed characters, by generating all the possible combinations (product):

  • Q followed by 2 space characters
  • Q followed by a space character and a tab character
  • Q followed by a space character and a carriage-return character
  • ...
  • Q followed by W and a space character (e.g., no whitespace between Q and W)
  • ...

Just a single regex needs to match for the rule to trigger:

rule rule_pdf_activemime {
        author = "Didier Stevens"
        date = "2023/08/29"
        version = "0.0.1"
        samples = "5b677d297fb862c2d223973697479ee53a91d03073b14556f421b3d74f136b9d,098796e1b82c199ad226bff056b6310262b132f6d06930d3c254c57bdf548187,ef59d7038cfd565fd65bae12588810d5361df938244ebad33b71882dcf683058"
        description = "look for files that start with %PDF- and contain BASE64 encoded string ActiveMim (QWN0aXZlTWlt), possibly obfuscated with extra whitespace characters"
        usage = "if you don't have to care about YARA performance warnings, you can uncomment string $base64_ActiveMim0 and remove all other $base64_ActiveMim## strings"
        $pdf = "%PDF-"
        $base64_ActiveMim1 = /Q  [ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim2 = /Q \t[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim3 = /Q \r[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim4 = /Q \n[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim5 = /Q\t [ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim6 = /Q\t\t[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim7 = /Q\t\r[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim8 = /Q\t\n[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim9 = /Q\r [ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim10 = /Q\r\t[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim11 = /Q\r\r[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim12 = /Q\r\n[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim13 = /Q\n [ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim14 = /Q\n\t[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim15 = /Q\n\r[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim16 = /Q\n\n[ \t\r\n]*W[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim17 = /QW [ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim18 = /QW\t[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim19 = /QW\r[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim20 = /QW\n[ \t\r\n]*N[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $base64_ActiveMim21 = /QWN[ \t\r\n]*0[ \t\r\n]*a[ \t\r\n]*X[ \t\r\n]*Z[ \t\r\n]*l[ \t\r\n]*T[ \t\r\n]*W[ \t\r\n]*l[ \t\r\n]*t/
        $pdf at 0 and any of ($base64_ActiveMim*)


By hardcoding the first 3 character combinations in each regex, the YARA engine can select atoms that are larger than one byte (3 bytes maximum in this case).

You can find this rule in my GitHub repository here and the PoCs in my GitHub repository here.

Remark that the maldocs in-the-wild have more obfuscation methods (like the MIME-Version header) and that it is possible to significantly reduce the MIME file in size.

PDF files need to start with header %PDF- at the first position in the file according to the PDF language specification, but PDF parsers are lenient and the %PDF- header can be located later in the file. The YARA rule I made does not account for this.

Didier Stevens
Senior handler
Microsoft MVP


Published: 2023-09-03

Analysis of a Defective Phishing PDF

A reader submitted a suspicious PDF file. TLDR: it's a defective phishing PDF.

Taking a look with pdfid.py, I see nothing special, but it contains stream objects:

With the recent PDF/ActiveMime polyglots in mind, I also use option -e to get some extra information:

This looks normal: the file is mostly composed of data inside streams, and the entropy of data inside streams is high (compressed), and outside streams is low. Plus, there's very little data outside streams.

Notice that the datetimes indicate that this file was created August 18th (mind that this can be spoofed, but that this date is likely reliable since the file was first submitted to VT on August 22nd).

As the file contains stream objects (/ObjStm, these are objects that contain other objects inside their compressed stream), it's best to generate statistics for this PDF file using pdf-parser.py using option -a and -O:

So this file contains no keywords that are typical for a phishing PDF (like /URI).

It does contain unreferenced objects, like 18 and 24, but that's normal (they are, respectively, /ObjStm and /XRef objects).

But object 14 could be something different:

It's a typeless object, without stream, and just a dictonary with a key /Names that is an empty list. This could be an indication of defectiveness (something missing), or it could be an artifact of the PDF library used to create this document.

Let's take a look at object 9 (/XObject), this is likely an image:

It is indeed a JPEG image (DCTDecode).

Let's dump this to disk to view it:

Before I open the file (inside a VM) to view the picture, I check with my jpegdump.py tool to verify that this is indeed a JPEG file:

It looks indeed like a valid JPEG file. Except for the 2 bytes at the end:

That's a CR & NL character, and is an artifact of the extraction with pdf-parser: pdf-parser does not take the /Lenght value into account, and just extracts everything up to the endstream keyword. The /Length value is 114386 and the extracted file is 114388 in size.

I can finally take a view at the image:

And that is indeed a typical phishing image.

I do open the PDF inside a VM to see if there is no clickable object that my tools missed, but there is none: this is a defective phishing PDF (the link is missing).

It requires far more work if you need to be absolutely sure that there is no malicious content in a PDF file, like I showed years ago in this diary entry series: "It is a resume".

I'm not going to repeat this for this document, I feel confident that this is a defective phishing PDF.

Last thing I did, was to take a look for indications of the recently reported PDF/ActiveMime polyglots:

No indicators.

Didier Stevens
Senior handler
Microsoft MVP


Published: 2023-09-02

What is the origin of passwords submitted to honeypots?

We use passwords just about everywhere in our daily lives. It's difficult to think of an online service where we don't have a need to enter some kind of credentials to access our content. DShield honeypots collect a variety of data, including passwords, that are submitted from SSH and telnet attacks.

Figure 1: Snapshot on 9/1/2023 of DShield submitted usernames and passwords [1]

The passwords in the above image are ones that are very common week passwords. This is only a small sample of the passwords submitted to honeypots and it made me curious whether there was any particular origin of the submitted passwords:

  • Default system passwords
  • Data breach passwords
  • Randomly generated passwords [2]

As a starting point, I complared the almost 250,000 unique passwords submitted to my honeypot with some publicly available sources:

  • Rockyou [3]
  • HaveIBeenPwned Passwords [4]


Extracting Honeypot Passwords

There are many ways to get the passwords out of a DShield honeypot, especially if external logging of the cowrie data is set up. The method used in this case was to pull it out of the local JSON logs I regularly archive.

# read all cowrie JSON logs
# cat /logs/cowrie.json.*
# select logs with the .password key present
# jq 'select(.password)'
# query the value in the password key and return in raw format (without surrounding quotes)
# jq -r .password
# sort the values alphabetically
# sort
# return only unique values and output to a text file
# uniq > 2023-08-15_unique_passwords_raw.txt

cat /logs/cowrie.json.* | jq 'select(.password)' | jq -r .password | sort | uniq > 2023-08-15_unique_passwords_raw.txt


Comparing Password Data

The data available from the three sources came in different formats and and needed to be converted for comparison.

Data Source Starting Format Converted format
Honeypot passwords utf-8 strings SHA1 Hash
Rockyou passwords latin-1 strings SHA1 Hash
HaveIBeenPwned passwords SHA1 hash with frequency count SHA1 Hash

Since a hash cannot be reversed, hashing the passwords supplied to the honeypot and from the rockyou was performed. This actually made the process easy since little processing was needed for the HaveIBeenPwned password list, which was around 36GB in size.

Seconds to process: 1800.039571
Total honeypot hashes:  247799
Total HaveIBeenPwned hashes:  865964448
Total RockYou hashes:  14343758
RockYou Matched Hashes:  78235
RockYou ONLY Matched Hashes:  15
HaveIBeenPwned Matched Hashes:  164048
Percentage of honeypot passwords found in HaveIBeenPwned breach data:  66.2%
Percentage of honeypot passwords found in RockYou data:  31.57%
Percentage of honeypot passwords found ONLY in RockYou data:  0.01%
Average processing pace:  481080.78 hashes per second

Something learned from this process was that using a Python set() is much faster than using a Python list[]. Nothing makes this much more evident than processing a 36GB text file. Since these values were unique within each data set, a Python set() worked very well.

Also, latin-1 strings were used with the Rockyou list due issues with attempting utf-8 encoding.


Data Comparisons

Looking frequently at cowrie attacks regularly from the DShield honeypot, I knew that there was going to be some unusual results. Rather than filter those out ahead of time, I decided to look at the information visually by comparing password length frequencies.

Figure 2: Password length frequencies from honeypot submissions

The data shows that the most common password length is 8 characters, but there are a lot of passwords with much greater length and lower frequencies. The longest password that had a match in the HaveIBeenPwned data was 48 characters.

Figure 3: Longest password matching HaveIBeenPwned data was 48 characters in length

So, what are these longer passwords? In most cases, the data is most likely not a password, but another part of an attack such as a terminal command or even data meant to be sent to another protocol, such as HTTP.

Figure 4: Examples of data that were not likely meant for password submissions

As the passwords get longer, these commands stand out even more. When filtering out passwords longer than 48 characters, there is not a large difference in the match percentages. It turns out that there are only a few hundred of these passwords out of almost 250,000.

  Count Percentage
HaveIBeen Pwned Matches 164041 66.28%
RockYou Matches 78233 31.61%
Total Hashes 247482  


Passwords Without Matches

Approximately 2/3 of the passwords used to attack my honeypot were available in HaveIBeenPwned password data. What about the other 1/3 of the passwords? I pulled out one specific password example since it had no matches within the breach data used, but was also one of the top 20 passwords attempted this year [5].

Figure 5: Password example with no matches in breach data, but frequently seen

There are a variety of search results in Google when searching for this value. From the search results I was unable to find a source, but many of the results came from honeypot data. The password below the one identified also came up in a variety of articles. WIthin GitHub, that password was available in other honeypot data. This left me with some other questions:

  • How do write-ups about specific passwords impact those passwords being used in attacks?
  • How often is reported information security data used to perpetuate attacks?
  • What is the source of these other "unmatched" passwords? Are they generated or just from breach data not as freely available?



Password breach data is commonly used in credential stuffing attacks.

  • Use a password manager (could even be a notebook in a locked drawer)
  • Use unique passwords in combination with Multifactor Authentication (MFA)
  • Check sites like HaveIBeenPwned [6] to see if your email has been part of a reported breach
  • Use password breach data to diallow the use of those paswords
  • If you find a password you use publicly available, change it


[1] https://isc.sans.edu/data/ssh.html
[2] https://isc.sans.edu/diary/How+I+made+a+qwerty+keyboard+walk+password+generator+with+ChatGPT+Guest+Diary/30152/
[3] https://github.com/danielmiessler/SecLists/blob/master/Passwords/Leaked-Databases/rockyou.txt.tar.gz
[4] https://haveibeenpwned.com/Passwords
[5] https://isc.sans.edu/ssh_passwords.html
[6] https://haveibeenpwned.com/

Jesse La Grew