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!

What Okta Bcrypt incident can teach us about designing better APIs - 1597

n0rdy    Reference →Posted 1 Year Ago
  • Okta had an interesting security incident. If the username was above 52 characters, then ANY password would be sufficient for logging in. If the username was 50 characters, then it would be only two. In Okta, the password hash included the concatenation of the userId, username and password.
  • Why did this happen? The hashing function BCrypt! In BCrypt, there is a limit to the size of the input to 72 characters. Since the user ID and username were included, it was possible to go above this. In some libraries, this would lead to a silent truncation of the data. With how much data Okta was using besides the password, this led to the entire password being truncated.
  • The author was curious about why the library even allowed this in the first place. A simple check on the input length would be sufficient in the library for preventing this from happening. They evaluated several implementations of libraries in different languages, all of which handled this case differently. Some errored out and some silently truncated the data. Why the truncation? They were conforming to the BSD implementation from years ago!
  • My personal favorite part of the article is the end. The author goes into Secure API Design. Recently, this has become a bigger concern of mine in my job so it was interesting to see these come out.
  • The first point is Don’t let the people use your API incorrectly. It should explicitly reject invalid input in order to prevent errors like this. If the functionality is required, then gate it behind a feature flag or unsafe variant of the function.
  • The next point was Be predictable. Good API design should be intuitive and obvious. Of course, this is subjective but we can use some common sense here.
  • No ego is the next one. Expecting users to read every bit of documentation or fully understand the implementations is totally unreasonable. Making systems easy to use for novice users should be the goal, with more advanced functionality being added to the more advanced ones. Good input validation goes a long way here.
  • The final point of note is Be Brave. To the authors point, be the new solution that is better. It's easy to fallback onto old implementations since it's always been there. Do something to make the world a better place.
  • Overall, an interesting read that further evaluates the Okta issue. I enjoyed the parts about secure API design the most that used Okta as a case study.

Nginx/Apache Path Confusion to Auth Bypass in PAN-OS (CVE-2025-0108)- 1596

Adam Kues    Reference →Posted 1 Year Ago
  • The authors of this post saw two vulnerabilities under active exploitation in Palo Alto firewalls. So, they reverse engineered the exploit to understand what was going on. The architecture is setup to have three separate components for web processing: Nginx -> Apache -> PHP.
  • First, it's a reverse proxy that sets a bunch of headers. The most important one is X-pan-AuthCheck: on, which indicates to check for authentication downstream. After this, Apache will re-normalize the request and re-process the request with a rewrite rule. Finally, if it's a PHP file, then an authentication check is done based on the header mentioned.
  • Anything you have a protocol that requires parsing complicated data, it's important to consider the differences between the tech stacks. The usage of authentication is set by Nginx and then processed by Apache. If we can trick Nginx to not set this header but have Apache still process it as a PHP request, then we can bypass authentication.
  • From reading previous research from Orange and messing around, the authors noticed some odd functionality within a RewriteRule. In Apache, the RewriteRule may perform an internal redirect. This is important because extra URL decoding may occur!
  • In Nginx, one of the paths that did NOT include the authentication header being set was /unauth. So, the goal is to get Nginx to not set the header yet have Apache use an interesting PHP route. Using the Apache trick from above, URL encoding directory traversal characters can be used to do this. For instance, /unauth/%252e%252e/php/ztp_gate.php/PAN_help/x.css will resolve to /unauth/../php/ztp_gate.php/PAN_help/x.css.gz after the multiple URL decodings. Of course, Apache will resolve the ../ now leading to /php/ztp_gate.php/PAN_help/x.css.gz.
  • Parser differential bugs strike again! Overall, a super interesting blog post against the exploitation of a real and impactful vulnerability.

form-action Content-Security-Policy Bypass And Other Tactics For Dealing With The CSP- 1595

