一周刷题记录 | 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.__globals__}} {{get_flashed_messages.__globals__}}
發現有current_app全局變量,查看一下config
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請求內網信息
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)
通過這道題學到了很多東西,ssrf+redis的考法還有很多種,會在另一篇博客中專門總結一下。
參考博客
https://www.jianshu.com/p/a940731cddaf
HECTF
0x00 ezphp
第一個if條件,md5強類型,沒有強制限制類型,所有用數組就可以
strtr() 函數轉換字符串中特定的字符。
自己本地測試一下就知道了
第一個if($md5_1 != $md5_2)不能使用hash弱類型比較,經過strtr() 函數替換之后,再使用hash弱類型繞過,既然這個函數可以將md5中出現的cxhp給替換成0123,第一個參數找一個數字(必須為全數字),md5加密后只要是ce開頭的即可
payload:
http://121.196.32.184:8081/?param1[]=123¶m2[]=111&str1=2120624&str2=QNKCDZO
這里在寫腳本找ce開頭的數字時挺有趣的
md5加密之后只可能含有以下a、b、c、d、e、f這個幾個字符
在寫腳本的時候,一開始只認為只要開頭是0e即可,但是測試發現行不通,明明也是0e開頭,為什么不相等那?如:
并沒有出現我們想要的flag,一開始以為是位數的問題,結果不是,觀察了通用的Hash 比較缺陷,有一個共同的特征
后面都是數字,不包含字母,才能使用科學計數法進行弱類型比較
0x01:ssrfme
正則表達式限制我們不能使用SSRF file_get_content函數的黑魔法了,那只能按照http或https協議來,然后下面有一個異常處理代碼,如果發生異常則返回flase,恰好最后一段代碼有一個!,所以我們只要讓代碼異常拋出即可利用函數讀取flag。
但這個異常不知道要如何利用,往下面看發現可以從這段代碼中得到flase
只要滿足傳入的地址經過ip2long函數處理后和前面不相等即可
簡單了解這幾個函數的作用:
- parse_url:解析 URL,返回其組成部分
- gethostbyname:返回主機名對應的 IPv4地址
- ip2long:將 IPV4 的字符串互聯網協議轉換成長整型數字
0.0.0.0代表本機ipv4的所有地址,使用ip2long函數處理后也是0,便可以使用這個進行讀取flag
payload:
?url=http://0.0.0.0/flag.php0x03:簽到
源代碼給出手機號,下面就是爆破驗證碼
得到驗證碼之后重置密碼,登陸即可獲取flag
2020 安洵杯
0x00:Bash
代碼也很簡單,命令執行,但是構造payload只能使用這幾個${#}\\(<)\去構造,還是做題少,之前見的無字母數字構造webshell的都不行,只能看官方的WP。
先了解幾個Shell符號
$# 的意思是參數的個數,這道題沒有其余的參數所以會是 0
stdin是標準輸入,一般指鍵盤輸入到緩沖區里的東西
<<< 的用途是將任意字符串交由前面的指令執行
(())表示整數擴展,只是執行,并不會返回值,$$ 代表的是目前的 pid ,pid 會 > 0 所以可以得到 1,${##} 也可以得到1
<<雙小于號,用來將后繼的內容重定向到左側命令的stdin中
將 bbb 以二進制制轉換成數字,其中2#表示二進制
命令替換: $(command)
算術擴展: $((arithmetic))
stdin重定向: command < file
stdin文字重定向: command <<< text
可變的字符串長度: ${#variable}
bash的參數數量: $#
bash進程ID: $$
Linux下高效編寫Shell——shell特殊字符匯總
因為bash 可以用 $'\ooo' 的形式來表達任意字節(ooo 是字節轉ascii 的八進制),所以可以執行任意命令
所以思路就是構造二進制,然后通過ASCII碼轉化得到所有字母,比如:
所以構造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一次解析只能解析到成數字,需要第二次解析。需要給原先的命令添加轉義字符
無命令回顯就用最常見的方法,反彈shell或者是盲注,記錄一下師傅的腳本
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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UNCTF2020 | Web Wp
- 下一篇: 第六届上海市大学生网络安全大赛 | Wp