Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Gitlab SSO Lack of Permission Revoking- 301

lauritzh    Reference →Posted 5 Years Ago
  • SSO's (single sign on) applications are used in order to give users access to an application while using another providers credentials. Alongside the SSO, certain permissions must be granted (by the user) to have at the third party site.
  • The issue was that if user deleted the account on the third party site or revoked access, the Gitlab SSO did NOT revoke access to the previous permissions.
  • Although this is a weird finding, permissions should be given and taken at will. This should be a normal test case going forward.

Tiki Wiki CMS Authentication Bypass- 300

Maximilian Barz    Reference →Posted 5 Years Ago
  • Brute force protections gone wrong! After 20 failed login attempts, an email attempts to be sent to the user/admin.
  • After 50 attempts, the password is cleared in order to indicate that the password should be reset. But, by sending a blank password, it will login the user!
  • This is a ridiculous auth bypass but is super interesting!

How to get root on Ubuntu 20.04 by pretending nobody’s /home- 299

Kevin Backhouse    Reference →Posted 5 Years Ago
  • An LPE on a Linux machine? Who would have thought that! Linux OS's are typically secure. This privilege escalation ONLY exists within the Desktop version of Ubuntu & not the server version.
  • The first bug is a denial of service within the accountservice daemon. The user sets the file .pam_environment to be a symlink to /dev/null. This makes the file infinitely long when trying to read it.
  • When the daemon decides to read this file, it DROPS the privileges down to the same as the user in order to prevent privilege escalation. Because of this privilege drop, there we have the ability to send signals to this process! What signal should we send? How about SIGSTOP? This will pause the running process.
  • Now, he is the real kicker. You log out of the current user! Once at this screen, we wait until the user dialog box pops up to create a new user. Why does this happen?
  • When there are no users on the system, GNOME is instructed to create a new user. It knows how many users there are by talking to the accountservice daemon!
  • The bug is in when the accountservice daemon is unresponsive and a timeout occurs. With this code path, the field that matters if knowing if a account exists for a user is the field priv->have_existing_user_accounts. However, this defaults to false! So, if the timeout occurs when trying to talk to the service daemon, then the functionality acts like there are no users on the system!
  • In a nutshell, this stops the accountservice daemon by first putting it into an infinite loop to drop the privileges then stopping the service with a signal. Then, by logging out and trying to log back in, the unresponsiveness of this daemon allows for the attacker to restart the user initialization process.
  • I love this type of finding! When I see bugs like this I wonder "What could I do better in order to find this bug in the future?". The crux of this bug was that an insecure state was used in the initialization of a field that was relying on a time-delimited action to fill it out. In the future, look for bad/insecure initialization of values.
  • By the way, the author found this bug by accident and it took them some help in order to find the root cause of the issue. As I would say, you miss 100% of the shots you don't take! At least by trying this guy gave himself a chance to get lucky.

Exploiting CSGOJackpot's Weak RNG- 298

