Zend sql injection prevention - sql

Hi I have this small code fragment from a web application built on ZEND framework that is not safe since 'name' is fetched from post request. Is there a standard ZEND way to prevent special symbols in $data? Like $where has the quoteInto.
$name = $this->_request->getParam('name');
// update query
$data = array(
'name' => $name
);
$where = array(
$users->getDbAdapter()->quoteInto('user_id = ?', $userId),
);
$users->update($data, $where);

This is safe from SQL injection. Zend_Db treats the array you pass to update() as an array of named parameters, so these values are escaped automatically.

Tim is correct if a bit terse. :)
The $data array in an update statment in Zend_Db is broken down into bound parameters. You can find the exact code in Zend_Db_Adapter_Abstract.
There are a number of procedures involved but the array ultimately ends up in this statement.
$set[] = $this->quoteIdentifier($col, true) . ' = ' . $val;
where your original array was $col => $val
then the SQL is created:
$sql = "UPDATE "
. $this->quoteIdentifier($table, true)
. ' SET ' . implode(', ', $set)
. (($where) ? " WHERE $where" : '');
It looks reasonably secure against SQL injection.
However you can always employ Zend_Filter_Input with Zend_Validate and Zend_Filter to really sanitize your input values.

Related

With PHRETS v2, Can I Sort the Data Fields Alphabetically? (Had this when using V1)

This code works in terms of retrieving data:
<?php
date_default_timezone_set('America/Phoenix');
require_once("composer/vendor/autoload.php");
$config = new \PHRETS\Configuration;
$config->setLoginUrl('my_url')
->setUsername('my_user')
->setPassword('my_pass')
->setRetsVersion('1.7.2');
$rets = new \PHRETS\Session($config);
$connect = $rets->Login();
$system = $rets->GetSystemMetadata();
echo "Server Name: " . $system->getSystemDescription();
$property_classes = ['Property'];
foreach ($property_classes as $pc) {
// generate the DMQL query
$query = "(BedroomsTotal=1+),(MlsStatus=ACT,PND)";
$results = $rets->Search('Property', $pc, $query);
file_put_contents('MyFolder/Property_' . $pc . '.csv', $results->toCSV());
} //end for each property class
php?>
I would like to know how to sort the fields alphabetically, in order to keep fields in a predicable order, which could also be used in an SQL CREATE TABLE statement. I had this ability with v1.
I would also like to be able to loop through the data fields with a FOR EACH kind of statement, in order to create a customized field delimiter; a custom delimiter helps with avoiding import errors in cases where the delimiter also appears within the metadata, such as quotes and commas within remarks section.
Any help is much appreciated. :)

ZF2: Is there a more efficient way to do this Zend\Db Update query?

Here's some ZF1 code for an update query:
$this->getAdapter()->update(
'users', $data, $this->getAdapter()->quoteInto('node_id = ?', $user->nodeId)
);
Here's the same query with ZF2:
$param = $this->getAdapter()->platform->quoteValue($user->nodeId);
$sqlOj = new Sql($this->getAdapter());
$update = $sqlOj->update('users')->set($data)->where('node_id = ' . $param);
$updateString = $sqlOj->getSqlStringForSqlObject($update);
$this->getAdapter()->query($updateString, Adapter::QUERY_MODE_EXECUTE);
As you can see, one line of ZF1 code has become 5 lines of ZF2 code, (actually without the fluent interface it would be 7 lines...)
Am I missing something? Or is ZF2's DB component just more verbose that ZF1?
BTW, I have found the same scenario with select and insert queries too...
I managed to limit it to 3 lines.
use \Zend\Db\Sql\Sql;
$sql = new Sql ($adapter);
$update = $sql->update ('users')->set ($data)->where (['id = ?' => 1]);
$adapter->query ($sql->getSqlStringForSqlObject ($update), $db::QUERY_MODE_EXECUTE);
The problem is they didn't expect you to run your updates like that. Instead, you are expected to use a table gateway.
This way it becomes one line again:
$this->tableGateway->update($data, array('id' => $id));

pdo is not returning an output. Fatal error: Call to a member function fetch() on a non-object in C:\webroot\wamp\www\index.php on line 12

<?php
$config['db'] = array (
'host' => 'localhost',
'username' => 'root',
'password' => '',
'dbname' => 'pdologin'
);
$db = new PDO("mysql:host={$config['db']['host']};dbname={$config['db']['dbname']}",
$config['db']['username'], $config['db']['password']);
$query = $db->query("SELECT * 'firstname' FROM 'login'");
while ($row = $query->fetch(PDO::FETCH_ASSOC)){
echo $row['firstname'], '<br>';
}
?>
When I run the code I get error "Fatal error: Call to a member function fetch() on a non-object in C:\webroot\wamp\www\index.php on line 12".
Whats making it error? The only thing I can think of is the SQL query.
This SQL query has two syntax errors in it:
$query = $db->query("SELECT * 'firstname' FROM 'login'");
You can't use a string literal as a table in the FROM clause.
Explanation: different types of quotes do different things in SQL.
Single-quotes are always delimiters for string literals or date literals.
In MySQL, back-ticks are delimiters for table identifiers (as well as columns and other metadata objects).
Double-quotes are delimiters for table identifiers in standard SQL, and in MySQL if you set SQL_MODE=ANSI_QUOTES. But by default in MySQL, double-quotes are the same as single-quotes, delimiting strings and dates.
You also had 'firstname' in your query in an invalid place. I can't tell if you meant that to name a column (if so, you were getting the quote type wrong again), or if you meant it to be a column alias (if so, you can't alias *, you can only alias a single specific column).
So your query should look like this:
$query = $db->query("SELECT * FROM `login`");
Another mistake in your script is that you don't verify that $query is an object of type PDOStatement before calling PDOStatement methods on it. PDO::query() will return false if there was an error in the SQL. false is a primitive value, not an object, so it will naturally not have any methods you can call. So you always have to check the return value before doing anything else with it.
For example:
$query = $db->query("SELECT * FROM `login`");
if ($query === false) {
die(print_r($db->errorInfo(), true));
}

