ctfshow私教课第四节

文件包含

文件包含的本质

代码复用
并行开发
模块化
增加移植性

include和eval的区别

include和eval一样,都不是函数,都是语言结构,无法通过配置文件禁用来禁用

include后面跟一个路径,表示要执行的php文件的路径,读取文件内容后,然后执行里面的php代码,像c语言中的函数。

eval后面跟php的代码,表示要执行的代码

php的常见为文件包含语言结构

include 仅仅是包含这个文件,如果文件不存在,就继续执行后面的代码,无视这个include

require 必须存在这个文件,不然就无法正常执行后面的代码,就报错不执行了

include_once 包含一次,遇到错误继续执行

require_once 成功包含一次,遇到错误停止

文件包含漏洞的含义

是指,通过文件包含时,包含的内容我们用户可控

ctfhsow私教课web30

1
2
3
4
5
6
<?php   
error_reporting(0);
highlight_file(__FILE__);
// flag in /var/www/secret
include $_GET['file'];
?>

当路径中不含有php代码的时候,一律认为是文档,就会直接输出其中的内容

输入图片说明

这里直接写路径,因为这个路径里的内容不含php代码,这里就直接输出了内容,我们就拿到了flag

php伪协议

1.什么是协议

网络层协议

IP协议
ICMP协议
ARP协议
IGMP协议

应用层协议

http协议
https协议
ftp协议
ssh协议

gopher协议

qq拉起协议 tencent ://qq/go123 交给专用的应用来处理,应用指本地程序

百度网盘拉起协议 下载 自动启动我们本地百度网盘的程序

2.协议的格式

协议头://内容

3.php中的协议

php支持的协议和封装协议

  • file:// — 访问本地文件系统 (常用)
  • http:// — 访问 HTTP(s) 网址 (常用)
  • ftp:// — 访问 FTP(s) URLs(常用)
  • php:// — 访问各个输入/输出流(I/O streams) (常用)
  • zlib:// — 压缩流
  • data:// — 数据(RFC 2397) (常用)
  • glob:// — 查找匹配的文件路径模式
  • phar:// — PHP 归档 (常用)
  • ssh2:// — Secure Shell 2
  • rar:// — RAR
  • ogg:// — 音频流
  • expect:// — 处理交互式的流

4.file协议

不写协议名字,就默认是file协议,意味着file://可以省略

相对路径和绝对路径

flag,php index.php
/var/www/html
执行 include”flag.php” 这是相对路径
相当于执行 include”file:///var/www/html/flag.php”; 这是绝对路径

include”flag.php”;
include”../html/flag.php”;
这里的../就是上一层目录
相当于include”/var/www/html/../html/flag.php”
与直接写flag.php作用是相同的

上层目录特性
  1. 每个目录都有上层目录
  2. 根目录的上层目录是根目录本身

/var/www/html/../../../ => 根目录
/var/www/html/../../../../../../../../../../ => 根目录 上溯

php目录整理特性

/var/www/html/ctfshow/../flag.php
传入的就是
/var/www/html/flag.php

ctfshow私教课web31

1
2
3
4
5
6
7
<?php   
error_reporting(0);
highlight_file(__FILE__);
//flag in /flag
$file = $_GET['file']?$_GET['file']:"nothing.php";
include "/var/www/html/".$file;
?>

题目中已经说了,flag在根目录的flag下
我们使用../看根目录就可以读到flag
这里的$file = $_GET[‘file’]?$_GET[‘file’]:”nothing.php”;
是一种三元表达式
A?B:C
如果A成立返回B,不成立返回C
这里和C语言中的三元表达式是相同的

输入图片说明

5.http协议

配合文件包含,可以读取远程的php代码并在本地执行,实现了最终RCE的效果输入图片说明

6.ftp协议

默认21端口,进行文件传输的协议

7.php协议(重点)

php伪协议,伪协议的意思就是,这些协议只能在php中使用,而在其他地方使用不了,不是通用协议

php://input

include”php://input” ,include包含的路径就是php://input
然后判断有没有带<?php,没带的话就以文本形式输出,带的话就执行里面的php命令,我们用BP传入/flag,输出/flag而不是/flag里面的内容的原因就是这个

我们不能用hackber直接进行传参,如果不符合正确的格式,hackber会直接给我们丢掉,,在hackber中,传入aabbvv,include“php://input”就什么都读不到,而传入aabbvv=123,include“php://input”就能读到aabbvv=123

使用BP的话就可以避免这种情况,我们传入什么BP就读到什么,不会自动给我们丢掉,因此遇见include“php://input”的时候,我们要使用BP进行传参,但是如果我们直接传入,而不带

ctfshow私教课web32

1
2
3
4
5
6
<?php   
error_reporting(0);
highlight_file(__FILE__);
//flag in /flag
include "php://input";
?>

输入图片说明

ctfshow私教课web33(filter)

1
2
3
4
5
6
7
8
9
10
<?php   
error_reporting(0);
highlight_file(__FILE__);
//flag in /flag
$file = $_GET['file'];
$content = $_POST['content'];
if(preg_match("/\<|\>|\;|\(|\?/i")){
die("content not safe"); }
file_put_contents($file,$content);
?>

这里题目的意思是,要求我们传入一个文件名和文件的内容,我们要使用php://filter

write是写入,convert.base64-decode是对传入的经过base64编码后的内容进行base64解码,后面的/resource=1.php,是指将内容写到1.php,然后我们再访问1.php就可以看到指令执行的结果

这里传入的content是经过base64编码后的

输入图片说明

然后访问1.php就能拿到flag输入图片说明

ctfshow私教课web34(filter绕过死亡代码)

1
2
3
4
5
6
7
8
<?php   
error_reporting(0);
highlight_file(__FILE__);
//flag in /flag
$file = $_GET['file'];
$content = $_POST['content'];
file_put_contents($file,"<?php die();?>".$content);
?>

是一个死亡代码,到这里时,他会终止php代码的执行,我们可以使用php://filter进行绕过,这里要用凯撒密码

输入图片说明

content是经过rot13编码后的内容
原内容为
然后我们再访问1.php,就能成功绕过死亡代码,拿到flag
string.rot13将传入的内容进行rot13编码,一共就有26个字母,经过两次编码后,就变回了原来的内容
原理: 第一次编码后的传入的是没有php标记的,不会被识别为恶意的php代码而死亡,传入后,经过第二次编码变回原来的php恶意代码,从而绕过了死亡代码

输入图片说明

ctfshow私教课web35(data协议)

1
2
3
4
5
<?php   
error_reporting(0);
highlight_file(__FILE__);
include $_GET['file'].".php";
?>

输入图片说明

记住data协议的格式
/?file=data://text/plain/,
data://text/plain/,可以省略为
data://,
甚至data:,

php的文件上传机制

我们强制上传文件时,它会自动将我们的文件存放在
/tmp/php??????后面六位是随机的
我们可以用/???/?????????来找我们强制上传的文件,但是这样的文件有很多,我们可以对最后一位进行缩小范围,根据ascii表我们可以知道@-[,在这个范围内有全部的大写字母,我们可以进一步精确为/???/????????[@-[],这样当最后以为是大写字母的时候,我们就能抓到我们强制上传的文件,然后我们使用linux下的一个执行符号(.)让我们强制上传的文件执行,所以最终的结构为

.+/???/????????[@-[]
这里的加号代替空格

ctfshow私教课web13 (无字母数字命令执行+php强制文件上传)

1
2
3
4
5
6
7
<?php      
error_reporting(0);
highlight_file(__FILE__);
$cmd=$_GET['cmd'];
if(!preg_match("/[a-z]|[0-9]/i",$cmd)){ system($cmd);
}
?>

注意这里不是远程代码执行,不能使用异或,或,自增,取反进行绕过,我们可以使用强制文件上传

首先先构造一个强制文件上传的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://d660c159-574d-4067-9b19-0df274ec82c6.challenges.ctfer.com:8080/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

得到的是这样的一个页面输入图片说明

然后我们随便构造一个文本输入图片说明

上传这个文本,使用BP进行抓包

输入图片说明

在图中画圈处,传上我们构造的强制文件上传和文件里的指令(将文本里的内容改成命令就可以执行了),因为后面六位数是随机的,因此可能不会一下子就匹配到,我们多点几下,能看到的命令执行的结果后停止就行了,这里就可以拿到flag


路漫漫其修远兮,吾将上下而求索。