Replies: 1 comment 1 reply
-
I think I was in the early stages of reversing the update process just trying to figure out what files to send and how to send them. The empty DATA messages were an attempt to get the updater to tell me what file(s) to send next through error messages rather than doing it with GDB/Ghidra. Even after validation of the manifest failed, it was letting me continue the process (as evident from my GDB breakpoints) and continuing to give me feedback so I figured I would record what things needed to be sent before addressing the validation problem. And then I got to the end of the update where it succeeded and I was shocked lol. In fact, I was worried that I had come across something that was unintended. Your exploit is really cool and matches more of what I expected from the last task based on the 2019 challenge. Thanks for sharing and congrats on completing it! |
Beta Was this translation helpful? Give feedback.
-
First of all, great write-up! Thanks for doing this!
Task 9 took a long time for me to complete, as I never came up with the 'passing blanks' strategy (curious what you observed that motivated you to try that?). Instead, I landed on an exploit that involved sending a partial update with a crafted
key.pub
followed by a full update with files that passed signature validation against the craftedkey.pub
. I took advantage of the fact that (1) the updater module allows performing an update from any existing version to any non-existing version (rather than requiring updates to be from the "live" version), and (2) the updater writes files to disk before validating their contents.Essentially, the sequence of events was something like:
OPEN - Initiate update v1.0 -> v1.2 (allows us to re-use manifest and manifest.sig from v1.1 which will pass validation)
DATA - Upload
manifest.sig
from v1.1 directory (passes validation)DATA - Upload
manifest
from v1.1 directory (passes validation)DATA - Upload a crafted
key.pub
(fails validation, but still written to disk)At this point the update to v1.2 is still in progress, and our crafted
key.pub
lives in a temporary directory like1.2.PPPPSSSS
, wherePPPP
is the PID of the updater process andSSSS
is the session ID. We already know the PID, and we can recover the session ID with a brute force search. Then, we can initiate the second update.OPEN - Initiate update v1.2.PPPPSSSS -> v1.3
DATA - Upload
manifest.sig
(passes validation since it's checked against the craftedkey.pub
)DATA - Upload
manifest
(passes validation since it's checked against the craftedkey.pub
; I re-used v1.0'smanifest
)DATA - Upload
key.pub
(passes validation; I re-used v1.0'skey.pub
)DATA - Upload
flightmonitor
(passes validation; I re-used v1.0'sflightmonitor
)CLOSE - Updates the symlink and deletes the temporary directory
Anyways, I'm guessing passing blanks was probably the intended approach, but I thought I would mention this as alternative exploitable weakness in the updater module. And props to the challenge designers; I thought the challenge was very well designed this year.
P.S. I'm amused that you didn't fully reverse the routing logic in Task 8; I also found that trying random values was more efficient :P
Beta Was this translation helpful? Give feedback.
All reactions