Extbase - get created sql from query

i want to get some database tables from my typo3 extensions.
The Extension is based on extbase.
The query always returns nothing but the data exists
I've tried this:
$query = $this->createQuery();
$query->statement('SELECT * FROM `my_table`
WHERE field = ? ORDER BY date DESC LIMIT 1',
array($condition));
$results = $query->execute();
and this:
$query = $this->createQuery();
$query->matching($query->equals('field', $condition));
$query->setOrderings(array('date' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING));
$query->setLimit(1);
$results = $query->execute();
both returns null as result.
Is it possible to get the sql that the class creates to look where the bug is?
I've looked in some extbase persistent classes but didn't find a clue
EDIT:
For those who are interested.. i found a "solution".
If you create the query with the statement() method, you can print the query with this function
echo $query->getStatement()->getStatement();
It doesn't replace the placeholder.
But you can get the Variables with this method
var_dump($query->getStatement()->getBoundVariables());
Thats the best Solution that i found, without editing the extbase extenstions
In TYPO3 6.2 you can use Extbase DebuggerUtility to debug the query.
Add this code before $query->execute():
$queryParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser');
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->parseQuery($query));
For TYPO3 8.7+ use this code instead:
$queryParser = \TYPO3\CMS\Core\Utility\GeneralUtilityGeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
$doctrineQueryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query);
$doctrineQueryBuilderSQL = $doctrineQueryBuilder->getSQL();
$doctrineQueryBuilderParameters = $doctrineQueryBuilder->getParameters();
Check this snippet, although it's not very comfortable in use it helps a lot:
in general you need this code at the end of the buildQuery(array $sql) method (*) - right before return $statement;
if (in_array("your_table_name", $sql['tables'])) {
var_dump($statement);
print_r($statement);
}
(*) Class file:
TYPO3 ver.: 4.x: typo3/sysext/extbase/Classes/Persistence/Storage/Typo3DbBackend.php
TYPO3 ver.: 6.x: typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
In 6.2.x ...
You can try within \TYPO3\CMS\Core\Database\DatabaseConnection::exec_SELECTquery method, just add the condition after fetching the $query, like (trim is important!):
public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
$query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
if (trim($from_table) == 'fe_users') {
DebuggerUtility::var_dump($query);
}
// rest of method
An easy way without changing any Typo3 core code and not mentioned in any forum so far is using the php "serialize()" method:
$result = $query->execute();
echo (serialize($result));
In the result object you find the SQL query ("statement;" ...)
Improvement to biesiors answer:
As Extbase replaces some placeholders after calling buildQuery(), you might prefer to place the debug output into getObjectDataByQuery(), just after $this->replacePlaceholders($sql, $parameters, $tableName);
if (strpos($sql, "your_table_name.")) {
debug($sql, 'my debug output');
};
Also, better use debug() instead of var_dump().
[File: typo3\sysext\extbase\Classes\Persistence\Generic\Storage\Typo3DbBackend.php. Line 339 in version 6.1]:
$query = $this->createQuery();
$query->getQuerySettings()->setReturnRawQueryResult(TRUE);
$getHotelInfo = 'SELECT * FROM `my_table` WHERE field = ? ORDER BY date DESC LIMIT 1';
return $query->statement($getHotelInfo)->execute();
For executing query you have to write 'setReturnQueryResult' on your repository
I just extended the above snippet, with a $_GET condition.
for debugging, just append "?dbg_table=tx_some_of_my_tables" to your address, and you're ready to go ;-)
if (in_array($_GET['dbg_table'], $sql['tables'])) {
echo('<div style="background: #ebebeb; border: 1px solid #999; margin-bottom: 20px; padding: 10px;"><pre style="white-space: normal">'.$statement.'</pre></div>');
}
A cleaner way to debug your statements when using TYPO3 6.1 is to use the query parser of Typo3DbBackend.
$parser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend');
$params = array();
$queryParts = $parser->parseQuery($query, $params);
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('query', 'my_extension', 1, array('query' => $queryParts, 'params' => $params));
The parser returns an array containing the different parts of the generated SQL statement.
With TYPO3 6.2 the parseQuery method was moved to Typo3DbQueryParser and lost its second parameter.
i suggest set this in typo3conf/LocalConfiguration.php file under 'SYS' array
'SYS' => array(
......
'displayErrors' => 1,
'sqlDebug' => 1
.......
)
and then write wrong field name in query intentionally and then execute code.
this will show last query execute with error.

Trying to get property of non-object Yii

I dont get this error, there is a row in database.
$tip = StringHelper::trimmer($_GET['tip']);
$sql = 'SELECT id FROM contact_reasons WHERE alias = "' . $tip . '"';
$model = ContactReasons::model()->findAllBySql( $sql );
die($model->id);
if(!is_null($model)) {
$this->render('kontakt', array(
'model' => $model,
));
} else {
$this->renderText('Tražena stranica ne postoji.');
}
I used debug to see if there is a response, and even used query on database, and it returns a row with ID. I get this error on line with die();
Please note that, findAllBySql returns an array of CActiveRecords, while findBySql returns a single CActiveRecord. You may also use parameter binding for your SQL statements to prevent SQL injection.
see also http://www.yiiframework.com/doc/api/1.1/CActiveRecord