# `wsrepl` - Websocket REPL for pentesters
`wsrepl` is an interactive websocket REPL designed specifically for penetration testing. It provides an interface for observing incoming websocket messages and sending new ones, with an easy-to-use framework for automating this communication.
![Screenshot](docs/screenshot.png)
## Features
- Interactively send and receive websocket messages
- Customize headers, ping/pong messages, and other parameters
- Handle SSL verification and reconnections
- Plug-in support for automating complex interaction scenarios
- Full logging and message history
- Supports curl command line arguments for easy onboarding from Developer Tools or Burp Suite (use 'Copy as Curl' menu and replace `curl` with `wsrepl`)
## Installation
You can download and install wsrepl using pip:
```
pip install wsrepl
```
Alternatively, you can clone this repository and install it from source:
```
git clone https://github.com/doyensec/wsrepl
cd wsrepl
pip install .
```
## Usage
The basic command for starting wsrepl is as follows:
```
wsrepl -u URL
```
Replace URL with your target websocket URL, e.g. `wss://echo.websocket.org`. For more options and settings, you can use the -h or --help option:
```
usage: wsrepl [-h] [-u URL] [-i] [-s] [-k] [-X REQUEST] [-H HEADER]
[-b COOKIE] [--compressed] [-S] [-A USER_AGENT] [-O ORIGIN]
[-F HEADERS_FILE] [--no-native-ping]
[--ping-interval PING_INTERVAL] [--hide-ping-pong]
[--ping-0x1-interval PING_0X1_INTERVAL]
[--ping-0x1-payload PING_0X1_PAYLOAD]
[--pong-0x1-payload PONG_0X1_PAYLOAD] [--hide-0x1-ping-pong]
[-t TTL] [-p HTTP_PROXY] [-r RECONNECT_INTERVAL]
[-I INITIAL_MESSAGES] [-P PLUGIN] [-v VERBOSE]
[url_positional]
Websocket Client
positional arguments:
url_positional Websocket URL (e.g. wss://echo.websocket.org)
options:
-h, --help show this help message and exit
-u URL, --url URL Websocket URL (e.g. wss://echo.websocket.org)
-i, --include No effect, just for curl compatibility
-s, --silent No effect, just for curl compatibility
-k, --insecure Disable SSL verification
-X REQUEST, --request REQUEST
No effect, just for curl compatibility
-H HEADER, --header HEADER
Additional header (e.g. "X-Header: value"), can be
used multiple times
-b COOKIE, --cookie COOKIE
Cookie header (e.g. "name=value"), can be used
multiple times
--compressed No effect, just for curl compatibility
-S, --small Smaller UI
-A USER_AGENT, --user-agent USER_AGENT
User-Agent header
-O ORIGIN, --origin ORIGIN
Origin header
-F HEADERS_FILE, --headers-file HEADERS_FILE
Additional headers file (e.g. "headers.txt")
--no-native-ping Disable native ping/pong messages
--ping-interval PING_INTERVAL
Ping interval (seconds)
--hide-ping-pong Hide ping/pong messages
--ping-0x1-interval PING_0X1_INTERVAL
Fake ping (0x1 opcode) interval (seconds)
--ping-0x1-payload PING_0X1_PAYLOAD
Fake ping (0x1 opcode) payload
--pong-0x1-payload PONG_0X1_PAYLOAD
Fake pong (0x1 opcode) payload
--hide-0x1-ping-pong Hide fake ping/pong messages
-t TTL, --ttl TTL Heartbeet interval (seconds)
-p HTTP_PROXY, --http-proxy HTTP_PROXY
HTTP Proxy Address (e.g. 127.0.0.1:8080)
-r RECONNECT_INTERVAL, --reconnect-interval RECONNECT_INTERVAL
Reconnect interval (seconds, default: 2)
-I INITIAL_MESSAGES, --initial-messages INITIAL_MESSAGES
Send the messages from this file on connect
-P PLUGIN, --plugin PLUGIN
Plugin file to load
-v VERBOSE, --verbose VERBOSE
Verbosity level, 1-4 default: 3 (errors, warnings,
info), 4 adds debug
```
## Automating with Plugins
To automate your websocket communication, you can create a Python plugin by extending the [Plugin](wsrepl/Plugin.py) class in wsrepl. This class allows you to define various hooks that are triggered during different stages of the websocket communication.
Here is an outline of how to define a plugin:
```python
class MyPlugin(Plugin):
# Messages that will be sent to the server on (re-)connect.
messages = ["message1", "message2", "message3"]
def init(self):
# This method is called when the plugin is loaded.
# Use it to set initial settings or generate self.messages dynamically.
pass
async def on_connect(self):
# This method is called when the websocket connection is established.
pass
async def on_message_received(self, message: WSMessage):
# This method is called when a message is received from the server.
pass
# ... Other hooks can be defined here.
```
Refer to the source of [Plugin class](wsrepl/Plugin.py) for the full list of hooks you can use and what they do:
![Plugin Hooks](docs/hooks-mermaid.png)
### Example Plugin
Here is an example of a plugin that sends a predefined authentication message to a server:
```python
from wsrepl import Plugin
import json
class AuthPlugin(Plugin):
def init(self):
auth_message = {
"messageType": "auth",
"auth": {
"user": "user-1234"",
"password": "password-1234"
}
}
self.messages = [json.dumps(auth_message)]
```
This plugin can be used by specifying it when running wsrepl:
```
wsrepl -u URL -P auth_plugin.py
```
Replace URL with your target websocket URL and auth_plugin.py with the path to the Python file containing your plugin.
[docs/](./docs/) directory contains a few more example plugins.
## Contributing
Contributions to wsrepl are welcome! Please, [create an issue](https://github.com/doyensec/wsrepl/issues) or submit a pull request if you have any ideas or suggestions. In particular, adding more plugin examples would be very helpful.
## Credits
This project has been sponsored by [Doyensec LLC](https://www.doyensec.com/).
![Doyensec Research](https://raw.githubusercontent.com/doyensec/inql/master/docs/doyensec_logo.svg "Doyensec Logo")
Raw data
{
"_id": null,
"home_page": "https://github.com/doyensec/wsrepl",
"name": "wsrepl",
"maintainer": "",
"docs_url": null,
"requires_python": ">3.10,<4.0",
"maintainer_email": "",
"keywords": "websocket,pentesting",
"author": "Andrew Konstantinov",
"author_email": "105389353+execveat@users.noreply.github.com",
"download_url": "https://files.pythonhosted.org/packages/80/ec/e4a5827df6ac61dfd03bfd4686b3b353215d02ed8732eaf26942046d20c4/wsrepl-0.2.0.tar.gz",
"platform": null,
"description": "# `wsrepl` - Websocket REPL for pentesters\n\n`wsrepl` is an interactive websocket REPL designed specifically for penetration testing. It provides an interface for observing incoming websocket messages and sending new ones, with an easy-to-use framework for automating this communication.\n\n![Screenshot](docs/screenshot.png)\n\n## Features\n\n- Interactively send and receive websocket messages\n- Customize headers, ping/pong messages, and other parameters\n- Handle SSL verification and reconnections\n- Plug-in support for automating complex interaction scenarios\n- Full logging and message history\n- Supports curl command line arguments for easy onboarding from Developer Tools or Burp Suite (use 'Copy as Curl' menu and replace `curl` with `wsrepl`)\n\n## Installation\n\nYou can download and install wsrepl using pip:\n\n```\npip install wsrepl\n```\n\nAlternatively, you can clone this repository and install it from source:\n\n```\ngit clone https://github.com/doyensec/wsrepl\ncd wsrepl\npip install .\n```\n\n## Usage\n\nThe basic command for starting wsrepl is as follows:\n\n```\nwsrepl -u URL\n```\n\nReplace URL with your target websocket URL, e.g. `wss://echo.websocket.org`. For more options and settings, you can use the -h or --help option:\n\n```\nusage: wsrepl [-h] [-u URL] [-i] [-s] [-k] [-X REQUEST] [-H HEADER]\n [-b COOKIE] [--compressed] [-S] [-A USER_AGENT] [-O ORIGIN]\n [-F HEADERS_FILE] [--no-native-ping]\n [--ping-interval PING_INTERVAL] [--hide-ping-pong]\n [--ping-0x1-interval PING_0X1_INTERVAL]\n [--ping-0x1-payload PING_0X1_PAYLOAD]\n [--pong-0x1-payload PONG_0X1_PAYLOAD] [--hide-0x1-ping-pong]\n [-t TTL] [-p HTTP_PROXY] [-r RECONNECT_INTERVAL]\n [-I INITIAL_MESSAGES] [-P PLUGIN] [-v VERBOSE]\n [url_positional]\n\nWebsocket Client\n\npositional arguments:\n url_positional Websocket URL (e.g. wss://echo.websocket.org)\n\noptions:\n -h, --help show this help message and exit\n -u URL, --url URL Websocket URL (e.g. wss://echo.websocket.org)\n -i, --include No effect, just for curl compatibility\n -s, --silent No effect, just for curl compatibility\n -k, --insecure Disable SSL verification\n -X REQUEST, --request REQUEST\n No effect, just for curl compatibility\n -H HEADER, --header HEADER\n Additional header (e.g. \"X-Header: value\"), can be\n used multiple times\n -b COOKIE, --cookie COOKIE\n Cookie header (e.g. \"name=value\"), can be used\n multiple times\n --compressed No effect, just for curl compatibility\n -S, --small Smaller UI\n -A USER_AGENT, --user-agent USER_AGENT\n User-Agent header\n -O ORIGIN, --origin ORIGIN\n Origin header\n -F HEADERS_FILE, --headers-file HEADERS_FILE\n Additional headers file (e.g. \"headers.txt\")\n --no-native-ping Disable native ping/pong messages\n --ping-interval PING_INTERVAL\n Ping interval (seconds)\n --hide-ping-pong Hide ping/pong messages\n --ping-0x1-interval PING_0X1_INTERVAL\n Fake ping (0x1 opcode) interval (seconds)\n --ping-0x1-payload PING_0X1_PAYLOAD\n Fake ping (0x1 opcode) payload\n --pong-0x1-payload PONG_0X1_PAYLOAD\n Fake pong (0x1 opcode) payload\n --hide-0x1-ping-pong Hide fake ping/pong messages\n -t TTL, --ttl TTL Heartbeet interval (seconds)\n -p HTTP_PROXY, --http-proxy HTTP_PROXY\n HTTP Proxy Address (e.g. 127.0.0.1:8080)\n -r RECONNECT_INTERVAL, --reconnect-interval RECONNECT_INTERVAL\n Reconnect interval (seconds, default: 2)\n -I INITIAL_MESSAGES, --initial-messages INITIAL_MESSAGES\n Send the messages from this file on connect\n -P PLUGIN, --plugin PLUGIN\n Plugin file to load\n -v VERBOSE, --verbose VERBOSE\n Verbosity level, 1-4 default: 3 (errors, warnings,\n info), 4 adds debug\n```\n\n## Automating with Plugins\n\nTo automate your websocket communication, you can create a Python plugin by extending the [Plugin](wsrepl/Plugin.py) class in wsrepl. This class allows you to define various hooks that are triggered during different stages of the websocket communication.\n\nHere is an outline of how to define a plugin:\n\n```python\nclass MyPlugin(Plugin):\n # Messages that will be sent to the server on (re-)connect.\n messages = [\"message1\", \"message2\", \"message3\"]\n\n def init(self):\n # This method is called when the plugin is loaded.\n # Use it to set initial settings or generate self.messages dynamically.\n pass\n\n async def on_connect(self):\n # This method is called when the websocket connection is established.\n pass\n\n async def on_message_received(self, message: WSMessage):\n # This method is called when a message is received from the server.\n pass\n\n # ... Other hooks can be defined here.\n```\n\nRefer to the source of [Plugin class](wsrepl/Plugin.py) for the full list of hooks you can use and what they do:\n\n![Plugin Hooks](docs/hooks-mermaid.png)\n\n### Example Plugin\n\nHere is an example of a plugin that sends a predefined authentication message to a server:\n\n```python\nfrom wsrepl import Plugin\nimport json\n\nclass AuthPlugin(Plugin):\n def init(self):\n auth_message = {\n \"messageType\": \"auth\",\n \"auth\": {\n \"user\": \"user-1234\"\",\n \"password\": \"password-1234\"\n }\n }\n self.messages = [json.dumps(auth_message)]\n```\n\nThis plugin can be used by specifying it when running wsrepl:\n\n```\nwsrepl -u URL -P auth_plugin.py\n```\n\nReplace URL with your target websocket URL and auth_plugin.py with the path to the Python file containing your plugin.\n\n[docs/](./docs/) directory contains a few more example plugins.\n\n## Contributing\n\nContributions to wsrepl are welcome! Please, [create an issue](https://github.com/doyensec/wsrepl/issues) or submit a pull request if you have any ideas or suggestions. In particular, adding more plugin examples would be very helpful.\n\n## Credits\n\nThis project has been sponsored by [Doyensec LLC](https://www.doyensec.com/).\n\n![Doyensec Research](https://raw.githubusercontent.com/doyensec/inql/master/docs/doyensec_logo.svg \"Doyensec Logo\")\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Websocket REPL for pentesters",
"version": "0.2.0",
"project_urls": {
"Homepage": "https://github.com/doyensec/wsrepl"
},
"split_keywords": [
"websocket",
"pentesting"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c07d95e0f6ec87a8a9864d659d2fca9606b85757fb7c23a796a1c68dda7f32dd",
"md5": "a3c33787826ec2df9be47de5b769eb87",
"sha256": "0d5ef85f2d18dbec90b803071c3f47c1b0caa09675a0fd6c5c462b2972f072d7"
},
"downloads": -1,
"filename": "wsrepl-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a3c33787826ec2df9be47de5b769eb87",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">3.10,<4.0",
"size": 23879,
"upload_time": "2023-07-18T16:42:33",
"upload_time_iso_8601": "2023-07-18T16:42:33.218003Z",
"url": "https://files.pythonhosted.org/packages/c0/7d/95e0f6ec87a8a9864d659d2fca9606b85757fb7c23a796a1c68dda7f32dd/wsrepl-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "80ece4a5827df6ac61dfd03bfd4686b3b353215d02ed8732eaf26942046d20c4",
"md5": "1e4fd957dff51b6634c80e63808d1f21",
"sha256": "072fc7be7728b92f1da1d9119d350f27e28b97641de1ef309609774835648942"
},
"downloads": -1,
"filename": "wsrepl-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "1e4fd957dff51b6634c80e63808d1f21",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">3.10,<4.0",
"size": 20220,
"upload_time": "2023-07-18T16:42:34",
"upload_time_iso_8601": "2023-07-18T16:42:34.777984Z",
"url": "https://files.pythonhosted.org/packages/80/ec/e4a5827df6ac61dfd03bfd4686b3b353215d02ed8732eaf26942046d20c4/wsrepl-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-18 16:42:34",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "doyensec",
"github_project": "wsrepl",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "importlib-metadata",
"specs": [
[
"==",
"6.8.0"
]
]
},
{
"name": "linkify-it-py",
"specs": [
[
"==",
"2.0.2"
]
]
},
{
"name": "markdown-it-py",
"specs": [
[
"==",
"3.0.0"
]
]
},
{
"name": "markdown-it-py",
"specs": [
[
"==",
"3.0.0"
]
]
},
{
"name": "mdit-py-plugins",
"specs": [
[
"==",
"0.4.0"
]
]
},
{
"name": "mdurl",
"specs": [
[
"==",
"0.1.2"
]
]
},
{
"name": "pygments",
"specs": [
[
"==",
"2.15.1"
]
]
},
{
"name": "pyperclip",
"specs": [
[
"==",
"1.8.2"
]
]
},
{
"name": "rich",
"specs": [
[
"==",
"13.4.2"
]
]
},
{
"name": "textual",
"specs": [
[
"==",
"0.30.0"
]
]
},
{
"name": "typing-extensions",
"specs": [
[
"==",
"4.7.1"
]
]
},
{
"name": "uc-micro-py",
"specs": [
[
"==",
"1.0.2"
]
]
},
{
"name": "websocket-client",
"specs": [
[
"==",
"1.6.1"
]
]
},
{
"name": "zipp",
"specs": [
[
"==",
"3.16.2"
]
]
}
],
"lcname": "wsrepl"
}