Nick Jonas    Reference →Posted 5 Years Ago
  • CSGOJackpot is a gambling website that allows players to bet & win Counter Strike skins or textures. Why is this a big deal? the average pot per hour is around $20,000 dollars! So, being able to swipe this money would be a big deal.
  • The game works as follows:
    1. Start a new round with an empty pot.
    2. A player puts in their skins (up to 10 at a time). These skins are calculated for a cent value and this is the value that the user put into the pot.
    3. If less than 50 skins, go back to step 2.
    4. The site generates a random number that determines who the winner is.
    5. The player with the winning ticket wins the whole pot.
  • From reading the HTML on the website, the hacker noticed that the backend was likely a nodejs server. Additionally, because the 16 digits of the winner percentage were the same as the nodejs default output & published at the end of the round, it was assumed that this was just using Math.random().
  • Math.random is being used? So, what is the big deal? This function uses Multiply-with-Carry for the pseudo randomness. Can this be predicted?
  • Apparently, all you need for breaking the randomness in JavaScript is TWO consecutive outputs!? What, that is unbelievable to me. I then realized that the attacker just BRUTE FORCED the 32-bit space (which only took about 30 seconds) in order to figure out WHAT the next number would be. Not an elegant solution but it does work well!
  • For more work into breaking JavaScript random, try this and this. .
  • However, this attack was not perfect... the attacker simply could not predict the next value. So, he assumed some OTHER calls to random must be made (which was the case). However, the pattern was inconsistent for how many calls to random had to be made. So, a deadend :(
  • But, from the ashes of this, a new attack arrives! The site claims to be provably fair by doing the following calculation: md5(blinding + winning percentage) BEFOREhand & shows this to the user; this is called the commit. So, what's the issue?
  • The blinding is just two calls to Math.random (converted to hex) and the winning percentage is the value guessed by the user. By using the previous bug (output from random for the winning percentage) in tandem with the commit being shown (THREE RANDOM numbers in a row!) it is possible to KNOW where the randomness currently lies.
  • The hacker (wisely) did not attempt to exploit this to win money. Instead, they had a Twitch stream where they showed him guessing the percentages LIVE. The bug was also recently fixed.
  • What is the moral of the story? Use cryptographically secure random number generators! Additionally, be careful with WHICH numbers you show to a user. Showing too many may break the ecosystem.

Look mum, no key! Bypassing Encrypted Secure Boot at Hardware.io- 297

Cristofaro Mune & Niek Timmers    Reference →Posted 5 Years Ago
  • Fault injection is super crazy! Instead of the standard voltage/clock glitching, they decided to use electromagnetic fault injection. In this video, they go over how they defeated encrypted secure boot via EM fault injection.
  • Their toolkit in order to perform this attack:
    • UART communicator
    • Electromagnetic fault injection probe
    • XYZ stage to move the probe precisely onto the chip.
    • FPGA for knowing WHEN to launch the attack
  • Besides launching the attack against a particular target, it is important to test to see if the technique has SOME affects on the device. Additionally, is the result predictable in some overall capacity. There's a happy medium where we can make changes, but not TOO many changes.
  • From running tests on the chip (with defined code that they wrote), they figured out the BEST location to glitch the code at. On the BPGA chip, there was a single point that corrupted a bunch of corruption.
  • Once the bootloader has been completely copied (can be noticed based upon data being sent from a particular location), this is when the fault injection should be sent out. With the glitch, they ONLY worry about the result, in terms of HOW much time it takes, not the amount of attempts.
  • The next question is how do we turn data transfer into code execution? They call it instruction corruption by altering HOW instructions just generally work.
  • TODO...

Kernel exploitation: weaponizing CVE-2020-17382 MSI Ambient Link driver- 296

Matteo Malvica    Reference →Posted 5 Years Ago
  • Why attack kernel drivers? They are the ONLY way to touch Ring 0, or the running kernel. Because of this, vulnerabilities in kernel drivers allow you to elevate to system with no issues. This post is about Windows Kernel Driver internals and how to go about attacking them. For Windows Kernel debugging, use the following post as a reference Getting Kernel Mode Driver Signed For Windows 10.
  • What does a driver look like? At a high level, a driver is a loadable kernel module that additionally has a user-mode application counterpart to communicate with it. Below are some more technical details on this process.
  • Device Objects is created by the driver itself for a communication channel. This can be done via the Windows CreateFile API with a symbolic link to a DEVICE_OBJECT.
  • In order to create the object, the main is called (DriverEntry). It accepts two parameters: DRIVER_OBJECT and RegistryPath. The DRIVER_OBJECT starts as an empty struct (from the kernel) and is initialized via the driver main function. The RegistryPath is a path where parameter keys are stored at for the driver.
  • The DRIVER_OBJECT structure has a lot of fields. The most important though, are the functions that the driver supports are added to this struct; they are in the MajorFunction member of this struct. In order to interface with the driver, these interfaces are made into DLLs that can be used in userland.
  • Under the hood, the flow looks like the following:
    • User requests a handle in order to interface with the driver.
    • The user uses the handle in order to send IRP (I/O Request Packer) to the driver. The important part of this request is the IOCTL code, which is just the ID for the kernel service routine to call.
    • The driver executes the routine.
    • The result is sent back to the user.
  • Easy starting points for finding bugs in Windows Kernel Drivers:
    • Driver allows low-privileged user to interact with it.
    • MmMapIoSpace or ZwMapViewOfSection are in the IAT table.
    • Customized memmove or known unsafe function is used.
  • For reversing, the first thing to do is fine the main function dispatcher & the register path. The bulk of the reversing process relies on finding the IOCTLs.
  • The author used a REALLY simple fuzzer on all of the IOCTLs. This led to a buffer overflow that overwrote a function pointer! :) However, it is not as simple as calling system in Ring 0; there is still more work to be done!
  • On Windows 7, the exploitation involved writing some shellcode. However, the author could not find a way to restore execution back to its normal state (crashes in the kernel are VERY bad). Instead of trying to gain kernel code execution, the author decided to copy the SYSTEM token to an arbitrary process. Thenm to keep execution going, used this trick (JMP 0x0) in order to get execution of the kernel thread from crashing.
  • On Windows 10, there are quite a few kernel mitigations that make this significantly harder, including KMCS, SMEP, KASLR, KPP, CFG and VBS.
  • Supervisor Mode Execution Prevention (SMEP) can be bypassed by using ROP gadgets in order to change the value in the control register where this lives at. Now, we can trivially jump to our shellcode.
  • The Kernel Patch Protection (KPP) will bluescreen the computer if it detects the alteration of critical kernel structures being tampered with (including the CR4 register to bypass SMEP). However, this is done on a timed basis. So, a fast enough and well-timed payload can bypass this protection.
  • KASLR (Kernel address space layout randomization) can be bypassed quite trivially. KASLR is only meant to protect low-integrity processes, like browsers. However, med privileged users can use the EnumDeviceDrivers API to easily get the Kernel Address.
  • As an extra treat, the author dove into running this exploit on the most recent version of Windows. Because of a software patch for the infamous Meltdown vulnerability, Software based SMEP was added. So, all we have to do is add an additional step, which is to disable Software SMEP.

