# SQL injection with Nodejs+MongoDB
###### tags: `工具`
### 安裝Nodejs
[https://nodejs.org/en](https://nodejs.org/en/)
### 安裝Mongodb
[下載](https://www.mongodb.com/download-center?filter=enterprise&utm_source=google&utm_campaign=APAC_Taiwan_MongoDB%20to%20Corp/Ent_Brand_Alpha_FM&utm_keyword=mongodb&utm_device=c&utm_network=g&utm_medium=cpc&utm_creative=241800805167&utm_matchtype=e&_bt=241800805167&_bk=mongodb&_bm=e&_bn=g&jmp=search&gclid=Cj0KCQjwn-bWBRDGARIsAPS1svtlSzij5KccBYltmJVU7kzvjM-H8NmcUxZHJQP1i0L9QR3RO9UK1YkaAqk9EALw_wcB#enterprise)
1. 下載Enterprise Server,輸入信箱、姓名等資料,公司名稱隨便填。
安裝在D槽,之後在mongodb資料夾內建立data資料夾,並在data底下建立db資料夾(D:/mongodb/data/db)
2. 開啟CMD
```
D:
cd mongodb\bin
mongod -dbpath D:\mongodb\data\db //指定資料儲存位置並啟動
```
3. 再開啟一個CMD
```
D:
cd mongodb\bin
mongo //開始mongodb操作介面
use blog //創建一個叫做blog的資料庫並切換至該資料庫;已經存在資料庫便直接切換
db.createCollection(“users”) //在資料庫內建立一個users的集合
db.users.insert({"name":"admin","password":"admin"})
//在users內加入物件 name為admin,password為admin
db.users.find() //查詢在users內的物件
```
### HTML、登入系統
**建立專案**
```
mkdir name
cd name
npm init
npm install -g express-generator //安裝Express套件
express -e project_name //建立express專案資料夾,-e表示使用ejs模板
cd projet_name
npm install
npm start //啟動server,預設路徑為localhost:3000
```
開啟專案內的app.js,修改ejs模板引擎成html(原網頁為ejs檔,修改後為html)
修改 app.set('view engine', 'ejs'); 成 app.set('view engine', 'html');
app.engine('.html',require('ejs').__express);
**首頁 index.html(刪除原本的index.ejs)**
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<title>my index</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>Hello ~~</h1>
<p><a href="login">登入</a></p>
</body>
</html>
```
**登入頁面 login.html**
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<title>my login</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<p id="fail_login">Fail to login QQ</p>
<form action="ucenter" method="post">
<p>
<span>name:</span>
<br>
<input id="name" name="name" type="text" pattern="[^$()/><\][\\\x22,;|]+">
</p>
<p>
<span>password:</span>
<br>
<input id="password" name="password" type="password" pattern="[^$()/><\][\\\x22,;|]+">
</p>
<p><input type="submit" value="submit"></p>
</form>
</body>
</html>
```
**登入失敗頁面 fail.html**
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<p>login fail</p>
<p><a href="login">重新登入</a></p>
</body>
</html>
```
**登入成功頁面 ucenter.html**
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<title>Login successfully</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<p>登入成功!!!!</p>
</body>
</html>
```
**修改router/index.js**
```javascript=
var express = require('express');
var router = express.Router();
var user = require('../database/db').user;
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'index' });
});
/* login */
router.get('/login', function(req, res) {
res.render('login', { title: 'login' });
});
/* login fall */
router.get('/fail', function(req, res) {
res.render('fail', { title: 'login falled' });
});
/*
使用find比對資料庫內資料,若是找不到資料doc.length=0則登入失敗;
反之登入成功
*/
router.post('/ucenter', function(req, res) {
var query = {name: req.body.name, password: req.body.password};
(function(){
user.find(query, function(err,doc){
if(doc.length==0){
console.log(query);
console.log(query.name + " : 登入失敗QQ " + new Date());
res.redirect('fail');
}
else{
console.log(query);
console.log(query.name + " : 登入成功~~ " + new Date());
console.log(doc.length);
res.render('ucenter', { title:'ucenter' });
}
});
})(query);
module.exports = router;
```
### 建立module、連結資料庫
在專案內建立 database資料夾,並在底下建立db.js
/database/db.js
```javascript=
var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost/blog');//連結database
var Schema = mongoose.Schema; //建立schema
var userScheMa = new Schema({
name: String,
password: String
}); //
module.exports.user = db.model('users', userScheMa);
```
**安裝mongodb相關package,修改package.json,存檔後執行npm install**
```
{
"name": "project-1",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"ejs": "~2.5.7",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"morgan": "~1.9.0",
"mongoose": "^4.13.12",
"mongoose-auto-increment": "^5.0.1"
}
}
```
**npm start 啟動伺服器,進到localhost:3000檢查網頁**
### 登入測試
在localhost:3000/login進行登入測試;
使用Postman直接對 http://localhost:3000/ucenter 發送post請求,選擇body
```
{
"name":"admin",
"password":"admin"
}
```
### Injection測試
使用 ```{"$gt":""}``` 進行測試,該指令意思為:長度大於""內字串的資料,由於""沒有字串,故長度大於0的字串都符合。
以 ```name:{"$gt":""} , password:{"$gt":""} ``` 進行登入,資料庫會回傳name長度大於0且password長度大於0的資料,這時候doc.length不等於0,會判定可登入。
自行修改登入成功判斷條件預防注入
1. 使用HTML5 pattern 限制使用者輸入的內容(直接對server發送post無法限制)
2. 修改index.js內的登入條件判斷
3. 在index.js檢查輸入字串,檢查後才與資料庫比對
### Brute Force
使用Hydra破解工具進行破解,下載不到Hydra可使用Kali Linux,Kali有內建Hydra及字典檔
**破解步驟**
1. 開啟CMD
2. cd 至 Hydra所在資料夾
3. 輸入指令
```shell=
Hydra -L dict.txt -P password.txt -s 3000 127.0.0.1 http-post-form "/ucenter:name=^USER^&password=^PASS^:login fail"
/*
-L dict.txt : 使用帳號字典檔dict.txt ;-l admin: 直接指定帳號為admin
-P password.txt: 使用密碼字典檔password.txt;-p admin :直接指定密碼admin
-s 3000 :指定port 3000
127.0.0.1 : 要攻擊的IP
http-post-form : 服務的形式為對發送http post
/ucenter:name=^USER^&password=^PASS^ 處理post的API(form action位置)
^USER^為帳號的變數,會自動取得字典檔內的帳號,name為form傳送的帳號參數
^PASS^為密碼的變數,會自動取得字典檔內的密碼,password為form傳送密碼參數
:login fail 登入失敗的頁面會有這些提示字,Hydra藉由比對是否出現提示字判斷是否登入成功
*/
```