1) 파라미터 변조 취약점이란 무엇인가?
Parameter Tampering Vulnerability
사용자 입력값인 파라미터를 통해서 액션이 이루어지는 기능에 대해서 악의적인 사용자가 파라미터를 변조하여 악의적인 행위를 하는 공격
정상 요청 hxxp://www.test.co.kr/mypage.jsp?id=hacker
공격 요청 hxxp://www.test.co.kr/mypage.jsp?id=admin
별도의 공격 페이로드가 없음.
idx=100 을 idx=101 로 변경했더니 101번 게시글(비밀글)이 확인된다.
→ 파라미터 변조에 의한 공격
2) 공격 원리 분석
정상 동작 예시
1) 사용자는 id가 guest 인 mypage.jsp 를 요청
2) 어플리케이션에서 DB로 id가 guest 인 정보를 요청
3) DB에서 id가 guest 인 정보를 어플리케이션으로 반환
4) 사용자에게 해당 정보 출력
공격 동작 예시
1) 공격자는 자신의 id 파라미터를 admin으로 변조하여 mypage.jsp 를 요청 ( id 파라미터에 사전 대입을 사용하여 무작위 공격 시도)
2) 어플리케이션에서 DB로 id가 admin 인 정보를 요청
3) DB에서 id가 admin 인 정보를 어플리케이션으로 반환
4) 공격자에게 admin 정보 출력
페이로드만 봐서는 실제 공격 여부를 판단하기 어렵지만, 어플리케이션에서는 세션을 통해 공격 여부를 판단할 수 있다.
세션을 통해서 요청하는 사용자가 hacker 인지 admin 인지 알 수 있다.
세션을 통해서 요청이 이루어지는 경우 사용자 입력값이 필요하지 않다.
파라미터를 통해서 동작이 이루어지므로 취약하다. (파라미터 변조가 가능하므로)
취약 원인
1. 입력값 검증 부재
2. 취약한 설계
실습9-1 파라미터 변조 취약점 공격을 통한 타 사용자 게시글 무단 수정, 삭제 실습
실습을 위해서는 소스코드 수정이 필요하다.
action.php 에서 세션 검증하는 코드를 주석 처리한다.
< action.php 의 modify 부분 세션 검증 코드 주석 처리 >
# Password Check Logic
#$query = "select * from {$tb_name} where idx={$idx} and password='{$password}'";
/*
$query = "select * from {$tb_name} where idx={$idx} and id='{$_SESSION["id"]}'";
$result = $db_conn->query($query);
$num = $result->num_rows;
if($num == 0) {
#echo "<script>alert('패스워드가 일치하지 않습니다.');history.back(-1);</script>";
echo "<script>alert('잘못된 요청 입니다.');history.back(-1);</script>";
exit();
}
*/
< action.php 의 delete 부분 세션 검증 코드 주석 처리 >
# Password Check Logic
#$query = "select * from {$tb_name} where idx={$idx} and password='{$password}'";
/*
$query = "select * from {$tb_name} where idx={$idx} and id='{$_SESSION["id"]}'";
$result = $db_conn->query($query);
$num = $result->num_rows;
if($num == 0) {
#echo "<script>alert('패스워드가 일치하지 않습니다.');history.back(-1);</script>";
echo "<script>alert('잘못된 요청 입니다.');history.back(-1);</script>";
exit();
}
*/
해커 계정으로 로그인 후 게시글을 작성한다.
로그아웃 후 admin 계정으로 로그인 후 아래와 같이 게시글을 작성한다.
다시 해커 계정으로 로그인한다.
공격자는 관리자가 작성한 회비 정보 게시글을 확인하고 해당 게시글 수정을 시도한다.
게시글 수정을 시도하기 전에 원활한 실습을 위해 패스워드 입력란을 삭제한다.
modify.php 에서 패스워드를 표시하는 코드를 삭제한다. (31 - 34번 라인)
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password Input">
</div>
action.php 에서 96번 라인에 empty($password) 부분을 삭제한다.
if(empty($idx) || empty($title) || empty($content)) {
echo "<script>alert('빈칸이 존재합니다.');history.back(-1);</script>";
exit();
}
다음과 같이 패스워드란이 없어졌으며, 수정이 가능하다.
다른 게시글을 무단으로 수정하는 방법은 2가지가 있다.
파라미터 변조 공격을 하기 위해서는 파라미터 대상이 있어야 한다.
여기서 대상은 83번 게시글이다.
해커 계정의 게시글을 modify 를 클릭하여 수정하는 페이지로 접속한다.
idx=82 부분을 수정할 게시글 idx=83 으로 변경한다.
다음과 같이 idx=83 게시글의 수정페이지로 이동하게 된다.
이제 공격자는 본인의 계좌로 게시글을 수정할 수 있다.
다음과 같이 해커 계좌로 게시글을 임의로 수정한다.
수정 후 83번 게시글을 확인하면 다음과 같이 게시글이 해커의 계좌로 수정되어 있는 것을 확인할 수 있다.
방금 같은 경우에는 form 페이지에 접속을 한 경우이며, form 페이지에 접속이 안되는 경우도 있다.
(modify 의 form 페이지에서 파라미터 변조에 대한 검증을 하는 경우)
modify.php -> action.php
파라미터 검증은 modify.php 가 아닌 action.php 에서 해야 한다.
modify.php 에서 action.php 로 넘어갈때 파라미터 변조를 시도한다. (버프스위트 사용)
해커는 82번 게시글에서 수정을 하되, 게시글 내용은 관리자가 작성한 내용으로 변경을 시도한다.
이때 버프스위트로 넘겨서 idx=82를 idx=83으로 변경한다. (관리자 게시글이 변경되도록)
Intercept On 후 게시글의 Modify를 클릭한다.
idx 부분을 83으로 변경한다.
변경 후 Intercept Off 를 하면 idx=83 게시글(관리자 게시글)이 기존과 동일하게 관리자 계좌의 내용을 변경된 것을 확인할 수 있다.
첫번째 실습과 두번째 실습의 차이점(파라미터 변조의 시점)
1. modify 의 form 페이지로 들어갈때 파라미터를 수정하는 경우
2. modify -> action 페이지로 넘어갈때 파라미터 변조를 하는 경우
첫번째 실습과 두번째 실습의 공통점
- 모두가 action 페이지로 넘어갈때 요청값이 동일하다.
개발자가 실수로 form 페이지에만 파라미터 검증 로직을 적용한경우, 두번째 실습과 같이 modify 에서 action 페이지로 넘어갈때 파라미터 변조가 가능하다. (action 페이지에 검증 로직을 적용해야 한다.)
이번에는 idx=83 게시글을 삭제해본다.
해커 계정으로 접속 후 idx=82 게시글 삭제를 시도한다.
버프스위트를 켜고 Intecpet On 을 클릭 후 게시글 Delete 버튼을 클릭한다.
idx=83 으로 변경해준다.
Intercept Off 후 게시글을 확인해보면 83번 게시글이 삭제된 것을 확인할 수 있다.
idx=82 게시글 삭제 페이지에 접속했지만, 버프스위트를 활용하여 파라미터를 idx=83 으로 변경하니 83번 게시글이 삭제되었다.
게시판의 파라미터 변조 주요 예시
- 타 사용자 게시글 무단 수정, 삭제
게시글 수정은 Form 페이지에서 파라미터 검증 로직을 적용해도 소용이 없으므로, 실제 동작이 이루어지는 Action 페이지에 파라미터 검증 로직을 적용해야 한다. (사용자 입력값을 받아서 데이터베이스에 값을 업데이트 하는 Action 페이지)
실습9-2 파라미터 변조 취약점 공격을 통한 타 사용자 정보 무단 열람 실습
해커 계정으로 MyPage 에 접속한다.
다음과 같이 id 가 hacker 로 확인된다.
버프스위트로 MyPage 패킷을 잡는다.
현재는 id=hacker 로 해커 계정의 MyPage 임을 알 수 있다.
만약에 id=hacker 부분이 없는 경우(파라미터를 받지 않는 경우)에는 어떻게 사용자 정보를 출력시킬 수 있을까?
→ 세션 ID를 통해서 사용자 정보를 출력시킨다. (파라미터 변조 공격에 대한 잠재적인 위협을 제거할 수 있음)
간혹 세션을 통해서 사용자 정보를 출력하지만, id 파라미터(더미 데이터)를 받아서 처리하는 것 처럼 보이는 경우도 있다.
→ 이런 경우 실제로는 세션을 통해서 사용자 정보를 출력하므로 파라미터 변조 공격에 취약하지 않다.
해당 기능을 확인하는 방법은 파라미터에 없는 사용자를 입력해보는 것이다.
id 파라미터에 아무값도 입력하지 않아도 여전히 해커 계정의 MyPage 에 접속된다.
현재는 id 파라미터가 아닌 세션을 통해 사용자 정보를 출력하기때문에 실습을 위해서 소스코드 수정이 필요하다.
(사용자 입력값을 받아서 처리하도록 소스코드를 수정)
< mypage.php 에 $id 값을 파라미터로 받도록 수정 >
include_once("./common.php");
$db_conn = mysql_conn();
$id = $db_conn->real_escape_string($_GET["id"]);
#$id = $_SESSION["id"];
$gubun = $_POST["gubun"];
id 파라미터에 빈값을 입력하니 존재하지 않은 사용자로 확인된다.
이를 통해 세션을 통해 사용자 정보를 출력하는 것이 아닌, 파라미터 정보를 통해서 출력하는 것을 알 수 있다.
현재는 파라미터를 받아서 사용자의 정보를 출력하는 기능을 가지고 있으므로, 파라미터를 변조하여 다른 사용자의 계정을 무단으로 열람할 수 있다.
이제 id 파라미터에 admin 을 입력해본다.
관리자 계정의 MyPage 로 접속된 것을 확인할 수 있다.
이런 경우에는 id 파라미터에 사전 대입(무차별 대입 공격)을 많이 시도한다.
만약 idx=, seq= 등의 숫자값을 받는 파라미터인 경우에는 1부터 사용자 정보가 노출될 때까지 계속 주입한다.
Case 1) id 값을 입력 받는 경우
- id를 유추해야 되기 때문에 Case 2에 비해 피해가 크지 않다.
?id=admin
Case 2) seq 값을 입력 받는 경우
- 파라미터 변조 취약점 공격을 통한 개인 정보 노출 피해가 굉장히 크다.
- K 통신사 개인정보 노출 사고
?idx=1 ~ 1000000
?seq=
실습9-3 파라미터 변조 취약점 공격을 통한 타 사용자 강제 탈퇴 실습
현재 상태는 코드가 안전한 상태로 적용되어 있으므로, 탈퇴하는 페이지의 코드를 수정해야한다.
세션을 통해 회원 탈퇴하도록 코드가 작성되어 있으므로, 파라미터를 통해 회원 탈퇴를 할 수 있는 코드로 변경한다.
withdrawal.php 를 삭제하고 이전에 백업한 withdrawal-backup.php 를 withdrawal.php 로 이름을 변경한다.
< withdrawal.php >
<?
@session_start();
include_once("./common.php");
unset($_SESSION["id"]);
session_destroy();
$db_conn = mysql_conn();
$id = $_GET["id"];
$query = "delete from members where id='{$id}'";
$result = $db_conn->query($query);
echo "<script>location.href='index.php'</script>";
?>
mypage 도 코드 수정이 필요하다.
이전에 CSRF Token 관련 코드를 작성했었는데, 해당 코드를 삭제하고 id 파라미터로 대체하는 코드를 작성한다.
withdrawal.php?csrf_token=<?=$csrf_token?> → withdrawal.php?id=<?=$id?>
86 - 89 번 라인 코드 수정
< mypage.php >
<div class="text-center">
<input type="submit" class="btn btn-info" value="수정하기">
<button type="button" class="btn btn-danger" onclick="if(confirm('탈퇴 하시겠습니까?')) location.href='withdrawal.php?id=<?=$id?>'">회원탈퇴하기</button>
</div>
코드 저장 후 해커 계정의 MyPage 로 접속한다.
개발자 도구를 켜고 회원탈퇴하기 버튼 부분의 element 를 확인하면 다음과 같이 id=hacker 로 확인된다.
이를 통해 id 파라미터를 받아서 회원탈퇴하는 로직으로 변경된 것을 확인할 수 있다.
test 계정을 추가로 생성하여 파라미터 변조를 통한 강제 탈퇴를 실습해본다.
해커 계정으로 로그인 후 MyPage 에 접속한다.
버프스위트를 켜고 Intercept On 후 MyPage 의 회원탈퇴하기 버튼을 클릭한다.
id 파라미터의 hacker 를 회원 탈퇴를 시도할 계정 test 로 변경한다.
id 파라미터를 test로 변경 후 Intercept Off 한다.
insecure_website 에서 로그아웃 되었다.
test 계정으로 로그인 시도 시 로그인이 불가능하다.
MySQL 에서 확인 시 기존에는 test 계정이 존재하였지만, 현재는 존재하지 않는 것을 확인할 수 있다.
이를 통해 회원탈퇴를 할 때 id 파라미터를 입력받아서 회원 탈퇴를 하는 기능이 있다면, 해당 파라미터를 변조하여 타 사용자를 강제로 탈퇴 시킬 수 있다는 것을 알 수 있다.
3) 대응 방안
1. 사용자 입력 값에 대한 검증
2. 세션을 통한 처리
게시글 수정, 삭제 → 파라미터 검증 + 세션
정보수정, 마이페이지 → 세션을 통해서 처리
공격자가 다 사용자의 게시글을 무단으로 수정, 삭제하려는 경우
- idx 파라미터를 변조하여 게시글 번호를 변조, idx=100 을 idx=101 로 변경
- 게시글 삭제를 요청한 사용자 세션과 idx=101 게시글을 작성한 사용자를 비교, 비교해서 두 사용자가 동일하면 삭제를 하고, 동일하지 않으면 에러 처리 및 로직 중단
정보수정, 마이페이지 접속 시 계정 사용자의 세션 유무를 확인하여 동작 수행
세션 ID를 받아서 계정 정보 조회 → 사용자 입력 값(파라미터) 자체를 받지 않음
사용자 입력값(파라미터)을 받는 경우
- 게시글 번호(idx)를 먼저 입력 받음
- 수정 또는 삭제 요청을 하는 사용자의 세션 ID를 불러옴, 해당 게시글 작성자의 세션 ID와 비교
실습9-4 취약 환경 시큐어 코딩 적용 실습
취약한 action.php / mypage.php / withdrawal.php 에 대해 시큐어 코딩을 적용해본다.
타 사용자 게시글 수정 - action.php
타 사용자 게시글 삭제 - action.php
회원 정보 무단 열람 - mypage.php
타 사용자 강제 탈퇴 - withdrawal.php
action.php 에는 이전에 CSRF 시큐어 코딩 시 사용했던 코드를 그대로 사용해도 된다.
idx 와 세션 id 를 가져와서 검증하는 코드이다.
< action.php 의 modify 와 delete 부분 >
# Password Check Logic
#$query = "select * from {$tb_name} where idx={$idx} and password='{$password}'";
$query = "select * from {$tb_name} where idx={$idx} and id='{$_SESSION["id"]}'";
$result = $db_conn->query($query);
$num = $result->num_rows;
if($num == 0) {
#echo "<script>alert('패스워드가 일치하지 않습니다.');history.back(-1);</script>";
echo "<script>alert('잘못된 요청 입니다.');history.back(-1);</script>";
exit();
}
위 소스코드를 통해 타 사용자 게시글 수정 및 삭제에 대한 시큐어 코딩 적용이 완료되었다.
관리자 계정으로 접속 후 게시글을 작성한다.
해커 계정으로 로그인 후 관리자가 게시글 수정 및 삭제를 시도해본다.
해커 계정으로 임의의 게시글을 작성한다.
modify 를 클릭 후 상단 URL 의 idx 를 84 로 변경한다. (관리자 게시글)
다음과 같이 idx 84 번 게시글을 임의로 변경하려는 시도를 한다.
게시글 수정 후 Modify 를 클릭한다.
다음과 같이 잘못된 요청이라는 에러 메시지가 발생하면서 게시글이 변경되지 않는다.
이번에는 버프스위트를 활용하여 idx 값을 84로 변경을 시도해본다.
동일하게 에러 메시지가 확인된다.
지금쯤 드는 생각은 게시글 수정 시 URL 의 idx 값 변경이 가능한데 이것은 파라미터 변조 취약점이 아닌가? 라고 생각할 수 있다.
다른 게시글은 타 사용자도 확인이 가능하므로 단순히 idx 값을 수정한다고 해서 이는 파라미터 변조 취약점으로 볼 수 없다. 다만 현재 코드에서는 비밀 게시글도 위와 같은 방법으로 노출이 되므로 소스 코드 수정이 필요하다.
임의의 게시글 수정 시 상단의 idx 를 비밀 게시글의 idx 로 입력하면 위와 같이 비밀 게시글 확인이 가능하다.
modify.php 에 idx 와 세션 ID를 같이 받는 코드를 추가해준다.
< modify.php 의 세션 ID 받는 코드 추가 >
<?
include_once("./common.php");
$db_conn = mysql_conn();
$idx = $_GET["idx"];
if(!is_numeric($idx)) {
echo "<script>alert('숫자 값만 가능합니다.');history.back(-1);</script>";
exit();
}
$query = "select * from {$tb_name} where idx={$idx} and id='{$_SESSION["id"]}'";
$result = $db_conn->query($query);
$num = $result->num_rows;
?>
게시글 수정 시 idx 와 게시글 수정을 요청한 사용자의 세션 ID를 받는다. 게시글 수정을 요청한 사용자의 세션 ID와 실제 게시글 작성자의 세션 ID를 비교한다. 동일한 경우 게시글이 수정 가능하며, 동일하지 않으면 에러 발생
다시 게시글 수정을 통해 비밀 게시글을 확인하니 다음과 같이 에러가 발생한다.
이를 통해 게시글 수정 페이지에서 idx 파라미터를 변경해도 타 사용자의 게시글을 수정할 수 없게 된 것을 확인할 수 있다.
이번에는 타 사용자 게시글을 무단 삭제를 시도해본다.
버프스위트를 켜고 Intecept On 후 해커의 게시글에서 Delete 버튼을 클릭한다.
idx 를 84로 수정 후 Intercept Off 를 한다.
다음과 같이 에러 메시지가 발생하면서 idx 84 게시글은 삭제되지 않는다.
이번에는 id 파라미터 수정을 통한 개인 정보 무단 열람에 대해 시큐어 코딩을 적용해본다.
기존에는 본인 계정의 MyPage 에서 id 파라미터를 타 사용자를 입력하게 되면 해당 사용자의 개인 정보를 무단으로 열람할 수 있었다.
mypage.php 에서 id 파라미터(사용자 입력값)를 받는 것이 아닌, 세션을 통해서 접속할 수 있도록 코드를 수정한다.
< mypage.php 에 세션 ID 받도록 코드 수정 >
include_once("./common.php");
$db_conn = mysql_conn();
#$id = $db_conn->real_escape_string($_GET["id"]);
$id = $_SESSION["id"];
$gubun = $_POST["gubun"];
소스코드 적용 후 MyPage 에서 id 파라미터 admin 을 입력해도 여전히 해커 계정의 MyPage 로 확인된다.
이전과 달리 id 파라미터의 값을 받는것이 아닌 사용자의 세션 ID를 받기 때문에 admin 의 MyPage 무단 열람이 불가능해진 것이다.
버프스위트를 통해 요청값을 확인해본다.
id 파라미터에는 admin 을 입력했지만, hacker 의 세션 ID 이므로 admin 이 아닌 hacker 사용자의 MyPage 가 확인된다.
MyPage 버튼의 링크 부분도 수정해준다.
index.php 에서 mypage 링크를 불러오는 코드를 수정한다.
아래 코드를
class="p-2 text-dark" href="index.php?page=mypage&id=<?=$_SESSION["id"]?>">MyPage</a>
이렇게 수정한다.
<a class="p-2 text-dark" href="index.php?page=mypage">MyPage</a>
소스코드 적용 후 MyPage 접속 시 다음과 같이 id 파라미터가 없는 것을 확인할 수 있다.
이번에는 타 사용자를 강제로 탈퇴시키는 부분에 대해 시큐어 코딩을 적용해본다.
기존에 CSRF 시큐어 코딩에 사용했던 코드를 그대로 사용하면 된다.
기존에는 $id 변수에 id 파라미터의 값을 받아서 SQL 쿼리로 DB에 전달하는 방식을 사용했다.
변경된 코드에는 현재 접속한 사용자의 세션 ID 를 받아서 SQL 쿼리로 DB에 전달하기때문에, 이전과 달리 id 파라미터를 변조해도 다른 사용자가 회원탈퇴가 되는 것이 아닌 현재 접속한 본인 계정이 회원탈퇴가 된다.
< 기존 withdrawal.php 코드 >
<?
@session_start();
include_once("./common.php");
unset($_SESSION["id"]);
session_destroy();
$db_conn = mysql_conn();
$id = $_GET["id"];
$query = "delete from members where id='{$id}'";
$result = $db_conn->query($query);
echo "<script>location.href='index.php'</script>";
?>
< 시큐어 코딩이 적용된 withdrawal.php 코드 >
<?
@session_start();
include_once("./common.php");
$db_conn = mysql_conn();
$csrf_token_session = $_SESSION["csrf_token"];
$csrf_token_param = $_GET["csrf_token"];
if(empty($csrf_token_session) && empty($csrf_token_param)) {
echo "<script>alert('정상적인 접근이 아닙니다.');history.back(-1);</script>";
exit();
} else {
if($csrf_token_param != $csrf_token_session) {
echo "<script>alert('정상적인 접근이 아닙니다.');history.back(-1);</script>";
exit();
}
}
$query = "delete from members where id='{$_SESSION["id"]}'";
$result = $db_conn->query($query);
unset($_SESSION["csrf_token"]);
unset($_SESSION["id"]);
session_destroy();
echo "<script>location.href='index.php'</script>";
?>
그리고 위 소스코드는 CSRF 토큰이 필요하므로, mypage.php 에도 CSRF 토큰 관련 코드를 추가해준다.
< mypage.php 에 csrf 토큰 코드 추가 >
<button type="button" class="btn btn-danger" onclick="if(confirm('탈퇴 하시겠습니까?')) location.href='withdrawal.php?csrf_token=<?=$csrf_token?>'">회원탈퇴하기</button>
버프스위트를 사용하여 해커 계정의 탈퇴를 시도해본다.
id 파라미터를 받지 않고 현재 접속한 사용자의 CSRF 토큰을 받는 것을 확인할 수 있다.
설령 저 부분에 id=admin 을 추가해도 관리자 계정은 회원 탈퇴되지 않고 해커 계정만 회원탈퇴가 된다.
( 소스코드에서 id 파라미터를 받지않고 세션 ID를 받기 때문에 )
해커 계정으로 로그인을 요청하니 회원탈퇴가 되어서 다음과 같이 로그인이 불가한 것을 확인할 수 있다.
MySQL 에서 확인해보니 admin 계정은 존재하고 hacker 계정은 확인되지 않는다.
참고
'웹 해킹 > 웹 해킹 및 시큐어 코딩 기초' 카테고리의 다른 글
URL 접근 제한 미흡 취약점 (0) | 2025.02.28 |
---|---|
파일 업로드 취약점 (0) | 2025.02.25 |
파일 다운로드 취약점 (1) | 2025.02.10 |
CSRF(Cross-Site Request Forgery) (0) | 2025.02.08 |
XSS (Cross-Site Scripting) (0) | 2025.01.24 |