There’s A Hole In Your SoC: Glitching The MediaTek BootROM- 295

Ilya Zhuravlev - nccgroup    Reference →Posted 5 Years Ago
  • Typically, computers are 100% deterministic. Given the same inputs, it should always produce the same outputs. But, what if this wasn't the case? What if you COULD alter the flow of execution? This is where our friend comes into the game: fault injection.
  • Generally, fault injection is about purposely creating faults or issues in how something is running. This is commonly done for load balancer testing, to see how much a system can handle if a few servers go offline. In the context of security, it is just about trying to introduce faults into the running program.
  • Typically, fault injection is done in two ways: voltage glitching and clock glitching. With voltage glitching, the idea is to give the system an unexpected power amount (a ton or very little) to try to cause a fault. In practice, this can be used in order to skip/alter instructions, change the state of the processor or brick the thing entirely.
  • This article is all about glitching a SoC chip to bypass the BootROM verification. This article is not just the hand-wavy 'glitching' works kind of thing; this is a very in-depth article into how to launch a voltage glitching attack on an SoC.
  • First, even if we get a glitch what can we do? This particular eMMC chip has the following process:
    • BootROM starts and is the immutable part of the Boot Process.
    • The pre-loader is stored on the Boot0 eMMC partition and is mutable code. This code is put into RAM to be executed.
    • Prior to executing, the BootROM validates that the signature of the pre-loader is valid.
    What does this mean? In practically, we want to inject our OWN code into the pre-loader and glitch the signature check to return true, even though it was not signed properly.
  • To do the actual glitching, an FPGA was programmed for this exact purpose. The FPGA must be used because of the timings being SO exact. The FPGA is connected to the eMMC clock and data0 lines in order to KNOW when to trigger the glitch.
  • Here's the actual flow:
    • The target board is in the middle of this, of course.
    • The FPGA then reads the eMMC clock and DATA0.
    • The FPGA outputs a flag to the ChipWhisperer in order to perform the glitch.
    • The ChipWhisperer is connected to VCCK_PMU; it will drop the power to gnd for a very short period of time in order to cause the glitch.
  • What is this flag? The FPGA is looking to read the very start of the pre-loader. Right after putting this into RAM, the glitch is attempted in order to screw up the signature validation.
  • To get the ability to glitch, we must set the proper parameters for the ChipWhisperer. What exactly needs to be set? The most important is the width of the glitch. Even with properly brute-forced parameters, the success rate of this attack was around 20% at the most.
  • With the ability to bypass the signature check, the researcher decided to alter a DEBUG string. In the article, they mention altering the DEBUG string, but I am unsure if they alter the pre-loader on the chip itself or if the modify the string in transit. The former seems more likely though.
  • Finally, we can run arbitrary code at a VERY low level. So, now what? A malicious actor would probably want to load a malicious firmware image or attempt to steal sensitive data from the device.
  • How can you patch against this attack? There are hardware mitigations for this but this can ALSO be made much harder in software.
    • Add redundant checks to important things, such as signature validation. If getting ONE glitch is hard, getting THREE would make it much more difficult.
    • Add random time delays. This works because the glitch attack is ran 700ms after seeing the pre-loader on the data line. Altering the timings would cause issues.
  • Overall, this was a really good article to look into real world fault injection, instead of the hand-wavy article we normally see.

