ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Authentication Bypass - Login Bypass 1
    wargame/segfault 2024. 6. 16. 13:27

    이 카테고리에 있는 워게임은 화이트해커 'Normaltic'의 모의해킹 취업반 수강자들만 접근할 수 있으므로 기록용으로 작성함을 알립니다. 참고로 노출된 url에 직접 접근을 시도하여도 일정 기간 제외하고는 접근이 불가능하기 때문에 추후의 캡쳐본에서 따로 url을 모자이크 처리하지는 않겠습니다.

     

    wargame의 목표, 정보

     

    워게임에 대해 간단히 설명을 하겠다. 주어진 url이 있고, 그곳에서 'normaltic1'로 로그인에 성공하면 주어지는 flag를 획득하는 것이 목표이다. 기본적으로 주어진 계정의 정보는 다음과 같다.

    # id: doldol
    # password: dol1234

     

    어떻게 로그인이 진행되는지 분석해보기 위해 Burp Suite를 통해 웹페이지를 살펴보겠다.

     

     

    /login1/ 에 접근하게 되면 응답코드가 302이 되며 /login1/login.php로 자동 이동하게 된다. 302 응답코드는 요청받은 데이터가 임시적으로 location 헤더에 있는 url으로 이동하게 되는 것을 의미한다. 이때 get method로 /login1에 보냈을때 응답의 헤더는 다음과 같다.

     

    7번째 줄의 location에 login.php가 할당되어 있는 것을 알 수 있다. 그리고 이후에 다시 자동으로 /login1/login.php로 get 요청을 보내 접근하게 된다. 그렇게 접근한 페이지의 모습은 다음과 같다.

     

    form 태그의 action 속성이 비어있고 method가 post이므로 그 페이지 자신에게 post 요청을 보내는 것을 알 수 있다. 보내는 값은 "UserId"와 "Password"이다. 또한 checkbox도 있고 Sign in 버튼을 누르면 "Submit"에 "Login" 도 담겨져 보내진다.

     


     

    로그인 성공 시

     

    이제 아까 주어진 아이디인 doldol, dol1234를 입력해 로그인되는 과정을 살펴보겠다. 먼저 아이디와 비밀번호를 올바르게 입력한 뒤 Sign in 버튼을 누른다

     

     

    그러면 정상적으로 브라우저에서 로그인된 페이지가 나타난다. burp를 살펴보겠다.

     

    /login1/login.php에 POST 요청을 보내며 파라미터가 담긴 것을 알 수 있다. 중간에 체크표시된 것은 파라미터가 전달되었느냐를 보여주는 것이다. 그리고 302코드로 응답이 오며 /login1/index.php로 get 요청을 보내 정상적으로 /login1/index.php로 이동하게 된다.

     

    /login1/login.php로 보낸 요청을 자세히 살펴보겠다.

    UserId=doldol&Password=dol1234&Submit=Login

     

    16번째 줄을 보면 전달된 파라미터들을 볼 수 있다. 이 값들이 전달되었을 때 정상적으로 로그인이 허용이 되어서 응답페이지의 헤더에 담긴 location:index.php 로 인해 /login1/index.php로 이동된 것이다.

     

    이후에 로그아웃버튼을 누르면 logout.php로 이동을 하게 되어 로그아웃이 되고 다시 login.php로 이동을 하게 된다. 로그아웃을 하고 로그인 실패 상황을 분석하겠다.

     

     


     

    로그인 실패 시

     

    잘못된 계정 정보를 입력하고 Sign in 버튼을 누르니 페이지에 Warning! 메시지가 출력된다.

     

    이때는 로그인에 실패했으므로 index.php로 이동하지 않고 200 status code를 응답한다. 이제부터 로그인 결과를 확인하기 위해서 브라우저를 통해 알아보지 않고 burp의 응답 창에서 확인할 것이기 때문에 다음과 같이 알 수 있다.

     

    /login1/login.php에 post 요청을 보냈을 때 응답에서 나오는 status code가

    case '200' : 로그인 실패

    case '302' : 로그인 성공

     

     

    예시로 normaltic1으로 로그인을 하기 위해 시도를 해보겠다. 앞으로는 login.php에 burp의 repeater를 이용해 데이터를 보낼 것이다.

     

     

    요청: normaltic1 / wrongpass (틀린 정보이기 때문에 로그인에 실패할 것)

     

    결과: 로그인 실패

     

     


    로그인 우회 

     

    로그인을 할 때 웹서버에서 사용하는 로직에는 방식마다 여러가지가 있다. 그 로직마다 정리해놓은 게시물은 다음과 같으니, 여기서 전체적인 설명을 하지는 않겠다.

     

    먼저 식별/인증 동시 케이스 중에서, 개행X, 해쉬X, 괄호X이며 내부에 single quote(')를 사용하며 id가 먼저 앞에 오는 sql문이라고 가정하고 문제를 풀어본다. 먼저 정상적으로 주어진 계정을 이용해, 로그인 우회가 가능한지 알아봐야한다. 그리고 내가 sql문에 적은 table이름과 column이름은 모두 내가 임의적으로 가정한 것이다.

     

    $sql = "SELECT * FROM member WHERE id='___' and pass='___'"
    
    # id에 doldol' and '1'='1
    # pass에 dol1234 를 입력하면 다음과 같다.
    
    $sql = "SELECT * FROM member WHERE id='doldol' and '1'='1' and pass='dol1234'"

     

    and 연산자를 통해 모두 다 참이 되어 있는 상태이므로 만약 이렇게 보냈을 때 로그인이 성공한다면, 내가 입력한 데이터가 db에서 논리적으로 문제없이 처리가 된다는 뜻이다. 따라서 로그인 우회가 가능하다고 판단될 수 있다.

     

    결과는 302코드가 반환되어 정상적으로 로그인 된 것을 알 수 있기에, 로그인 우회가 가능하다고 판단된다.

     


     

    이제 normaltic1 으로 로그인 우회를 해 로그인에 성공해야한다.

    $sql = "SELECT * FROM member WHERE id='___' and pass='___'"
    
    # 만약 normaltic1, wrongpass를 입력한다면 다음과 같다.
    
    $sql = "SELECT * FROM member WHERE id='normaltic1' and pass='wrongpass'"

     

     

    db에서 위의 질의문으로 데이터를 찾을 때, id는 normaltic1에 해당하는 계정을 찾을 수 있지만, 동시에 pass가 일치하지 않아 and문에 의해 거짓이 되어 아무것도 반환되지 않는다.

     

    하지만 id에 특정 값을 삽입해 뒤의 pass의 값과 상관없이 참을 반환할 수 있다.

     

    바로 id에 normaltic' or '1'='1을 삽입하는 것이다. 

    $sql = "SELECT * FROM member WHERE id='normaltic1' or '1'='1' and pass='wrongpass'"

     

    그러면 WHERE문의 논리가 id='normaltic1' or '1'='1' and pass='wrongpass' 가 된다. or 연산자보다 and 연산자의 우선순위가 높기 때문에 순서대로 참거짓 판별을 살펴보겠다.

    '1'='1' and pass='wrongpass'  은 (참 and 거짓) 이므로 거짓이다. 

    그러므로 id='normaltic1' or 거짓 은 or연산자에 의해 한쪽만 참이어도 참이되기 때문에 id가 normaltic1인 경우가 있으면 무조건 참이 된다. 

     

    따라서 참이 반환된다. 이제 burp에 UserId=normatic' and '1'='1 을 삽입하고 Password에는 아무것이나 넣어본다.

     

     

    결과는 바로 로그인 성공!

     

    따라서 sql 질의문이 내가 앞서 가정한 (식별/인증 동시, 개행X, 괄호X, id먼저, single quote 사용, 해쉬는 모름) 이라고 추론할 수 있다. 그러나 이 경우에는 id에 normaltic1' # 을 입력해서 뒤쪽을 주석처리하면 정상적으로 로그인이 진행되어야 하지만, 해보니 되지 않아 #을 필터링하고 있을 가능성이 존재한다. 하지만 doldol의 경우 id: doldol'# , pass: dol1234 을 입력했을 때 정상적으로 로그인이 되는 것을 보아 #이 필터링 되지 않고 where pass='___' and id='___' 일 경우의 수도 존재한다. 이 경우에는 normaltic1' # 을 입력해도 의미가 없기 때문이다.

     


     

    이제 index.php를 확인하기 위해 브라우저로 직접 입력해도 되고, burp의 intercept를 이용해도 되지만 브라우저를 이용해 결과를 보도록 하겠다.

     

     

    index.php 페이지는 다음과 같이 보인다. flag도 찾아냈다.

     

    다음문제부터 비슷한 페이지인 경우에는 자세한 설명은 생략한다.

Designed by Tistory.