You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
WShell is a post-exploitation tool designed to exploit any web-based command injection vulnerability into an interactive and feature-rich pseudo-shell. It provides an agentless, language-agnostic shell that feels like a native terminal, complete with command history, change directory support, file transfers and much more.
19
-
20
-
## ✨ Key Features
14
+
WShell takes a raw command injection point and turns it into something you can actually work with: persistent history, `cd` support, file transfers, and OS-aware behavior, all without uploading anything to the target.
21
15
22
-
-**Interactive Pseudo-Shell**: Experience a shell with support for commands like `cd` and a persistent command history.
23
-
-**Automatic OS Detection**: Automatically identifies the target OS (Linux, Windows CMD, Windows PowerShell) and adjusts its behavior accordingly.
24
-
-**Extensible Input/Output Scripts**: Manipulate command payloads and server responses on-the-fly with a chain of scripts (e.g., `base64encode`, `urlencode`, `unescape`, `space2ifs`).
25
-
-**Built-in Custom Commands**: Powerful custom commands like `download` and `upload` that abstract away OS-specific complexities for file transfers.
26
-
-**Flexible HTTP Configuration**: Full control over HTTP requests, including method, headers, cookies, and body (form-data or JSON).
27
-
-**Extensible by Design**: Easily add your own custom commands and scripts to tailor WShell to your needs.
28
-
-**Agentless**: No need to upload a separate web shell file; WShell leverages the existing vulnerability.
16
+
Point it at a vulnerable endpoint, tell it where to inject, and it handles the rest.
29
17
30
-
## 🚀 Getting Started
18
+
## Installation
31
19
32
-
### Installation
33
-
34
-
Install WShell using your favorite Python package manager. `pipx` or `uv` are recommended as they install the tool in an isolated environment.
35
-
36
-
**With `pipx`:**
20
+
`pipx` or `uv` are recommended to keep dependencies isolated:
WShell automatically checks for new versions and eventually upgrade itself on startup. This can be disabled by passing the `--no-update` flag. If you want to include pre-releases in the update check, use `--include-prerelease`.
30
+
WShell checks for updates on startup. Pass `--no-update` to skip this, or `--include-prerelease` to track pre-releases.
51
31
52
-
To upgrade manually, use the appropriate command for your package manager.
32
+
## Quick start
53
33
54
-
### Quick Start
55
-
56
-
Let's say you've found a command injection vulnerability in a `ping.php` page.
57
-
58
-
**Vulnerable Code (`ping.php`):**
34
+
Say you've found a command injection in a `ping.php` page:
59
35
60
36
```php
61
37
<?php
62
-
// ping.php
63
38
$host = $_POST['host'];
64
39
$count = intval($_GET['count']);
65
-
// Insecurely uses user input to build a shell command.
66
40
$command = "ping -c {$count} {$host} 2>&1";
67
41
echo "<pre>" . shell_exec($command) . "</pre>";
68
42
?>
69
43
```
70
44
71
-
To exploit this, you can use `wshell`.
72
-
73
-
> The placeholder `WSHELL` marks where your commands will be injected.
45
+
Use the `WSHELL` placeholder to mark where commands get injected:
WShell detects the target OS (Linux, Windows CMD, or PowerShell) and adjusts behavior accordingly.
86
58
87
-
The basic syntax is:
59
+
## Features
60
+
61
+
-**No upload required.** Works through the injection point directly — no web shell file needed.
62
+
-**`cd` and command history** work as expected across requests.
63
+
-**Input/output scripts** let you manipulate payloads and responses in a chain — useful for bypassing filters or decoding output (see [Scripts](#inputoutput-scripts)).
64
+
-**`download` and `upload` commands** handle file transfers in chunks and abstract away OS differences.
65
+
-**Full HTTP control** — method, headers, cookies, body format (form or JSON), delays, timeouts, redirects, custom User-Agent.
66
+
-**Extensible** — add your own scripts and commands without touching core code.
67
+
68
+
## Usage
88
69
89
70
```
90
71
wshell [OPTIONS] URL [REQUEST_ITEMS...]
91
72
```
92
73
93
-
-`URL`: The vulnerable endpoint.
94
-
-`REQUEST_ITEMS`: HTTP headers (`Key: value`) and body parameters (`key=value`) for the request. The `WSHELL` placeholder can be placed in one of these items or in the URL.
|**Core**|`URL`| The vulnerable endpoint URL. | (Required) |
101
-
||`REQUEST ITEMS...`| Headers (`Key: value`) and body data (`key=value`). | - |
102
-
||`--os`| Specify the target OS and shell (`linux`, `win-cmd`, `win-psh`). | Auto-detected (send additional requests) |
103
-
||`--placeholder`| The placeholder for command injection. |`WSHELL`|
104
-
||`--prompt`| A custom static prompt for the shell. | (Dynamic prompt based on target OS) |
105
-
|**HTTP**|`-m, --method`| HTTP method for requests. | Auto-detected (POST if data, else GET) |
106
-
||`-t, --timeout`| Connection timeout in seconds. Use `--no-timeout` to disable. |`3.0`|
107
-
||`-d, --delay`| Delay in seconds between each request. |`0`|
108
-
||`--data-raw`| Raw data string to be sent (form-urlencoded or JSON). | - |
109
-
||`-j, --json` / `-f, --form`| Serialize body data as JSON (`-j`) or form fields (`-f`). |`--form`|
110
-
||`--keep-alive`| Use a persistent HTTP connection (`--no-keep-alive` to disable). |`True`|
111
-
||`--follow`| Follow 30x redirects (`--no-follow` to disable). |`True`|
112
-
||`-ua, --user-agent`| Set a custom User-Agent. |`WShell X.Y.Z`|
113
-
||`-r, --random-agent`| Use a random User-Agent from a built-in list. |`False`|
114
-
|**Scripts**|`--input-scripts`| Comma-separated chain of scripts to process commands _before_ sending. | - |
115
-
||`--output-scripts`| Comma-separated chain of scripts to process the server response. | - |
116
-
||`--list-scripts`| List all available input and output scripts. | - |
117
-
|**App**|`--log`| Set logging level (`critical`, `error`, `warning`, `info`, `debug`). |`warning`|
118
-
||`--update` / `--no-update`| Enable or disable the automatic update on startup. |`True`|
119
-
||`--include-prerelease`| Include pre-releases in the update check. |`False`|
120
-
||`-v, --version`| Show the version number and exit. | - |
121
-
||`-h, --help`| Show the help message and exit. | - |
74
+
`REQUEST_ITEMS` follows HTTPie-style syntax: `Key: value` for headers, `key=value` for body parameters. The `WSHELL` placeholder can go in any of these or in the URL itself.
||`--update` / `--no-update`| Toggle auto-update on startup. |`True`|
99
+
||`--include-prerelease`| Include pre-releases in the update check. |`False`|
100
+
||`-v, --version`| Print version and exit. | — |
101
+
||`-h, --help`| Print help and exit. | — |
122
102
123
103
---
124
104
125
-
## 🔬 Advanced Features
126
-
127
-
### Input/Output Scripts
105
+
## Input/output scripts
128
106
129
-
Scripts are powerful functions that manipulate the command payload (input scripts) or the server's response (output scripts). This is essential for bypassing filters or decoding responses.
107
+
Scripts transform the command payload before it's sent (input scripts) or process the server's response after it's received (output scripts). They're most useful when the target requires encoded input or returns encoded/escaped output.
130
108
131
-
**Example**: If the vulnerable app requires commands to be base64-encoded and blocks commands containing spaces, you can use a chain of inputscripts to match the requirements.
109
+
Run them in a comma-separated chain with `--input-scripts` or `--output-scripts`:
132
110
133
111
```shell
134
-
#The command 'ls -la' will be transformed to 'ls${IFS}-la' and base64-encoded before being sent.
112
+
#Replace spaces with ${IFS}, then base64-encode — useful for filters that block spaces
[INFO] File '/etc/passwd' downloaded to 'passwd.txt'
155
131
```
156
132
157
-
This abstracts away the complexity of encoding/decoding files, download large files in chunks or any OS-specific commands and techniques.
158
-
159
-
## 🛠️ Extending WShell
160
-
161
-
WShell is built to be extensible. You can easily add your own scripts and commands.
133
+
It handles chunking and encoding automatically, regardless of whether you're on Linux or Windows.
162
134
163
-
### Developing a Script
135
+
##Extending WShell
164
136
165
-
1. Create a Python file in `wshell/scripts/input/` or `wshell/scripts/output/`. The filename becomes the script name.
166
-
2. Inside the file, define a function `run(data: str) -> str` with a docstring.
137
+
### Adding a script
167
138
168
-
**Example (`wshell/scripts/input/reverse.py`):**
139
+
Create a Python file in `wshell/scripts/input/` or `wshell/scripts/output/`. The filename becomes the script's name. Define a `run(data: str) -> str` function with a docstring.
169
140
170
141
```python
142
+
# wshell/scripts/input/reverse.py
171
143
defrun(command: str) -> str:
172
144
"""Reverses the command string."""
173
145
return command[::-1]
174
146
```
175
147
176
-
You can now use `--input-scripts=reverse`from the command line.
148
+
Now `--input-scripts=reverse`works.
177
149
178
-
### Developing a Custom Command
150
+
### Adding a custom command
179
151
180
-
1. Create a Python file in a subdirectory of `wshell/commands/`. The subdirectory defines the command's category in the `help` menu.
181
-
2. Create a class that inherits from `wshell.commands.WShellCommandSet` and follows the `cmd2`[Modular Commands](https://cmd2.readthedocs.io/en/stable/features/modular_commands/) guide.
152
+
Create a Python file in a subdirectory of `wshell/commands/`. The directory name sets the category shown in `help`. Your class should inherit from `wshell.commands.WShellCommandSet` and follow the [cmd2 modular commands](https://cmd2.readthedocs.io/en/stable/features/modular_commands/) pattern.
182
153
183
-
WShell provides `self._cmd.injector` to execute commands on the target and `self._dispatch()` to create OS-specific functions.
184
-
185
-
**Example (`wshell/commands/php/phpinfo.py`):**
154
+
Use `self._cmd.injector` to run commands on the target, and `self._dispatch()` to handle OS-specific logic.
186
155
187
156
```python
157
+
# wshell/commands/php/phpinfo.py
188
158
import argparse
189
159
from cmd2 import with_argparser
190
160
from wshell.commands import WShellCommandSet
@@ -195,42 +165,42 @@ class PHPInfoCommandSet(WShellCommandSet):
195
165
196
166
@with_argparser(_argparser)
197
167
defdo_phpinfo(self, args) -> None:
198
-
"""Creates a file that executes `phpinfo()` in the current directory."""
168
+
"""Creates a file that runs phpinfo() in the current directory."""
We welcome contributions! Please look through existing [Issues](https://github.com/unlock-security/wshell/issues) and [Pull Requests](https://github.com/unlock-security/wshell/pulls).
246
-
If you have a new idea or a bug to report, please create an issue.
213
+
## Contributing
247
214
248
-
[See the Contribution Guide →](https://github.com/unlock-security/wshell/blob/main/CONTRIBUTING.md)
215
+
Check the open [Issues](https://github.com/unlock-security/wshell/issues) and [Pull Requests](https://github.com/unlock-security/wshell/pulls) before opening something new. The [contribution guide](https://github.com/unlock-security/wshell/blob/main/CONTRIBUTING.md) has more details.
249
216
250
-
## 📜 License
217
+
## License
251
218
252
-
This project is licensed under the GPL-3.0 License. See the [LICENSE](https://github.com/unlock-security/wshell/blob/main/LICENSE) file for details.
219
+
GPL-3.0. See [LICENSE](https://github.com/unlock-security/wshell/blob/main/LICENSE).
0 commit comments