Skip to content

qeeqbox/session-fixation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

An application manages session identifiers in an insecure manner, making them susceptible to reuse by threat actors. Session identifiers are crucial for maintaining a user's authenticated session. If an application permits the reuse of a session identifier, a threat actor could trick a victim into logging in with a session identifier they already control. Once the victim successfully logs in, the threat actor can use that same session identifier to hijack the authenticated session and impersonate the legitimate user.

Clone this current repo recursively

git clone --recurse-submodules https://github.com/qeeqbox/session-fixation

Run the webapp using Python

python3 session-fixation/vulnerable-web-app/webapp.py

Open the webapp in your browser 127.0.0.1:5142

Use John's default credentials (username: john and password: john) to login

Open the Storage tab in the developer tools to examine the request cookies, note the session_id used for the current session

Open the private tab (or change the browser profile), type the webapp address in your browser 127.0.0.1:5142?session_id=

Use Jane's default credentials (username: jane and password: jane) to login

Open the Storage tab in the developer tools to examine the request cookies, the session_id should be the same as John

Go to John's session and refresh the webpage, it will be Jane's session

Code

When a user logs in to the page, the parameters like session_id are passed to the gen_cookie() function

def do_POST(self):
    parsed_url = urllib_parse.urlparse(self.path)
    post_request_data_length = int(self.headers.get('content-length'))
    post_request_data = urllib_parse.parse_qs(str(self.rfile.read(post_request_data_length),"UTF-8"))
    query_request_data = urllib_parse.parse_qs(parsed_url.query)
    self.session = self.check_logged_in()
    if parsed_url.path == "/login" and "username" in post_request_data and "password" in post_request_data:
        ret = self.check_creds(post_request_data['username'][0],post_request_data['password'][0])
        if isinstance(ret, list) and ret[0] == "valid":
            self.send_content(302, self.gen_cookie(ret[1],60*15,query_request_data)+[('Location', URL)], None)
            self.log_message("%s logged in" % post_request_data['username'][0])
            return
        elif isinstance(ret, list) and ret[0] == "password":
            if "debug" in post_request_data:
                if post_request_data["debug"][0] == "1":
                    self.send_content(302, self.gen_cookie(ret[1],60*15,query_request_data)+[('Location', URL)], None)
                    self.log_message("%s logged in" % post_request_data['username'][0])
                    return
            self.send_content(401, [('Content-type', 'text/html')], self.msg_page(f"Password is wrong".encode("utf-8"), b"login"))
            return
        elif isinstance(ret, list) and ret[0] == "username" or isinstance(ret, list) and ret[0] == "error":
            self.send_content(401, [('Content-type', 'text/html')], self.msg_page(f"User {post_request_data['username'][0]} doesn't exist".encode("utf-8"), b"login"))
            return

The gen_cookie() function sets up the session_id with one passed from the request parameters if it exists

    def gen_cookie(self, row, max_age, query):
        session_id = None
        cookies = SimpleCookie(self.headers.get('Cookie'))
        if 'session_id' in query:
            session_id = query['session_id'][0]
        elif 'session_id' in cookies:
            session_id = cookies['session_id'].value
        else:
            session_id = "".join(str(randint(1, 9)) for _ in range(5))
        #end_time = datetime.now() + timedelta(days=1)
        SESSIONS[session_id] = {"username":row[1], "department": row[3],"access":row[4], "is_admin":row[5]}
        cookie1 = SimpleCookie()
        cookie1['session_id'] = session_id
        cookie1['session_id']['path'] = '/'
        cookie1['session_id']['max-age'] = max_age
        cookie2 = SimpleCookie()
        cookie2['is_admin'] = row[5]
        cookie2['is_admin']['path'] = '/'
        cookie2['is_admin']['max-age'] = max_age
        cookie3 = SimpleCookie()
        cookie3['access'] = row[4]
        cookie3['access']['path'] = '/'
        cookie3['access']['max-age'] = max_age
        cookie4 = SimpleCookie()
        cookie4['department'] = row[3]
        cookie4['department']['path'] = '/'
        cookie4['department']['max-age'] = max_age
        cookies = [('Set-Cookie', cookie1.output(header='', sep='')),('Set-Cookie', cookie2.output(header='', sep='')),('Set-Cookie', cookie3.output(header='', sep='')),('Set-Cookie', cookie4.output(header='', sep=''))]
        return cookies

About

A threat actor may trick a user into using a known session identifier to log in. after logging in, the session identifier is used to gain access to the user's account

Topics

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

Contributors