문제를 읽어보면 웹사이트에서 flag를 발견할 수 있을 거 같다. 바로 웹사이트로 이동해봤다.
Say hello 버튼을 누르면 위와 같은 팝업이 뜬다. 해결방법이 없어 코드를 확인해보자.
코드를 확인해보면 위와 같이 쉽게 flag를 획득할 수 있다.
이번 문제도 웹사이트에서 flag를 발견할 수 있을 거 같다. 바로 웹사이트로 이동해봤다.
이번문제 flag도 개발자페이지에서 쉽게 발견 할 수 있었다.
이번 문제도 웹사이트에서 flag를 발견할 수 있을 거 같다. 바로 웹사이트로 이동해봤다.
보안 고객 포털이라고 적혀있고 id, pw에 문자와 숫자만 사용할 수 있다고 나와있다.
id : admin pw : admin | guest,guest 해봤는데 위와 같이 로그인 실패가 뜬다.
로그인 페이지 코드로 얻을 수 있는 것은 Login 버튼을 누르면 login.php로 넘어간다는 것을 알았다.
login.php로 이동하고 코드를 확인해봤다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Login Page</title>
</head>
<body>
<script src="secure.js"></script>
<p id='msg'></p>
<form hidden action="admin.php" method="post" id="hiddenAdminForm">
<input type="text" name="hash" required id="adminFormHash">
</form>
<script type="text/javascript">
function filter(string) {
filterPassed = true;
for (let i =0; i < string.length; i++){
cc = string.charCodeAt(i);
if ( (cc >= 48 && cc <= 57) ||
(cc >= 65 && cc <= 90) ||
(cc >= 97 && cc <= 122) )
{
filterPassed = true;
}
else
{
return false;
}
}
return true;
}
window.username = "";
window.password = "";
usernameFilterPassed = filter(window.username);
passwordFilterPassed = filter(window.password);
if ( usernameFilterPassed && passwordFilterPassed ) {
loggedIn = checkPassword(window.username, window.password);
if(loggedIn)
{
document.getElementById('msg').innerHTML = "Log In Successful";
document.getElementById('adminFormHash').value = "2196812e91c29df34f5e217cfd639881";
document.getElementById('hiddenAdminForm').submit();
}
else
{
document.getElementById('msg').innerHTML = "Log In Failed";
}
}
else {
document.getElementById('msg').innerHTML = "Illegal character in username or password."
}
</script>
</body>
</html>
조금 길어서 코드를 첨부해봤다.
이 부분을 보면 문제에 나와있듯이 문자와 숫자만 사용할 수 있게 필터링을 해준다.
그리고 이부분을 보면 필터링을 한 ID, PW가 입력되면 표시해놓은 코드가 실행되는 것 같다.
바로 저 코드를 콘솔에서 실행시켜보자.
콘솔에서 코드를 실행시키니깐 flag가 나왔다.
더 분석하던 중 2번째 풀이방법도 발견했다.
쉽게 secure.js 파일에 들어가보면 id, pw가 나와있다.
그대로 로그인창에 입력해도 flag를 찾을 수 있다.
문제를 보면 /usr/share/nginx/html에 웹사이트 파일이 있고 flag는 /flag.txt에 있다고 한다. 근데 웹사이트가 절대경로를 필터링한다고 한다. 필터링을 피해서 flag를 찾으면 되는 문제다.
사이트에 들어가보면 Web eReader이 나오고 Filename을 입력할 수 있는 칸이 나온다.
위와 같이 filename에 책이름을 넣으면 책 내용이 나온다.
다시 돌아와서 filename에 /flag.txt를 넣어보니 승인되지 않는다고 나온다.
문제에 나와있듯이 지금 웹사이트 파일이 /usr/share/nginx/html에 있다고 하니깐 상대경로를 이용해보자.
상대경로를 이용하니 flag를 찾을 수 있었다.
문제를 읽어보면 웹사이트에서 flag를 발견할 수 있을 거 같다. 바로 웹사이트로 이동해봤다.
웹사이트에 접속해보니 Online Fradebook이 나와있고 Continue as guest 버튼이 있다.
Continue as guest 버튼을 눌러보니 위와 같이 guest service가 없다고 한다.
문제 이름이 Power Cookie 이므로 쿠키를 바로 확인해보자.
역시 isAdmin쿠키가 있고 값이 0으로 들어가있다.
값을 1로 바꾸고 새로고침하니 flag를 찾았다.
PostgreSQL 서버에 연결하고 flag를 찾으면 될 것 같다.
pico ctf에서 제공하는 Webshell을 이용해서 PostgreSQL에 접속했다.
psql 접속한 DB Instance의 Table 목록 조회 명령어인 \dt를 이용해 조회해본다.
조회했더니 name이 flag인 테이블을 찾을 수 있었다.
바로 sql 구문으로 flag 테이블을 조회해보자.
sql 구문으로 테이블 조회하니 flags를 찾을 수 있었다.
이 문제는 SQL을 이용해 로그인하는 문제인 것 같다. 사이트로 이동해보자.
사이트로 이동해보니 역시 로그인 페이지가 나온다.
admin / admin 로그인 시도를 해봤는데 sql 구문이 뜬다.
sql injection을 이용해 우회를 해야될 것 같다.
admin'-- / 123 로그인 시도를 해봤다.
로그인을 성공했다.
개발자 도구에서 flag 를 찾을 수 있다.
내가 로그인을 admin'-- / 123 으로 한 이유는 위에서 나온 sql구문 취약점을 이용한 것이다.
위에서 sql구문이 SELECT * FROM users WHERE name='admin' AND password='admin'이거였다.
내가 처음에 입력한 admin / admin을 입력하면 웹에서는 위와같이 입력받는다.
그래서 sql injection을 이용해서 문제를 풀어야된다. 위와같이 admin'-- / 123을 입력하면
웹에서는SELECT FROM users WHERE name='admin'--' AND password='123' 이렇게 입력된다.
sql에서 --는 주석처리다 따라서 웹에서는 SELECT FROM users WHERE name='admin'--' AND password='123' 즉 id : admin이고 뒤 구문은 주석처리로 인식돼서 admin으로 로그인을 할 수 있었던 것이다.