stevegeek / hashids.rb

A small Ruby gem to generate YouTube-like hashes from one or many numbers. Use hashids when you do not want to expose your database ids to the user.
http://www.hashids.org/ruby/
MIT License
0 stars 0 forks source link

`Hashids#internal_decode` uses `String#tr` incorrectly #1

Open stevegeek opened 1 year ago

stevegeek commented 1 year ago

Hashids#internal_decode uses String#tr incorrectly. It is being used to replace all characters in @seps/@guards with a space, but the first argument to tr is in fact a Ruby "character selector" string https://docs.ruby-lang.org/en/master/character_selectors_rdoc.html

Certain inputs, as found by fuzzing, can cause @seps for example to contain a string which looks like an invalid selector, thus causing it to raise.

hashids.rb/lib/hashids.rb:124:in `tr': invalid range "H-" in string transliteration (ArgumentError)

      breakdown = breakdown[1 .. -1].tr(@seps, " ")
                                        ^^^^^^^^^^
        from ...hashids.rb/lib/hashids.rb:124:in `internal_decode'
        from ...hashids.rb/lib/hashids.rb:49:in `decode'
stevegeek commented 1 year ago

Eg from fuzzing (input, alphabet and salt are all Base64.strict_encode64 encoded below):

Random Input: +JGWGLiTpw51guWxaeJiG+9H2YPcGxOOtKomIlIPx+xWeok572++DNvasYMLv3/Jz2k0mr1m Alphabet: vr06/KkbUBRVN8pZK29ANfd41XPCngWd5wOjgT5OWDzYP92Jy7uoGTPaRuAYO4Asl342XySiZ/qyhCi6oVq31NFSHlFN7pyajHYBzzFIf79JBJEOqyPIld90tA8qY4aSTNdqYovHRBGC6egHjfSIoD1k7VPlQ5vcYYUTJwZyLUs4LuRFFmu5wMa2fKS8Jt5X+W31sEpxkP7E6vtllB1w+M4v4VbNMhD2KWZsW+LTjlQifRoCQk97n+Nuwx/WsRLFuIe1YJODafJ6FUFo8KfBrtvsF6bS/cx5JeZ3r//J Salt: 15tyyKsQhlf59cL2nsQ3/iA3lvIU6yIydfPypwalZRrQg+rM0SCSiw/awAS8BhDOhGwwAl7/SeZ54J1+KTx3OJ8= Length: 4862

stevegeek commented 1 year ago

Repro:

require "base64"

Hashids.new(Base64.strict_decode64("15tyyKsQhlf59cL2nsQ3/iA3lvIU6yIydfPypwalZRrQg+rM0SCSiw/awAS8BhDOhGwwAl7/SeZ54J1+KTx3OJ8="), 4862, Base64.strict_decode64("vr06/KkbUBRVN8pZK29ANfd41XPCngWd5wOjgT5OWDzYP92Jy7uoGTPaRuAYO4Asl34
2XySiZ/qyhCi6oVq31NFSHlFN7pyajHYBzzFIf79JBJEOqyPIld90tA8qY4aSTNdqYovHRBGC6egHjfSIoD1k7VPlQ5vcYYUTJwZyLUs4LuRFFmu5wMa2fKS8Jt5X+W31sEpxkP7E6vtllB1w+M4v4VbNMhD2KWZsW+LTjlQifRoCQk97n+Nuwx/WsRLFuIe1YJODafJ6FUFo8KfBrtvsF6bS/cx5JeZ3r//J")).decode(Base64.strict_decode
64('+JGWGLiTpw51guWxaeJiG+9H2YPcGxOOtKomIlIPx+xWeok572++DNvasYMLv3/Jz2k0mr1m'))