
Could I steal my own Telegram session with a QR code?
Telegram Web lets you log in by scanning a QR code from an already-authenticated phone. Open the app, scan, you're in. I started wondering how brittle that handoff really is when the browser is talking to a site you did not intend to visit. I had no idea what would break first, which was enough reason to build a small lab and find out.
The lab
I wanted a reproducible setup, not a one-off demo, so everything runs in Docker and can be thrown away afterwards.
The architecture is a straightforward adversary-in-the-middle: the browser talks to my server, my server talks to Telegram Web, and most traffic passes through unchanged. The interesting part is in the browser. Instead of serving Telegram's original JavaScript, I inject a small payload that waits for QR authentication to complete, then reads whatever the session leaves behind (Local Storage, Session Storage, cookies, IndexedDB) and sends it back to the server before the redirect.
Importing that material into another browser turned out to be the boring step. Once the plumbing works, the rest is mostly bookkeeping.
What breaks (and what does not)
I expected the story to be about cryptography. It wasn't. Telegram isn't using broken crypto, and HTTPS is doing what HTTPS does. Nobody is decrypting TLS or bypassing certificates.
The weakness is simpler. If you can steer someone to the wrong origin, their browser will happily complete a valid HTTPS handshake with you. Encrypted, authenticated, and pointed at the wrong place. I kept waiting for a clever trick behind that. There wasn't one.
Browser storage
A side thread I did not plan for: how web apps actually persist "logged in" state. It is rarely one mechanism. Some apps lean on cookies, others on Local Storage or IndexedDB, sometimes Service Workers join the pile. Telegram's choices made this experiment work; another app might not behave the same way, which is why reproducing the setup matters more than arguing from screenshots.
What the QR code is not
"Is QR login insecure?" stopped feeling like the right question. A QR code is just a transport for data; the security properties live in what happens after the scan.
I ended up thinking about origins and whether session material is bound to where it was created. The QR code was never the interesting part.
Things I Learned While Building This
- Browser storage is often more valuable than people assume.
- Reverse proxies are easy; making them invisible is the hard part.
- HTTPS fixes transport problems, not wrong-site visits.
- A reproducible lab beats twenty opinion threads.
- Weekend project estimates remain unreliable.
The lab is on GitHub: isolated Docker setup, Telegram Web clone, storage capture after QR login, session replay when auth material is not origin-bound. Built for research, not deployment.
If you take one thing from this: ask what assumptions a login flow is making, not only how the happy path is supposed to work.