Leak JWT Private Key leads to Bypass Authentication

Son Nguyen
7 min readFeb 27, 2024

--

(Vietnamese below)

Today I want to share with you a case I encountered during the bug bounty hunt, not too special but the impact it brought was P1. Hopefully this writeup can help you with some ideas when testing NodeJS applications.

I will call this application target.com because it is a private target and I don’t want the product to be affected.

Hiden path — Hiden gem

One fine day, my colleague said he had just found a misconfigured website related to Express. He found a .js file containing a “private key”, which was used to sign and verify the cookie jwt token. Alright, we’ve almost set a foot in the door to be able to Authentication Bypass. However, because of some reason so my colleague couldn’t go in-depth to demonstrate the impact of ‘private key’, so he assigned the job to me.

privateKey

So after we have the private key, what do we need to do?

  1. Find out the JWT cookie structure of the website to sign the token.
  2. Then test APIs/endpoints to demonstrate impact (like login or authentication required endpoint ).

It’s very easy if we have a sample token to sign with the private key, right?

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXJ0bmVySWQiOiJ0YXJnZXQiLCJ0eXBlcyI6InRpY2tldHMiLCJwZXJtaXNzaW9ucyI6MX0.atl--C1lrCHIH9IRIC4wB7EYBad3Xkf-F6E8fCA3Mag

However, the problem now is that this “misconfiguration” is in the API domain (call it api.target.com) and I don’t know what its specific application is to find the jwt cookie structure pattern. In addition, we also do not know the features and endpoints used to prove that the signed token is valid.

At this point, I have to rely on the API domain to find other subdomains that are also using this API domain. The results after a while of discovering still did not find any specific application. So how can I get the sample jwt token to build the structure? T.T

Recall that at handover, my colleague gave me a tool to search for accessible backend .js source files. I immediately used it and also found out quite a few other backend source .js files. Proceed to review it in hopes of finding some necessary information.

God bless me, I’ve gathered all the source .js files I can reach and are clear:
The private key is located at: https:///api.target.com/config/environment/index.js
And more interestingly, I found a source file: https://api.target.com/auth/index.js
Here is the structure of the jwt token:

auth/index.js

Hehe, so we know the jwt token structure of this website will be:

{
"partnerId": "AT005",
"types": "tickets",
"permissions": 1
}

Information about parmerId, type, permissions are all in the auth/index.js file.

And from here, I used the private key to sign with the above information and created a jwt token thanks to https://jwt.io like this:

jwt token example

However, to know whether this generated token is valid or not, we still have to know the features and api/endpoint to use the token. Because I searched for this target’s products and didn’t find anything I’m a bit confused. So I tried bruteforce path to see if there was any other information?
Ahihi, I found the endpoint : api.target.com/overseasPackages… and it is the Swagger UI.

Swagger

I quickly tried using APIs like create ticket, Get ticket as above and everything was OK.

Done, so the private key and jwt created token from it are valid. In addition, I looked through other APIs and it seems that this is an admin tool of that company to manage all information about booking, hotels, travel… and if it has a real partner, I can completely control it anything I want. Just report.

=> Bypass Authentication.

I’m writing this blog quickly, because I’m running monthly KPIs and just want to present my bug hunting mindset. That finding bugs is not too hard core in exploiting, maybe exploiting is only 20% and than 80% is recon, finding endpoints, finding params, finding misconfig… bla bla…

=============================================================

Hôm nay mình muốn chia sẻ với các bạn một case trong quá trình kiếm bug bounty mình đã gặp phải, không quá được biệt nhưng impact nó mang lại là P1. Hi vọng writeup này có thể giúp các bạn một vài idea khi test các ứng dụng NodeJs.

Mình sẽ gọi ứng dụng này là target.com vì nó lỗ hổng chưa public và mình không muốn product bị ảnh hưởng

Hiden path — Hiden gem

