In ColdFusion, whenever we have to place any variable into the SQL Statements, which are inside CFQuery Tags, we must use the CFQueryParam tags, to make sure they are protected from SQL Injections. However, there are many a cases, when these tags have been missed (knowingly or unknowingly) by the developer, and then at a later stage, applying the CFQueryParam tags to all of them is a very tedious job. So, i came up with this script that does this job for you. The project is located at http://code.google.com/p/cfml-sqlvc/. I have also put my very basic script here, in order to help those who are looking for a similar kind of script. You can always go to the project home page and download the latest version, with bug fixes and many more features.
It scans a particular folder, creates a list of files that need CFQueryParam Validation tags, and then applies them. IT DOES NOT change the original file. It just tells where changes are needed and then displays the new SQL Statement that should be present. So, it leaves scope for manual work. Guys, relax, you won't be fired :-)
And for those people, who want everything to be done by this program or may be report issues, you can visit the project's homepage at http://code.google.com/p/cfml-sqlvc/
#!/usr/bin/env python
##"""
## A script to make sure all CFM Files have the CFQueryParam validation tags
##
## Copyright (C) 2008 Pranav Prakash pranny@gmail.com
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see http://www.gnu.org/licenses/
##
##"""
import sgmllib, re
class CFMLParser(sgmllib.SGMLParser):
def __init__(self, verbose=0):
sgmllib.SGMLParser.__init__(self, verbose)
self.insideCFQuery = False
self.insideComment = False
self.insideLogic = False
self.SQLQueries = []
self.QueryNames = []
self.NewSQLQueries = []
self.tempQuery = ''
self.unvalidatedPattern = re.compile("\s\w+\.?\w+\s=\s'?#\w+\.?\w+\(?\w*\)?#'?")
self.varcharPattern = re.compile("'#\w+\.?\w+\(?\w*\)?#'")
self.nonVarcharpattern = self.token = re.compile("#\w+\.?\w+\(?\w*\)?#")
self.lhs = re.compile("\s\w+\.?\w+\s=\s")
self.map = dict({'bit':'CF_SQL_BIT',
'dat':'CF_SQL_DATE',
'time':'CF_SQL_TIME',
'timeStamp':'CF_SQL_TIMESTAMP',
'int':'CF_SQL_INTEGER',
'vch':'CF_SQL_VARCHAR'})
def start_cfquery(self, attributes):
self.insideCFQuery = True
for k,v in attributes:
if k == 'name':
self.QueryNames.append(v)
def end_cfquery(self):
self.insideCFQuery = False
if self.tempQuery != '':
self.SQLQueries.append(self.tempQuery)
self.tempQuery = ''
def start_cfqueryparam(self, attributes):
self.tempQuery += self.get_starttag_text()
def end_cfqueryparam(self):
pass
def start_cfif(self, attributes):
if self.insideCFQuery:
self.tempQuery += self.get_starttag_text()
self.insideLogic = True
def end_cfif(self):
if self.insideLogic:
self.tempQuery += '</cfif>'
self.insideLogic = False
def start_cfelse(self, attributes):
if self.insideLogic:
self.tempQuery += self.get_starttag_text()
def handle_data(self, data):
if self.insideLogic or self.insideCFQuery and len(data.lstrip()) > 0:
self.tempQuery += data
def handle_comment(self, comment):
if self.insideCFQuery:
self.tempQuery += '<!--'+comment+'-->'
def report_unbalanced(tag):
if tag == 'cfqueryparam':
end_cfqueryparam()
if tag == 'cfelse':
end_cfelse()
def get_QueryNames(self):
return self.QueryNames
def get_OldSQLQueries(self):
return self.SQLQueries
def get_NewSQLQueries(self):
return self.NewSQLQueries
def ScanQuery(self, query):
self.NewSQLQueries.append(re.sub(self.unvalidatedPattern, self.handleIndividualTokens, query))
def findDataType(self, lvalue, rvalue):
for k in self.map:
p = k+'\w+'
pa = re.compile(p)
l = pa.findall(rvalue)
if l != []:
return self.map.get(k)
for k in self.map:
p = '\.?'+k+'\w+'
pa = re.compile(p)
l = pa.findall(lvalue)
if l != []:
return self.map.get(k)
return 'CF_SQL_INTEGER'
def handleIndividualTokens(self, s):
tag = s.group(0)
m = self.varcharPattern.findall(tag)
if len(m) > 0:
rhsValue = self.token.findall(m[0])[0]
lhsValue = self.lhs.findall(tag)[0]
finalVal = lhsValue + '<cfqueryparam value = "'+rhsValue+'" cfsqltype="CF_SQL_VARCHAR" />'
return finalVal
else:
lhsValue = self.lhs.findall(tag)[0]
rhsValue = self.nonVarcharpattern.findall(tag)[0]
finalVal = lhsValue + '<cfqueryparam value = "'+ rhsValue+'" cfsqltype="'+self.findDataType(lhsValue, rhsValue)+'" />'
return finalVal
def ScanQueries(self):
for SQL in self.SQLQueries:
self.ScanQuery(SQL)
def ScanAndReplace(text):
myCFMLParser = CFMLParser()
myCFMLParser.feed(text)
myCFMLParser.close()
myCFMLParser.ScanQueries()
o = myCFMLParser.get_OldSQLQueries()
n = myCFMLParser.get_NewSQLQueries()
for i in (0, len(n)-1):
text = text.replace(o[i], n[i])
return text
if __name__ == '__main__':
inFile = '/home/pranav/projects/cfmparser/test.cfm'
f = open(inFile, 'r')
FileContentText = f.read()
f.close()
print ScanAndReplace(FileContentText)
Don't forget top check the latest development at http://code.google.com/p/cfml-sqlvc/.
No comments:
Post a Comment