I was working on the agent for SSH Pot and ran into something interesting last night. A lot of the brute force attempts attempt to run a command like this:

This is different than:

1 ssh [email protected] 2 $ uname

The first command is executing a command then exiting, the second is actually logging in and giving the user a shell. The first requests a exec subsystem and the second requests a shell subsystem - so there are two ways to handle it.

1 func HandleShellRequest ( channel ssh . Channel , in <- chan * ssh . Request ) { 2 for req := range in { 3 ok := true 4 logfile . Println ( "[request " + req . Type + "]: " + string ( req . Payload )) 5 switch req . Type { 6 case "shell" : 7 req . Reply ( ok , nil ) 8 case "exec" : 9 if string ( req . Payload ) == string ( "uname" ) { 10 channel . Write ([] byte ( "

\rLinux

\r" )) 11 } 12 13 channel . Close () 14 } 15 } 16 }

When logging in my logfile it would show something like:

1 [ request exec ] : uname

And even when comparing the two side by side with something like this:

1 logfile . Println ( "[" + string ( req . Payload ) + "]:[" + "uname" + "]" )

I would get this output:

1 [ uname ] : [ uname ]

Yet the comparison on line 9 would not get hit. After sitting and thinking about it for a while I decided to print the bytes out:

1 INFO: 2014 /07/07 23 :15:18 sshd.go:157: [ 0 0 0 5 117 110 97 109 101 ] 2 INFO: 2014 /07/07 23 :15:18 sshd.go:158: [ 117 110 97 109 101 ]

Aha! So for some reason req.Payload is padded with 3 null bytes and a ENQ byte (hex 5).

Here is the corrected version removing the correct bytes - now the string comparison works: