Quote raw sql in ZEND to avoid sql injection - zend-framework

Long story short, I have an admin section where the user can choose from multiple dropdown lists the tables and fields that must be queries in order to get some values. Therefore, the query in ZEND is performed by concatenating the strings
$query = "SELECT $fieldName1, $fieldName2 from $tableName where $fieldName1 = $value";
How can I escape the above using ZEND approach to avoid sql injection? I tried adding them all as ? and calling quoteinto but it seems this does not work on some of the variables (like table names or field names)

ZF has quoteIdentifier() specifically for this purpose:
$query = "SELECT ".$db->quoteIdentifier($fieldName1).","...
In your case you might (also) want to check against a white list of valid column names.

Use quoteInto() or Zend_db_Select::where() for the values, and for the table and column names, I would simply strip any non alpha characters and then wrap them in ` quotes prior to using them in your SQL.
Example:
// Strip non alpha and quote
$fieldName1 = '`' . preg_replace('/[^A-Za-z]/', '', $fieldName1) . '`';
$tableName = '`' . preg_replace('/[^A-Za-z]/', '', $tableName) . '`';
// ....
// Build the SQL using Zend Db Select
$db->select()->from($tableName, array($fieldName1, $fieldName2))
->where($fieldName1 . ' = ?', $value);

In SafeMysql you can make it as simple, as
$sql = "SELECT ?n, ?n from ?n where ?n = ?s";
$data = $db->getAll($sql,$fieldName1,$fieldName2, $tableName, $fieldName1, $value);
though I understand that you won't change your ZF to SafeMysql.
Nevertheless, there is one essential thing that is ought to be done manually:
I doubt you want to let users to browse users table or financial table or whatever.
So, you have to verify a passed table name against an allowed tables array.
like
$allowed = ('test1','test2');
if (!in_array($tableName, $allowed)) {
throw new _403();
}

Related

How to search in SQL for cloumn with asterisk?

I try to create advanced search to my database.
I want to do something like that: if the user type for search = overf**w
and I have in my database an cloumn that his value = overflow - show him.
this my code:
$name = str_replace('*', '_', $name);
SELECT name FROM table WHERE name LIKE CONCAT('%', ?, '%')
its not working, I dont know what the problem.
You can't use LIKE in this situation, you need to use REGEXP() to do a wildcard search. Replace * or ** with .*. To only return names that starts with the given value use ^ at the beginning of the regular expression
SELECT name
FROM actors
WHERE name REGEXP('^overf.*w')
I don't know php but your $name parameter should be set like this (in pseudo code)
$name = '^' + replace($name, '**', '.*')

PHP: extract comma separated values from MySQL

my table is:
id | id_fruit | name
2|1|orange|
3|1|apple|
23|1|banana|
34|1|ananas|
35|3|kiwi|
I want to extract all name where id_fruit=1 and print them in a form field as values in this way:
orange, apple, banana, ananas
I've tried
select concat_ws(', ', name) from fruits where id_fruit=1 but doesn't work.
Ho can I do it? thanks!
User Group_Contact function in mysql
Select group_concat(name) from my table where fruit_id=1
I think you misunderstood the concat_ws() use.
MySQL documentation about this function explains you must give every argument to join at once.
So you sql statement has no effect.
As Raja says, you can go with your back-end programming language (such as php, python or whatever you use).
You just select without the concat_ws and do the join on the back-end side.
It seems concat_ws() main use is to concat two fields from the same entry in mysql, such as the firstname and lastname (fields) for example of the same user (entry).
Simply through PHP, you can do like that!
You can while loop all the names like this.
PHP
$in = 0;
$fruits = "";
while($row = mysqli_fetch_assoc($exeutedquery)){
if($i == 0){
$fruits += $row['name'];
$i++;
}else{
$fruits += ",".$row['name'];
}
}
AND FOR SQL
SELECT STUFF
(
(select ',' + name
from
fruits
where
ID in (1,2,3)
FOR XML PATH('')
),1,1,''
)
BAM!

Modifying Columns In Zend Framework Select

In a Zend_Db_Select object, I am doing a join to get user information for some data records. For the join is on a userId, I would like to combine the user first and last name into a single column of name.
Basically I am looking to have something similar to this:
$table = array('u' => 'User');
$condition = 'u.id = t.id';
$columns = array('UserName' => 'u.FirstName + " " + u.LastName')
$select->joinLeft($table, $condition, $columns);
I have tried using a Zend_Db_Expr with no luck and the above does not work.
How would I go about doing this?
Zend_Db_Expr is the way to go, but you'll have better luck if you use the database's concatenation function. Assuming MySQL:
$columns = new Zend_Db_Expr("CONCAT(u.FirstName, ' ', u.LastName') AS name")

[zend][db] fetchAll with multiple variables

I'm trying to use fetchAll on a query that has 2 variables. I can't figure out the syntax.
I can manage with only 1 variable:
$sql = "SELECT * FROM mytable WHERE field1 = ?";
$this->_db->fetchAll($sql,$value1); # that works
However I'm having some issues when query has multiple variables
$sql = "SELECT * FROM mytable WHERE field1 = ? AND field2 = ?";
$this->_db->fetchAll($sql,$value1,$value2); # doesn't work
$this->_db->fetchAll($sql,array("field1"=>$value1,"field2"=>$value2)); # doesn't work either
The reason why I want to use ? instead of placing the variables directly into the query is that I've learned that using ? allows for the query to be compiled generically by the db engine and improves performances.
There are two types of parameter, named parameters and positional parameters. You're mixing the two types and that won't work.
Named parameters match a placeholder by name. Names are started with the : symbol. The parameter names are not the same as the names of the columns you happen to use them for. You supply parameter values in an associative array, using the parameter name (not the column name) as the array keys. For example:
$sql = "SELECT * FROM mytable WHERE field1 = :param1 AND field2 = :param2";
$this->_db->fetchAll($sql,array("param1"=>$value1,"param2"=>$value2));
Positional parameters use the ? symbol for the placeholder. You supply parameter values using a simple (non-associative) array, and the order of values in the array must match the order of parameter placeholders in your query. For example:
$sql = "SELECT * FROM mytable WHERE field1 = ? AND field2 = ?";
$this->_db->fetchAll($sql,array($value1,$value2));
Most brands of SQL database natively support only one style or the other, but PDO attempts to support both, by rewriting the SQL if necessary before preparing the query. Since Zend_Db is modeled after PDO, Zend_Db also supports both parameter styles.
This question is a bit old, but I thought I'd just add to it for reference sake.
I would recommend starting to use Zend_Db_Select with Zend_Db. I've been doing a lot with Zend_Db lately. More from Zend_Db_Select reference guide.
Lets assume you have a Zend_Db adapter: $this->_db
# this will get the Zend_Db_Select object
$select = $this->_db->select();
# now you build up your query with Zend_Db_Select functions
$select->from('mytable');
$select->where('field1 = ?', $field1);
$select->where('field2 = ?', $field2);
[...]
# echo to see the SQL (helps in debugging)
# SELECT * FROM mytable WHERE field1 = ? AND field2 = ? [...]
echo '<p>My SQL: ' . $select . '</p>';
# Execute the SQL / Fetch results
$results = $select->query()->fetchAll();
That's the basics from your given example, but the Zend Framework reference guide on the select object has a lot of good information on how to build even more complex queries with JOINS, UNIONS, GROUP BY, LIMIT, HAVING, etc.
If you wanted to use an alias name for a table or parameters, you use an associative array with the alias name being the index value:
# SELECT p.* FROM products AS p
$select->from('p' => 'products');
If you want to return only selected fields, you add an array of field names as a second parameter:
# SELECT model FROM products
$select->from(products, array(model));
Actually, the above could should produce fully qualified SQL as:
SELECT 'products'.model FROM 'products'
but I wrote the above for brevity and clarity in the example.
One thing I just came across is using AND and OR in the WHERE condition.
# WHERE a = $a
$select->where('a = ?', $a);
# WHERE a = $a AND b = $b
$select->where('a = ?', $a);
$select->where('b = ?', $b);
# WHERE a = $a OR b = $b
$select->where('a = ?', $a);
$select->orWhere('b = ?', $b);
# WHERE a = $a AND b = $b
$select->orWhere('a = ?', $a);
$select->where('b = ?', $b);
Notice, that whatever the following "where" function you use, will combine with the previous statement as that operand. Ok, that sounded confusing.
If the second "where" is an "OR" it will be an "OR" conditional. If the second "where" is a "AND" the statement will be "AND".
In other words, the first WHERE function is ignored in terms of what condition it will use.
In fact, I just asked a question on Stack Overflow yesterday regarding doing a complex WHERE using select.
Hope that helps!
Cheers!
Try this:
$sql = "SELECT * FROM mytable WHERE field1 = ? AND field2 = ?";
$statement = $this->_db->query($sql,array("field1"=>$value1,"field2"=>$value2));
$data = $statement->fetchAll();
$this->_db must be an instance of Db adapter.
Heres the actual Zend way to code for this.
$sql = "SELECT * FROM mytable WHERE field1 = :param1 AND field2 = :param2";
$this->_db->fetchAll($sql,array("param1"=>$value1,"param2"=>$value2));
$where = $this->_db->select()
->from('mytable')
->where('field1 = ?',$value1)
->where('field2 = ?',$value2);
$rowSet = $this->_db->fetchAll($where);
This works great for me

Is there an equivalent of PHP's mysql_real_escape_string() for Perl's DBI?

Could some tell me if there is a function which works the same as PHP's mysql_real_escape_string() for Perl from the DBI module?
You should use placeholders and bind values.
Don't. Escape. SQL.
Don't. Quote. SQL.
Use SQL placeholders/parameters (?). The structure of the SQL statement and the data values represented by the placeholders are sent to the database completely separately, so (barring a bug in the database engine or the DBD module) there is absolutely no way that the data values can be interpreted as SQL commands.
my $name = "Robert'); DROP TABLE Students; --";
my $sth = $dbh->prepare('SELECT id, age FROM Students WHERE name = ?');
$sth->execute($name); # Finds Little Bobby Tables without harming the db
As a side benefit, using placeholders is also more efficient if you re-use your SQL statement (it only needs to be prepared once) and no less efficient if you don't (if you don't call prepare explicitly, it still gets called implicitly before the query is executed).
Like quote?
I would also recommend reading the documentation for DBD::MySQL if you are worried about utf8.
From http://www.stonehenge.com/merlyn/UnixReview/col58.html :
use SQL::Abstract;
...
my $sqa = SQL::Abstract->new;
my ($owner, $account_type) = #_; # from inputs
my ($sql, #bind) = $sqa->select('account_data', # table
[qw(account_id balance)], # fields
{
account_owner => $owner,
account_type => $account_type
}, # "where"
);
my $sth = $dbh->prepare_cached($sql); # reuse SQL if we can
$sth->execute(#bind); # execute it for this query
Database Handle Method "quote"
my $dbh = DBI->connect( ... );
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote("Don't");
http://metacpan.org/pod/DBI#quote