Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LeaseSet::ReadFromBuffer doesn't check leases bounds #1644

Closed
chadf opened this issue Mar 22, 2021 · 0 comments
Closed

LeaseSet::ReadFromBuffer doesn't check leases bounds #1644

chadf opened this issue Mar 22, 2021 · 0 comments

Comments

@chadf
Copy link
Contributor

chadf commented Mar 22, 2021

Crash due to invalid packet when lease count in message exceeds message size (lack of proper bounds checking).


Program terminated with signal SIGSEGV, Segmentation fault.

#0  0x000000000060544e in buf64toh (buf=0x807638ffc) at build/../libi2pd/I2PEndian.h:75
#1  0x0000000000605415 in bufbe64toh (buf=0x807638ffc) at build/../libi2pd/I2PEndian.h:91
#2  0x0000000000635506 in i2p::data::LeaseSet::ReadFromBuffer (this=0x8043d1398, readIdentity=false, verifySignature=true) at libi2pd/LeaseSet.cpp:98
#3  0x0000000000635723 in i2p::data::LeaseSet::PopulateLeases (this=0x8043d1398) at libi2pd/LeaseSet.cpp:54
#4  0x000000000057aa55 in i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6::operator()(std::__1::shared_ptr<i2p::data::LeaseSet>) const (this=0x804d4ba08, ls=...) at libi2pd/Destination.cpp:234
#5  0x000000000057a994 in std::__1::__invoke<i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6&, std::__1::shared_ptr<i2p::data::LeaseSet> > (__f=..., __args=...) at /usr/include/c++/v1/type_traits:3539
#6  0x000000000057a912 in std::__1::__invoke_void_return_wrapper<void>::__call<i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6&, std::__1::shared_ptr<i2p::data::LeaseSet> >(i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6&, std::__1::shared_ptr<i2p::data::LeaseSet>&&) (__args=..., __args=...) at /usr/include/c++/v1/__functional_base:348
#7  0x000000000057a8d2 in std::__1::__function::__alloc_func<i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6, std::__1::allocator<i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6>, void (std::__1::shared_ptr<i2p::data::LeaseSet>)>::operator()(std::__1::shared_ptr<i2p::data::LeaseSet>&&) (this=0x804d4ba08, __arg=...) at /usr/include/c++/v1/functional:1540
#8  0x0000000000579873 in std::__1::__function::__func<i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6, std::__1::allocator<i2p::client::LeaseSetDestination::FindLeaseSet(i2p::data::Tag<32ul> const&)::$_6>, void (std::__1::shared_ptr<i2p::data::LeaseSet>)>::operator()(std::__1::shared_ptr<i2p::data::LeaseSet>&&) (this=0x804d4ba00, __arg=...) at /usr/include/c++/v1/functional:1714
#9  0x00000000005953bd in std::__1::__function::__value_func<void (std::__1::shared_ptr<i2p::data::LeaseSet>)>::operator()(std::__1::shared_ptr<i2p::data::LeaseSet>&&) const (this=0x804d4b9d0, __args=...) at /usr/include/c++/v1/functional:1867
#10 0x0000000000587bb8 in std::__1::function<void (std::__1::shared_ptr<i2p::data::LeaseSet>)>::operator()(std::__1::shared_ptr<i2p::data::LeaseSet>) const (this=0x804d4b9d0, __arg=...) at /usr/include/c++/v1/functional:2473
#11 0x0000000000581ece in i2p::client::LeaseSetDestination::LeaseSetRequest::Complete (this=0x805f98478, ls=...) at build/../libi2pd/Destination.h:104
#12 0x000000000056e4c8 in i2p::client::LeaseSetDestination::HandleDatabaseStoreMessage (this=0x803a9f418, buf=0x8065a0577 "\201\024*\371\204y\224\340\203A\003}\b\206|^\215<f\304\260k\241\363\071\364\001E\374\226\302/\003", len=920) at libi2pd/Destination.cpp:452
#13 0x000000000056d7fd in i2p::client::LeaseSetDestination::HandleCloveI2NPMessage (this=0x803a9f418, typeID=i2p::eI2NPDatabaseStore, payload=0x8065a0577 "\201\024*\371\204y\224\340\203A\003}\b\206|^\215<f\304\260k\241\363\071\364\001E\374\226\302/\003", len=920) at libi2pd/Destination.cpp:351
#14 0x000000000056d756 in i2p::client::LeaseSetDestination::HandleI2NPMessage (this=0x803a9f418, buf=0x8065a0567 "\001\221\200$5", len=966) at libi2pd/Destination.cpp:336
#15 0x00000000005d5b42 in i2p::garlic::GarlicDestination::HandleGarlicPayload (this=0x803a9f418, buf=0x8065a0567 "\001\221\200$5", len=967, from=...) at libi2pd/Garlic.cpp:662

57              void LeaseSet::ReadFromBuffer (bool readIdentity, bool verifySignature)
58              {
59                      if (readIdentity || !m_Identity)
60                              m_Identity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen);
61                      size_t size = m_Identity->GetFullLen ();
62                      if (size > m_BufferLen)
63                      {
64                              LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", m_BufferLen);
65                              m_IsValid = false;
66                              return;
67                      }
68                      if (m_StoreLeases)
69                      {
70                              if (!m_EncryptionKey) m_EncryptionKey = new uint8_t[256];
71                              memcpy (m_EncryptionKey, m_Buffer + size, 256);
72                      }
73                      size += 256; // encryption key
74                      size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
75                      uint8_t num = m_Buffer[size];
76                      size++; // num
77                      LogPrint (eLogDebug, "LeaseSet: read num=", (int)num);
78                      if (!num || num > MAX_NUM_LEASES)
79                      {
80                              LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num);
81                              m_IsValid = false;
82                              return;
83                      }
84
85                      UpdateLeasesBegin ();
86
87                      // process leases
88                      m_ExpirationTime = 0;
89                      auto ts = i2p::util::GetMillisecondsSinceEpoch ();
90                      const uint8_t * leases = m_Buffer + size;
91                      for (int i = 0; i < num; i++)
92                      {
93                              Lease lease;
94                              lease.tunnelGateway = leases;
95                              leases += 32; // gateway
96                              lease.tunnelID = bufbe32toh (leases);
97                              leases += 4; // tunnel ID
98                              lease.endDate = bufbe64toh (leases);
 ^^^ SEGV here
99                              leases += 8; // end date
100                             UpdateLease (lease, ts);
101                     }

Relevant class & local variables:

m_BufferLen = 883
size = 680
num = 16
i = 4


Bounds exceeded:

size + (num * (32 + 4 + 8)) = 680 + (12 * 44) = 1208

1208 > 883


Perhaps changing:

78                      if (!num || num > MAX_NUM_LEASES)

to

78                      if (!num || num > MAX_NUM_LEASES || (size + (num * LEASE_SIZE)) > m_BufferLen)

would fix it.

i2pd-num_check-LeaseSet.cpp.patch.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant