# 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藉由比對是否出現提示字判斷是否登入成功 */ ```