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!

FortMajeure: Authentication Bypass in FortiWeb (CVE-2025-52970)- 1738

https://pwner.gg    Reference →Posted 6 Months Ago
  • The Session Cookie on this website contains three parts:
    • Era: Type of session.
    • Payload: Encrypted data with session information, such as the username.
    • AuthHash: SHA1 HMAC hash for the ciphertext of Payload above. This uses the same secret key as the Payload for encryption.
  • This C server selects the shared key based upon the Era value from an array. It decrypts the Payload using the key. Then, it verifies the AuthHash using the key and ciphertext. Pretty simple!
  • The vulnerability lies in the use of the Era value, which should only be 0 or 1. However, there is no check on the value, which leads to an out-of-bounds access. Since this is used for direct access to the key, this is a significant issue. When the Era is 2-9, it will read uninitialized memory! This removes all entropy from the key space, which allows us to encrypt and sign the data ourselves.
  • To run this attack, the target user must have an active session running. Still, it's a pretty sick bug! It's not very often that a memory corruption bug leads to a cryptographic bypass. I believe that as binary exploitation presentation methods become more sophisticated, application-level attack methods will also become more prevalent.

Our plan for a more secure npm supply chain- 1737

Xavier René-Corail - GitHub    Reference →Posted 6 Months Ago
  • Recent attacks on the NPM ecosystem have scared the security industry. A simple compromised package is enough to infiltrate all Fortune 500 companies at once. Several high-profile hacks of NPM maintainer accounts have led to the addition of post-install scripts to steal secrets. GitHub removed the compromised packages and blocks the addition of new packages with the attacks' IoCs.
  • So, what's the next step then? We cannot let this continue happening. GitHub has decided to force 2FA for local publishing of NPM packages. Additionally, many aspects related to tokens will be updated. The deprecation of classic tokens, TOTP 2FA will be deprecated, granular tokens will contain scoped permissions and have short expirations, and the 2FA option for local package publishing will no longer be bypassable.
  • The next step is to make Trusted Publishing a more prominent feature, as described here. Instead of using tokens within the build pipeline, short-lived and tightly scoped OIDC identity tokens will be utilized. PyPI pioneered this approach and has since been adopted by many other ecosystems.
  • Trusted Publishers ensures that a package is coming from a specific CI system, workflow and build pipeline, limiting the ability to publish to the package manager arbitrarily. This allows package repositories to function even with systems that have decentralized build pipelines. There is also the prevention of "Star Jacking" attacks, which can confuse users about the trustworthiness of a project.
  • A good callout from GitHub on how to secure these ecosystems. I love this article and it shows their proactive nature.

Threat Contained: marginfi Flash Loan Vulnerability - 1736

Felix Wilhelm    Reference →Posted 6 Months Ago
  • Flash loans, or the borrowing of a large amount of money within a single transaction, work because they must be repaid with interest by the end of the transaction. In EVM, an external call from the context of the smart contract can be made with a callback to a user-controlled contract.
  • In Solana, Cross-Program Invocations (CPI) make this too hard to do. Therefore, instruction introspection is used to ensure that the flash loan is indeed paid by examining the instructions that are supposed to be executed in the future. The instruction sysvar account makes this possible.
  • MarginFi is a lending platform on Solana but it adds some extra flexibility to this. The account MarginfiAccount is used to track users' assets and liabilities. It must remain healthy at all times except in the case that a flash loan has been created for it. In this case, the health check is skipped, assuming that everything will be resolved by the end of the call.
  • When creating a flashloan, the lending_account_start_flashloan function will ensure that there's a following call to lending_account_end_flashloan. Using this call, a health check is performed to ensure that the funds from the flash loan have been returned.
  • Recently, a new instruction called transfer_to_new_account was created. This is for migrating the original MarginfiAccount to a fresh account and empties the original one. This call fails to ensure that we're not in the middle of a flash loan though!
  • This leads to the following attack:
    1. Create an account A with a flash loan.
    2. Borrow the maximum amount of funds for the flash loan.
    3. Call transfer_to_new_account to move the outstanding liabilities from A to a new account B.
    4. End the loan on account A. Since the liabilities are now good and the call to lending_account_end_flashloan is made, this is sufficient.
    5. End the call and never repay the funds. Now, account B contains a flash loan account that has never been paid back.
  • A solid find from Felix! A good lesson for me is that even small changes in functionality can have horrible consequences. The more functionality you have, the more these can interact and cause havoc with each other.

