서비스에서 XSS가 터졌다. 왜 터졌나... 고민을 좀 해보다가 F12로 살펴보다 뭔가 수상해보이는 해당 속성을 발견했다.
innerhtml? 이게 뭐지?
innerHTML은 요소(element) 내에 포함 된 HTML 또는 XML 마크업을 가져오거나 설정합니다.
말 그대로 HTML 내에서 속성이나 태그 등을 사용할 수 있도록 도와주는 속성이다. 예를 들면, <img src="주소"/> 해당 입력값을 입력하면 innerhtml이 입력값을 속성이나 태그로 입력 받고 실행을 시켜준다는 것이다. 그럼 여기서 위험한 점은 무엇이냐...
A 홈페이지를 운영하는 앨릭스가 있다. 외부에서 개발자에게 외주를 넣어 최근에 홈페이지를 구축을 완료했다. 그런데 외주 개발자가 해당 페이지를 innerhtml 속성으로 코딩을 해주었다. 그리고 여기서 앨릭스의 홈페이지를 이용하기 위해 들어온 해커 B가 있다. 심심해서 F12로 홈페이지 코드를 구경하다가, innerhtml을 발견했다. 군침이 싹 도는 해커 B는 당장 Q&A 게시판에 가서 아래 구문을 작성하기 시작한다.
그럼 어떤 일이 일어날까? 해당 사이트는 innerhtml 속성으로 태그나 속성들이 전부 정상 작동이 가능한 상태이니 해당 구문도 실행이 가능할 것이다. 그럼 여기서 구문을 좀더 바꿔본다면 여러가지 공격이 더 가능할 것이다.
과정을 좀 더 살펴보자면 이렇다
1. 해커의 공격 구문 입력 및 전달(요청) 2. 요청에 대한 서버의 응답 3. 클라이언트 JS에서 innerHTML 사용 (브라우저가 HTML 재파싱을 수행하면서 문자열 <를 <로 해석) 4. DOM 노드 생성 및 이벤트 핸들러 활성화 6. XSS 실행
그럼 앨릭스는 어떻게 해야할까? 가만히 앉아서 해킹 당한 상태로 알거지가 되어야할까?
아니다... 제대로 먹고 살고 싶으면 당장 일어나 개발자에게 찾아가 innerhtml은 xss에 취약한 속성이니 textContent를 사용해서 코드를 다시 짜달라고 이야기해야한다.
그럼 여기서 textcontent란?
요소(element)와 그 자손에 있는 텍스트 콘텐츠를 가져오거나 설정하며, HTML 태그나 속성은 해석하지 않는다.
한마디로 사용자 입력값으로 속성이나 태그가 들어오면 묻고 따지지도 않고 해석하는 innerhtml이랑 달리 해당 속성은 태그가 들어오든 이벤트 핸들러가 들어오든 text로만 해석한다는 뜻이다. 당연히 해커 B가 뭔짓을 해서 구문을 작성해도 실행 될 리가 전혀 없다는 뜻이다. 그러니 보안성도 좋다.
글을 좀 간단히 쓴 면이 있긴 한데 읽으면서 궁금한 점이 있었다면 더 공부해보는 게 좋다.
뉴비 컨설턴트... 입사한지 1달만에 기초도 없고 아무것도 모른다고 탈탈 털렸다... 잘하고 싶었는데 탈탈 털려서 슬펐다... 그래서 실력 증진을 위해 드림핵으로 다시 공부해보려고 한다 혼났다고 울기만 하면 아무것도 될 수 없다... 슬프지만 이게 현실이니까
오늘 풀어볼 문제는 비기너 레벨의 cookie 문제다.
쿠키로 인증 상태를 관리하는 로그인 서비스란다... 사실 여기서부터 취약한 웹 사이트임을 알 수 있는 문제다. 시중의 서비스를 보면 알겠지만 보통 웹 사이트들은 로그인 등의 인증에 쿠키 하나만을 쓰지 않는다. 궁금하면 네*버나 다*이나 카*오 등의 홈페이지에 들어가서 패킷을 인터셉트 후 입력값을 보면 된다. (물론 공격은 하면 안 된다)
네*버의 메인 홈페이지에서 새로고침 후 잡은 패킷 중 하나
쿠키란에 뭔가 많은 걸 볼 수 있다. (보안 컨설턴트로 취업 준비 중이라면 이런 값들을 많이 봐두길 바란다... 이게 뭘 나타내는지... 아니면 현장 나가서 이게 뭐지?하다가 혼남)
아무튼 admin 계정으로 로그인에 성공하면 플래그를 획득할 수 있다고? 주어진 파일을 다운로드 받고 주어진 사이트에 접속을 해보자
사실 난 코드 까막눈이라 잘 모른다. 물론 이걸 다 읽을 수 있다면 문제 푸는데 너무 너무 좋긴 하겠지...
특별히 눈에 띄는 부분은
users = {
'guest': 'guest',
'admin': FLAG
해당 부분이다. 유추하건데 로그인 정보로 보인다. guest 계정은 ID/PW가 guest/guest 고 admin은 비밀번호를 알려주지 않는다... 일단 대입해보자
코드에 나온 정보로 주어진 사이트에 로그인하면 아래와 같이 뜬다.
관리자는 아니지만 안녕은 한댄다... 나머지 메뉴에 뭔가 더 있을 것 같아 확인을 해보지만 별 다른 기능은 보이질 않는다!
그럼 여기서 어떻게 해야할까? 고민을 좀 해보다, 로그인 패킷을 잡아보기로 한다.
버프슈트를 키고 로그인 패킷을 잡아본다.
값을 보아하니 ID와 PW가 평문으로 날아가고(이것도 취약점이긴하다) Cookie는 username=guest로 나와있음을 알 수 있다. 쿠키 외엔 다른 로그인 인증 방식을 사용하지 않는 듯 싶다~
그럼 여기서 변조 포인트는 어디일까? 고민을 해보다가 쿠키 문제니까 쿠키를 변조해보도록한다. 아까 admin이 아니라고 까였으니 admin을 넣어보자~
이렇게 값을 날리면
플래그 값이 나왔다
사실 해당 문제는 n년 전에 풀었던 문제인데 초심을 다 잡기 위해 다시금 풀어봤다... 그리고 이런 문제를 풀 때는 답을 찾는 게 장땡이가 아니라 어떤 포인트를 변조해야하고, 어떤 부분이 취약한지 계속 찾아가면서 풀어야하는 것 같다... 실무에서 도움이 되는 경우가 있다!
<html>은 문서의 루트 요소를 정의할 때 사용한다. 브라우저에게 작성된 문서가 HTML 문서임을 알려준다.
예시)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>간결한 학습 페이지</title>
</head>
<body>
<h1>안녕하세요!</h1>
<p>이것은 HTML 문서의 가장 기본적인 뼈대입니다.</p>
</body>
</html>
<head>는 문서의 문자 인코딩, 타이틀, 설명, 스타일 시트, 스크립트 등 문서 정보에 관련된 다양한 요소들을 모아둔 태그다. 화면에 표시되지는 않지만, 브라우저, 검색 엔진 및 다른 웹 기술 등 기계적인 처리를 위한 정보들이다.
예시)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>가장 간결한 HTML</title>
</head>
<body>
이것이 실제 웹 페이지 콘텐츠입니다.
</body>
</html>
<body>는 HTML 문서의 텍스트, 하이퍼링크, 이미지와 같은 모든 컨텐츠를 포함하는 영역을 정의할 때 사용한다.
<h1>는 HTML에 제목을 정의할 때 사용한다. <h1>부터<h6>까지 글자수가 점점 작아진다.
예시)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>H1 태그 사용 예시</title>
</head>
<body>
<h1>이것은 페이지의 메인 제목입니다. (가장 크게 표시됨)</h1>
<p>웹 페이지의 모든 콘텐츠는 이 메인 제목 아래에서 시작됩니다.</p>
</body>
</html>
<title>는 해당 문서의 제목을 정의할 때 사용한다. 주로 브라우저의 제목 표시줄이나 페이지 탭의 제목으로 사용된다.
예시)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>HTML 학습 - Title 태그의 역할</title>
</head>
<body>
<h1>이 내용은 화면에 보이지만, 위의 Title은 탭에만 보입니다.</h1>
<p>Title 태그는 페이지의 주제를 명확하게 알려주는 중요한 메타데이터입니다.</p>
</body>
</html>
<p>는 문단을 정의할때 사용한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>P 태그 사용 예시</title>
</head>
<body>
<h1>문서의 주요 제목</h1>
<p>이것은 첫 번째 단락입니다. 단락은 브라우저에 표시되는 주된 텍스트 블록입니다. HTML은 콘텐츠의 구조를 정의합니다.</p>
<p>두 번째 단락은 첫 번째 단락과 자동으로 구분됩니다. 브라우저는 단락 위아래에 약간의 공백(margin)을 추가하여 가독성을 높입니다.</p>
<hr>
<p>이처럼 `<p>` 태그는 텍스트를 논리적인 단위로 나누는 데 필수적입니다.</p>
</body>
</html>