[원데이 취약점 분석] gnuboard5 1-day 1

1mn·2022년 9월 29일
0
post-thumbnail

00. 시작

코드 분석 능력을 키우기 위해 스터디를 시작했다!!!
gnuboard5의 원데이 취약점들을 분석해서 취약한 버전으로 돌린 뒤에, POC(Proof of concept)코드를 짜보는 것으로 스터디가 진행된다.

1) 환경 구축

먼저 원격에서도 쉽게 접근이 가능하도록 집에서 라즈베리파이를 이용한 웹서버를 구축했다.

라즈베리파이에는 Apache2와 mysql, php, php-gd 를 설치해 구성을 완료했다.

01. 취약점 선정


친절하게도 Stored XSS라고 나와있다...
이전 버전의 해시코드를 찾아 체크아웃한다.

수정 전(73-82)

$content = '';
    if ($w == '') {
        $content = html_purifier($qaconfig['qa_insert_content']);
    } else if($w == 'r') {
        if($is_dhtml_editor)
            $content = '<div><br><br><br>====== 이전 답변내용 =======<br></div>';
        else
            $content = "\n\n\n\n====== 이전 답변내용 =======\n";

        $content .= get_text($write['qa_content'], 0);

수정 후(73-83)

$content = '';
   if ($w == '') {
       $content = html_purifier($qaconfig['qa_insert_content']);
   } else if($w == 'r') {
       if($is_dhtml_editor)
           $content = '<div><br><br><br>====== 이전 답변내용 =======<br></div>';
       else
           $content = "\n\n\n\n====== 이전 답변내용 =======\n";

       // KISA 취약점 권고사항 Stored XSS (210624)
       $content .= get_text(html_purifier($write['qa_content']), 0);

02. 분석

코드를 보면 $content라는 변수에 get_text 함수의 리턴 값이 더해지는 코드에서, 패치 후 get_text 파라미터를 html_purifier로 감싼 모습이다.

여기서 html_purifier는 주로 XSS 관련된 취약점을 화이트리스트를 이용해 입력값을 안전하게 바꿔주는 함수이다.

여기서 취약한 버전 코드의 82번째 줄에,

$content .= get_text($write['qa_content'], 0);

다음과 같이 다른 입력값에는 html_purifier가 있는것에 비해, 이곳에만 적용이 안된 모습을 볼 수 있다.

이제 실제 페이지로 가보면

다음과 같이 QNA 페이지인것을 알 수 있다.

그래서 저 코드가 언제 실행되는지 확인해보면

저 w라는 변수는 글쓰기 기능을 정하는 변수이고, 이것은

QnA 페이지에서 답변 완료된 질문에 추가질문을 할때 취약한 부분이 열린다.

이제 get_text 라는 함수를 살펴보면

// TEXT 형식으로 변환
function get_text($str, $html=0, $restore=false)
{
    $source[] = "<";
    $target[] = "&lt;";
    $source[] = ">";
    $target[] = "&gt;";
    $source[] = "\"";
    $target[] = "&#034;";
    $source[] = "\'";
    $target[] = "&#039;";

    if($restore)
        $str = str_replace($target, $source, $str);

    // 3.31
    // TEXT 출력일 경우 &amp; &nbsp; 등의 코드를 정상으로 출력해 주기 위함
    if ($html == 0) {
        $str = html_symbol($str);
    }

    if ($html) {
        $source[] = "\n";
        $target[] = "<br/>";
    }

    return str_replace($source, $target, $str);
}

위 코드가 get_text 함수고, str_repalce는 문자열을 치환해주는 기본 함수, html_symbol은 뭔지 해서 살펴보니,
common_lib.php(1510-1513)

function html_symbol($str)
{
    return preg_replace("/\&([a-z0-9]{1,20}|\#[0-9]{0,3});/i", "&#038;\\1;", $str);
}

정규 표현식을 이용한 필터링 함수.

Stored XSS니 아마 추가 질문을 하면서 원래 글의 내용을 가져오는데, 여기서 문제가 생길거라고 생각해 공격을 해보았다.

03. POC(Proof Of Concept)

질문 작성 페이지로 가서 공격을 진행해보았다.
먼저 글쓰기에서 script 태그로 작동하는 것은 작동하지 않는것을 확인할 수 있었다.


그래서 img 태그를 이용해 공격을 진행해보았다.

<img src=# onerror='alert(1)'>

먼저 작성한 글로 인해 Reflected XSS가 성공한 것을 볼 수 있고, 진짜 목적은 Stored XSS이므로 추가 질문 페이지로 들어간다.


다음과 같이 DB에 있는 글을 불러오면서 alert가 발동되는 것을 볼 수 있다.

물론 공격에 한계는 있다. 일단 이 페이지는 1대1 QNA 페이지로, 다른 사람이 접근을 할 수 없기 때문에 쿠키 탈취 등 실효성 있는 공격은 할 수 없을 것 같다.(관리자가 답변하면서 XSS가 발동하지 않기에)

04. 방어 방법

다른 변수처럼 html_purifier로 필터링하면 된다.

       // KISA 취약점 권고사항 Stored XSS (210624)
        $content .= get_text(html_purifier($write['qa_content']), 0);

사실상 다른곳에는 다 적용한것으로 보이지만, 이곳만 적용하지 않은것으로 보아 그냥 휴먼에러인것으로 추측한다.

05. 여담

일단 지금 글을 마무리하긴 하지만, 아직 왜 script 태그는 작동하지 않고 img만 작동되는지, 필터링이 정확히 어떻게 적용되는지 알 수 없었다. 공부 후에 더 추가해야겠다.

Reference

http://htmlpurifier.org/
https://github.com/gnuboard/gnuboard5

profile
정보보안 응애대학생

0개의 댓글