ruben - nzrt 48    Reference →Posted 1 Year Ago
  • The Content Security Policy (CSP) is a browser-based protection to protection against XSS. In many ways, it does kill XSS but this post is about bypassing CSPs using forms.
  • default-src works well for is the fallback directive in the CSP. Unfortunately, it doesn't include several, such as form-action.
  • By creating a form that does not have an end, it's possible to have this form contain a bunch of sensitive data upon submission. Additionally, the form can be made to take up the entire page using CSS, leading to a single click doing the submission. Although this can't read variables, it can be used for data exfiltration.
  • An additional method is abusing autofill in browsers. By making the form look like a password, it will autofill the inputs for many password managers. If the form is the whole page and the page is clicked on, this will then be submitted to the attacker.
  • Even with the form-action directive in the CSP being set to self, there are still some issues with it. First, same-site request forgery is possible when using form-based auth. Dangling markup attacks are another option as well.
  • There's a bunch of good tricks in this article for using forms to get around CSPs. Pretty neat!

C stdlib isn't threadsafe and even safe Rust didn't save us- 1594

EdgeDB    Reference →Posted 1 Year Ago
  • The authors of this post are porting significant amount of networking code in EdgeDB from Python to Rust. While doing this, they have ran into a lot of interesting issues, including this post. While trying the port, they noticed that it always failed on ARM64 CI runners but nothing else.
  • The CI runner appeared to hang for a while then stop. Upon logging onto the CI box, they noticed that the program had actually crashed but this was detected by the runner. They noticed a coredump, which indicated something weird had happened.
  • They loaded the coredump into GDB and noticed that it was a crash within the Rust getenv() function. The function is crashing when loading a byte from environment variables. It was attempting to load data from an invalid memory location. Why is Libc crashing!?
  • One of their co-workers dropped a line: getenv isn't threadsafe. From looking at the crash dump, it was clear that while this process was reading the environment variables, another one had write to them. In all likelihood, the memory safe for the env vars was too small so it was reallocated to be bigger. However, the other code was still reading from this.
  • The variables associated with the crash were in OPEN SSL. In their code, they were using openssl to probe for packets, which was the offending code. Since they are using a combination of Python and Rust, Rust didn't think that an unsafe operation was happening.
  • To fix the bug, they moved from rust-native-tls and used the rustls instead. By calling try_init_ssl_cert_env_vars from Python, a global lock would prevent this race condition. Looking forward, Rust is marking the environment-setter functions unsafe and glibc has tried making getenv more thread-safe.
  • Why does this only happen on ARM? The crash occurs in a call to realloc within setenv. To hit this code path, the environmental variables need to line up just write for the realloc to cause issues in getenv(). Given this information, they're pretty lucky that they found this at all.
  • Personally, a really good read. Learning about debugging techniques and interesting bugs is fun!

Attacks on Maven Proxy Repositories- 1593

Michael Stepankin - Github Security     Reference →Posted 1 Year Ago
  • Apache maven is a common build tool for Java. Artifacts needed for the code are in an XML file. During the build process, the Maven console will download the deps it needs for local use. When it does this, a call to the Maven Artifact Resolver is made.
  • Maven Central is the main place where Java libraries are downloaded from. Thie site is public and has group ids to publish artifacts. For instance, org.springframework.boot repos can only be written to by the owner of this group. To host these, they are done by a global portal or through a legacy OSS repository hosting. JFrog, JBoss and many others are used under the hood to resolve these.
  • There is a proxy mode that allows for private Maven repo usage. Two of the in-house repo hosting software where vulnerability to XSS via rendering a malicious XML file. Since the XML file is controlled by the attacker and renders on the local browser, this leads to executing arbitrary commands as the logged in user for the page.
  • When a repo manager makes a request to download artifacts, it provides all of the information in the URL - group id, artifact id, etc. What would happen if this information contained slashes or pounds? It's not escaped at all. So, it would be possible to change the meaning of the URL. Additionally, the values after the artifact are truncated by all of the servers.
  • For some reason, JFrog supports semi-colons in the URLs as a deliminator. The semi-colon ends the parsing for JFrog but not other things. So, we can effectively do cache poisoning when proxies are being used! The proxied request will get things after the directory traversal then the next cached request will get the poisoned values.
  • Both Nexus and JFrog support URL query parameters for proxy repos. Messing around with these was a good attack surface as a result. The Nexus host was doing authorization checks based upon some route matching. By appending an extra slash in the URL path, this verification was bypassed. This allowed for overwriting unintended files on the server.
  • To make exploitation easier, they found that the contentGenerator tag could be set to velocity. This is a templating engine! So, by overwriting the file with velocity template, RCE is achieved but with authentication.
  • Overall, a pretty awesome post. The author has a good insight for how they found many of these bugs: "This [architecture] may introduce a second-order vulnerability when an attacker uploads a specially crafted artifact to the public repository first, and then uses it to attack the in-house manager." Integrators multiple pieces of software is complicated.

