posted 2023-03-29 - go back
Some bold text to start off with:
This vulnerability is patched in the latest version of Penumbra and TexTools. If you aren’t up to date (Penumbra 0.6.4.0+ and TexTools 18.104.22.168+), do it now. TexTools users will have to switch to the beta branch to get the latest version. Additionally, Mare Synchronos likely was never able to sync/execute this (and now can’t with the Penumbra fix).
Now, let’s explain what the vulnerability is. This vulnerability allows an attacker to build a specially crafted mod that would execute arbitrary code on file load, abusing what is fundamentally a bug in the base engine of FFXIV. By overwriting a certain path in the game’s filesystem, you could load code on game startup.
So, how was it possible?
Never trust your Lua state
FFXIV uses Lua 5.1 to script a lot of things in the game. It doesn’t store just raw .lua files, though - it stores the weirdly-obscure Lua bytecode format (compiled with a 32-bit
luac). These are in the
game_script category in the game’s virtual filesystem, under the
.luab file extension.
By writing custom code, compiling it into bytecode, and replacing files with it, your code can run in FFXIV’s Lua state! Oof.
And, if you modify the event handler Lua script, your code can run on startup! I found this path by replacing every known Lua script in the game (lol) with a script that would write the filename to a text file on my desktop. Just be careful when doing this, as the event handler is used a lot.
…wait a minute, write to a text file? Does that mean they- Oh no.
io in the Lua global table.
YEP! This means you can read and write files and execute arbitrary programs! It’s literally this easy:
Then you create the bytecode, swap the file, and you’re done! Calculator popped.
What you could do with this
There’s a lot of fun to be had with modifying Lua! You could:
- Write a malicious payload to a file and run it
- Break cutscenes, menus, and much more
- Mess with the internals of FFXIV (spawn objects, play cutscenes, maybe even send invalid data to the server!)
Overall I haven’t explored the Lua state as much as I want to. The primary worry, of course, is executing malicious payloads from mod authors. This would have about the same amount of danger as running
totally_not_a_virus.mp4.exe off of some shady corner of the Internet (it could do anything you can do).
Some tactics, featuring DLLs
package.cpath is set to load DLLs from the
game folder. This means not only can you run arbitrary code, you can run arbitrary code inside of the FFXIV process! With a little work in Rust (featuring the
ctor crate), and storing the DLL as a byte array in the script (then writing it to a temporary file), we get free process access. We’re basically as powerful as a third party Dalamud plugin, which has big red text when installing it for a reason.
With enough effort, we can get the player’s session ID - the value that represents you when you log into the game - and do whatever with it. An attacker with this in their hands can log in as you!
Here’s a little proof of concept showing off viewing the user’s session ID:
How to blend in
While TexTools prompts you with every file, nobody really reads that. Stuff a bunch of unrelated files in there that mask the .luab and you’re good to go. Because sites like XIV Mod Archive don’t host mod files themselves, they can’t automatically scan for malicious files, meaning it has to be done in the modloader. Heliosphere is the only mod site I know of that blocks certain file extensions automatically on upload.
The lowest hanging fruit possible
I’m aware that this “vulnerability” is incredibly low hanging fruit. Sorry to the people that thought I found a vulnerability in file parsing or something.
Some may view me publishing this as immature and stupid, and causing shit for no good reason, but I can’t in good conscience keep this a secret. Just because nobody has exploited this yet doesn’t mean it won’t happen. Get your stuff patched!
All times Eastern Time.
- 01/20: I realize this vulnerability is conceptually possible
- 01/21, 4:48 PM: I execute
calc.exefrom inside FFXIV using Penumbra
- 01/22, 10:39 AM: Ottermandias commits to Penumbra to fix this
- 01/22, 8:19 PM: I execute
calc.exefrom inside FFXIV using TexTools
- 01/22, 11:33 PM: I submit a proof of concept to PrettyKitty, owner of the TexTools Discord server
- 01/30, 12:07 PM: The Penumbra stable channel updates to patch the vulnerability
- 03/03, 11:17 AM: After 40 days, I contact PrettyKitty for a status update
- 03/27, 11:59 AM: I reach out to PrettyKitty one final time
- 03/29, 09:42 AM: TexTools is updated to patch the vulnerability
Update: 02/29, 7:36 PM: Seeing some people attack the TexTools team for their response time - please don’t! They’re doing this in their free time (volunteer work) and I was informed that most were busy with other stuff. I also (with permission) revealed that my contact wasn’t a moderator but actually PrettyKitty, who informed me my messages were delivered to the developers very quickly.
Penumbra and TT should’ve been blocking modifying these files for a very long time. I just so happened to be the first skid to put two and two together and break something! Good thing it’s fixed now. Maybe it was good that the first person to shout about this was me, because I’m not a malicious actor - I’m just an idiot.
I haven’t seen this exploited in the wild, but I am concerned that it could be (given that this post is essentially a how-to). Make sure to update your modloaders!
This “fun afternoon project” wouldn’t have been possible without:
- Perch’s ResLogger2 for making it easy to yoink the Lua script file list
- Anna’s excellent TTMP Rust library for making my TexTools testing easier, and Heliosphere for making it easy to avoid malicious files
- Otter for fixing the Penumbra vulnerability fast and making modding painless
- Pohky for telling me how fucked the Lua state was in the first place
- The people who have built our decade of research into FFXIV for satisfying my autistic curiosity (too many to count)