openssh 6.8p1 heap buffer overflow

Credit: Hanno Böck
Risk: High
Local: No
Remote: Yes

Quick background story: I started a while ago to develop a solution to use american fuzzy lop with networking input. I did so by creating a library to be preloaded with LD_PRELOAD that would intercept some functions to simulate a network connection and pass data from a file. This is trickier than it sounds and doesn't really work yet, but I managed to use this to fuzz the ssh client handshake. In combination with address sanitizer this turned up a read heap overflow. I reported this to openssh's damien miller. He considered it not security relevant and committed the fix to the public repo: With that it was public, but nobody noticed. Until today someone proposed a very similar approach to network fuzzing on the afl mailing list and I answered that I was working on this and briefly mentioned the ssh overflow: Now this is making rounds on twitter, so I thought I'd publish all details. I just pasted below what I reported to openssh. As this is only a read overflow it likely is not exploitable in any way, but itsec history has shown that often enough when people think something is not exploitable they were wrong. If this makes you nervous apply the patch linked above (which will just remove the length argument from the function) or this shorter patch which will just fix the wrong function cal: --- openssh-6.8p1/compat.c 2015-03-17 06:49:20.000000000 +0100 +++ openssh-6.8p1-fix/compat.c 2015-05-03 17:51:32.251293388 +0200 @@ -229,7 +229,7 @@ buffer_init(&b); tmp = orig_prop = xstrdup(proposal); while ((cp = strsep(&tmp, ",")) != NULL) { - if (match_pattern_list(cp, filter, strlen(cp), 0) != 1) { + if (match_pattern_list(cp, filter, strlen(filter), 0) != 1) { if (buffer_len(&b) > 0) buffer_append(&b, ",", 1); buffer_append(&b, cp, strlen(cp)); ------------------------------- I think I found a bug in ssh, maybe security relevant. It's surprisingly easy to reproduce: * Compile latest openssh 6.8p1 with address sanitizer (./configure CFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address"; make) * Run this netcat-command: echo "SSH-2.0-OpenSSH_6.5"|nc -l -p 22 * ssh to it: ./ssh I'm not entirely sure when and why this is triggered, doesn't work against a real ssh server (I assume something with the version number and not answering after the inital banner to the client) However, here is why it causes an invalid memory access: In combat.c there is this call for the function match_pattern_list in line 232: if (match_pattern_list(cp, filter, strlen(cp), 0) != 1) { The function definition (match.c, line 120): match_pattern_list(const char *string, const char *pattern, u_int len, Looking at the function (match.c, line 141/142) we have this: for (subi = 0; i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; subi++, i++) It will iterate over pattern with length len. pattern is the second parameter passed. But in the function call len is given as the length of the first parameter. So they don't match and this will cause a buffer overflow if cp is longer than filter. So the function call really should be: if (match_pattern_list(cp, filter, strlen(filter), 0) != 1) { Right? (Not 100% sure if I got everything what's happening here...) See attached patch. Will also attach an address sanitizer stack trace (for reasons unknown to me this stack trace only appears if I compile openssh with afl + asan, not with asan alone) -- Hanno Böck


Vote for this issue:


Thanks for you vote!


Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.

(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024,


Back to Top