Thread View: borland.public.cppbuilder.internet.web
1 messages
1 total messages
Started by Borland Lover
Wed, 17 May 2006 20:17
HELP: defend against brute force on an ISAPI module?
Author: Borland Lover
Date: Wed, 17 May 2006 20:17
Date: Wed, 17 May 2006 20:17
163 lines
5752 bytes
5752 bytes
Hi, BCB6. Questions are short but the post is long due to code - please
read on.
I have an ISAPI application that exposes some SOAP web-services. I want to
defnd against brute-force programatic attacks on the server such that: If a
large number of requests come in in less than a predefined period of time
from a single IP - to simply drop the requests and stop responding to that
IP (at least temporarily). While continuing to service requests from
others. I think I have a fair underastanding of the threading issues in
ISAPI apps and am prepared to handle them - but this problem is a bit of a
beast.
So far I have the folowing concept:
1) Declare a *global* threadlist:
TThreadList * pIncomingRequests = NULL;
2) When a web-module gets constructed ensure the global thread list is
created:
__fastcall TMyWM::TMyWM(TComponent* Owner)
: TWebModule(Owner)
{
if (! pIncomingRequests)
{
pIncomingRequests = new TThreadList();
}
}
3) Define a structure to hold info on requesters to be added to the global
thread list:
class TIncomingRequester : public TObject
{
public:
AnsiString FIP; // IP address
DWORD FNumRequests; // number of times request recieved from this IP
TDateTime FFirstRequestTime;
TDateTime FLastRequestTime;
__fastcall TIncomingRequester(const AnsiString AnIP, const TDateTime
ADateTime);
};
4) And some constants to define maximum requests per period:
const int MAXREQUESTSPERQUANTA = 100;
const int REQUESTQUANTA = 5; // 5minutes
5) Before a request gets dispatched - decide whether or not to bother
responding by checking the requester against the list:
void __fastcall TMyWM::WebModuleBeforeDispatch(TObject *Sender,
TWebRequest *Request, TWebResponse *Response, bool &Handled)
{
TList * lockedList = pIncomingRequests->LockList();
try
{
RemoveOldRequests(lockedList);
TIncomingRequester* pIR = NULL;
for (int i = 0; i < lockedList->Count; ++i)
{
pIR = (TIncomingRequester*)lockedList->Items[i];
if (pIR->FIP == Request->RemoteAddr)
{
break;
}
}
if (pIR)
{
pIR->FNumRequests++;
pIR->FLastRequestTime = Now();
}
else
{
pIR = new TIncomingRequester(Request->RemoteAddr, Now());
lockedList->Add(pIR);
}
Handled = IgnoreRequester(pIR);
}
__finally
{
pIncomingRequests->UnlockList();
}
}
//---------------------------------------------------------------------------
bool __fastcall TMyWM::IgnoreRequester(TIncomingRequester * pIR)
{
if (!pIR)
return true;
else
return ( (pIR->FNumRequests > MAXREQUESTSPERQUANTA)
&& (MinutesBetween(pIR->FLastRequestTime,
pIR->FFirstRequestTime) < REQUESTQUANTA));
}
//---------------------------------------------------------------------------
void __fastcall TMyWM::RemoveOldRequests(TList * ALockedList)
{
if (ALockedList)
{
TIncomingRequester* pIR = NULL;
const TDateTime utcNow = Now();
for (int i = ALockedList->Count - 1; i >= 0 ; --i)
{
pIR = (TIncomingRequester*)ALockedList->Items[i];
if (MinutesBetween(pIR->FFirstRequestTime, utcNow) >
REQUESTQUANTA)
{
// remove it
ALockedList->Remove(pIR);
}
}
ALockedList->Pack();
}
}
So far so good.... I think... First question is - do you see any problem
with what I have so far? How would you do it better?
One main thing I am concerned about is memory. I need to (at some point)
destroy the thread list. In the destructor I have:
__fastcall TMyWM::~TMyWM()
{
if (pIncomingRequests) // and i am the last web-module ! ???
{
TList * lockedList = pIncomingRequests->LockList();
for (int i = 0 ; i < lockedList->Count; ++i)
{
delete (TIncomingRequester*)lockedList->Items[i];
}
delete pIncomingRequests;
pIncomingRequests = NULL;
}
}
However - as you can see - I don't know how to determine if indeed *this*
web-module is the *last* web-module to be destroyed because the dll is being
unloaded. This is important because if a web-module is destroyed in an
ISAPI it does not necessarily mean that there are no other web-modules
(either inactive or active) in the thread pool - in fact there could be many
that are still working with the list. If the rest of my methodology is OK,
how do I solve this problem?
Thank You.
M.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads