SONOTRI
  • Old-26
    2024년 12월 31일 17시 58분 01초에 업로드 된 글입니다.
    작성자: sonootri

    문제

    소스코드가 주어졌다. 이외에는 별다른 기능이 보이지 않는걸 보니 쿼리문을 사용해서 푸는게 아닐까 싶다.

    <?php
      include "../../config.php";
      if($_GET['view_source']) view_source();
    ?><html>
    <head>
    <title>Challenge 26</title>
    <style type="text/css">
    body { background:black; color:white; font-size:10pt; }    
    a { color:lightgreen; }
    </style>
    </head>
    <body>
    <?php
      if(preg_match("/admin/",$_GET['id'])) { echo"no!"; exit(); }
      $_GET['id'] = urldecode($_GET['id']);
      if($_GET['id'] == "admin"){
        solve(26);
      }
    ?>
    <br><br>
    <a href=?view_source=1>view-source</a>
    </body>
    </html>

     

     

    문제 분석

    #(1)

    첫 번째 조건문이다. 사용자로부터 url 쿼리 문자열에서 id값을 받아온다. 이때 id값이 admin이라면 no를 출력한다.

     

    #(2)

    사용자로부터 id값을 받아온다. 그리고 받아온 id값을 디코딩한다. 예를들어 '#'은 인코딩하면 %23이 되고, 이를 디코딩하면 #가 된다. 이후 디코딩한 값이 admin이라면 문제가 풀리는 것 같다.

    <body>
    <?php
      if(preg_match("/admin/",$_GET['id'])) { echo"no!"; exit(); } #(1)
      $_GET['id'] = urldecode($_GET['id']); #(2)
      if($_GET['id'] == "admin"){
        solve(26);
      }
    ?>
    <br><br>
    <a href=?view_source=1>view-source</a>
    </body>
    urldecode()
    % 기호와 뒤에 있는 두 개의 16진수 숫자로 이어진 인코딩된 문자를 실제 문자로 변환하여 디코딩하고, + 기호는 공백 문자로 대체하는 함수이다.
    $url = 'https://www.example.com/page.php?name=John Doe';
    $encoded_url = urlencode($url);
    echo $encoded_url . '<br>';
    // 출력: https%3A%2F%2Fwww.example.com%2Fpage.php%3Fname%3DJohn+Doe
    
    $decoded_url = urldecode($url);
    echo $decoded_url;
    // 출력: https://www.example.com/page.php?name=John Doe​

    <주의해야할 점>
    $_GET, $_POST, $_REQUEST와 같은 슈퍼글로벌 변수는 이미 URL 디코딩이 된 상태이다. 이러한 변수에서 urldecode() 함수를 사용하면 예상치 못한 결과 및 보안 문제가 발생할 수 있다. 따라서 이러한 변수를 추가로 디코딩하지 않아야 한다.

     

     

    취약점

    1. (1)번에 의해 id가 admin이면 안되고, (2)에 의해 복호화된 id가 admin이면 문제가 풀린다. 입력값은 admin이 아니되 출력값은 admin이여야한다?

     

     

    익스플로잇(write-up 참고)

    PHP에서 url로 전달되는 데이터 id는 슈퍼글로벌 변수에 저장되기 전에 자동으로 디코딩된다(정리 부분 참고). 때문에 url 인코딩 된 문자열이 디코딩된 상태로 preg_match()에 전달된다.

    if(preg_match("/admin/",$_GET['id'])) { echo"no!"; exit(); } #(1)
    $_GET['id'] = urldecode($_GET['id']); #(2)
      if($_GET['id'] == "admin"){
        solve(26);

     

    따라서 우리는 admin을 2번 인코딩 한 값을 id값으로 넣어주면 된다. 

    인코딩 1번 %61%64%6d%69%6e
    인코딩 2번 %2561%2564%256d%2569%256e

     

    -> preg_match()가 두 번째 조건문보다 위에 위치하기 때문에 %2561%2564%256d%2569%256e이 디코딩 된 %61%64%6d%69%6e값은 admin과 다르기 때문에 걸리지 않게 되고, 아래 조건문의 urldecode에 의해 admin으로 디코딩되며 문제가 풀리는 것이다.

     

     

    정리

    이중 인코딩(Double Encoding)
    : 동일한 인코딩 체계(URL Encoding)를 이용하여 이중으로 인코딩한 것을 의미한다. 일반적으로 사용자 입력을 가로채는 권한 부여 첵께나 보안 필터를 우회하는 공격 기법으로 사용된다.
    웹 서버와 브라우저 사이에서 데이터를 교환할 때, 브라우저는 <form>에서 입력 받은 데이터를 자동으로 인코딩한 값으로 보내고, php는 자동으로 디코딩 하여 해석한다.
    -> 슈퍼 글로벌 변수는 단순히 디코딩된 데이터를 제공할 뿐이다.

     

    'PRIVATE > webhacking.kr' 카테고리의 다른 글

    old-16  (0) 2025.01.02
    old-15  (0) 2024.12.31
    댓글