AgentFlayer: Discovery Phase of AI Agents in Copilot Studio- 1735

Tamir Ishay Sharbat - Zenity Labs    Reference →Posted 6 Months Ago
  • A CoPilot Studio Customer Support Management service by McKinsey sparked some interest in hacking. The system contains a service inbox that listens for inquiries, looks up previous engagements, and then responds via email to the request. To test this out, they created their own version of the bot using Microsoft CoPilot Studio with a custom knowledge source with the customer information and a "get records" tool to access the company's CRM.
  • Using a prompt injection, they were able to confuse the bot to send an email to the attacker's email address instead of the proper one. The new prompt includes disclosing the knowledge sources and tools as well. With this information, they are ready to tackle the service further. This serves more as a recon step. It appears that this is somewhat of an access control issue letting all email contact the bot.
  • In the next article, they simply ask it to leak the entire file for the customer information using prompt injection. The same thing can be done via a prompt injection on the CRM as well.
  • Sadly, there is no complete "fix" for all of this besides restricting the email from which this can be received. Where a bot can access sensitive data, a user can also steal it through prompt injection. The tone of the article is a little condescending, which I don't appreciate though. The goal is to make the world more secure and have folks be more interested in getting security help; tones like this create a gap between developers and security imo.

Github Actions: A Cloudy Day For Security - Part 1- 1734

Sofia Lindvist     Reference →Posted 6 Months Ago
  • GitHub Actions are actually pretty hard to secure against all of the threats. In particular, insider threats. This article goes over some GitHub protections that can help a repository be better.
  • Branch Protections prevent modifications to specific named branches. This prevents straight pushes to main from compromised developers. This can also be used to require signed commits or request pull requests before merging.
  • Another good feature is Dismiss Stale pull request approvals. This prevents a PR from being approved and then having a major change being made from underneath it. Again, insider threats are very hard to protect against.
  • GitHub Actions can have Secrets as well. One annoying component about this is that a user with push permissions on the repository can create a branch with a new GitHub action and just leak the secrets. To prevent this, I have required PRs from users only and not allowed branches except for admins.
  • Environments are a collection of variables and secrets in GitHub. They can be created with specific names, like prod and dev. Secrets within an environment take place over those in the secrets directly.
  • The environment feature has several helpful features. First, you can have required reviewers for using a particular environment. Second, you can only allow the environment to be used within a branch, such as a protected branch. This prevents the stealing of sensitive secrets as a result.
  • There are also Tag-based protections. Restricting deletions, blocking force pushes, and requiring deployments to succeed are all somewhat helpful.

LG WEBOS TV PATH TRAVERSAL - AUTHENTICATION BYPASS AND FULL DEVICE TAKEOVER- 1733

Ssd Disclosure    Reference →Posted 6 Months Ago
  • When WebOS has a USB thumb drive plugged into it, it opens a port on the TV. This allows peer devices to call the API /getFile?path=xxxxxx to get files from the mounted USB.
  • The device doesn't have any filtering on the path for directory traversal vulnerabilities. By using a classic directory traversal, you can read arbitrary files from the system.
  • This by itself is bad but what can we do with it? There's a database that contains peer authentication keys. By stealing these keys, it's possible to bypass authentication on the secondscreen service. With this, they can enable developer mode to install arbitrary apps and gain control of the device.
  • The vulnerability is simple yet the impact derived from this is terrible. Good find! I was also surprised to find that the PoC includes a Docker image for the TV, making it easy to run.

TLS NoVerify: Bypass All The Things- 1732

f0rw4rd    Reference →Posted 6 Months Ago
  • A tool for bypassing TLS verification on Linux. This makes intercepting clients much easier.

Subverting Code Integrity in Electron- 1731

