Neste post resolvi disponibilizar algo para ajudar ainda mais as ações de segurança nas aplicações com relação ao ponto de entrada de dados. Dentro do CF, a combinação das tags CFQUERY e CFQUERYPARAM ajudam e muito a evitar ataques do tipo SQL Injection, porém elas sozinha minimizam a possibilidade e não neutralizam.
Para isso criei um conjunto de três funcções para detectar se no texto existe ou não intenções de injection. A utilização é bem simples, basta chamar a função hasAtack() antes de executar seu sql. O funcionamento é uma combinação da busca em cima dos scoopos CGI, Url, Form, Cookie e Arguments localizando palavras típicas de ação de injection. Recomendo colocar essa funcionalidade no seu Application.cfc ou cfm para poder chamade de qualquer página o teste.
<cffunction name="checkSQLInject" access="private" returntype="string" output="no"> <cfscript> // list of db objects/functions to protect var insSql = 'insert|delete|select|update|create|alter|drop|truncate|grant|revoke|declare|' & 'exec|backup|restore|sp_|xp_|set|execute|dbcc|deny|union|Cast|Char|Varchar|nChar|nVarchar'; // Build the regex var regEx='((or)+[[:space:]]*\(*''?[[:print:]]+''?' & '([[:space:]]*[\+\-\/\*][[:space:]]*''?' & '[[:print:]]+''?)*\)*[[:space:]]*' & '(([=»<!]{1,2}|(like))[[:space:]]*\(*''?' & '[[:print:]]+''?([[:space:]]*[\+\-\/\*]' & '[[:space:]]*''?[[:print:]]+''?)*\)*)|((in)' & '[[:space:]]*\(+[[:space:]]*''?[[:print:]]+''?' & '(\,[[:space:]]*''?[[:print:]]+''?)*\)+)|' & '((between)[[:space:]]*\(*[[:space:]]*''?' & '[[:print:]]+''?(\,[[:space:]]*''?[[:print:]]+''?)' & '*\)*(and)[[:space:]]+\(*[[:space:]]*''?[[:print:]]+''?' & '(\,[[:space:]]*''?[[:print:]]+''?)*\)*)|((;)([^a-z>]*)' & '(#insSql#)([^a-z]+|$))|(union[^a-z]+(all|select))|(\/\*)|(--$))'; return regEx; </cfscript> </cffunction> <cffunction name="loadPattern" access="private" returntype="any" output="no"> <cfscript> var reMatcher = ""; var blacklist = checkSQLInject(); var rePattern = createObject("java", "java.util.regex.Pattern"); rePattern = rePattern.compile(blackList); return rePattern; </cfscript> </cffunction> <cffunction name="hasAttack" access="public" returntype="boolean" output="no"> <cfscript> var hackattempt = false; var testvar = ""; var reMatcher = ""; var CGIvars = "script_name,remote_addr,query_string,path_info,http_referer,http_user_agent,server_name"; var scoopes = [Url, Form, Cookie, Arguments]; var i = 1; //Make sure the Matcher is available in Application Scope if(NOT StructKeyExists(Private, "regExChecker")) { Private.regExChecker = loadPattern(); } //load matcher reMatcher = Private.regExChecker.matcher(""); for(i = 1; i LE ArrayLen(scoopes); i++) { for(testvar in scoopes[i]) { if(reMatcher.reset(lcase(scoopes[i][testvar])).find()) { hackAttempt = true; break; } } if(hackAttempt) break; } if(NOT hackAttempt) { for(i = 1; i LE ListLen(CGIvars); i=i+1) { testvar = ListGetAt(CGIvars, i); if(StructKeyExists(CGI, testvar) AND reMatcher.reset(lcase(CGI[testvar])).find()) { hackAttempt = true; break; } } } return hackAttempt; </cfscript> </cffunction>
Por Rafael Bandeira