100점짜리고, 기존 문제들에 비해 다소 난이도가 낮다. 우선 문제를 열고 view-source를 클릭해보면,
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
if(!$_COOKIE['user']){
$val_id="guest";
$val_pw="123qwe";
for($i=0;$i<20;$i++){
$val_id=base64_encode($val_id);
$val_pw=base64_encode($val_pw);
}
$val_id=str_replace("1","!",$val_id);
$val_id=str_replace("2","@",$val_id);
$val_id=str_replace("3","$",$val_id);
$val_id=str_replace("4","^",$val_id);
$val_id=str_replace("5","&",$val_id);
$val_id=str_replace("6","*",$val_id);
$val_id=str_replace("7","(",$val_id);
$val_id=str_replace("8",")",$val_id);
$val_pw=str_replace("1","!",$val_pw);
$val_pw=str_replace("2","@",$val_pw);
$val_pw=str_replace("3","$",$val_pw);
$val_pw=str_replace("4","^",$val_pw);
$val_pw=str_replace("5","&",$val_pw);
$val_pw=str_replace("6","*",$val_pw);
$val_pw=str_replace("7","(",$val_pw);
$val_pw=str_replace("8",")",$val_pw);
Setcookie("user",$val_id,time()+86400,"/challenge/web-06/");
Setcookie("password",$val_pw,time()+86400,"/challenge/web-06/");
echo("<meta http-equiv=refresh content=0>");
exit;
}
?>
<html>
<head>
<title>Challenge 6</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
</style>
</head>
<body>
<?php
$decode_id=$_COOKIE['user'];
$decode_pw=$_COOKIE['password'];
$decode_id=str_replace("!","1",$decode_id);
$decode_id=str_replace("@","2",$decode_id);
$decode_id=str_replace("$","3",$decode_id);
$decode_id=str_replace("^","4",$decode_id);
$decode_id=str_replace("&","5",$decode_id);
$decode_id=str_replace("*","6",$decode_id);
$decode_id=str_replace("(","7",$decode_id);
$decode_id=str_replace(")","8",$decode_id);
$decode_pw=str_replace("!","1",$decode_pw);
$decode_pw=str_replace("@","2",$decode_pw);
$decode_pw=str_replace("$","3",$decode_pw);
$decode_pw=str_replace("^","4",$decode_pw);
$decode_pw=str_replace("&","5",$decode_pw);
$decode_pw=str_replace("*","6",$decode_pw);
$decode_pw=str_replace("(","7",$decode_pw);
$decode_pw=str_replace(")","8",$decode_pw);
for($i=0;$i<20;$i++){
$decode_id=base64_decode($decode_id);
$decode_pw=base64_decode($decode_pw);
}
echo("<hr><a href=./?view_source=1 style=color:yellow;>view-source</a><br><br>");
echo("ID : $decode_id<br>PW : $decode_pw<hr>");
if($decode_id=="admin" && $decode_pw=="nimda"){
solve(6);
}
?>
</body>
</html>
이런 코드가 나온다. 대강 해석해보면 user 쿠키값이 없으면 id의 guest값과 pw의 123qwe값을 20번 Base64 인코딩 한 뒤에 각각 특별한 치환작업을 해주고, 이 값을 각각 user, password 쿠키에 저장한다. 실제로 쿠키를 확인해보면 엄청나게 긴 문자열이 저장되어 있을 것이다. 그리고 이 쿠키값을 읽어들여서 다시 아까의 방식으로 디코딩 해준 뒤 이 문자들을 메인화면에 띄워준다. 그러니까 이 소스에 나온 guest, 123qwe 값은 인코딩 - 디코딩을 거쳐 다시 guest, 123qwe로 메인화면에 나오게 된 것. 그리고 아래 소스를 더 보면, 디코딩된 id 가 admin이고 pw가 nimda일 경우 문제를 해결했음을 뜻하는 함수를 호출한다. 즉 이 인코딩 방식 그대로 구현해준 뒤에 admin과 nimda 문자열을 인코딩 시켜준 후 그 값을 쿠키값에 저장해주면된다.
참고로 여기서 쓰인 인코딩 방식은 BASE64 방식이다.
BASE64방식은 인코딩 과정에서 '남은 문자열을 패딩처리'하는, 즉 부족한 bit 수를 패딩처리했다는 뜻으로 = 인코딩 값 마지막에 주로 붙어있곤 하죠. 인코딩 값 뒤에 = 가 붙어있으면 그냥 BASE64방식이라고 바로 의심해 볼 수 있습니다. 그렇다고 = 가 항상 붙는 것은 아니고, BASE64는 인코딩 과정에서 문자열을 나누고 치환하는데, 이 과정에서 부족한 bit 수를 0으로 채워 패딩처리했다는 의미로 =를 추가합니다.(=는 경우에 따라 0개~2개까지 추가됩니다.)
여튼 BASE64의 방식에 대해서 알고 있지 않아도 풀 수 있기 때문에 이정도로 넘어갑니다.. 대충 이렇다는 뜻..!
저는 문제의 암호화 방식을 java로 코드를 짰습니다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Base64;
public class base64 {
public static void main(String args[])
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// Base64 인코더 객체 생성
Base64.Encoder encoder = Base64.getEncoder();
byte[] id_encode_result, pw_encode_result;
try {
id_encode_result = br.readLine().getBytes();
pw_encode_result = br.readLine().getBytes();
for(int i = 0; i < 20; i++)
{
id_encode_result = encoder.encode(id_encode_result);
pw_encode_result = encoder.encode(pw_encode_result);
}
String id = new String(id_encode_result);
String pw = new String(pw_encode_result);
id = id.replace("1","!")
.replace("2", "@")
.replace("3","$")
.replace("4","^")
.replace("5","&")
.replace("6","*")
.replace("7","(")
.replace("8",")");
pw = pw.replace("1","!")
.replace("2", "@")
.replace("3","$")
.replace("4","^")
.replace("5","&")
.replace("6","*")
.replace("7","(")
.replace("8",")");
bw.write("id : "+id+"\n");
bw.write("pw : "+pw+"\n");
bw.flush(); br.close(); bw.close();
}catch (Exception e){
}
}
}
요렇게 하고 admin, nimda 를 입력해주면 어마어마하게 긴 문자가 출력이 됩니다. 이걸 복사해서 쿠키값 user, password에 각각 넣어주면 끄읏.
고생하셨습니다