GraffitiFirewall

Preview #

About #

GraffitiFirewall is a Web Application Firewall for Xojo Web apps. It’s as fast as lightning and scans each incoming connection nearly instantaneously against a list of more than 30,000 criteria. It includes a guided setup wizard and intuitive dashboard. It can go everywhere your app can go and can help provide security from:

  • Known Malicious IPs
  • Known Malicious UserAgents
  • Known Malicious Referrers
  • Local File Inclusions
  • Cross Site Scripting
  • SQL Injections
  • Crawlers
  • Direct Denial of Service attacks
  • Login or sensitive action Security via custom event tracking
  • Custom blocklists for IPs or UserAgents with expiration

Security features include:

  • Time-base One-Time Password (TOTP) login
  • Encrypted Database
  • Managed and curated definition updates

Enumerations #

NameValues
EvaluationTypesAll
LocalFileInclusion
CrossSiteScripting
SQLInjection
HTTPSecurityModesOff
Block
RedirectTemporary
RedirectPermanent

Constants #

This class exposes no constants.

Events #

This class exposes no events.

Methods #

This class exposes no methods.

Shared Methods #

NameParametersReturn ValueDescription
Blockinstance as GraffitiFirewallBlockNoneBlocks the address identified by the GraffitiFirewallBlock object.
CountEventsidentifier as String
type as Integer
IntegerCounts the matching events for the identifier (typically an IP Address) that have been added using RegisterEvents which have not yet expired. Type values of 0 and 1 are reserved.
CountEventsrequest as WebRequest
type as Integer
IntegerCounts the matching events for the requesting user that have been added using RegisterEvents which have not yet expired. This is not WebRequest-specific, but uses the WebRequest object to get the information required. Type values of 0 and 1 are reserved.
CountEventssession as WebSession
type as Integer
IntegerCounts the matching events for the session that have been added using RegisterEvents which have not yet expired. This is not WebSession-specific, but uses the WebSession object to get the information required. Type values of 0 and 1 are reserved.
DeleteDatabaseNoneNoneDeletes the database from the system. This should only be used if uninstalling GraffitiFirewall from your application. Once this method is called, all data will be unrecoverable.
EvaluateConnectionrequest as WebRequest
response as WebResponse
BooleanEvaluates a WebRequest to determine if the user is potentially malicious. Returns True if an action is taken or False if the request matches none of the criteria to block the connection.
EvaluateContenttype as EvaluationTypes
content as String
BooleanEvaluates a string of data to scan for potentially malicious data. Useful for checking form data before performing database operations.
EvaluateEventidentifier as String
type as Integer
threshhold as Integer = 0
BooleanReturns whether the threshhold for this event type has been exceeded based on the identifier (typically an IP Address).
EvaluateEventrequest as WebRequest
type as Integer
threshhold as Integer = 0
BooleanReturns whether the threshhold for this event type has been exceeded based on the requesting user. This is not WebRequest-specific, but uses the WebRequest object to get the information required.
EvaluateEventsession as WebSession
type as Integer
threshhold as Integer = 0
BooleanReturns whether the threshhold for this event type has been exceeded based on the requesting user. This is not WebSession-specific, but uses the WebSession object to get the information required.
GeofencingClearCacheNoneNoneClears the geofencing cache. Results are cached for 30 days to reduce calls to the third-party API.
GetBlockipaddress as StringGraffitiFirewallBlockReturns an unexpired block entry, if found, for the ipaddress.
GetBlockrequest as WebRequestGraffitiFirewallBlockReturns an unexpired block entry, if found, for the requesting user. This is not WebRequest-specific, but uses the WebRequest object to get the information required.
GetBlocksession as WebRequestGraffitiFirewallBlockReturns an unexpired block entry, if found, for the requesting user. This is not WebSession-specific, but uses the WebSession object to get the information required.
InstantiateNoneNoneCreates a new shared instance of the class and, if not created previously, sets up the basic database configuration.
LastUpdateNoneDateTimeReturns the last DateTime that the firewall phoned home for updates.
RebuildDatabaseNoneNoneDeletes and recreates the database. Useful if you have somehow locked yourself out of the database. Behaves the same as if you’ve deleted the database files on the system then called the Instantiate method.
RegisterEventidentifier as String
type as Integer
comment as String = “”
expiresAfterSeconds as Integer = 0
NoneRegisters a new event for use with CountEvents and EvaluateEvent.
RegisterEventrequest as WebRequest
type as Integer
comment as String = “”
expiresAfterSeconds as Integer = 0
NoneRegisters a new event for use with CountEvents and EvaluateEvent.
RegisterEventsession as WebSession
type as Integer
comment as String = “”
expiresAfterSeconds as Integer = 0
NoneRegisters a new event for use with CountEvents and EvaluateEvent.
Unblockinstance as GraffitiFirewallBlockNoneRemoves any matching access blocks based on the criteria specified in the GraffitiFirewallBlock.
UpdateDatabaseForce as Boolean = FalseNoneUpdates the definitions in the database if the set update frequency has been exceeded or Force = True. It would be most beneficial to setup a path in App.HandleURL that calls this method then create a cronjob to execute it as updates may stall a user connection when an update is due to be performed.