Một ngày đẹp trời, đồng nghiệp của tôi nói rằng anh ta vừa tìm được một trang web bị cấu hình sai liên quan tới Express. Cậu ta đã tìm được một file .js chứa một “private key”, nó dùng để sign cũng như verify token jwt của website. Có được nó, chúng ta gần như đã đặt 1 chân vào việc có thể Authentication Bypass rồi. Tuy nhiên, vì một số công việc mà đồng nghiệp của tôi không thể deep dive để chứng minh impact được và đã bàn giao công việc còn lại cho tôi.

privateKey

Vậy sau khi đã có private key, chúng ta cần làm gi?

  1. Tìm hiểu struct jwt của trang website để sign token.
  2. Sau đó thử các API/endpoint để chứng minh impact (như login hay tính năng bắt authentication).

Rất dễ nếu như chúng ta có được 1 mã token sample để sign với private key đúng không.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXJ0bmVySWQiOiJ0YXJnZXQiLCJ0eXBlcyI6InRpY2tldHMiLCJwZXJtaXNzaW9ucyI6MX0.atl--C1lrCHIH9IRIC4wB7EYBad3Xkf-F6E8fCA3Mag

Tuy nhiên, câu chuyện bây giờ là việc “misconfiguration” này nó nằm ở domain API ( gọi nó là api.target.com) và tôi không biết ứng dụng cụ thể của nó là gì để tìm kiếm một mã jwt sample hay. Chưa kể là các tính năng khác để chứng minh nó có thể tạo ra một valid token.

Đến đây, bắt buộc tôi phải dựa vào domain api để tìm các subdomain khác đang sử dụng domain api này. Kết quả sau một vòng tìm kiếm vẫn là không tìm được ứng dụng cụ thể nào. Vậy thì làm sao kiếm được jwt token mẫu để build struct đây T.T

Nhớ lại lúc bàn giao đồng nghiệp có cho tôi một công cụ để tìm triệt để các file source backend .js có thể reach tới, tôi vội vàng sử dụng nó và cũng dump được kha khá file source js backend. Tiến hành kiểm tra nó với hi vọng tìm được vài manh mối cần thiết.

Trời không phụ lòng người, tôi crawl hết tất cả các file source .js có thể reach tới về và tìm thấy đã rõ tìm thấy:

Private key nằm ở: https:///api.target.com/config/environment/index.js

Và thú vị hơn tôi tìm thấy 1 file source: https://api.target.com/auth/index.js. Nơi đây chứ struct của jwt token:

auth/index.js

Hehe, vậy là ta biết cấu trúc jwt token của site này sẽ là:

{
"partnerId": "AT005",
"types": "tickets",
"permissions": 1
}

Với các thông tin về partnerId , types , permissions đều có ở trong file auth/index.js

Và từ đây, mình đã dùng private key sign với các thông tin trên và tạo ra một jwt token nhờ https://jwt.io như thế này:

private key tượng trưng nha

Tuy nhiên, để biêt token tạo ra này có valid hay không, chúng ta vẫn phải biết các tính năng, api/endpoint để sử dụng token. Vì đã tìm một vòng các product của target này nhưng không phát hiện được gì nên mình cũng hơi bí… Thế là thử bruteforce path thử xem có hay không…
Ahihi, mình tìm được các endpoint : api.target.com/overseasPackages… và nó là một Swagger UI.

Swagger

Mình lẹ cái hand thử sử dụng các API như tạo ticket, và Get tickets như trên xem thì okie luôn.

Done, vậy là private key và token tạo ra từ nó valid. Ngoài ra, mình xem qua các API khác thì có vẻ như đây là một tool admin của công ty đó để quản lý tất cả các thông tin về booking, hotels,travel… và nó nếu có partner thật sự, thì mình hoàn toàn control bất cứ thứ gì mình muốn. Report thôi.

=> Bypass Authentication.

Blog lần này mình viết nhanh thôi, vì chạy KPI tháng và cũng chỉ muốn trình bày mindset kiếm bug một tí. Rằng kiếm bug không quá hard core vào việc khai thác, maybe khai thác chỉ chiến 20% thôi, còn 80% còn lại là tìm kiếm, kiếm endpoint, kiếm param, kiếm misconfg… bla bla…

--

--

Son Nguyen
Son Nguyen

Responses (1)