[erlang-questions] 'ssh' security issue

Ingela Andin ingela.andin@REDACTED
Wed Dec 11 09:25:28 CET 2013


Hi!

As I mentioned in my previous post, ssh will change quite a lot in the
upcoming release so please
try it when it comes and let me now if there are any further improvements
that you need.

Regards Ingela Erlang/OTP team - Ericsson AB


2013/12/10 OvermindDL1 <overminddl1@REDACTED>

> Be calling the option with Exec added to it with a fixed
> handle_ssh_option test to test for if a fun as well.
>
> On Tue, Dec 10, 2013 at 3:15 PM, OvermindDL1 <overminddl1@REDACTED>
> wrote:
> > Nevermind, and for future documentation I found this in ssh_cli.erl:
> > ```
> > start_shell(_ConnectionHandler, Cmd, #state{exec={M, F, A}} = State) ->
> >     Group = group:start(self(), {M, F, A++[Cmd]}, [{echo, false}]),
> >     State#state{group = Group, buf = empty_buf()};
> > start_shell(ConnectionHandler, Cmd, #state{exec=Shell} = State) when
> > is_function(Shell) ->
> >
> >     ConnectionInfo = ssh_connection_handler:info(ConnectionHandler,
> >                                                  [peer, user]),
> >     {ok, User} =
> >         proplists:get_value(user, ConnectionInfo),
> >     ShellFun =
> >         case erlang:fun_info(Shell, arity) of
> >             {arity, 1} ->
> >                 fun() -> Shell(Cmd) end;
> >             {arity, 2} ->
> >                 fun() -> Shell(Cmd, User) end;
> >             {arity, 3} ->
> >                 [{_, PeerAddr}] =
> >                     proplists:get_value(peer, ConnectionInfo),
> >                 fun() -> Shell(Cmd, User, PeerAddr) end;
> >             _ ->
> >                 Shell
> >         end,
> >     Echo = get_echo(State#state.pty),
> >     Group = group:start(self(), ShellFun, [{echo,Echo}]),
> >     State#state{group = Group, buf = empty_buf()}.
> > ```
> > The exec property of the state record is set on init, so I figured I
> > could just pass in a fun instead like I can the shell option:
> > ```
> > {error,{eoptions,{exec,#Fun<msw_ssh_server.2.72054487>}}
> > ```
> > Nope.  But yet it looks like it should accept a fun fine, so... what
> > is going on.
> > I take a look at where ssh_cli is called and found this in
> > ssh_connection_handler.erl:
> > ```
> >     Shell = proplists:get_value(shell, Opts),
> >     Exec = proplists:get_value(exec, Opts),
> >     CliSpec = proplists:get_value(ssh_cli, Opts, {ssh_cli, [Shell]}),
> >     State#state{starter = Pid, connection_state = Connection#connection{
> >                                                     cli_spec = CliSpec,
> >                                                     exec = Exec,
> >                                                     system_supervisor
> > = SystemSup,
> >
> > sub_system_supervisor = SubSystemSup,
> >
> > connection_supervisor = ConnectionSup
> >                                                    }}.
> > ```
> > So, it seems the exec is set here as an option to the connection
> > state, and the exec is filtered on this in ssh.erl:
> > ```
> >
> > handle_ssh_option({exec, {Module, Function, _}} = Opt) when
> is_atom(Module),
> >
> is_atom(Function) ->
> >
> >     Opt;
> > ```
> > And that looks like it should work, but wait, remember what I said
> > about exec only being set on init in ssh_cli.erl, and look at the line
> > above that sets the default ssh_cli option:
> > ```
> >     CliSpec = proplists:get_value(ssh_cli, Opts, {ssh_cli, [Shell]}),
> > ```
> > Hmm, so it never sets the exec option in the ssh_cli, if it did then
> > it should actually be calling:
> > ```
> >     CliSpec = proplists:get_value(ssh_cli, Opts, {ssh_cli, [Shell,
> Exec]}),
> > ```
> > Yet it is not.  So I removed my shell and exec options from ssh:daemon
> > and replaced it with a single option of:
> > ```
> >     {ssh_cli, {ssh_cli, [
> >         fun(User, PeerAddr) -> msw_ssh_server_shell:start(User,
> PeerAddr) end,
> >         fun(Cmd, User, PeerAddr) -> msw_ssh_server_shell:exec(Cmd,
> > User, PeerAddr) end]}},
> > ```
> > And badda bing it works.  I am not sure if this is the 'proper' way to
> > do it (and I would love to learn of a proper way if it exists), but it
> > works with both setting a shell, exec, and getting the User and
> > PeerAddress in both cases as well.
> >
> > On Tue, Dec 10, 2013 at 2:26 PM, OvermindDL1 <overminddl1@REDACTED>
> wrote:
> >> Another question while I am at it with this exec option, the 'shell'
> >> option gets a User and PeerAddr passed in, any way to do that with
> >> exec?  If I can at least get the User then I can allow them to issue
> >> one-off commands this way too, which would be quite useful for remote
> >> scripting.
> >>
> >> On Tue, Dec 10, 2013 at 2:22 PM, OvermindDL1 <overminddl1@REDACTED>
> wrote:
> >>> Ah all you are amazing, I never saw that option in the docs indeed and
> >>> looks like it should do what I want.  Thanks much for all the help!
> >>>
> >>> On Tue, Dec 10, 2013 at 10:20 AM, Jakob Cederlund <jakobce@REDACTED>
> wrote:
> >>>> Actually, the sample cli module works quite all right. The problem is
> that
> >>>> the default implementation in ssh_cli for the "exec" thing in ssh is
> >>>> actually to execute it (using erl_scan and erl_eval and stuff). There
> is an
> >>>> undocumented option to ssh (actually to the ssh_cli module) that can
> be used
> >>>> to customize this. The option {exec, {M, F, []}} takes an exported
> function
> >>>> (M:F/1) that is called with the parameters given to the ssh commands
> as a
> >>>> string. This function should spawn a process that writes the desired
> output
> >>>> on stdout.
> >>>>
> >>>> So to avoid the strange eval phenomenon, and provide another function
> that
> >>>> just echoes the parameters back, you can write a module x:
> >>>> -module(x).
> >>>> -export([exec/1]).
> >>>> exec(A) -> spawn(fun() -> io:format("~p\n", [A]), exit(normal) end).
> >>>>
> >>>> and specify the function x:exec/1 as a call-back for the exec option:
> >>>> B=ssh_sample_cli:listen(8323, [{subsystems, []}, {exec, x, exec, ""]).
> >>>>
> >>>> And then when you do:
> >>>>> ssh -p 8323 to.the.host 'lists:reverse("test").'
> >>>>
> >>>> You get back:
> >>>> "list:reverse(\"test\")."
> >>>>
> >>>> Hope this helps. (And sorry for the mess…)
> >>>> /Jakob
> >>>>
> >>>>
> >>>>
> >>>> 2013/12/10 Ingela Andin <ingela.andin@REDACTED>
> >>>>>
> >>>>> Hi!
> >>>>>
> >>>>> The CLI example in the SSH application must be seen as a hack. We
> intend
> >>>>> to clean it up and
> >>>>> extend the SSH documentation, when it gets prioritized I can not
> say. Well
> >>>>> anyway your CLI
> >>>>> implementation must take care of SSH exec request as well.  You can
> also
> >>>>> look at the ssh_cli.erl  module.
> >>>>> If I remember correctly there was a bug, before ssh-2.1.7, with
> regards to
> >>>>> the exec request  so that  it was not forwarded to CLI process but
> rather
> >>>>> always interpreted in the erlang shell environment.
> >>>>>
> >>>>> Regards Ingela Erlang/OTP team - Ericsson AB
> >>>>>
> >>>>>
> >>>>>
> >>>>> 2013/12/7 OvermindDL1 <overminddl1@REDACTED>
> >>>>>>
> >>>>>> Greetings,
> >>>>>>
> >>>>>> I am attempting to just create an SSH shell to connect to a system
> by
> >>>>>> users so they can do commands without the web interface, and as
> such I
> >>>>>> certainly do not want things like port forwarding or being able to
> run
> >>>>>> arbitrary erlang code, however I do not seem to be able to disable
> >>>>>> running arbitrary erlang code.  An example of the ssh_sample_cli
> >>>>>> included with erlang:
> >>>>>> """
> >>>>>> $ erl
> >>>>>> Erlang R16B02 (erts-5.10.3) [source] [64-bit] [smp:8:8]
> >>>>>> [async-threads:10] [hipe] [kernel-poll:false]
> >>>>>>
> >>>>>> Eshell V5.10.3  (abort with ^G)
> >>>>>> 1> c(ssh_sample_cli).
> >>>>>> ssh_sample_cli.erl:146: Warning: this expression will fail with a
> >>>>>> 'badarith' exception
> >>>>>> {ok,ssh_sample_cli}
> >>>>>> 2> B=ssh_sample_cli:listen(8323, [{subsystems, []}]).
> >>>>>> {ok,<0.67.0>}
> >>>>>> """
> >>>>>>
> >>>>>> And from another shell/computer:
> >>>>>> """
> >>>>>> $ ssh -p 8321 to.the.host
> >>>>>> myusername@REDACTED's password:
> >>>>>> Enter command
> >>>>>> CLI> help
> >>>>>> CLI Sample
> >>>>>> crash                  crash the cli
> >>>>>> exit                   exit application
> >>>>>> factors    <int>       prime factors of <int>
> >>>>>> gcd        <int> <int> greatest common divisor
> >>>>>> help                   help text
> >>>>>> host                   print host addr
> >>>>>> lcm        <int> <int> least common multiplier
> >>>>>> prime      <int>       check for primality
> >>>>>> primes     <int>       print all primes up to <int>
> >>>>>> rho        <int>       prime factors using rho's alg.
> >>>>>> self                   print my pid
> >>>>>> user                   print name of user
> >>>>>>
> >>>>>> ---> ok
> >>>>>> CLI> exit
> >>>>>> ---> done
> >>>>>> Connection to to.the.host closed.
> >>>>>> """
> >>>>>>
> >>>>>> So far so good (the main program where I have this implemented has a
> >>>>>> well running shell of its own), but lets try a couple other things:
> >>>>>> """
> >>>>>> $ sftp -P 8321 to.the.host
> >>>>>> myusername@REDACTED's password:
> >>>>>> subsystem request failed on channel 0
> >>>>>> Connection closed
> >>>>>> """
> >>>>>>
> >>>>>> Also good, no file transfers can be done since the option subsystem
> is
> >>>>>> set to [], but notice:
> >>>>>> """
> >>>>>> $ ssh -p 8323 to.the.host 'lists:reverse("!?ti pots I od woh dna
> ereh
> >>>>>> gnineppah si tahw woN").'
> >>>>>> myusername@REDACTED's password:
> >>>>>> "Now what is happening here and how do I stop it?!"
> >>>>>> """
> >>>>>>
> >>>>>> So... I can still run arbitrary erlang commands, how do I stop this?
> >>>>>> Unable to find an option to pass in or anything through a quick code
> >>>>>> perusal to no avail.  Help?
> >>>>>> _______________________________________________
> >>>>>> erlang-questions mailing list
> >>>>>> erlang-questions@REDACTED
> >>>>>> http://erlang.org/mailman/listinfo/erlang-questions
> >>>>>
> >>>>>
> >>>>>
> >>>>> _______________________________________________
> >>>>> erlang-questions mailing list
> >>>>> erlang-questions@REDACTED
> >>>>> http://erlang.org/mailman/listinfo/erlang-questions
> >>>>>
> >>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20131211/6ec0a089/attachment.htm>


More information about the erlang-questions mailing list