LOADING

加载过慢请开启缓存 浏览器默认开启

NewStar2023

2023/9/25

Web

week1

Begin of HTTP

这题最后一步有个本地用户伪造,这次不是用xff头了,是用的 X-Real-IP:127.0.0.1

然后这里有一些其他的伪造方法

X-Forwarded-For:127.0.0.1
X-Forwarded:127.0.0.1
Forwarded-For:127.0.0.1
Forwarded:127.0.0.1
X-Forwarded-Host:127.0.0.1
X-remote-IP:127.0.0.1
X-remote-addr:127.0.0.1
True-Client-IP:127.0.0.1
X-Client-IP:127.0.0.1
Client-IP:127.0.0.1
X-Real-IP:127.0.0.1
Ali-CDN-Real-IP:127.0.0.1
Cdn-Src-Ip:127.0.0.1
Cdn-Real-Ip:127.0.0.1
CF-Connecting-IP:127.0.0.1
X-Cluster-Client-IP:127.0.0.1
WL-Proxy-Client-IP:127.0.0.1
Proxy-Client-IP:127.0.0.1
Fastly-Client-Ip:127.0.0.1
True-Client-Ip:127.0.0.1
Host: 127.0.0.1

Begin of PHP

这是源码

<?php
  error_reporting(0);
highlight_file(__FILE__);

if(isset($_GET['key1']) && isset($_GET['key2'])){
  echo "=Level 1=<br>";
  if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2'])){
    $flag1 = True;
  }else{
    die("nope,this is level 1");
  }
}

if($flag1){
  echo "=Level 2=<br>";
  if(isset($_POST['key3'])){
    if(md5($_POST['key3']) === sha1($_POST['key3'])){
      $flag2 = True;
    }
  }else{
    die("nope,this is level 2");
  }
}

if($flag2){
  echo "=Level 3=<br>";
  if(isset($_GET['key4'])){
    if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){
      $flag3 = True;
    }else{
      die("nope,this is level 3");
    }
  }
}

if($flag3){
  echo "=Level 4=<br>";
  if(isset($_GET['key5'])){
    if(!is_numeric($_GET['key5']) && $_GET['key5'] > 2023){
      $flag4 = True;
    }else{
      die("nope,this is level 4");
    }
  }
}

if($flag4){
  echo "=Level 5=<br>";
  extract($_POST);
  foreach($_POST as $var){
    if(preg_match("/[a-zA-Z0-9]/",$var)){
      die("nope,this is level 5");
    }
  }
  if($flag5){
    echo file_get_contents("/flag");
  }else{
    die("nope,this is level 5");
  }
} 

一共有五层
第一层是md5弱比较
用下面这些0e开头的字符串,比较的时候他们会被当作科学计数法结果为0

QNKCDZO
240610708
byGcY
sonZ7y
aabg7XSs
aabC9RqS
s878926199a
s155964671a
s214587387a
s1091221200a

如果是强比较的话不能这样,可以用数组绕过
因为md5()这个函数不接受数组,传数组的时候会被当成null
比如

md5(a[]=1) === md5(b[]=1)

  //就是null=null

然后如果后面的md5是强比较的话,就需要md5碰撞了

第二层是md5和sha1的比较
同样 sha1()函数也是不接受数组的,只需要传一个数组就可以实现null=null

第三层是strcmp绕过
strcmp是一个比较函数,在本题中是比较key4和/flag是否相等,同样,当传入一个数组时这个函数就会报错并返回0,使if(0==0),为true
适用于5.3版本前的php

第四层是is_numberic绕过
is_numeric()是一个判断是不是数字的函数,题中需要这个判断为false然后还要大于2024
可以通过这几种方法

2024’
2024,
2024%00
%002024
2024%20
2024.0(不行)

第五层是extract变量覆盖绕过
因为题目中有这段extract($_POST),所以让人想到变量覆盖,extract()这个函数的作用在php手册是这样说的
image.png
他还特意提醒了不要对用户输入的数据做这个操作呢

所以就是我们需要在绕过$var的正则表达式匹配的同时,将flag5变量覆盖,让他在if的判断里为true
例如我们传入 key3[]=gggg&flag5=1111111111的话,$var就只会是gggg,但是如果是key=%&flag5=1111111111的话因为有foreach()函数他循环遍历$_POST数组中的每个值,最终遍历到flag5然后die()

所以我们不能通过前面传%来绕过后面的判断,我们只能去寻找无数字字母绕过
具体的可以看看这两篇文章
https://www.freebuf.com/articles/network/279563.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

这里我们可以通过取反的操作

<?php
$a='1';
echo urlencode(~$a);

//输出%CE

于是可以传key3[]=%&flag5=~%CE

好吧……其实不用取反也可以,只要flag5不是匹配的那些都可以,随便输一个符号就行,因为php的if的判断条件是
image.png

R!C!E!

<?php
  highlight_file(__FILE__);
if(isset($_POST['password'])&&isset($_POST['e_v.a.l'])){
  $password=md5($_POST['password']);
  $code=$_POST['e_v.a.l'];
  if(substr($password,0,6)==="c4d038"){
    if(!preg_match("/flag|system|pass|cat|ls/i",$code)){
      eval($code);
    }
  }
} 

第一个md5需要爆破,0到6位是c4d038,可以用https://github.com/playGitboy/bruteHASH这个工具
image.png
然后只需要传password=yjzyejsmdmd就可以了

第二个就是要传e_v.a.l但是php的传参的变量只能是数字字母下划线,其他的会被当做非法变量,其中点号和等号会被转化为下划线
image.png

所以e_v.a.l在我们传上去的时候就会变成e_v_a_l,那肯定不行,但是在php8以下的版本中有一个特性就是如果参数中有[中括号的时候,其会被转化为下划线,并且会出现错误让之后参数中的非法字符不能转化为下划线

于是我们就可以传一个e[v.a.l,然后它就会变成e_v.a.l,最后直接命令执行就好了