Microsoft Configuration Manager (ConfigMgr) 2403 Unauthenticated SQL injections - 1592

Mehdi Elyassa - Synacktiv    Reference →Posted 1 Year Ago
  • Microsoft Configuration Manager (MCM) is a systems management software by Microsoft. It manages computers with remote control, patch management, etc. If you find a bug, it's a really bad day for the administrators that use it!
  • The requests to this server are made over HTTP. While reverse engineering LocationMgr.dll, they found that some of the provided input was not being properly sanitized. In what way? In a SQL query!
  • The content is XML that is zipped. The input used for exploitation is a user GUID. The author wrote a nice Python script to make exploitation easy with a simple web request.
  • Using SQL injection, it's possible to create a new user account and set their role on the database. Deployment information can now be changed to execute arbitrary commands on all linked systems and bash commands via SQL on the server itself.
  • They found one more very similar SQL injection vulnerability as well. Somewhere and some way, it's required to put in effort. Sometimes, it's a crazy vulnerability. Other times, it's reverse engineering. You gotta put the work in or the bug you're looking for has already been found.

Decommissioning Prisma Finance - A Turbulent but Ultimately Soft-Landing- 1591

wavey    Reference →Posted 1 Year Ago
  • Prisma Finance is a hacked Liquidity fork that has been a ghost ever since. However, there is still some liquidity in it that they needed to get out. They discovered several other bugs in it while trying to decommision it.
  • As the TVL dwindled, a subtle account bug came to light. This was discovered after seeing a mismatch in the sum of the user debt and the actual user debt. The culprit is a stale value being used that did not include the interest from a previous call. Over time, a drift between the collateral's asset value and the tracking of debt would occur. If too much was tried to be withdrawn, then an integer underflow would occur, rendering it all useless.
  • At first, they thought fixing this was impossible, since it was in a sunset mode. However, they noticed that Governance was still enabled. By setting the oracle contract to return a value of uint256.max, users could withdraw their collateral again. This manipulated price created a bunch of bad debt in the protocol but users could get their funds back.
  • The second bug is MUCH worse. A Discord user posted that collateral gains from the ULTRA pool could not be claimed. At the top of the function claimCollateralGains(), the author noticed _accrueDepositorCollateralGain. This function rests a value that SHOULD have been zeroed out. Effectively, this removes the replay protection. This was exploited for 13ish ETH a while ago.
  • Prisma needed to reduce the debt ceiling to zero. Because of this, the mkUSD and ULTRA loans were not allowed. When this happened, Prisma's stablecoins deviated from their $1 peg to as high as $1.45. Why? The stablecoins are required for users to close their loans. Since this was the case, the token became more valuable. Traders hoarded the token to drive up the price and got a profit from the sale.
  • Because of this bad market dynamic, they added a manual 1 to 1 peg to allow users to close their loans without paying high amounts.
  • There are still $80K in debt remaining that needs to be claimed. Overall, a super interesting post on the complexities of shutting down a protocol.

Hacking Subaru: Tracking and Controlling Cars via the STARLINK Admin Panel- 1590

