June 16, 2026
Improper Access Control Leading to Account Deletion Without 2FA
So I’d already found a hidden vulnerability on [REDACTED] before (wrote about it here: Hidden Page with 2FA Bypass). After that success,I…
Excessium
2 min read
So I'd already found a hidden vulnerability on [REDACTED] before (wrote about it here: Hidden Page with 2FA Bypass). After that success,I shifted my entire focus to finding hidden Functions.
Down the 2FA Rabbit Hole
I was testing the 2FA implementation, trying to access all endpoints, supplying empty 2fa cookie, supplying 0000 :) , still nothing happened
That's when I applied a script I created via chatgpt , to reveal hidden elements in HTML:
function unhideElement(el) {
if (!(el instanceof HTMLElement)) return;
// Reset common hiding styles
el.style.display = 'block';
el.style.visibility = 'visible';
el.style.opacity = '1';
el.style.height = 'auto';
el.style.width = 'auto';
el.style.overflow = 'visible';
el.style.clipPath = 'none';
el.style.position = 'static';
el.style.zIndex = '9999';
// Highlight with red border
el.style.border = '2px solid red';
}
function unhideSequentially(delay = 200) {
const elements = Array.from(document.querySelectorAll('*')).filter(el => {
if (!(el instanceof HTMLElement)) return false;
const style = window.getComputedStyle(el);
return (
style.display === 'none' ||
style.visibility === 'hidden' ||
style.opacity === '0'
);
});
elements.forEach((el, i) => {
setTimeout(() => unhideElement(el), i * delay);
});
}
// Run it
unhideSequentially(200); // 200ms between eachfunction unhideElement(el) {
if (!(el instanceof HTMLElement)) return;
// Reset common hiding styles
el.style.display = 'block';
el.style.visibility = 'visible';
el.style.opacity = '1';
el.style.height = 'auto';
el.style.width = 'auto';
el.style.overflow = 'visible';
el.style.clipPath = 'none';
el.style.position = 'static';
el.style.zIndex = '9999';
// Highlight with red border
el.style.border = '2px solid red';
}
function unhideSequentially(delay = 200) {
const elements = Array.from(document.querySelectorAll('*')).filter(el => {
if (!(el instanceof HTMLElement)) return false;
const style = window.getComputedStyle(el);
return (
style.display === 'none' ||
style.visibility === 'hidden' ||
style.opacity === '0'
);
});
elements.forEach((el, i) => {
setTimeout(() => unhideElement(el), i * delay);
});
}
// Run it
unhideSequentially(200); // 200ms between eachThis script basically unhides everything that's been hidden with CSS and highlights it with a red border.
The Hidden Button
And there it was — a button labeled "Cancel" that wasn't visible before.
I clicked it. A DELETE request was sent, but… nothing happened. The endpoint didn't even exist. The request just failed.
Then I remembered something important: when I was testing account creation earlier, all the requests went to /en endpoints. Same thing with email modification - everything went through /en.
So I thought to myself, "If creating accounts goes through /en, and modifying emails goes through /en... surely deleting accounts would also go through /en, right?"
I sent the DELETE request again, modified the endpoint to include /en, and sent it.
The account was deleted. Just like that.
No 2FA prompt. No confirmation. No security check. The account was just… gone.
The Vulnerability
What happened here was a classic case of improper access control combined with hidden functionality:
- There was a "Cancel" button hidden in the UI (probably leftover from development or disabled for some reason)
- The button triggered a DELETE request to a non-existent endpoint
- But the actual working endpoint existed at
/en(following the same pattern as other sensitive operations) - The endpoint had zero 2FA verification despite being a critical account deletion function
Impact:
- Bypassed 2FA protection entirely
Lessons Learned
- Always look for hidden elements. i have found tons of hidden stuff , surely not all of em were vulns, but tons of hidden stuff outhere.
Alhamdullilah for his grace upon me.