--- a/src/common/classes/ClumpletReader.cpp
+++ b/src/common/classes/ClumpletReader.cpp
@@ -591,6 +591,8 @@ FB_SIZE_T ClumpletReader::getClumpletSize(bool wTag, bool wLength, bool wData) c
return 0;
}
+ const FB_UINT64 maxTotalLength = buffer_end - clumplet;
+
FB_SIZE_T rc = wTag ? 1 : 0;
FB_SIZE_T lengthSize = 0;
FB_SIZE_T dataSize = 0;
@@ -666,15 +668,17 @@ FB_SIZE_T ClumpletReader::getClumpletSize(bool wTag, bool wLength, bool wData) c
invalid_structure("unknown clumplet type", t);
}
- const FB_SIZE_T total = 1 + lengthSize + dataSize;
- if (clumplet + total > buffer_end)
+ // Avoid possible overflow
+ FB_UINT64 totalLength = 1 + lengthSize + static_cast<FB_UINT64>(dataSize);
+
+ if (totalLength > maxTotalLength)
{
- invalid_structure("buffer end before end of clumplet - clumplet too long", total);
- FB_SIZE_T delta = total - (buffer_end - clumplet);
+ invalid_structure("buffer end before end of clumplet - clumplet too long", totalLength);
+ FB_UINT64 delta = totalLength - maxTotalLength;
if (delta > dataSize)
dataSize = 0;
else
- dataSize -= delta;
+ dataSize -= static_cast<FB_SIZE_T>(delta);
}
if (wLength) {
Summary
Incorrect parsing of clumplet allows authenticated user to DoS the server.
Details
The main bug is in the
ClumpletReader::getClumpletSize()function, It is possible to overflowtotalLengthwhen parsingWidetype, which can lead to an infinite loop. I have found that this can be exploited in batch clumplet (there may be other ways in which it can be abused that I have not yet figured out).The following is an example of a stack trace when this vulnerability is exploited:
Stacktrace
Therefore, if an authenticated user has the INSERT privilege for a given table, they can create an infinite number of requests that will cause a DoS attack on the server.
PoC
I created a database with one table and granted the user INSERT privileges for that table. Then I attached it, started a transaction and created a batch with specific bpb (Batch Parameter Block) (this bpb can be found inside the Program below).
I wrote a simple C++ program to reproduce this:
Program
Impact
Essentially, every server is affected.
Patch with fix
I have write a possible fix for this issue:
Patch diff