[CSAW CTF Qualification Round 2017] - Shia Labeouf-off! (Web 150)

題目資訊

Do it
Just do it
Don’t let your dreams be dreams
Yesterday you said tomorrow
So just do it
Make your dreams come true
Just do it
Pick 1: http://web.chal.csaw.io:5487 http://web.chal.csaw.io:5488 http://web.chal.csaw.io:5489 http://web.chal.csaw.io:5490

解法

網站是用 Django 寫成,在 http://web.chal.csaw.io:5487/ad-lib/ 有個 textarea 提供使用者寫 template 給 server 用。
介面大致上長這樣子:

Give me an ad lib and I will Shia Labeouf it up for you!
Where you want a noun, just put: ““, for a verb: ““, and for an adjective: ““!


先輸入 {{}} 來引發錯誤,可以看到 debug 資訊。
顯示了錯誤的行數跟 template 的 source :

1
2
3
4
5
6
7
{% extends 'base.html' %}
{% load pools_extras %}
{% block breadcrumb-page %}Format{% endblock breadcrumb-page %}
{% block content %}
{{}}
{% endblock content %}

在 Traceback 也有一些資訊:
./ad-lib/views.py in index

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def index(request):
global obj
if request.method == "POST":
data = request.POST.get('formatdata', '')
template_data = TEMP.format(data.replace("noun", "noun|safe").replace("verb", "verb|safe").replace("adjective", "adjective|safe"))
template = Template(template_data)
context = RequestContext(request, {
'noun': '<img src="https://media0.giphy.com/media/arNexgslLkqVq/200.webp#70-grid1" />',
'verb': '<img src="https://media3.giphy.com/media/R0vQH2T9T4zza/200.webp#165-grid1" />',
'adjective': '<img src="https://media1.giphy.com/media/TxXhUgEUWWL6/200.webp#129-grid1" />',
'mrpoopy': obj
})
shit = template.render(context)
return HttpResponse(shit)
return render(request, 'ad-lib/format.html')

看起來 mrpoopy 應該是個關鍵, render 後是一個 obj 。
嘗試輸入 {{ mrpoopy }} 得到 <ad-lib.someclass.Woohoo instance at 0x7fa795932638>
不過不知道有哪些 attribute ,所以再來應該就是要想辦法得知才能使用。

再觀察一下可發現在 template 裡有 {% load pools_extras %} ,也許 load 進來後有一些東西可以利用。

再來看看 http://web.chal.csaw.io:5487/polls/

有兩個連結,分別是 /polls/2//polls/1/
隨意嘗試了投票,都會顯示 You are unable to vote at this time.
那麼如果連到 http://web.chal.csaw.io:5487/polls/3/ 看看呢?
出現了 Our infrastructure can't support that many Shias! 錯誤,列出 debug 資訊!

./polls/templatetags/pools_extras.py in checknum

1
2
3
4
5
6
7
8
9
10
@register.filter(name='getme')
def getme(value, arg):
return getattr(value, arg)
@register.filter(name='checknum')
def checknum(value):
check(value) ...
@register.filter(name='listme')
def listme(value):
return dir(value)
def check(value):

./polls/templatetags/pools_extras.py in check

1
2
3
4
5
6
@register.filter(name='listme')
def listme(value):
return dir(value)
def check(value):
if value > 2:
raise Exception("Our infrastructure can't support that many Shias!") ...

發現 pools_extrasgetmelistme 可以用!

回到 http://web.chal.csaw.io:5487/ad-lib/
先看有哪些 attribute 可以用
輸入 {{ mrpoopy|listme }}

1
['Woohoo', '__doc__', '__flag__', '__module__']

再來就用 getme 來執行 __flag__
輸入 {{ mrpoopy|getme:'__flag__' }}

1
flag{wow_much_t3mplate}

Flag: flag{wow_much_t3mplate}

後記

我不會 Django QAQ,看了一堆官方文件,找了一堆資料,努力把 template tag 的部分看完,最後終於知道 template 跟 view 怎麼運作的了!我看得好辛苦啊啊 _(:з」∠)_
簡單來說就是:Template(template_data).render(RequestContext(request, context_data))
view 在 render 時把 context 資料放進 teamplate 裡,就會得到最後看到的網頁 HTML 了。

寫網誌也遇到一些問題,像是 {{ }}{% %} 會被 hexo 解析,所以要用 {% raw %} {% endraw %} 把它們包起來,有點麻煩呢 (´・ω・`)