Browse Source

Changed engine update number to .14 (now Version 3.0.14).

Modified FilterChainDefunker to avoid recursion when eating (X)HTML tags. Now there is a new mechanism that allows deeper states to return nothing (no conversion) by setting a boolean flag. The result is that the root state will skip that result and try again with the next available byte in a simple loop (no recursion). This eliminates a vulnerability where a message constructed with deeply embeded / chained (X)HTML tags could cause the system to run out of stack space under some conditions.


git-svn-id: https://svn.microneil.com/svn/SNFMulti/trunk@32 dc71a809-1921-45c4-985c-09c81d0142d9
wx
madscientist 14 years ago
parent
commit
f3a6bb0900
3 changed files with 34 additions and 16 deletions
  1. 25
    15
      FilterChain.cpp
  2. 8
    0
      FilterChain.hpp
  3. 1
    1
      SNFMulti.cpp

+ 25
- 15
FilterChain.cpp View File

@@ -528,19 +528,28 @@ unsigned char FilterChainDefunker::Preamble() { // Emit the preamble.
return GetInternal(); // and return the next byte.
}

unsigned char FilterChainDefunker::DefunkRoot() { // While in DefunkRoot state
unsigned char x = GetStore(); // grab the next byte.
if(x == '<') { // If it matches < then
Internal = &FilterChainDefunker::OpenTag; // go to OpenTag state and
return GetInternal(); // return the next byte.
} else
if(x == '&') { // If it matches & then
Internal = &FilterChainDefunker::OpenAmp; // go to OpenAnd state and
EnQueue(x); // push in the amphersand.
return GetInternal(); // return the next byte.

} // If we did not match then
return x; // return what we grabbed.
unsigned char FilterChainDefunker::DefunkRoot() { // While in DefunkRoot state...
unsigned char x = 0; // One byte at a time via x.
do { // Loop through any emptiness.
ReturnNothing = false; // Be ready to return a byte.
x = GetStore(); // Grab the next byte to process.

if(x == '<') { // If it matches < then
Internal = &FilterChainDefunker::OpenTag; // go to OpenTag state and
x = GetInternal(); // return the converted byte.
} else
if(x == '&') { // If it matches & then
Internal = &FilterChainDefunker::OpenAmp; // go to OpenAnd state and
EnQueue(x); // push in the amphersand.
x = GetInternal(); // return the converted byte.
}
// If x is none of the above then x is just x.
} while (true == ReturnNothing); // Returning nothing? Go again!
return x; // otherwise return a funkless x.
}

unsigned char FilterChainDefunker::OpenTag() { // While in OpenTag state
@@ -763,9 +772,10 @@ unsigned char FilterChainDefunker::MatchAMP() { // If our mode is Mat
unsigned char FilterChainDefunker::EatTag() { // If our mode is EatTag
if(LastGetStore != '>') { // and our last byte was not
while(GetStore()!='>')continue; // endtag then eat through
} // the end tag. Then set our
} // the end tag. Then set our
ReturnNothing = true; // ReturnNothing flag, set our
Internal = &FilterChainDefunker::DefunkRoot; // mode to DefunkRoot and
return GetInternal(); // return the next byte.
return 0; // return 0 (nothing, really).
}

unsigned char FilterChainDefunker::DecodeNum() { // If our mode is DecodeNum

+ 8
- 0
FilterChain.hpp View File

@@ -430,6 +430,14 @@ static const int DefunkerQueueSize = 24; // Size of defunk
class FilterChainDefunker : public FilterChain { // Class definition.

private:
// Occasionally when parsing a chunk of data we must return nothing and
// instead try again for the next character. Instead of resursing we can
// set this flag and the root state will simply try again in a loop.
bool ReturnNothing; // Set true to skip this round;
// Storeage

unsigned char StoreBuffer[DefunkerSize];
int InputPosition;

+ 1
- 1
SNFMulti.cpp View File

@@ -23,7 +23,7 @@ using namespace std;

//// Version Info

const char* SNF_ENGINE_VERSION = "SNFMulti Engine Version 3.0.13 Build: " __DATE__ " " __TIME__;
const char* SNF_ENGINE_VERSION = "SNFMulti Engine Version 3.0.14 Build: " __DATE__ " " __TIME__;

//// Script Caller Methods


Loading…
Cancel
Save