Assault Cube RCE- 294

Elon Gliksberg    Reference →Posted 5 Years Ago
  • AssaultCube is a video game that is open source. The main goal of the research was to get a client to server RCE.
  • To find the bug, the author of the vulnerability went through all points of input and looked for general bad parsing. Finding the bug is hard; exploiting it almost feels impossible, in the real world. This article goes into chaining one bug to cause all sorts of corruption, to eventually get code execution.
  • The main vulnerability is an issue with an index validation (which can be seen below). What's the issue? The validation checks with an & instead of an |. Because of this, the break on the index check will NEVER work!
    if (nextprimary < 0 && nextprimary >= NUMGUNS)
        break;
    
  • With the ability to control this index, it is possible to write a seemingly random integer to anywhere in memory. This creates a write-WHERE primitive, which is similar to the unsorted bin attack with heap exploitation.
  • Using the ability to overwrite ANYWHERE in memory (with the bad index), the author looked for ways to edit the inherit flow of the client. Using the C++ client, the author decided to edit a vector variable; in particular, overwrite the amount of variables that can be held within the vector (max size of the array).
  • The messages buffer was chosen, as a user could easily control this vector. In order to get code execution, the data next to the vectors V-Tables would allow for the ability to edit function pointers, if overwritten! The V-Table was adjacent to the data on the heap.
  • Another issue was getting this payload to be consistent. A path had to be found that would not cause the program to crash upon corruption. Real world exploits are VERY messy.
  • Sound like a gameover, right? Well, the messages can only contain printable characters, which makes writing function pointers SO hard. To get a foothold, eventually syslog was called as an easy way to create ANOTHER vuln (format string issue).
  • From the format string vuln, they used it in order to overwrite the GOT entry of strcmp with the PLT of system! Now, just send a message with an easy /bin/sh and a shell was popped :)
  • Overall, real world exploitation is MUCH harder than some CTF, as there are less ways to get a foothold on the system. Additionally, small, seemingly insignificant issues, can lead to further memory corruptions to eventually allow for complete compromise. Awesome article!

Time Based SQLi in the Referer Header- 293

Yassine Benfakih    Reference →Posted 5 Years Ago
  • SQL injection is about being able to directly modify the SQL query being made. By altering the logic of the query, data can be stolen or altered in the database.
  • Because NO data is returned back to the user, this was a blind SQLi. So, in order to exfiltrate data, a timing based method was used in order to leak data.
  • Timing Based SQLi is not something new. Personally, I found that the SQLi existed in the Referer header to be very interesting! Why here?
  • The Request Headers are data that is processed to! Giving a small set of test cases, even on very common headers, can cause some fruit :)

Rollback Attack on Mozilla Firefox - 292

Xiaoyin Liu    Reference →Posted 5 Years Ago
  • First, it should be noted that this is on the Firefox Attack & Defense blog, which looks like an amazing resource for the future.
  • CVE-2017-7766 & CVE-2017-7760 combined could both be used on the Firefox updater for an arbitrary file execution via updating the updater.ini file and an arbitrary file write with partial controllable data. This is important for later on.
  • Although the update.exe is digitally signed by Mozilla the specific version is not checked. So, an OLD updater can be inserted to the file path (for updating) and be used. This works as the classic rollback attack.
  • By combining the CVE's from 2017 and this rollback attack, it is possible to exploit the CVE's from 2017 AGAIN.
  • It should be noted that this attack only works if the user has installed this in a writable location (non-standard). Even though this is not the default, the replay attack is an interesting use-case that SHOULD be considered.
  • To patch this vulnerability, the team fixed the 2017 CVE's with more strict patches. I find this super interesting because a rollback attack may be possible again in the future.