Properties #

This class exposes no properties.

Shared Properties #

NameTypeDefault ValueDescription
ApplicationNameString“”The application name assigned during setup. This value should not be changed as it may invalidate TOTP logins.
BypassLocalBooleanFalseBypasses all checks for connections originating from 127.0.0.1 when True.
DatabaseSchemaVersion (Read Only)String0Schema version of the currently loaded database.
EnabledOnDebugBooleanTrueWhen False, bypasses all checks when running the web application in debug mode.
GeofencingBlockHostingBooleanFalseOptionally blocks IP addresses that are known to belong to hosting networks.
GeofencingBlockMobileBooleanFalseOptionally blocks IP addresses that are known to belong to mobile networks.
GeofencingBlockProxyBooleanFalseOptionally blocks IP addresses that are known proxy nodes.
GeofencingEnabledBooleanFalseEnables the geofencing engine. Blocked countries must be set via the dashboard.
HTTPSecurityModeHTTPSecurityModesHTTPSecurityModes.OffDetermines how the firewall handles insecure connections. Should be set to Off if behind a load balancer such as nginx or Apache (or when deployed via Xojo Cloud).
LockdownBooleanFalseUsed to lockdown the server and refuse all connections. Can be cleared by setting to True or restarting server app instance.
ManagementAPIEnabledBooleanFalseControls whether the Management API is enabled for using GET requests with query strings to perform maintenance operations such as updates of log truncations.
ManagementAPIRemoteEnabledBooleanFalseControls whether remote networks may be used to initiate calls to the Management API.
ManagementAPITruncateLogsEnabledBooleanFalseControls whether the Management API may be used to truncate logs.
ManagementAPIUpdateEnabledBooleanFalseControls whether the Management API may be used to perform definition updates.
MaximumCookieSizeInteger10240Maximum size, in bytes, of all cookie data.
MaximumCookieSizeEnabledBooleanTrueEnforces the maximum cookie size when True.
MaximumPathSizeInteger1024Maximum size, in bytes, of path data.
MaximumPathSizeEnabledBooleanTrueEnforces the maximum path size when True.
MaximumQuerySizeInteger2048Maximum size, in bytes, of all query string data.
MaximumQuerySizeEnabledBooleanTrueEnforces the maximum query size when True.
MaximumRequestSizeInteger8192Maximum size of request body data.
MaximumRequestSizeEnabledBooleanTrueEnforces the maximum request size when True.
OutputDebugMessageBooleanFalseReplaces the #DEBUG# token in BlockedTemplate for block messages when True.
RateLimitEnabledBooleanTrueApplies the rate limit property values to repeated connections when True.
RateLimitMaxRequestsInteger50Maximum number of connection attempts allowed within RateLimitPeriod.
RateLimitMaxPeriodInteger300Number of seconds within which connections are counted toward the RateLimitMaximum.
RateLimitMaxTimeoutInteger300Number of seconds new connection attempts will be blocked for the affected remote host when they exceed the RateLimitMaximum within RateLimitPeriod.
RateLimitRejectionCountInteger5Number of rejections a single remote client is allowed with the time supplied by RateLimitBlockedPeriod.
RateLimitRejectionPeriodInteger10Amount of seconds over which rejections count toward a block.
RateLimitRejectionTimeoutInteger300Number of seconds a client is blocked after exceeding RateLimitRejectionCount within RateLimitRejectionSeconds.
RegisteredEmailString“”The email address used when setting up the firewall. This is used for providing definition updates and TOTP and is sent to the GraffitiSuite server for determining if the user has access to updates.
RejectAnonymousUserAgentsBooleanTrueRejects requests with an invalid or empty UserAgent string when True.
RejectCrawlersBooleanFalseRejects known “bad” crawlers when True.
RejectBodySQLIBooleanTrueScans body data of request for attempts to inject SQL when True. May generate false positives if using on a REST service application. Test thoroughly.
RejectBodyXSSBooleanTrueScans body data of request for attempts to inject JavaScript when True. May generate false positives if using on a REST service application. Test thoroughly.
RejectCookieSQLIBooleanTrueScans cookie data for attempts to inject SQL when True.
RejectCookieXSSBooleanTrueScans cookie data for attempts to inject JavaScript when True.
RejectionTemplateString<Large HTML String>The HTML data rendered to blocked clients. Use the token #DEBUG# to output the block reason on the page when OutputDebugMessage is True.
RejectLocalFileInclusionBooleanTrueScans body, cookie data, path, and querystring for attempts to include local system files in responses.
RejectPathSQLIBooleanTrueScans the request path for attempts to inject SQL when True.
RejectPathXSSBooleanTrueScans path for attempts to include JavaScript when True.
RejectQuerySQLIBooleanTrueScans query strings for attempts to inject SQL when True.
RejectQueryXSSBooleanTrueScans query strings for attempts to include JavaScript when True.
RejectSpamReferrersBooleanTrueScans requests’ “referer” property for known spam bots. As the “referer” property has been increasingly blocked by clients from being transmitted to servers, this will only catch old/blatant offenders.
RejectUnknownEndpointsBooleanFalseWhen True, any attempt to access an endpoint that does not have a specified permissions setting will be rejected. This may help prevent probing.
ShareStatsBooleanTrueOptionally share basic anonymous statistics with GraffitiSuite during the update process. This includes only the number of accesses, redirects, and blocks.
UpdateAPIKeyString“”Generated API key to use when requesting definition updates.
UpdateEnabledBooleanTrueDetermines whether to attempt to retrieve periodic updates from the server. GraffitiFirewall has many functions that do not rely on an active subscription, but more advanced features can not function optimally without periodically updated data.
UpdateFrequencyInteger172800Number of seconds between update attempts. Minimum is 86400 (24 hours), default is 172800 (48 hours).
UpdateLastPerformed (Read Only)DateTimeNilDateTime of the last update check.
UpdateLastResult (Read Only)BooleanFalseUsed to determine whether the last update completed successfully or failed.

