findOne 기능에 주의
11060 단어 securityjavascript
이 게시물에서는 NoSQL 주입으로부터 웹 애플리케이션을 보호하는 방법을 알아봅니다.
OWASP Top 10 - 2017에 따르면 지난해 가장 빈번하게 발생한 취약점은 취약한 시스템의 특정 지점에 악성코드를 주입하는 것을 의미하는 A1:2017-Injection으로, 가장 많이 알려진 주입은 URL, 형태를 통한 SQL 주입이다. 피해자의 데이터베이스에 악의적인 쿼리를 보낼 수 있습니다.
요즘에는 사용자를 인증하는 API가 있고 비관계형 데이터베이스를 사용하여 이 정보를 저장하는 시스템을 찾는 것이 일반적입니다. 많이 사용되는 은행은 Mongo 입니다.
아래 예에서는 Mongo와 매우 유사한 구문을 가진 NeDB 은행을 사용했습니다.
제어 장치
exports.login = async (req, reply) => {
try {
let { user, pass } = req.body
let result = await findOne({user, pass})
return reply.code(200).send(result)
} catch (e) {
return reply.code(500).send({ success: false, result: 'user/pass not found' })
}
}
db.findOne
async function findOne(query) {
return new Promise((resolve, reject) => {
db.findOne(query, (err, result) => {
if (err) return reject(err)
resolve({ success: true, result })
})
})
}
우리가 findOne에 전달한 개체가 유효한 개체였기 때문에 로그인이 이루어졌습니다. 즉, user와 pass 모두 데이터베이스에 실제로 존재하는 값을 가집니다.
이 글 초반에 SQL Injection에 대해 언급했는데, NoSQL Injection에 대해 들어보셨나요? 아니다? 자, 이것이 무엇인지 이해하게 될 것입니다. 다음 기능을 참조하십시오.
db.findOne(query, (err, result) => {
if (err) return reject(err)
resolve({ success: true, result })
})
기본적으로 이 함수가 하는 일은 사용자 && 패스에 전달한 값이 있는 레코드가 있는지 데이터베이스를 확인하는 것입니다. 여기서는 논리 연산자 &&(및 )를 사용했습니다.
이것은 우리가 적어도 유효한 사용자를 전달하고 전달 대신 TRUE를 반환하는 다른 유효성 검사를 알리면 함수가 작동한다고 생각하게 만들지 않습니다.
Mongo와 NeDB 모두 데이터베이스의 쿼리에 사용할 수 있는 필터(예: $gt)가 있으며 이는 관계 연산자 ">"와 동일합니다. 암호 대신 이 필터를 사용하여 쿼리를 수행해 보겠습니다.
즉, 우리는 데이터베이스에 "wubba"라는 사용자가 있는 레코드가 있는지, pass 값이 "nothing"보다 큰지 묻는 쿼리를 만들었습니다. 해당 이름을 가진 사용자가 있으면 물론 암호가 더 클 것입니다. "아무것도"보다.
동일한 개체
{"$ gt": ""}
를 user에 전달하고 전달하면 은행은 가지고 있는 첫 번째 레코드를 반환합니다!이것은 우리가 전달하는 값에 대한 처리를 만들지 않으면 findOne 함수가 위험하다는 것을 보여줍니다. 이 경우 정보가 객체가 아닌지 확인할 수 있습니다.
이를 수정하기 위해 다음 기능을 사용할 수 있습니다.
제어 장치
exports.loginProtected = async (req, reply) => {
try {
let { user, pass } = req.body
await isObject({ user, pass })
let result = await findOne({user, pass})
return reply.code(200).send(result)
} catch (e) {
return reply.code(500).send({ success: false, result: 'user/pass not found' })
}
}
객체
async function isObject(params) {
return new Promise((resolve, reject) => {
Object.keys(params).forEach((v, i) => {
if (typeof params[v] === 'object') return reject(false)
})
resolve(true)
})
}
이 사례는 NeDB 은행을 사용하여 재현되었지만 Mongo 및 Sails/Waterline을 사용하여 시뮬레이션되었습니다. 다른 은행에서 찾으면 여기에 댓글을 달아 다른 사람을 돕습니다 😉
Github 프로젝트 https://github.com/nulldreams/nosql-pentest
Reference
이 문제에 관하여(findOne 기능에 주의), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/nulldreams/beware-of-the-findone-function-15g텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)