Bug 3295 - ssh connection is closed when session id is not 32 bytes (Error - Session Id mismatch error)
Summary: ssh connection is closed when session id is not 32 bytes (Error - Session Id ...
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 8.5p1
Hardware: Other Windows 10
: P5 normal
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-04-09 11:50 AEST by balu
Modified: 2022-02-25 13:59 AEDT (History)
2 users (show)

See Also:


Attachments
ssh client log (28.59 KB, text/plain)
2021-04-21 10:33 AEST, balu
no flags Details
sshd server logs (23.51 KB, text/plain)
2021-04-21 10:33 AEST, balu
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description balu 2021-04-09 11:50:45 AEST
I'm from the win32 OpenSSH team. After merge V8.5, I'm occasionally getting session-id mismatch. If I retry then it goes away.

Looking at the sshd logs, the ssh->kex->session_id and session_id2 are matching but memcmp fails. one interesting observation is  session_id2_len is always 32 no matter how big the session id is.

---------------------
6220 2021-04-08 18:38:30.216 debug1: ssh->kex->session_id:+\350\274{\371b \276\220\030\272DC\206K!\301)\275\257c{\377\340\352\226\310 session_id2:+\350\274{\371b \276\220\030\272DC\206K!\301)\275\257c{\377\340\352\226\310 session_id2_len:32 ssh->kex->session_id_len:27
6220 2021-04-08 18:38:30.216 fatal: monitor_apply_keystate: session ID mismatch
6220 2021-04-08 18:38:30.216 debug1: do_cleanup
---------------------
5312 2021-04-08 18:01:51.939 debug1: ssh->kex->session_id:\0234\206 session_id2:\0234\206 session_id2_len:32 ssh->kex->session_id_len:3
5312 2021-04-08 18:01:51.939 fatal: monitor_apply_keystate: session ID mismatch
5312 2021-04-08 18:01:51.939 debug1: do_cleanup
---------------------
4484 2021-04-08 17:57:25.640 debug1: ssh->kex->session_id: session_id2: session_id2_len:32 ssh->kex->session_id_len:0
4484 2021-04-08 17:57:25.640 fatal: monitor_apply_keystate: session ID mismatch
4484 2021-04-08 17:57:25.640 debug1: do_cleanup
Comment 1 Damien Miller 2021-04-10 19:31:02 AEST
I can't really tell what is going on for lack of context.

At what point in the connection is the mismatch occuring?

> 5312 2021-04-08 18:01:51.939 debug1: ssh->kex->session_id:\0234\206 session_id2:\0234\206 session_id2_len:32 ssh->kex->session_id_len:3

The session ID length should only ever be exactly the same size as the KEX hash. There is no KEX hash that has a 3 byte output length :)
Comment 2 balu 2021-04-21 10:33:08 AEST
Created attachment 3497 [details]
ssh client log
Comment 3 balu 2021-04-21 10:33:42 AEST
Created attachment 3498 [details]
sshd server logs
Comment 4 balu 2021-04-21 10:41:51 AEST
Scenario - Normal ssh connection fails when session_id length is not 32.
Code - V8.5 introduces new code (in monitor_apply_keystate(), monitor.c) wherein authenticated sshd process verifies if the session_id. If there is a mismatch in the session id then it closes the connection. 

https://github.com/openssh/openssh-portable/blob/0727dd09eca355e7539cbcb23b148fcee9b21513/monitor.c#L1726

	if (memcmp(sshbuf_ptr(ssh->kex->session_id), session_id2,
	    session_id2_len) != 0)
		fatal_f("session ID mismatch");

strlen(sshbuf_ptr(ssh->kex->session_id)) is not always 32 but session_id2_len is always 32. If the strlen(sshbuf_ptr(ssh->kex->session_id)) is not 32 then memcmp condition fails on windows.

Fix - Use strlen(sshbuf_ptr(ssh->kex->session_id)) instead of session_id2_len.

	if (memcmp(sshbuf_ptr(ssh->kex->session_id), session_id2,
	    strlen(sshbuf_ptr(ssh->kex->session_id))) != 0)
		fatal_f("session ID mismatch");

FYI, I have attached the client, server-side logs on my windows machine for this issue when the session id is not 32 bytes.
Comment 5 balu 2021-04-27 11:48:27 AEST
ping. 
Did you get a chance to look at this issue?

Thank you.
Comment 6 Damien Miller 2021-04-30 14:04:04 AEST
I don't have any idea what is going wrong here - this does not occur with OpenSSH as we release it, so it is likely related to changes made by OpenSSH for Windows.

In any case, strlen() should never be called on the session ID and nor should printf("%s"). It is binary data and may contain \0 characters. For this reason the dumps in your sshd log aren't usable for debugging this - they are truncated.

If you are at some point treating it as an ASCIIZ/UTF8 string, then that's likely to be your problem.

I would recommend adding some sshbuf_dump(kex->session_id, stderr) to kex.c:kex_derive_keys(), packet.c:kex_to_blob(), packet.c:kex_from_blob() and monitor.c:monitor_apply_keystate()

Also sshbuf_dump_data(session_id2, session_id2_len, stderr) to monitor.c:mm_answer_sign() and monitor.c:monitor_apply_keystate()

These will dump all the session ID copies at various stages of their lifecycle and might clarify what is getting corrupted.
Comment 7 balu 2021-05-04 04:45:20 AEST
Thank you for your input.

Windows don't have the fork() so we added code (3 years back) to pass the required information from sshd root process to sshd authenticated process. 
OpenSSH V8.5 verifies the sessionid2 in the authenticated sshd process. I added a new code to pass the sessionid2 from sshd root process to sshd authenticated process. The bug lies here, I used sshbuf_put_cstring() which caused the bug.
Comment 8 Damien Miller 2022-02-25 13:59:10 AEDT
closing bugs resolved before openssh-8.9