Examples #

Evaluating Custom Events #

As a simple example, we’ll setup evaluation for login attempts. In your login form, upon submission, register failed login attempts:

'// The second parameter of 100 here is an identifier used
'   to separate different custom criteria. It is recommended
'   that you use values of 100 or greater as anything lower
'   is reserved for internal use within the firewall.
'
'   The second parameter is logged to the database for informational
'   purposes.
'
'   The final parameter is the lifespan of the event in seconds,
'   during which it will be returned as valid in CountEvents. In
'   this instance we're using 300 seconds(5 minutes).
GraffitiFirewall.RegisterEvent(Session, 100, "Failed login attempt", 300)

You can then use the CountEvents method to see if they’ve exceeded your threshold for failed login attempts, and block the source if they have:

If GraffitiFirewall.CountEvents(Session, 100) >= 5 Then '// Maximum of 5 login failures allowed.
  Var block as new GraffitiFirewallBlock(Session, 300) '// Block this source for five minutes.
  GraffitiFirewall.Block(block) '// Register the block to be applied automatically by EvaluateConnection.
  Session.Close '// Close the session so that any new attempts will be evaluated as new connections.
End If

Using these methods, you can create protection schemes for nearly any operation in your web application and respond appropriately. It is important that you call Session.Close. Session.Close is not done automatically to allow you to display a custom message if you so desire.

Notes #

Adding/Updating GraffitiFirewall #

  • Open the GraffitiFirewall project file in Xojo.
  • Copy the GraffitiFirewall folder in the IDE’s Project Navigator.
  • Open the destination project file in Xojo.
  • Select Edit > Paste in the IDE’s menu bar.
  • Save and close the destination project.
  • Reopen the destination project.
  • Continue the following steps only is adding GraffitiFirewall to a project.
  • In the App.Opening event, add the following code:
GraffitiFirewall.Instantiate
  • In the App.HandleURL event, add the following code:
If GraffitiFirewall.EvaluateConnection(Request, Response) Then Return True