Ask a Jedi: Question on DBA's and their plans to ruin our lives...
Ok, so maybe DBAs really aren't out to get us, but I know from time to time I've butted heads with a few DBAs and I'm sure others have as well. Here is an interesting story from someone dealing with something similar. A reader asks:
An associate of mine sent me the following and I wasn't sure how to respond, since I'd never heard of such a thing and so figured I might bug you for your take:
"Our DBA has instituted a new policy to protect his databases against possible corruption by SQL Injection attacks: from now on, ALL applications must use one datasource for all writes and another for all reads. Those datasources are limited to writes and reads respectively both in ColdFusion Administrator and at the database level. We've argued that we religiously use stored procedures or cfqueryparam in all of our database calls, but his response is that developers can't be trusted to practice these techniques consistently.
Our response is to try to think about how much work it will require to modify all existing applications to observe this practice and to make it a part of our development process for all future efforts.
But we're also preparing to push back a little and argue
A) that this policy is silly and that a read and a write datasource offers negligible additional security over a datasource that allows both reads and writes,
B) that it will take x number of hours to modify all of our existing code,
C) that this is NOT an industry standard practice and that we'd like to see some documentation,
and
D) that most if not all off the shelf and open source software does not distinguish between read and write datasources and so any applications we try to bring in from the outside would have to be modified accordingly."
And that's my question to you, Ray: would you happen to know if C and D are pretty accurate statements and, more generally, have you ever heard of read-only and write-only datasources being used as a defense against SQL injection attacks?
Well first off - I do not pretend to be a database expert of any level. Folks know my open source applications use rather simple queries and I don't really have Jedi SQL skills. That being said - I tend to agree that this policy seems rather draconian. Last time I checked, a database server was meant to - well - serve.
If I have to use one DSN for queries that do writes and another for reads, this doesn't make the Write dsn any safer. I can still write bad sql that is vulnerable to sql injection attacks. I'd say all the DBA has done is added more work to your plate without making anything any more secure than it is now.
I could see using the restrictions in the CF Admin to block things like drop, etc, that would be dangerous. You could limit the connection (and at the DB user level) to only allow select, update, insert, and delete, and that would help a bit.
I think your time would be much better spent doing a review to ensure your queries are using cfqueryparam and aren't vulnerable to other attacks. So for example, if you use cfqueryparam it in a query that gets the bank account for user X, but don't verify that the current user is X, no use of cfqueryparam will help you.
As for your point C - I've never heard that before, and I'll let my readers chime in. It could certainly be that we (my reader and myself) have just never heard of this practice.
p.s. In case it isn't obvious... I know DBAs aren't out to get us. I love DBAs. They can take my slow, ugly SQL and make it scream. It's a joke folks. I'm sure most DBAs don't mind though. Except maybe Oracle DBAs. They really are out to get us!
Comments
Ray is right - separating the datasources as read and write brings no extra level of safety and only complicates your job. I have been in the industry for a rather large number of years and have never seen or heard of this in any kind of "standards and practices".
We run MANY COTS packages as well as a large number of in-house applications for our Defense contract customers - and even THEIR DBA's do not understand how this could possibly enhance data security (I asked around to make sure I wasn't just being silly).
Suffice it to say that while I think your DBA probably means well - his efforts are misdirected and misguided.
I'm all for securing systems, and making sure table grants are made only for what the app user needs is a must (i.e., don't grant delete to public or anything silly). But the job of a DBA isn't to make the lives of programmers miserable. Nor is it the job of the programmer to make DBAs miserable. One cannot really exist without the other, lest you read and write your data to flat files or some such thing (then you might make yoiur sysadmin cross).
In this situation, what I would recommend is that the programming team do an internal code review, find any places where SQL injection isn't protected by CF, resolve those issues, then present to the DBA and show him that every conceivable means available to CF (cfqueryparam, DSN rights in CF Admin, etc.) are being used to protect the application and the database. If the DBA still takes issue, discuss it. It could be that the DBA doesn't know what the capabilities are in CF, so a little education could go a long way.
Another solution could be to have the apps talk to a staging database, where all transactions are made in a separate database, or schema or whatever. Then the DBA can write processes that will ensure the validity of the data before letting it into the production system. If there's a staging area for these transactions, and it gets attacked, it may make life less painful if compromised (i.e., you're not exposing your full production system, just a stripped down staging area).
And, as far as write only DSNs go, that won't stop bad code or SQL attacks. That'll just make sure the apps use a different path to get the badness in to the database. So it's not a solution, it's a maintenance nightmare, for the CF admin, the programmer AND the DBA.
bottom line is that as long as the datasources are pointing to the same database, having one datasource for reads and another for writes doesn't nothing to prevent data corruption since they are both altering the same database and as such the same data.
In my PROFESSIONAL opinion, the only thing that a design like the one proposed will do:
1) add complex to development since (you are correct) most application and framework are designed around using a single datasource (Ruby in Rails).
2) offer no advantage of security (only give a false impression of) since the same database is being targeted by both datasources.
3) add addition, unnecessary costs to the bottom line, since (as you stated) you will need to rewrite all existing application to meet the new specification and existing application will take long to write to meet the new specification.
one more thing. just make it a company policy to use cfqueryparam in all calls to the database and remember to strip all html tags from user inputted data. just doing those two thing will give 1000 fold more security over instituting a policy like this.
Another REALLY bad scenario I have seen of late are programmers/systems admins that create CF Datasources using an "sa" account. VERY VERY BAD/DANGEROUS>
As long as the results of such tools are considered critically and not blindly accepted, some sort of scanning could be incorporated into your deployment process to ensure that developers behave, ahem, "consistently."
Sometimes I think that DBA's don't "get cold fusion," and they want to make life hard for us. If I'm using cfqueryparam, that ought to be good enough--anything beyond that is just noise!
Really, what most are saying here makes good sense. Properly written queries used with cfqueryparam and properly configured DBMS account should adequately secure most, if not all, application.
The bigger risk is the extensibility of the database. Tight coupling will kill extensibility and will cost a fortune to fix later, or maybe even sink the organagation.
Then the DBA can report back any problematic unbound SQL they found which you can then easily fix.
Teamwork can achieve wonders and management tend to like such security audits
z
I worked for a company that had a security audit of an application done by E&Y. The main thing we were told was to not use insert/update queries in inline sql. It was suggested to use stored procedures everywhere we could. Mostly any sql statement that had some value that could have been tampered with by the client. While this would not block injection 100% of the time, a correctly written stored procedure would offer some inherit protection.
If the policy is to use stored procedures and the developers are not then you have another issue on your hands.
My 2 cents...
--Dave
The best approach is to param all your vars, whether it be cfqueryparam or paraming inside the db procedures. Also lock down the CF datasources to remove unneccessary options under the advanced portion. We typically remove create, drop, grant and revoke from all our datasources as our apps do not typically do this via the web interface.
1. Least Privileges: Access should be based on performing only the actions necessary for the connection. This means no SA or similar access. I would state, it also means that applications should have different DSN's for guests/read-only users, editing users, and data administrators. This is where, I will bring up again, the Oracle Proxy Authentication, would come in handy, if Adobe would support it. Oracle Proxy Authentication connects through a common account (ALTER USER xyz GRANT CONNECT THROUGH abc), but retains the traditional database role security and auditing down to the individual level. MS SQL Server doesn't have a Proxy Authentication method, but it does allow for trusted connections via Kerebos authenticated sessions, which .NET can use. This is another area where CF is missing in its connectivity.
2. Fine Grain User Permissions via Roles: This practice means that one uses database roles to grant permissions to objects. To start with, in MS SQL server, one can limit the data connection to the built-in DataReader and DataWriter roles. These roles do not allow for creation of objects. I would often create custom web-related roles and grant permissions to objects via these custom roles, like limiting the roles to only executing stored procedures or access via views, instead of direct table access.
3. Access via Views and/or Stored Procedures: Another common practices is to only allow web access via Views (reading of data) and Stored Procedures (reading and writing of data). This eliminates access to the underlying tables themselves. Writing via Stored Procedures also allows the Stored Procedures to do data-checking and has the same effect as parameterized queries.
None of these help for third-party apps, but if an organization implements these practices, it can include these requirements in their RFP's. Including the practice in the RFP's may force third-party developers to start addressing these concerns. If you don't make security a requirement for awarding a contract, then the vendors aren't going to address it.
I dont think it would be to hard to write a CF application that checks for SQL injection vulnerabilities.
If you watch that program do it's thing it is looking for 500 errors as it tries to tack in multiple SQL queries.
They also have a nice document on SQL injection that gives good examples of injections.
http://products.spidynamics.com/asclabs/sql_inject...
Cool. :)
To address the idea of data security, the best answer is "It depends". When I worked for an insurance company, all web data went into a write-only database, and then went through a data check for various things (security was part of it, but not all of it) before being allowed into the central database that was shared with the desktop-client ERP system.
And that was A Good Thing (tm). One massive application with a rotating cast of about 10 developers over a 2-year span of time, standards were hard to enforce. This added a constant layer of data security.
Secondly, it's been shown that having a read-only database and a write-only database is a performance boost. To keep the explanation short, the more you optimize a database for quick reading, the slower writing will generally be, and vice versa. Our development group just did a sit-down meeting with one of our DBAs to talk about performance optimization, and this was one of his recommendations.
As for the dreaded "Industry Standard" argument, keep in mind that not all that long ago, a parametrized query went against industry standards. ;)
Heh- look at that. Totally missed that one. Mea Culpa.
Nope- having a hard time coming up with a reason two dataSOURCES pointing to the same dataBASE would offer any greater security over one properly resricted datasource.
Regardless of the annoyance, and the possible lack of necessity, I've got to say I do think this approach would make your site more secure and here's why: Every cfquery and cfstoredproc on your site represents a possible window of vulnerability. Each time you add a query to a page you are placing an open database connection to your DBMS and the code you put in that cfquery will determined whether or not it can be exploited. Let's say you have 100 cfqueries on your site. That's 100 ways you can get hacked. On average, 50 of them read and 50 of them write. If you can remove 50 of those from the "potentially vulnerable" pool, you have just eliminated half of your worries. Further to the point, I have successfully exacted SQL injection attacks before on my own sites etc and I have found places like search screens with multiple inputs and dynamic SQL are MORE likely to allow for SQL injection. If anything, these are the queries that only need to be read-only in the first place!
Now, before you flame me, I'm not condoning the practice. In fact I think it is a little ridiculous since ColdFusion makes it VERY easy to prevent SQL injection, but I think the DBA has a point-- albeit a little obtuse.
I would work on trying to strengthen your relationship with him and being more transparent about what SQL you are using-- perhaps he can review it all. This DBA obviously doesn't trust you (which I think comes natural to them), but see if he can recall any recent incidents where this has been a problem that would justify the change. Also, go over the ColdFusion administrator settings with him that allow you to block drops, grants, etc.
--
Only thing I can think of is to separate logging. When you look at one datasource->db account you're looking at all the reads. If you look at the other, you look at all the writes.
No idea. Just a weird DBA that doesn't understand what the front end technology is doing and protecting his ass. Your best bet is to educate him on <cfqueryparam> and show him examples of <cfquery> with and without it.
Public site user/datasource should be limited to just those tables, views and procedures it needs. It will need write access to something but usually it's quite limited. As long as admin side is properly protected that user/datasource could have relaxed access.
This would also help with performance tuning and tracking connections at the database end.
I don't get it. I think your entire comment just refuted the DBA's point because this is what I was going to say also.
It doesn't matter if the datasources allow only read, or only write. If there is a parametered query, it is a point for sql injection no matter what that query is doing, read or write. In fact, most sql injection attacks use union selects to scope out your database schema and read out your user data tables (email, creditcards, names, social security #s, addresses, etc). So separating datasources into read and write is totally pointless because it produces no benefit for the extra work involved. All that time that could be better spent doing code reviews, security audits, building in audit trails, and cqqueryparam'ing queries.
CooLJJ
1) Access private data they are not supposed to.
2) Modify/delete data they should have no control over
3) Modify the schema of your database by creating/dropping objects/permissions etc.
Hopefully the user your data sources authenticate through does not allow for option 3 regardless of whether you are reading or writing.
You are very correct that Option 1 is still problematic even with a read only authentication.
My point is that Option 2 will have been eliminated as a possibility from all of your selects.
Again, whether or not this extra step of security is WORTH it to your organization would need to be determined by yourself. I am simply stating that the DBA's suggestion would in fact eliminate a portion of risk to his Database by minimalizing the places in code which have write access.
Trust me, organizations who take security very seriously will jump through seemingly absurd hoops that are probably "technically" not necessary, but each one covers part of their butt a little bit more. :)
Also, it seems to me that if you had a read-only datasource, could you leave out all the cfqueryparams in the read-only queries? Speed coding up a bit?
On the other side of the argument...say you do use 2 datasources...what's to stop you from just using the write datasource for everything? And then SQL injection problems could occur again. So unless you have code reviews, or preferably some automated tool to find potential security holes, it all seems like wasted effort.
"Hopefully the user your data sources authenticate through does not allow for option 3 regardless of whether you are reading or writing."
True. Hopefully everyone unchecks Create, Drop, Alter, Grant, and Revoke from the advanced settings when setting up datasources.
"My point is that Option 2 will have been eliminated as a possibility from all of your selects. Again, whether or not this extra step of security is WORTH it to your organization would need to be determined by yourself."
I could see that point if eliminating the treat footprint actually lowers the risk, and like you said it is pretty much up to the organization to decide if it does so in any significantly measurable way. But then again, it doesn't eliminate the treat, it just eliminates the treat footprint. A wise cracker could still scope out your schema, then move to a form that writes data to the DB, and manipulate queries to write malicious data where ever he wants.
If the DBA guy thinks this scheme is the end all to protect his databases against possible corruption by SQL Injection attacks, I would say he is misguided.
CoolJJ
About 4 years ago I took an advanced CF class and the instructor recommended that we use 2 database users and 1 DSN. The DSN was setup with the username and password for the read-only account. Then if you wanted to update or delete data you had to supply the other set of credentials in your cfquery tag.
So, here are my questions:
1: What do you think about that reasoning?
2: Are you storing the username and password in your DSN or do you supply it for every cfquery, cfstoredproc, etc?
I totally trust what Adobe has to say about this, and think maybe we should seek their official wisdom on the matter.
Unfortunately I have since switched jobs so I don't have access to the manual to check.
Often developer do know the best practices but in practice they are forgotten every now and then. If there is second line of defence it can't be too bad!
IIRC, any series of queries within a given pair of cftransacation tags must all be referencing the same datasource (otherwise CF complains).
I don't know if that restriction has been removed in more recent versions of CF, but I'd see that as a deal-killer (regarding this splitting approach) right from the start - if transactions are thrown out the window, then this strictly decreases the consistency of the db-hosted data.
Apparently from this DBA's perspective, we programmers are completely unreliable. It gives him hives just thinking that we have access to his database(s). The least he can do is completely eliminate the possibility of SQL injection with inserts or deletes on the select queries. For many sites, the select queries are likely more prominent and easiest to find.
The 2 datasource approach would "work" to protect the read-only queries because the read-only datasource would allow SELECT statements only and the write datasource would allow INSERT/UPDATE/DELETE statements only... Using the write database for select statements would not work, enforcing the 2 datasource approach on we weaselly programmers.
I don't think this is the solution to his/her concerns. The solution is a code review and careful usage of query params like everyone has said. But this requires trust. If you don't trust the programmer(s) and were a control freak, I can understand why you would come to this 2 datasource approach.
Ugh. I feel for ya.
This DBA reminds me of the so-called 'Usability and Section 508 expert' who demanded that source code (CFML & Fusebox XML files) be Section 508 compliant.
Debating technical implementation can go on forever, and this is not what's in the best interest of the business.
I'd recommend the following steps:
1) A representative or two from the DBA and Development teams get together, including the manager(s).
2) Define the problem. This is the biggest issue I see here, if it's not defined then everyone is trying to solve different problems, and solving only the symptoms of the problem in the process. Is the problem Security, unreliable developers, trust, etc...
3) With the problem now defined, itemize all of the options to solve the problem, along with the pros and cons of each. Multiple data sources, cfqueryparams, stored procs, code reviews, SQL permissions, CF Admin settings, process changes (e.g. prior to release you use that sql injection scanning tool that Chad mentioned), etc... And don't limit pros and cons to just the technical perspective, what is the cost/effort, limitations, business impact, etc...
4) Solicit feedback from the teams, external experts like Ray.
5) Recommend one or more of the options stating why.
6) Have someone with the authority to support the decision sign off.
7) There's no more debate anymore, the solution is backed by mgmt. Execute the plan, and if anyone doesn't like it - they can quit.
And if that user has access to other databases, the DSN doesn't limit access to those, either.
This might be of interest if you want to see what your exposures are:
http://yougiveloveabad.name/archives/2008/06/27/cf...
My Oracle DBA makes statement like yours on a daily basis, but we've just learned to keep him in the corner and knod our heads...
I think his suggestion makes no sense... SQL Injection attacks only effect write changes... so making two seperate accounts only adds extra work and complexity to your application...
Poor guy... I feel for you bro.


https://download.spidynamics.com/Products/scrawlr/...
I tried it with this code and it said i did have a vulnerability. I added a cfqueryparam and the vulnerability was gone.
<code>
<cfparam default="1" name="URL.FORMID">
<cfquery datasource="UPS_Shipping" name="test">
SELECT *
FROM package
WHERE id = #URL.FORMID#
</cfquery>
<a href="?formid=2">test</a>
<cfdump var="#test#">
</code>