curl_exec及parse_url绕过

0x00简介

最近肺炎爆发,被迫宅在家。闲来无事,做了道web题,正巧碰到了盲点,记录一下。
题目允许用户输入一个图片url,并通过curl发起请求返回图片给用户。
源码如下:

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
<?php
include "config.php";
session_start();
if(!isset($_SESSION['username'])) {
header('Location: index.php');
exit();
}

function insert_img() {
if (isset($_POST['img_url'])) {
$img_url = @$_POST['img_url'];
$url_array = parse_url($img_url);
if (@$url_array['host'] !== "localhost" && $url_array['host'] !== "timgsa.baidu.com") {
return false;
}
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $img_url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($c);
curl_close($c);
$avatar = base64_encode($res);

if(filter_var($img_url, FILTER_VALIDATE_URL)) {
return $avatar;
}
}
else {
return base64_encode(file_get_contents("static/logo.png"));
}
}
?>

0x01 curl_exec读取任意文件

这题考点就是利用curl来读取本地文件。又因为curl支持file协议,所以构造payload:img_url=file://localhost/flag 即可。
php curl识别出来这是个file协议,他会忽略host,而是直接读取文件path,也就是/flag。

0x02 parse_url

一开始自己的注意点主要是集中在这个函数上,但这个函数的作用仅仅是绕过url合法检测,并不会实质性的改变curl的请求内容。
所以本题这个函数的作用并不大。
此函数在php5.4.7之前可以进行很多绕过,但当前大多都是5.6,所以不做过多解释了。感兴趣的可以浏览这篇博客parse_url函数的解释和绕过