Darius Houle - Trail of Bits    Reference →Posted 6 Months Ago
  • Electron packages are signed in order to prevent tampering. Many applications, such as Signal and 1Password, use this.
  • Electron is based on the Chrome browser. V8 heap snapshots occur from a user-writable directory in Chrome. These are used for rendering various browser components from disk instead of doing it over and over again.
  • The bypass for the code integrity is simply done by modifying the V8 snapshots on the system. By clobbering Array.isArray() in JavaScript, the author can easily trigger a crash. Naturally, this hijacking of functions and be used to add arbitrary code and circumvent all integrity checks.
  • This vulnerability is super simple but requires a deep knowledge of Chrome. Understanding something popular very well can lead to seemingly simple security issues with devastating consequences, such as this one.

OAuth Non-Happy Path to ATO- 1730

Omid Rezaei    Reference →Posted 6 Months Ago
  • OAuth is a fickle monster. This post dives into a website that was automatically redirecting to the Referer header when coming back from the OAuth flow. Likely, this was a multi-website system where they had a global OAuth page and needed to get back to the original page. Of note, the Referer header survives redirects.
  • An arbitrary redirect in OAuth is usually an automatic game over. This is because the auth information itself is stored within the fragment or parameters in a URL. So, the goal of the attack was to trigger a redirect to steal the token information of the user.
  • Upon trying to abuse this functionality, they learned that client-side redirects will remove the fragment but server-side will not. In the standard flow for OAuth, a client-side redirect was used. However, by changing the type to be id_token instead, this triggered a server-side redirect to keep the code around.
  • They tried reviewing the OAuth providers used by the application: Facebook, GitHub and Google. Facebook had a confirmation step that changed the referer, and GitHub doesn't use the response_type parameter. Gmail had a selection screen if users had more than one account. By adding the parameter prompt=none, this prompt was bypassed though.
  • The final flow of the attack tricked a victim into visiting their website and used window.open() to trigger the OAuth flow. Since they were the referrer of this interaction, it would eventually redirect to their website, where they could steal the token information.
  • This blog post was a good example of seeing bad functionality and finding the primitives to trigger it properly. This contained numerous small tricks and required considerable perseverance. Great write-up!

Forcing Quirks Mode with PHP Warnings + CSS Exfiltration without Network Requests- 1729

Takeshi Kaneko    Reference →Posted 6 Months Ago
  • This is a Cross-Site (XS) Leaks CTF challenge with a couple of nifty tricks. The user creates a page with HTML injection that the admin then clicks on using a tool like Selenium. The goal is to leak the user's session cookie using this with a known token format. This uses a PHP server that is behind Caddy.
  • The limitations are also interesting. The content for the HTML injection is limited to 1024 characters. The characters can be 0x20-0x7E and newlines, but block several things like astriks, backslashes, and a few keywords. There's a CSP that prevents outbound loading of scripts, inline JavaScript, or web requests.
  • The browser has what is called Quirks Mode that relaxes some MIME checks. If the document loads a page with the wrong content type, it will treat it as text/css anyway. This challenge was set up to NOT use quirks mode because of the <!DOCTYPE html> at the beginning of the page. Can this be forced into Quirks mode?
  • If the beginning part of the page were to change in some way before loading, then this would be possible. In PHP, there are multiple ways to trigger errors that will be put at the top of the file instead. In previous research, this was done to drop CSP headers. In this case, if you added a large number of variables (more than a thousand), PHP gives a warning that ends up disabling quirks mode! Neat!
  • The HTML injection occurs. However, there is no practical way to exfiltrate the data due to the CSP. So, the only way is to use CSS data exfiltration. This is why the issue pointed out above with the Quirks mode is so helpful! With a simple payload, it's possible to change the color of the page.
  • Because of some character limitations, we need to find a way to load more data for our stylesheet. Luckily, the PHP 404 page will reflect input and can be used for this. Using /not-found.txt?{}body{background:limegreen} is a good sink for this.
  • Finally, in the CSS selectors, use the input:valid flag to decide whether to render the data or not based on the input from the previous step. Why does this matter? Frame counting! By viewing the page and counting the frames, we can figure out if the code was correct or not.
  • Overall, a pretty neat set of tricks! CTFs are sometimes on the cutting edge and niche; this is a perfect example of that.