By choirish | July 6, 2018
(난) 알고싶지만 (너)에겐 쓸데없는 Web
잡동사니 CH.01
안녕하세요, choirish
입니다 :)
어떤 걸 해볼까 고민하던 중.. 나도 이제 Web
을 할 때가 되지 않았나… 하는 생각이 들어서
웹해킹의 시작,webhacking.kr
문제를 하나씩 풀어보기로 했습니다.
하지만 webhacking.kr
문제를 풀고 쓰는 일반적인 롸업은 아니라고 미리 말씀드리고 싶어요!
저만의 특기를 살려서…(?!)
문제를 풀면서 생기는 소소한 궁금증에 대해 이것저것 질척대며 탐구해볼까 합니다.
밑밥을 깔아보자… (훗)
사실 고백하자면 저는 웹알못입니다 ㅎㅎ;;
이번 시리즈 제목을 자세히 살펴보면…. 알쓸웹잡(!)
알
(난) 알고싶지만
쓸
(너에겐) 쓸데없는
Web
웹 & 웹해킹
잡
잡동사니
지극히 개인적인 궁금증 해소기라.. 제목 그대로 잡동사니 모음일 예정입니다(!)
But, 누군가 궁금했지만 그냥 넘어갔을 “엇 이건 뭐하는 녀석이지? 왜 필요하지? 이건 또 왜 안돼?” 등의 질문에 대해 소소한 답변을 줄 수 있는 잡동사니 모음이 되길 바랍니다.
저는 웹 개발도 안해봤고, html도 javascript도 (거의) 모릅니다…
그래서 알쓸웹잡 시리즈의 초반에는 웹의 가장 기본적인 내용이나 웹 언어의 문법에 대한 궁금증이 폭발할 수 있음을… 미리 알려드립니다. ㅎㅎ
하지만 기본을 쌓아가면서, 웹해킹에 대한 지식 탐구도 게을리하지 않겠다 다짐해봅니다 (후우)
오늘의 탐구 Challenge
- 회원 가입
- Challenge 10
- Challenge 54
회원 가입
webhacking.kr
에 처음 접속하였더니… 회원가입 기능이 없어서 매우 당황스럽다…
알고보니 회원가입부터 웹해킹.kr 입문의 시작이다…
오 나도 이렇게 뭔가 숨겨놓는 거 좋아하는데 내 스타일이다 ㅋㅋㅋ
<F12>
를 눌러 개발자 도구를 열어 Sources
를 확인해보니 중간즈음에 초록색으로 주석처리 되어있는 부분이 보인다.
주석처리 된 부분을 클라이언트 측에서 없애주려면, 개발자도구의 Elements
기능을 이용하여 편집할 수 있다.
왠지 Login 버튼 위의 빈 공간에 Register 버튼이 있을 것만 같으니… 개발자도구의 항목 선택 기능을 이용하여 해당 부분을 클릭하면, 해당 부분의 소스 영역을 알려주고.. 접힌 화살표를 열면 주석처리된 소스가 거기에 뙇 있다.
<input> 태그 내용만 남기고, 주석처리된 부분을 지워주면? 똰 Register 버튼이 생긴다 >. <
이렇게 찾아낸 Register 버튼으로 회원가입을 하면 성공(!)
자… 여기서 웹알못은 궁금하다…
뭔가 해킹을 하는 입장에서 너무나 유용할 거 같은 이 개발자 도구… 누가 만들어줬을까? 왜 만들어졌을까?
<F12> 개발자 도구는 무엇?
사실 그 해답은 조금만 생각해봐도 간단하게 알 수 있다.
이름부터 개발자 도구(!)
웹 개발자들이 웹페이지를 만들 때 디버깅을 하거나 기능 등을 테스트 할 때 유용하게 쓸 수 있도록 만들어 진 것이다.
이 개발자 도구의 시초는 넷스케이프 브라우저라고 한다…..(!)
원래는 “모질라”라는 이름으로 발매하려고 했다는 것으로 보아도… 파이어폭스의 전신 정도라고 생각할 수도 있을 것 같다!
위험한 블로그
의 포스팅에 따르면, 넷스케이프 브라우저가 처음으로 자바스크립트 디버거 기능을 갖추었고… 뒤이어 모질라는 파이어폭스 브라우저에 개발자를 위한 여러 가지 기능을 탑재함으로써, 파이어폭스가 웹 개발자를 위한 브라우저(혹은 해커를 위한 브라우저)라는 얘기를 들을 수 있도록 만들었다.
그렇게 시작은 파이어폭스였으나, 이러한 개발자 도구가 웹 개발자들에게 꼭 필요한 기능임을 인식하면서 다른 브라우저들도 개발자 도구 기능을 갖추게 되었고…
웹 개발자들 뿐만아니라 해커들에게도… 유용한 도구가 되었다(!)
나는 크롬 브라우저를 애용하는 사람으로써…
크롬 개발자 도구 사용법을 간단히 알수 있는 참고 링크를 투척한다(!)
webhacking.kr 회원가입 시에는 Elements
, Sources
패널만 이용했지만…
웹과 웹해킹에 대해 더 많이 알게 될수록 개발자 도구의 다양한 기능을 활용하게 되겠지!
그리고.. 개발자 도구의 꽃은 Console 이지 않을까, 개인적인 의견을 보태본다 :)
어떻게 내가 소스코드를 고친 대로 화면에 나타날 수 있지?
사실 나는… 개발자 도구로 고친 소스코드가 실제로 브라우저에 반영되어 보이는 것도 신기했는데…
(python 코드 테스트할 때, 내가 임의로 작성한 코드의 결과를 실시간으로 출력해 보는 것과 같은 것이었다!)
내가 직접 소스코드를 고쳐서 되살린 Register 버튼이 실제 회원가입 기능으로 동작하는 게 더 신기했던 것 같다.
근데 사실 그건 백엔드 코드에서 Regitser 버튼을 눌렀을 때의 동작을 정의해두었기 때문에,
내가 변경한 클라이언트 측의 코드가 실제 기능으로 실행될 수 있었던 것이다.
여기서 내가 생각한 point
는 두 가지이다.
백엔드 관리자만을 위해 구현해놓은 숨겨진 기능이 있다면?
- 사용자가 어떤 방법으로든 숨겨진(hidden) 기능을 찾아낸다면 이를 악용할 수 있다.
백엔드(서버 사이드 스크립트)와 프론트엔드(클라이언트 사이드 스크립트) 동작의 차이를 이해하자.
프론트엔드는 사용자의 화면에 나타나는 웹 화면을 말한다.
사용자에게 보이는 화면은, 웹 브라우저가 프론트엔드 코드(html, javascript, …)를 해석하여 화면에 그려준 것이다. 즉 개발자 도구로 프로트엔드의 코드를 고치면 웹 브라우저는 그것을 해석하여 화면에 나타내 줄 뿐이니 내가 고친 대로 화면에 표시되는 것이다.
하지만 백엔드는 DB(데이터베이스)의 데이터 등 중요한 데이터를 다루는 영역으로, 서버 측에 저장된 코드로 구현되기 때문에 사용자가 임의로 조작하기가 쉽지 않다.
이 때, 서버 측의 데이터나 코드를 조작하기 위한 여러가지 노력을 해커들이 시도하고 있는 것이다(!)
결국 웹 브라우저는 프론트엔드 코드를 해석하여 화면에 표현해 주는 것이므로, 내가 고친 코드가 화면에 그대로 반영되어 나타나는구나~ 하고 이해했다 :)
Challenge 10
해당 페이지의 소스코드는 다음과 같다.
<html>
<head>
<title>Challenge 10</title>
</head>
<body>
<hr style=height:100;background:brown;>
<table border=0 width=900 style=background:gray>
<tr><td>
<a id=hackme style="position:relative;left:0;top:0" onclick="this.style.posLeft+=1;if(this.style.posLeft==800)this.href='?go='+this.style.posLeft" onmouseover=this.innerHTML='yOu' onmouseout=this.innerHTML='O'>O</a><br>
<font style="position:relative;left:800;top:0" color=gold>|<br>|<br>|<br>|<br>buy lotto</font>
</td></tr>
</table>
<hr style=height:100;background:brown;>
</body>
</html>
여기에서 핵심 부분은 <a>
태그 안의 내용이다.
<a id=hackme style="position:relative;left:0;top:0" onclick="this.style.posLeft+=1;if(this.style.posLeft==800)this.href='?go='+this.style.posLeft" onmouseover=this.innerHTML='yOu' onmouseout=this.innerHTML='O'>O</a><br>
<a>
tag는 다른 페이지로 연결되는 하이퍼링크를 정의한다.
그런데 여기서는 if문의 특정 조건을 만족했을 때에만 href
속성이 정의되어있고, 해당 링크로 연결될 수 있다.
그 조건이 무엇인고 하니… style.posLeft
값이 800이 되어야 한다.
onclick
속성의 정의를 보면, “O(yOu)“를 한 번 클릭할 때마다 그 위치가 오른쪽으로 한 칸씩 이동한다.
800번 모두 클릭하여.. 할 수도 있겠지만!
우리에겐 개발자 도구가 있으니 posLeft의 값을 직접 조작해보자!
근데…. 아무리 조작해봐도 안됨…
- onclick=“this.style.posLeft+=799;” 로 조작해도 X
- if(this.style.posLeft==0) 으로 조작해도 X
- style=“position:relative;left:800;top:0” 으로 조작하면 위치는 바뀌는데 링크는 안생김!
why….? Chrome 이라서… ㅡㅡ?
테스트해봤더니 엣지에서도 posLeft 안됨…. ㅜㅜ
posLeft 값(property)은 크롬에서 해석하지 않는다고 한다.. 왜??
여기서 쓸데없는 궁금증 발생! ㅋㅋㅋㅋ 뒤져보았다(!)
posLeft, Chrome에서 왜 안됨?
구글에 “style.posLeft chrome”으로 검색했더니 우선 이러한 내용이 있었다.
posOOO 값은 IE의 style 오브젝트와 runtimeStyle 오브젝트에서만 사용 가능하다고 한다…!
뭔가 IE에서만 사용하는 property 인건가.. 싶다!
알고보니 Dynamic HTML: The Definitive Reference 책에 똑같은 내용이 있더라 ^^
책에 쓰여져있으니 이제 좀 믿을만해진다 ㅎㅎ
Javascript Reference - javascript STYLE posBottom, posLeft, posRight, posTop
[Book] Dynamic HTML: The Definitive Reference
더 뒤져보다보니… Microsoft Windows Dev Center 에서 posLeft와 style, runtimeStyle 오브젝트에 대해 정의해두었다.
- msdn - posLeft property : https://msdn.microsoft.com/en-us/ie/ms531143(v=vs.94)
- msdn - style object : https://msdn.microsoft.com/en-us/ie/ms535870(v=vs.94)
msdn - runtimeStyle object : https://msdn.microsoft.com/en-us/ie/ms535889(v=vs.94)
- 이게… URL에
( )
괄호가 포함된 건 하이퍼링크가 잘 안된다…
끝에)
까지 정확히 입력하면 해당 페이지로 갈 수 있음(!)
각 오브젝트의 properties 목록에 posLeft가 뙇 있는 것을 눈으로 확인하니 안심할 수 있다 ㅎㅎ
뭔가 Chrome에서 동작하지 않는 녀석이라 미심쩍었는데 소속을 정확히 밝혀낸 느낌이랄까!
무튼… 이렇게 posLeft는 원래 IE에서만 되는 거구나~ 납득할 수 있게 되었다.
브라우저마다 javascript를 해석하는 엔진이 다 달라서…
어느정도 표준이 있긴 하지만, 브라우저 별로 쓸 수 있고, 쓸 수 없는 property…같은 것들이 있다고 한다!
거 참 어렵구만!
이래서 개발자들이……. 브라우저끼리 서로 다른 거 맞춰주느라 핵고생한다고….. (주륵)
개발자들의 고충을 조금이나마 이해할 수 있는 시간이었다…
www.yaldex.com - JavaScript Object Reference
TechNet - left property : https://technet.microsoft.com/en-us/ms530778(v=vs.71)
TechNet - posLeft property : https://technet.microsoft.com/en-us/ms531143(v=vs.71)
IE Test
그럼 IE에서는 잘 되는지 보자…
우선 posLeft가 잘 동작하는지 콘솔창에서 테스트 해보았다.
그래.. 이렇다..!
posLeft가 잘 동작하는 IE에서 그 값을 프린트해보았더니
posLeft는 단위(px)를 제외한 그 값 자체를 출력하고, left는 단위(px)를 포함한 “0px”을 출력한다…
IE에서 <a> 태그의 내용을 아래와 같이 수정하면 O의 위치가 800으로 바뀌고,
“O”를 클릭했을 때 오른쪽으로 움직이지는 않고, if 조건문을 만족하여 href에 정의된 링크로 이동하여 문제를 클리어할 수 있다!
<a id=hackme style="position:relative;left:800;top:0" onclick="this.style.posLeft+=0;if(this.style.posLeft==800)this.href='?go='+this.style.posLeft" onmouseover=this.innerHTML='yOu' onmouseout=this.innerHTML='O'>O</a><br>
여기서 포기할 수 없다. Chrome에서도 되게 해보자…
이것 저것 건드려보고 싶어서 여러 가지 방법으로 시도해보았다 :)
Chrome Test 1
Chrome에서는 style.left를 사용할 수 있는데 이건 단위(px)까지 붙어서 출력되므로…
“O”를 클릭했을 때 한 칸씩 오른쪽으로 이동하는 것을 가능하게 하기위해
parseInt
를 써서 1px씩 덧셈을 하도록 했다… 다른 방법도 알려주신다면 환영한다(!)
그리고 if 조건문에서도 this.style.left의 값을 800이 아닌 ‘800px’로 비교해야만 올바르게 통과할 수 있다.
<a id=hackme style="position:relative;left:0;top:0" onclick="this.style.left = parseInt(this.style.left) + 1 + 'px';if(this.style.left=='800px')this.href='?go='+this.style.left" onmouseover=this.innerHTML='yOu' onmouseout=this.innerHTML='O'>O</a><br>
Chrome Test 2
IE에서처럼 초기 left 값을 800으로 바꾸고, if 조건문에서 ‘800px’로 비교하면 된다.
그런데 사실 [Test 1]에서는 클릭할 때마다 “O”가 오른쪽으로 이동할 수 있도록 코드를 고친 것이고… 800번 클릭해도 링크로 잘 연결이 되지 않는다.
그 이유는 href 속성을 정의할때 go 인자의 값이 800px로 들어가기 때문!
우리는 if 조건문이 성립되었을 때 this.style.posLeft
의 값이 800인 것을 이미 알고 있다.
그러므로, 본래 제작자가 posLeft를 썼을 때는 go의 인자값이 800이 되길 바랐을 것이다.
그럼 우리는 href 속성에서 go의 인자값을 800으로 그냥 넣어줄 수 있다.
<a id=hackme style="position:relative;left:800;top:0" onclick="this.style.posLeft+=1;if(this.style.left=='800px')this.href='?go='+800" onmouseover=this.innerHTML='yOu' onmouseout=this.innerHTML='O'>O</a><br>
위와 같이 수정 후 href 링크를 클릭하면 다음 주소로 이동한다.
→ http://webhacking.kr/challenge/codeing/code1.html?go=800
Chrome Test 3
left의 초기값을 수정하지 않고 if 조건문에서 ‘0px’과 비교하도록 바꾼 후,
[Test 2]와 같이 href 속성의 go 인자값을 숫자 그대로 넣어주면 된다.
<a id=hackme style="position:relative;left:0;top:0" onclick="this.style.posLeft+=1;if(this.style.left='0px')this.href='?go='+800" onmouseover=this.innerHTML='yOu' onmouseout=this.innerHTML='O'>O</a><br>
Challenge 54
해당 페이지의 소스코드는 다음과 같다.
<html>
<head>
<title>Challenge 54</title>
</head>
<body>
<h1><b>Password is <font id=aview></font></b></h1>
<script>
function run(){
if(window.ActiveXObject){
try {
return new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
return new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
return null;
}
}
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}else{
return null;
}
}
x=run();
function answer(i)
{
x.open('GET','?m='+i,false);
x.send(null);
aview.innerHTML=x.responseText;
i++;
if(x.responseText) setTimeout("answer("+i+")",100);
if(x.responseText=="") aview.innerHTML="?";
}
setTimeout("answer(0)",10000);
</script>
</body>
</html>
우선 run 함수는 XMLHttpRequest
오브젝트를 생성합니다.
XMLHttpRequest는 javascript 객체(object)로, HTTP를 통해 쉽게 데이터를 받을 수 있도록 해줍니다.
흘러흘러 보다보니 AJAX
에 이르렀다…. ㅎㅎ
AJAX란 비동기 JavaScript와 XML을 말하는 것으로, 서버 측 스크립트와 통신하기 위한 XMLHttpRequest 객체를 사용하는 것 일컫는 말이다.
결국 XMLHttpRequest의 연장선인가보다(!)
그리고 run 함수의 복잡한 if/else 문은, 모든 브라우저에서 사용할 수 있도록 하기 위한 장치라고 한다.
MDN web docs - AJjAX 시작하기
AJAX Introduction
AJAX - The XMLHttpRequest Object
AJAX - The XMLHttpRequest Object
페이지에서, answer 함수에서 사용된 XMLHttpRequest
의 Methods에 대해 잘 설명되어 있다.
소스 코드의 핵심 부분은 answer
함수이다.
<script>
x=run();
function answer(i)
{
x.open('GET','?m='+i,false);
x.send(null);
aview.innerHTML=x.responseText;
i++;
if(x.responseText) setTimeout("answer("+i+")",100);
if(x.responseText=="") aview.innerHTML="?";
}
setTimeout("answer(0)",10000);
</script>
i를 하나씩 늘려가며 GET 방식으로 m 인자값을 전송하고 그 응답을 받아온다.
그리고 응답이 ““이 아닐 때는 재귀적으로 setTimeout()을 이용하여 answer 함수를 실행한다.
setTimeout
method는, 특정 코드나 함수를 의도적으로 일정 시간 지연한 후에 실행할 때 사용된다. 신기하구만(!)
처음엔 이런 걸 왜 굳이 따로 만들었지? 싶었는데..
실제 웹페이지를 만들다보면 이런 기능도 당연히 쓸 일이 있을 거 같고…ㅋㅋ
자주 쓰이니까 이렇게 method로 만들어 두었겠지(!) ㅎㅎ
w3schools.com - Window setTimeout() Method
MDN web docs - WindowTimers.setTimeout()
결국 값을 하나씩 하나씩 화면에 표시해주는 건데…
이 값을 모아야만 할 것 같다!
이번엔 개발자도구의 Console 창을 이용해서 나만의 answer 함수를 만들고 결과값을 모아서 출력해보자.
Test 1
우선 하나씩 오는 응답 text를 눈으로 확인해보자. (아직 결과 모으기는 안함)
setTimeout의 두번째 인자값을 10000ms가 아닌 100ms로 줄여서 신속하게 진행해보았다 ㅎ
function answer(i)
{
x.open('GET','?m='+i,false);
x.send(null);
console.log(x.responseText);
i++;
if(x.responseText) setTimeout("answer("+i+")",100);
}
위와 같이 나만의 answer 함수를 개발자도구의 Console 창에 정의하고
answer(0) 하고 호출해주면 뜌뜌뜐 응답값이 하나씩 Console에 출력된다 :)
Test 2
하나씩 모으니 합치기가 귀찮다 ㅎㅎ
stirng 변수를 만들고 응답값을 모두 덧붙이기 해주자!
function answer(i)
{
x.open('GET','?m='+i,false);
x.send(null);
console.log(x.responseText);
i++;
string += x.responseText;
if(x.responseText) setTimeout("answer("+i+")",100);
}
string = ''
answer(0)
string
string을 빈 문자열로 둔 다음, answer 함수를 호출하고…
모두 끝났다 싶으면 string을 출력해보면 된다 :)
해보고 나니 간단!!
- 후기
- 스크립트에 정의된 함수를 살짝만 바꿔서 활용할 수 있는 게 신기했다.
- XMLHttpRequest 오브젝트를 예전에도 한번 써 본 적이 있었는데… 활용 방법이 무궁무진한 거 같다!
앞으로 다양하게 사용해봐야겠다.
- 스크립트에 정의된 함수를 살짝만 바꿔서 활용할 수 있는 게 신기했다.
웹 해킹을 처음 시작하는 거라… (웹도 처음)
개발자 도구에서 이것저것 만져보고 노는 것만으로 끝난 느낌인데…(?)
원래 해킹이라는 게 특정 대상을 의도하지 않은 방향으로 조작하는 거라고 생각하는데,
어떻게 조작해야 할지 방법을 찾아내려면…!
그 대상이 어떻게 동작하는지를 잘 알고있으면 큰 도움이 된다고 했다!
개발을 잘 하는 사람이 해킹도 잘 할 수 있다는 말이 있지 않은가(!)
아직 뭔가 아직 웹해킹을 하는 게 아닌 것 같다고 생각되더라도
차근차근 하나씩 생각해보며 알아봐야지! (#셀프토닥 #합리화 ㅋㅋㅋ)
그럼 다음 편에서 만나요! 안녕!!