ch4n3-world의 중복 인증 이슈에 관하여
2020. 2. 28. 21:10
내가 운영하는 워게임에 가끔 중복 인증에 관한 문의가 꾸준히 들어왔었는데 어이없게도 오늘에서야 그 이유를 알게 되어 블로그에 글을 포스팅하게 되었다.
router.post('/auth', async (req, res) => {
let getChallengeByFlag = async (flag) => {
let sqlData = await ChallengeAPI.getChallengeByFlag(flag);
if (sqlData)
return sqlData.dataValues;
return null;
};
let isSolvedChallenge = async (user_no, challenge_no) => {
let sqlData = await SolversAPI.isSolvedChallenge(challenge_no, user_no);
if (sqlData)
return sqlData.dataValues;
return null;
};
let insertAuthLog = async (challenge_no, user_no, user_flag, state) => {
return await LogAPI.insertAuthLog(challenge_no, user_no, user_flag, state);
};
let insertIntoSolvers = async (challenge_no, user_no) => {
return SolversAPI.addSolver(challenge_no, user_no);
};
let main = async () => {
if (!req.session.email)
return res.json({status: 'not signed in'});
let user_flag = req.body.flag;
let user_no = req.session.user_no;
let challenge = await getChallengeByFlag(user_flag);
let result = {};
if (challenge) {
let challenge_no = challenge.no;
result.challenge = challenge;
if (await isSolvedChallenge(user_no, challenge.no)) {
result.status = 'already solved';
await insertAuthLog(challenge_no, user_no, user_flag, "ALREADY SOLVED");
}
else {
result.status = 'solved';
await insertIntoSolvers(challenge_no, user_no);
await insertAuthLog(challenge_no, user_no, user_flag, "CORRECT");
}
}
else {
result.status = 'invalid_flag';
await insertAuthLog(0, user_no, user_flag, "WRONG");
}
return res.json(result);
};
await main();
});
위의 소스코드는 /auth 에서 POST로 flag 인증을 검사하는 코드이다. 다음 코드의 실행 과정을 정리하면 다음과 같다.
1. 사용자가 HTTP POST로 flag 를 보낸다.
2. getChallengeByFlag() 함수를 이용해서 해당 flag에 맞는 문제를 불러온다.
3. 해당 flag를 갖는 문제가 있다면 이미 푼 문제인지 확인하고 Solvers 테이블에 사용자 데이터를 넣는다.
3-1. 문제를 불러오지 못했다면 끝낸다.
4. flag 인증한 내역을 DB에 로깅한다.
중복 인증이 된다는 것은 위의 소스코드에서 isSolvedChallenge() 함수가 예상과는 다르게 동작한다는 것을 의미한다. 그래서 디버깅을 하려고 다음과 같은 코드를 추가해보았다.
console.log("=================================");
console.log(await isSolvedChallenge(user_no, challenge.no));
console.log("=================================");
그랬더니.. ?
이럴리가 없는데? 하면서 SolversAPI.isSolvedChallenge가 정의된 코드를 봤는데..
async isSolvedChallenge(challenge_no, user_no) {
return await API.Solvers.count({where: {user_no: user_no, challenge_no: challenge_no}});
}
let isSolvedChallenge = async (challenge_no, user_no) => {
let sqlData = await SolversAPI.isSolvedChallenge(challenge_no, user_no);
if (sqlData)
return sqlData.dataValues;
return null;
};
아,,, count() 메소드를 사용해서 dataValues를 리턴할 필요가 없었던 것이었다. 하... 그런데 왜 될 때도 있고 안될 때도 있었던 걸까? 자바스크립트 원리 상으로 될리가 없는데? 그건 생각해보기 귀찮아서 나중에 생각해보는 걸로 했다. 앞으로 이런 실수는 하지 말자. ...
끝.
'Hacking > Web.' 카테고리의 다른 글
MySQL에서의 Error Based Injection에 대한 간단한 고찰 (0) | 2020.03.10 |
---|---|
CTF 웹해킹 문제 풀 때 루틴 (0) | 2019.11.16 |
Bypassing with special chars in XSS exploit (0) | 2019.04.19 |
XSS awesome confirm variants (0) | 2019.04.17 |
Airbnb – When Bypassing JSON Encoding, XSS Filter, WAF, CSP, and Auditor turns into Eight Vulnerabilities (0) | 2019.03.28 |