SNMP vulnerability

Martin Bjorklund mbj@REDACTED
Wed Feb 13 13:12:30 CET 2002


Hi,

You might have seen that CERT has found vulnerabilities in many
implementations of SNMP (http://www.cert.org/advisories/CA-2002-03.html)

I've had an oppurtunity to run the tool they're using to find these
falws towards OTP's SNMP agent (some 30.000 cases with mostly
malformed ASN.1 PDUs).  No security issues were found, and the agent
did not waste resources during the test.

However, I did found a couple of bugs; in some of the corner cases the
packets were silently dropped but the snmpInASNParseErrs counter was
not incremented.  A patch for this bug is attached.  (Also, looking at
the code in snmp_pdus.erl, I realize that there is lots of room for
improvments!)


/martin

-------------- next part --------------
*** /usr/local/lib/erlang/lib/snmp-3.3.3/src/snmp_pdus.erl	Wed Dec 12 11:23:05 2001
--- snmp_pdus.erl	Wed Feb  6 14:49:59 2002
***************
*** 256,274 ****
      {{'IpAddress', Value}, Rest};
  dec_value([65 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     {{'Counter32', Value}, Rest};
  dec_value([66 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     {{'Unsigned32', Value}, Rest};
  dec_value([67 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     {{'TimeTicks', Value}, Rest};
  dec_value([68 | Bytes]) ->
      {Value, Rest} = dec_oct_str_notag(Bytes),
      {{'Opaque', Value}, Rest};
  dec_value([70 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     {{'Counter64', Value}, Rest};
  dec_value([128,0|T]) ->
      {{'NULL', noSuchObject}, T};
  dec_value([129,0|T]) ->
--- 253,287 ----
      {{'IpAddress', Value}, Rest};
  dec_value([65 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     if Value >= 0, Value =< 4294967295 ->
! 	    {{'Counter32', Value}, Rest};
!        true ->
! 	    exit({error, {bad_counter32, Value}})
!     end;
  dec_value([66 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     if Value >= 0, Value =< 4294967295 ->
! 	    {{'Unsigned32', Value}, Rest};
!        true ->
! 	    exit({error, {bad_unsigned32, Value}})
!     end;
  dec_value([67 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     if Value >= 0, Value =< 4294967295 ->
! 	    {{'TimeTicks', Value}, Rest};
!        true ->
! 	    exit({error, {bad_timeticks, Value}})
!     end;
  dec_value([68 | Bytes]) ->
      {Value, Rest} = dec_oct_str_notag(Bytes),
      {{'Opaque', Value}, Rest};
  dec_value([70 | Bytes]) ->
      {Value, Rest} = dec_integer_notag(Bytes),
!     if Value >= 0, Value =< 18446744073709551615 ->
! 	    {{'Counter64', Value}, Rest};
!        true ->
! 	    exit({error, {bad_counter64, Value}})
!     end;
  dec_value([128,0|T]) ->
      {{'NULL', noSuchObject}, T};
  dec_value([129,0|T]) ->
***************
*** 288,294 ****
  	length(Tail) == Size ->
  	    Tail;
  	true ->
! 	    exit({error, {'wrong length', Bytes}})
      end.
  
  split_at(L, 0, Acc) -> {lists:reverse(Acc), L};
--- 301,307 ----
  	length(Tail) == Size ->
  	    Tail;
  	true ->
! 	    exit({error, {wrong_length, Bytes}})
      end.
  
  split_at(L, 0, Acc) -> {lists:reverse(Acc), L};
***************
*** 676,686 ****
  
  enc_integer_tag(Val) when Val >= 0 ->  %% stdcase positive ints
      Bytes = eint(Val,[]),
!     [2, length(Bytes) | Bytes];
  
  enc_integer_tag(Val) ->  %% It's a negative number
      Bytes = enint(Val,[]),
!     [2, length(Bytes) | Bytes].
  
  enc_integer_notag(Val) when Val >= 0 ->  %% stdcase positive ints
      eint(Val,[]);
--- 689,699 ----
  
  enc_integer_tag(Val) when Val >= 0 ->  %% stdcase positive ints
      Bytes = eint(Val,[]),
!     [2 | elength(length(Bytes))] ++ Bytes;
  
  enc_integer_tag(Val) ->  %% It's a negative number
      Bytes = enint(Val,[]),
!     [2 | elength(length(Bytes))] ++ Bytes.
  
  enc_integer_notag(Val) when Val >= 0 ->  %% stdcase positive ints
      eint(Val,[]);


More information about the erlang-questions mailing list