Wireshark 4.6.7 Released
Wireshark release 4.6.7 fixes 12 vulnerabilities and 16 bugs.
Didier Stevens
Senior handler
blog.DidierStevens.com
"Comment stuffing" in an HTML phishing attachment as a mechanism for evading AI-based detection?
Anyone who deals with phishing messages caught by basic security filters knows that most phishing samples tend to blend into one another, since only a small set of techniques and approaches keeps reappearing in them. That is precisely why it is worth pausing on the occasional message that does something a little out of the ordinary.
One such unusual message was caught on Tuesday by an e-mail security solution used by one of my clients. At first glance, both the e-mail body and the attached credential-stealing HTML page looked entirely generic, however, the fact that the attachment was fairly large, and that Outlook claimed the date on which the e-mail had been sent was “None”, caught my attention and made me take a second look… Which was fortunate, because it appears that the large size of the attachment might be connected to the increasing role that AI is playing in e-mail security in an interesting way.
Before we get to the attachment, however, the phishing message itself deserves a brief mention, since several small details in its headers suggest that it was not sent through any normal mail path, but rather generated by a simple, homemade script.
The e-mail presented itself as a Microsoft Teams notification about a document shared over SharePoint, with another document attached directly to the message (note the text “None” in the upper right corner where a date should be).
As you can see, the “From” header claimed that the message came from “Microsoft Teams Notifications <[email protected]>”. Unsurprisingly, this actually wasn’t the case…
When looking at the headers, three interesting points stood out:
- It turned out that the envelope sender was empty (i.e., “MAIL FROM:<>” was used). In principle, the use of an empty envelope sender – which is called a “null reverse-path” – is perfectly legitimate[1]. It is what bounce messages are supposed to use, so this was not a violation of any standard. It did, however, mean that there was no envelope domain against which SPF could be evaluated, which is why the receiving system fell back to the “HELO/EHLO” identity and ended up checking “postmaster@[10.88.0.3]” – i.e., an internal/RFC 1918 address presented by the sending host (which was actually hosted on the public IP 35.195.254.112 in the Google Cloud). Since we mentioned SPF, it is worth adding that no DKIM signature was present either (for obvious reasons), and that DMARC evaluation therefore unsurprisingly failed.
- The message carried no “Date” header whatsoever, which was the reason for the “None” date shown by Outlook. Unlike the empty envelope sender, this is against standardized requirements, as RFC 5322 requires an “origination date” field to be present[2]. A message put together by any normal e-mail client (or sent through a normal e-mail server) would essentially always have one, so its absence is telling.
- The “X-Priority” header was set to 0. This header was never formally standardized in an RFC, but per Microsoft’s specification[3], which is the de-facto authority for it, only the values 1 (highest) through 5 (lowest) are defined, so a “0” is outside the meaningful range.
While none of these oddities were especially remarkable on their own, taken together they painted a fairly clear picture of the tooling used to send the message – it was most likely a homemade script that interfaced directly with a receiving e-mail server and handed the message to it, without any standard e-mail server being involved on the sending end.
With that out of the way, let's take a closer look at the attachment.
The attached file was named “<name of company>_Pending_Approvals#<digits>.xls.html”, and its most immediately noticeable characteristic (besides the double extension) was its size. At 2,589 kB, it was significantly larger than one would expect a self-contained HTML phishing page to be, since these usually take up no more than a few tens (or at most hundreds – if images are included) of kilobytes.
The reason for this became clear as soon as the file was opened in a text editor. The entire contents were wrapped in a single layer of trivial obfuscation – the whole page was stored as a long sequence of “\uXXXX” escapes and handed to the “unescape()” JavaScript function inside a “document.write()” call.
<script type="text/javascript">document.write(unescape("\u003c\u0021\u0044\u004f\u0043\u0054\u0059\u0050\u0045\u0020\u0068\u0074\u006d
...
\u0058\u0058\u0058\u0058\u0058\u0058\u0058\u0058\u002d\u002d\u003e"));</script>
Once the escaped string was decoded, only 431 kB of HTML were left. Of that size, though, only the first 11 kB or so constituted an actual, working phishing page, while the remainder was padding. This padding was placed after the closing “</html>” tag and was made up of a single HTML comment containing a little over 430 thousand copies of the letter “X” (originally encoded as “\u0058”, which you can see above).
It is worth pointing out that the file size was, in effect, “inflated” twice over – first by the aforementioned ~420 kB comment, and then by the “\uXXXX” encoding, which stored each character (padding included) as six bytes. Between the two, the block of “X”s ended up accounting for something on the order of 2.5 MB, i.e., roughly 97 % of the entire file.
While phishing pages bloated with large quantities of copy-pasted, unused content are not new[4], in this case the padding is interesting because of what it might have plausibly been aimed at.
The classic reason for padding malicious files is covered by the MITRE ATT&CK “Obfuscated Files or Information: Binary Padding” sub-technique[5]. In short, threat actors may append a large, low-entropy blob to a file in order to push its size past the maximum that anti-malware engines are configured to scan, while keeping the file easy to compress (and therefore still convenient to deliver). While not as common as run-of-the-mill obfuscation, malware using this technique can be found in the wild reasonably often[6,7].
This sub-technique, however, does not quite fit our sample. Even leaving aside that the attachment is padded using a comment rather than a binary blob, at 2.5 MB the file falls well short of the scan-size limits used by present-day e-mail security solutions, which usually process attachments well into the tens of megabytes.
The padding is also about as low-entropy as any data can get, which means it wouldn’t help the file blend in with benign content on a statistical level either (if anything, a huge block of identical bytes would be trivial to spot and would make the file look more anomalous, not less). Whatever the padding is meant to defeat, in other words, it does not appear to be the sort of size or entropy-based checks that techniques traditionally used in phishing try to bypass…
One thing that has changed in the area of e-mail security over the past couple of years, though, is that a growing number of solutions have started to incorporate some form of NLP or AI-based mechanism for assessing message content, and this is where the padding might begin to make sense.
Earlier this year, KnowBe4 described a phishing technique they refer to as “NLP obfuscation”, in which malicious content is placed at the start of a message and then buried under a large amount of benign-looking filler[8]. According to their analysis, this can shift the “probability scale” that some content-classification models rely on – basically, if a message contains enough innocuous material, the weight of the malicious portion can be diluted to the point where the model no longer flags it with sufficient confidence. The same bulk can also make a message large enough so that scanning it using AI-based mechanisms takes too long, leading some solutions to release it rather than delay delivery indefinitely.
Although our attachment doesn’t fully match the samples described in the aforementioned analysis (the filler here is a single repeated character rather than natural-looking text) its overall structure (i.e. payload first, followed by filler) is the same.
If some form of AI or NLP-based content assessment was indeed the intended target, the padding would work not by disguising the “malicious” portion of the HTML file, but simply by drowning it out. Whether the message was scored by a traditional content classifier or passed to an actual LLM, the genuinely malicious portion would end up as a tiny fraction of a large, low-information whole, which might have been enough to pull an averaged or probability-based verdict below the threshold at which the message would be blocked. And since the bulk of the file carries no meaning, the same padding may serve a second, cruder purpose – inflating the sheer volume of data (and, for an LLM, the number of tokens) that has to be processed to the point where a scanner working under a per-message time or size budget would cut its analysis short, or skip it altogether[9].
Of the two, the second goal strikes me as the more likely one here. It is consistent with where the padding was placed – after the payload, where it does nothing to actually conceal the malicious portion of the HTML code – and it is the one objective for which a featureless block of “X” works just as well as carefully crafted filler, which would also explain why the author saw no need to use anything more elaborate.
I should stress that all of the above is, ultimately, only an informed speculation – short of asking the author of the phishing, there is no way to know for certain what they had in mind. It should also be said that, against any reasonably capable model, a solid block of a single repeated character would be a blunt instrument at best, since it is trivially recognizable as padding (see the entropy chart below).
For the sake of completeness, it should be mentioned that the functional part of the attachment was an otherwise unremarkable SharePoint-themed credential-harvesting page. It attempted to load the recipient organization’s logo dynamically through the Clearbit logo API, though, as the figure below shows, the lookup failed and a placeholder (image with Microsoft squares) was displayed instead… Which is unsurprising given that the free Clearbit logo API was shut down at the end of 2025[10] – this in itself is a small sign that the page was assembled from older, borrowed or LLM-generated code. Any credentials that were entered would be submitted through a POST request to the Formspark form-handling service[11], which was being misused as a convenient data collection point. The page additionally contained a routine that intercepted the developer-tools and view-source keyboard shortcuts – a trivial and fairly common anti-analysis feature[12].
[1] https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.5
[2] https://www.rfc-editor.org/rfc/rfc5322.html#section-3.6
[3] https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmail/2bb19f1b-b35e-4966-b1cb-1afd044e83ab
[4] https://isc.sans.edu/diary/32510
[5] https://attack.mitre.org/techniques/T1027/001/
[6] https://isc.sans.edu/diary/26464
[7] https://isc.sans.edu/diary/30524
[8] https://blog.knowbe4.com/nlp-obfuscation-techniques-email-security-evasion
[9] https://genai.owasp.org/llmrisk2023-24/llm04-model-denial-of-service/
[10] https://developers.hubspot.com/changelog/upcoming-sunset-of-clearbits-free-logo-api
[11] https://formspark.io/
[12] https://isc.sans.edu/diary/30412
-----------
Jan Kopriva
LinkedIn
Nettles Consulting
0 Comments
My Stack Simulator
The stack is a memory region where a program stores temporary data - like local variables and return addresses. Think of the stack as a pile of plates in your kitchen: you can only add a new plate to the top, and you can only take one away from the top too. Programs use this same "last in, first out" principle to keep track of what they're doing. Every time a function is called, the program pushes a new plate onto the stack containing things like local variables and the address to return to once the function finishes. When the function is done, that plate is popped off the top, and execution resumes exactly where it left off. This simple mechanism is what allows programs to call functions within functions, and always find their way back - but it's also precisely why a stack that grows too large, or gets overwritten with unexpected data, becomes a favorite target for attackers looking to hijack a program's execution flow.
In the SANS class FOR610[1] (malware analysis), there is an introduction to assembly and, when students learn how functions work, they have to understand how the stack also works. If you’ve no prior experience, it could be a bit challenging. To help students to vizualise how the stack works, I created a “stack simulator” that allows to “see” what’s happening when code is executed.

How does it work?
- Select the architecture (32-64 bits) in the assembly editor
- Select a predefined set of instructions (“lesson”, “call”, “prologue”, …).
- Click on “Step” to you can see the impact on the stack and registers (like in a debugger).
Note that you can modify the predefined ASM code and add your own instructions.
The stack simulator is available on my website[2].
If you’re interested in malware analysis, my next classes will be:
[1] https://www.sans.org/cyber-security-courses/reverse-engineering-malware-malware-analysis-tools-techniques
[2] https://xameco.be/stack-simulator.html
[3] https://www.sans.org/cyber-security-training-events/tokyo-autumn-2026
[4] https://www.sans.org/cyber-security-training-events/paris-november-2026
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
0 Comments
_HELP_ME_ESCAPE_FROM_BELARUS_PLEASE_ [Guest Diary]
[This is a Guest Diary by Jason Callahan, an ISC intern as part of the SANS.edu BACS program]
Every so often a honeypot hit comes along that is less about the exploit and more about the intent behind it. While reviewing DShield logs I ran into a scanning bot that caught my eye: a URI string that appeared to be a plea for help.
On 2026-06-06 my DShield honeypot logged back-to-back HTTP requests from the same source IP hitting two different ports with both carrying an identical, oddly formatted request path:
.png)
The request path itself /?_HELP_ME_ESCAPE_FROM_BELARUS_PLEASE_ is not a known exploit path, it appeared to be a plain-text message in the URL. Searching my logs for that particular string returned around a dozen similar HTTP requests over a 2 months period. These came from various IPs from around the globe with no discernible pattern which pointed to a self-propagating bot rather than a single attacker.
Further research showed that this bot was first reported to ISC in May 2026. The number of reports peaked shortly after the first report before a sharp drop and has remained steady since. [1]

I was unable to locate much more information about this bot other than a reddit thread on r/selfhosted describing the same requests hitting a Traefik reverse proxy. According to that thread, the user emailed the address embedded in the User-Agent and received a reply pointing to a page on a free web-hosting service. The page is a static HTML document with no scripts and it lays out what the bot is & why it exists.
The author, who identifies himself only as “Alex,” claims to be based in Belarus and writes that the bot is intentionally limited: no exploits, no command-and-control, no persistence. In his words, paraphrased and summarized from the page:
• The bot scans random IP addresses for open HTTP ports (80, 8000, 8080) and SSH ports (22, 2222).
• If it finds an open HTTP port it sends a single request (GET, CONNECT, or HEAD)
• If it finds an open SSH port it attempts a brute force with a small, fixed list of default credential pairs (admin:admin, root:root, etc.)
• It runs fully autonomously with no C2 channel; discovered IP/credential pairs are reported back to a loader only.
• It does not establish persistence, typically running from /tmp, and it is designed to self-terminate roughly six months after release.
• The stated purpose is to draw attention to conditions in Belarus. They describe it as a “performance piece,” saying they are not seeking funding and only asking for non-financial help leaving the country (job leads, advice, connections).
Disregarding the origin and supposed intent of the bot, this is a straightforward scan-and-brute-force bot and it should be treated like any other hitting a honeypot. The HTTP request is reconnaissance/fingerprinting that tells the operator a host is alive and reachable on that port. The risk is on the SSH side: any host reachable on TCP 22/2222 that still uses a default or weak credential pair is exposed, regardless of the creator’s stated intentions.
I want to give some healthy skepticism here rather than take the linked page at face value. I have no way to verify the age, location, or motive claimed on that page, whether the page itself is the full extent of the bot's behavior, or whether the “self-terminate after six months” and “no persistence” claims hold up under closer reverse engineering. Sob stories and appeals to sympathy are also a known social-engineering lever, and a URI designed to make analysts pause and read a web page rather than immediately blocklist an IP is an effective way to buy a scanner some goodwill. None of that changes the defensive posture: treat it as an untrusted, credential-guessing scanner.
[1] https://isc.sans.edu/weblogs/urlhistory.html?url=Lz9fSEVMUF9NRV9FU0NBUEVfRlJPTV9CRUxBUlVTX1BMRUFTRV8=
[2] https://isc.sans.edu/honeypot.html
[3] https://www.sans.edu/cyber-security-programs/bachelors-degree/
Disclosure: Claude was used for grammar and polish checks. No further use of generative A.I. was used in the creation of this post.
-----------
Guy Bruneau IPSS Inc.
My GitHub Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu
0 Comments
More Odd DNS Records: NIMLOC
Yesterday, I talked about NAPTR records and how they are related to RCS. But there is another "odd" record that shows up in my DNS logs. This one isn't new, but I don't think I ever covered it: NIMLOC. At least that is what Zeek calls it. But let's see what it is all about.
At first, it looks like NIMLOC records are no longer used. Google's AI overview explains: "A NIMLOC (Nimrod Locator) DNS record is an obsolete resource record type (Type 32) originally designed for the Nimrod routing architecture to map names to network locators. Because Nimrod was an experimental protocol, NIMLOC records are considered historic and are not used in modern, standard network operations."
While I do have one or the other odd IOT device in my network, I doubt any of them speak "Nimrod". On the other hand, the queries originate from my macOS systems. This turns out to be an older standard, replaced by a newer (but still old) standard, with the newer standard becoming obsolete before the even older standard is phased out.
DNS defines several resource record types. The official list is maintained by IANA [1] and I am including a sample below:
| TYPE | Value | Meaning | References |
| A | 1 | IPv4 Address | RFC1035 |
| NS | 2 | Name Server | RFC1035 |
| PTR | 12 | Domain Name Pointer | RFC1035 |
| MX | 15 | Mail Server | RFC1035 |
| TXT | 16 | Text String | RFC1035 |
| AAAA | 28 | IPv6 Address | RFC3596 |
| NIMLOC | 32 | Nimrod Locator | (no RFC) |
| SRV | 33 | Server Selection | RFC2782 |
| NAPTR | 35 | Naming Authority Pointer | RFC3403 |
There is a range of unassigned RR types, so one would think that it is not necessary to reuse RR Types. But this is exactly what happened here.
RR Type 32 was originally assigned for the old NetBIOS over TCP/UDP (RFC 1002, [2]). This actually became one of the few Internet Standards (STD 19). RR Type 32 is assigned ot "NB" (NetBIOS General Name Service) and 33 to "NBSTAT", the NetBIOS Node Status. If you search for it in the RFC, look for the hex values 0x0020 and 0x0021 (took me a while to find them).
NetBIOS is long gone, and modern Windows networks use DNS and SMB over TCP, eliminating the NetBIOS layer. But macOS is still holding on to it and broadcasting name announcements on port 137 using these records. Zeek (which I used to collect the logs), translates RR Type 32 to "NIMLOC", which conforms to the current IANA assignment for this type. But in reality, you are probably going to see NetBIOS and not the never-quite-implemented Nimrod routing scheme.
[1] https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
[2] https://www.rfc-editor.org/info/rfc1002/
--
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|
0 Comments
RCS and DNS: The NAPTR Record
Over the last year, with recent updates to iOS and Android, RCS (Rich Communication Services) has become an increasingly used protocol [1]. RCS is supposed to eventually replace SMS, and in addition to richer formatting, provides added (but optional) security. RCS messages may be end-to-end encrypted and digitally signed. Unlike SMS, which was "bolted on" to existing voice-focused phone standards. The SMS standard was based on old-fashioned pagers and allowed for limited clear-text communications. RCS is built from the ground up around modern IP-based network infrastructure and behaves more like IP chat services (think iMessage, WhatsApp...). RCS defines the message format, while protocols like SIP are used to establish connections and transport messages.
"Do as you say", I do from time to time take a look at odd DNS traffic on my network. An activity I recommend when teaching SEC503. Recently, I noticed more "NAPTR" queries, a record type I had not seen before. The record type is defined in RFC 2915 [2], which was ratified in 2000. It is not a new record. But so far, at least in my network, it has not really shown up before.
The description of the record sounds rather ominous:
"a Resource Record that included a regular expression that would be used by a client program to rewrite a string into a domain name."
Wow. Regular expressions to rewrite resource records? What could possibly go wrong? However, right now, I just want to talk about how it "goes right" and how these records are currently being used for RCS.
Below is the relevant part of the t-shark decode of a record typical for what I have seen in my network:
Queries
fp-us-verizon.rcs.telephony.goog: type NAPTR, class IN
Name: fp-us-verizon.rcs.telephony.goog
[Name Length: 32]
[Label Count: 4]
Type: NAPTR (35) (Naming Authority Pointer)
Class: IN (0x0001)
Answers
fp-us-verizon.rcs.telephony.goog: type NAPTR, class IN, order 100, preference 100, flags s
Name: fp-us-verizon.rcs.telephony.goog
Type: NAPTR (35) (Naming Authority Pointer)
Class: IN (0x0001)
Time to live: 295 (4 minutes, 55 seconds)
Data length: 61
Order: 100
Preference: 100
Flags Length: 1
Flags: s
Service Length: 8
Service: SIPS+D2T
Regex Length: 0
Regex:
[Replacement Length: 43]
Replacement: _sips._tcp.fp-us-verizon.rcs.telephony.goog
This was the only applicable NAPTR record, so order and preference do not matter in this case. The "S" flag indicates that the next lookup should be a SRV record. And indeed, we do have a SRV query (see below). Only a "U" flag would result in a URI.
Remember that this record is about URIs, not IP addresses? The "Service" field indicates what service we may find at the to-be-determined URI. In this case, it is SIPS+D2T. SIPS+D2T is a transport protocol defined in the SIP standard (RFC 3263). SIPS+D2T stands for "Secure SIP Direct to TCP". So we will be using SIP over TLS with TCP as the transport protocol. The SIP standard specifically calls for NAPTR records to find SIP servers. The reason for the NAPTR record is to allow URIs to be returned, not just IP addresses/hostnames (as an SRV record would).
Lucky for us (and the DNS server), the regular expression is empty. And this appears to be normal for this use case. Instead, we just get a "SRV" record to request:
Queries???????
_sips._tcp.fp-us-verizon.rcs.telephony.goog: type SRV, class IN
Name: _sips._tcp.fp-us-verizon.rcs.telephony.goog
[Name Length: 43]
[Label Count: 6]
Type: SRV (33) (Server Selection)
Class: IN (0x0001)
Answers
_sips._tcp.fp-us-verizon.rcs.telephony.goog: type SRV, class IN, priority 20, weight 0, port 5223, target fp-us-verizon.rcs.telephony.goog
Service: _sips
Protocol: _tcp
Name: fp-us-verizon.rcs.telephony.goog
Type: SRV (33) (Server Selection)
Class: IN (0x0001)
Time to live: 300 (5 minutes)
Data length: 40
Priority: 20
Weight: 0
Port: 5223
Target: fp-us-verizon.rcs.telephony.goog
_sips._tcp.fp-us-verizon.rcs.telephony.goog: type SRV, class IN, priority 30, weight 0, port 443, target fp-us-verizon.rcs.telephony.goog
Service: _sips
Protocol: _tcp
Name: fp-us-verizon.rcs.telephony.goog
Type: SRV (33) (Server Selection)
Class: IN (0x0001)
Time to live: 300 (5 minutes)
Data length: 40
Priority: 30
Weight: 0
Port: 443
Target: fp-us-verizon.rcs.telephony.goog
And yes, in the end, there is a "normal" A and AAAA lookup for fp-us-verizon.rcs.telephony.goog.
So far, NAPTR records do not appear to be used to their full potential. I am sure that the use of regular expressions will be of interest to bug hunters and penetration testers.
[1] https://support.google.com/messages/answer/13508703?hl=en
[2] https://www.ietf.org/rfc/rfc2915.txt
--
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|
0 Comments
Why Ask Credentials If There Are Secret Codes?
This morning, an interesting phishing email hit my mailbox. It targets Metamask[1], a cryptocurrency wallet, available as a browser extension and a mobile app, that lets users store, send, and receive crypto money. It’s pretty popular, so a juicy target for criminals. In February, I already mentioned a campaign against them[2].
Today’s email was different and used another approach. Most services that we use daily ask us to implement a 2nd authentication factor. That makes simple credentials useless if you can’t interact with the victim and grab the temporary token, code, …
But most services also offer a “password recovery” process. In the case of Metamask, it’s based on your secret security phrase that you created during the account creation process[3]. That’s exactly the target of this phishing campaign. They ask you to provide this secret phrase.
First, they put some pressure on you, pretending that your wallet is at risk:

Then, they ask you to provide your secret phrase:

The campaing relies on the domain captchasolve[.]help that has been registered two days ago.
[1] https://metamask.io
[2] https://isc.sans.edu/diary/Fake+Incident+Report+Used+in+Phishing+Campaign/32722
[3] https://support.metamask.io/configure/wallet/how-can-i-reset-my-password/
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
0 Comments




0 Comments