How an accidental step into an out of scope asset lead to unauthenticated SQL injection in OneLogin

Hello everyone! This is the first out of (hopefully) many blog-posts about my bug bounty journey. This blog-post will talk about how accidentally stepping into an out-of-scope asset while bug hunting lead me and SkyLinx to discovering an unauthenticated blind SQL injection in OneLogin

First and foremost, we want to give a big thank you to Blaklis for offering his help, when we were having issues finding an actively monitored channel for reporting issues to OneLogin. I did find an email address meant for reporting security issues on https://www.onelogin.com, but it seemed to be outdated and forgotten about. As you can see in the images below, it took at least 5 days just for us to find an actively monitored channel for reporting security issues to OneLogin.

Blaklis personally contacted people from Bugcrowd, HackerOne, LinkedIn and X and eventually somehow found an active channel for reporting security issues to OneIdentity.

Thank you Blaklis for the help :)


So what is OneLogin? OneLogin is one of the industry leading IAM providers in the world with over 5500 customers and 6000 application integrations worldwide. This makes application and customer security a very important focus area for them. Luckily for them, we managed to make this discovery and report it before a malicious attacker managed to leverage it for their gain.


Okay, lets start talking about the discovery of the bug. I was doing my typical bug hunting on a public HackerOne program while using a Match & Replace rule for a correlation header polyglot I learned from Frans Rosén on an episode of the Critical Thinking - Bug Bounty Podcast. Definitely check them out!

X-Request-Id: ' " % & > [ ${ $( ` ; \

At some point of me testing the features of a particular application, I was redirected to https://<target>.onelogin.com. I did not think much about it during the time, but after a while I realized there was a request to that domain with a 500 HTTP-status code in my HTTP-history.

Being very curious me, I went back to that request to check why it was giving a server error. I removed my polyglot header from the request and the response status was a 302. This immediately started the alarm bells in my head, and very quickly I realized a single-quote ( ' ) inside the X-Request-Id HTTP-request header was causing this. I went to OneLogin's homepage to see if this same behavior was happening there too, and it was. At this moment something totally else caught my interest for some reason and I forgot about this weird behavior for a month or two.

After a short while I again remembered this weird behavior and visited OneLogin's home page to see if they offer free trials for their products. They were and soon enough I opted for a personal 30 day free trial instance of OneLogin for investigation purposes. With the help of SQL comments I pretty much confirmed my input was in SQL context. Below you can see a snippet of my notes taken during this engagement.

In case you are not familiar with the term of SQL injection and what it can lead to, I will explain it here quickly. A SQL injection happens when user submitted data is used in a SQL query in an unsafe way, which allows an attacker to add additional SQL keywords to the original query. This can lead to full database compromise, allowing an attacker to read and / or modify data in it and in some cases even achieve Remote Command Execution (RCE).

I was already quite sure that the backend database was PostgreSQL, but I was having serious difficulties triggering any kind of conditional responses. This was making me very confused.

SkyLinx and I decided to team up in this investigation, since we were sure my finding and his extensive experience on developing and securing web applications would lead to something fruitful. This was also for him the first time seeing a SQL injection in a correlation header.

Quite soon we realized why I was not able to trigger any kinds of conditional errors with my own testings. I never tried batched queries. I felt quite dumb but it was definitely a very big lesson learned!

Using X-Request-Id: '; select version(); – we confirmed the backend database was actually PostgreSQL (status code 302). Since OneLogin had not implemented any WAFs to this section of the application, exploitation was very straight forward. We ended up with the following payload (tests if the first character of the version information is the letter "P") to achieve a blind time based SQL injection, which triggered a 2 second timeout in the application:

X-Request-Id: '; SELECT CASE WHEN (SUBSTRING(version(), 1, 1) = 'P') THEN pg_sleep(2) END; --

This was the moment when I knew we had it! We only had to do a simple intruder attack to actually read plaintext data from the DB, so we decided to read the database version, which ended up being PostgreSQL 15.10.

Down under is the actual PoC video we sent to OneLogin

0:00
/1:32

After this we reported the finding to OneIdentity using their self hosted reporting channel and a mitigation process was immediately started with the URGENT category. CVE-2025-52924 was set for the vulnerability with the CVSS score of 4.0, which we still are quite confused about (updates coming hopefully).