Sam Curry    Reference →Posted 1 Year Ago
  • Sam Curry and friends had pwned the auto industry for fun multiple times. This time, they set their eyes on Subaru.
  • The initial tests around the main Subaru mobile app didn't lead to anything. It was well secured. After talking with Shubs about this, Shubs discovered a website that Sam hadn't seen before - subarucs.com. Upon looking at subdomains of this, they found a website that had the title STARLINK Admin Portal.
  • Not the Elon Musk Starlink - it's the name of the Subaru in-vehicle infotainment system for remote functionality. With no login creds, it wasn't very interesting. While reading the JavaScript, they found both starlinkEnroll.js and login.js that included references to a password reset.
  • The JavaScript used for the password reset functionality had ZERO confirmation token on it. If this functionality worked as it looked in the JS, then a single POST request could reset the password of an internal employee account. Unfortunately, this required a valid email which they didn't have - but it DID work for enumeration.
  • This had 2FA - literally just the city you lived in. Luckily for them, the 2FA was client-side enforced only. Now, they could login with this users account with the password that they had set.
  • On the website, they were able to track a users exact coordinates for the last year. It contained a vehicle search based on a lot of criteria as well. The panel allowed for attachment to an account without the consent of anyone. So, they used this to attachment their account to a friends car then remotely started executing commands. Wild!
  • Two fairly simple bugs. To me, the asset discovery and reverse engineering of the web page are interesting to me. In web3, virtually everything is open source so this process is super fascinating to me.

Breaking Free from Duplicate Submissions: A Strategic Approach to Bug Bounty Success - 1589

NahamSec    Reference →Posted 1 Year Ago
  • Only a single person gets paid for a vulnerability when found. These duplicates kill the ego and drain the mind. This article is about overcoming the duplicate vulnerability issues.
  • If you use the same methodology as everyone else, you'll find the same bugs—IDORs, business logic flaws, etc. The author compares bug hunting to a treasure map where all of the obvious spots have already been picked clean. What's the solution? Become a vulnerability expert. Become the best at XSS, IDORs, etc. This isn't about quick wins; it's about building up the necessary skills.
  • The next issue surrounds program selection. Most people don't have a rhyme or reason for picking a program. Understand the program/product working inside and out; a good way is to be a power user on the platform.
  • Choose programs that are likely to have issues with the expertise learned. It may be close to finding the right program. But it will be more fruitful in the end. Success in bounty hunting is about being different.

Next.js, cache, and chains: the stale elixir- 1588

zhero_web_security    Reference →Posted 1 Year Ago
  • NextJS is a popular ReactJS framework that this website even uses. The function getStaticProps is used for prerendering a page for information already available in the build process. getServerSideProps transmits data at the time of the request based upon the provided data, making it dynamic. The former is cachable while the latter is not.
  • While doing some previous research, they noticed that there are many headers/URL parameters used by NextJs internals. These headers/parameters could be used to change some of the rendering and caching settings. To start with, they found the __nextDataReq=1 parameter would make this a data request. This means that data can be sent back instead of the HTML, using this flag.
  • At first glance, this doesn't matter, but it is a good primitive for cache poisoning. Adding the parameter above to a getServerSideProps call returns the JSON for the page instead. Assuming that URL parameters are not used in caching, this leads to the JSON being returned from the cache instead of the HTML.
  • Diving back into NextJS, they were curious about other ways to control the rendering process. The different routes return different cache-control headers based upon the type of the page. Using the x-now-route-matches can get these headers to change, resulting in unintentional data caching.
  • Crazily enough, the content-type of this page isn't application/json! It's text/html. If any data can be reflected in the page props response, it leads to XSS!
  • The end of the article goes through their bounty payouts. It's interesting that they reported this directly to the owners of NextJS and to many websites with bug bounty programs. To me, this feels weird because the crux of the issue is in NextJS, which paid out. Double dipping seems unfair to the programs. At the same time, if this deep research didn't result in large payouts, then they wouldn't be incentivized to do it. So, is this just the cost of securing the ecosystem or is this morally wrong? I'm not sure.
  • Great research and an awesome article on the internals of caching/NextJS. Followed on Twitter for sure!