I have the following code in PHP:
$IDs = implode(",", array_keys($result["matches"]));
$sql = "SELECT * FROM table WHERE id IN ($IDs)";
I am "translating" it into Node.js, and I suppose that implode becomes array.join, so I tried this:
var ids = Object.keys(answer['matches']).join(",");
var sql = "SELECT * FROM xml_it WHERE id IN (" + ids + ")";
now, if I echo the PHP $sql variable, I get the expected result:
SELECT * FROM table WHERE id IN (3187,3220,3233,3245,3246,3251,3253,3256, ...
BUT, with node.js, I am getting this:
SELECT * FROM xml_it WHERE id_xml IN ([0,1,2,3,4, ...
The answer['matches'] obviously is the same result (it's basically a Sphinx search result)
Any idea why I am not getting it as a string but the keys?
the data of $result and var answer looks like this:
[{"doc":3187,"weight":1,"attrs":{}},{"doc":3220,"weight":1,"attrs":{}},{"doc":3233,"weight":1,"attrs":{}},
This should work:
var matches = answer['matches'].map( function( o ) {
return o.doc;
});
var ids = matches.join(",");
var sql = "SELECT * FROM xml_it WHERE id IN (" + ids + ")";
gotta map out the doc field since the structure is different
Related
I am writing code using nestjs and typeorm.
However, the way I write is vulnerable to SQL injection, so I am changing the code.
//Before
.where(`userId = ${userId}`)
//After
.where(`userId = :userId` , {userId:userId})
I am writing a question because I was changing the code and couldn't find a way to change it for a few cases.
//CASE1
const query1 = `select id, 'normal' as type from user where id = ${userId}`;
const query2 = `select id, 'doctor' as type from doctor where id = ${userId}`;
const finalQuery = await getConnection().query(`select id, type from (${query1} union ${query2}) as f limit ${limit} offset ${offset};`);
//CASE2
...
.addSelect(`CASE WHEN userRole = '${userRole}' THEN ...`, 'userType')
...
//CASE3 -> to find search results in order of accuracy
...
.orderBy(`((LENGTH(user.name) - LENGTH((REPLACE(user.name, '${keyword.replace( / /g, '', )}', '')))) / LENGTH('${keyword.replace(/ /g, '')}'))`,
'ASC')
...
//CASE4
let query = 'xxxx';
let whereQuery = '';
for(const i=0;i<5;i++)
whereQuery += ' or ' + `user.name like '%${keyword}%'`
query.where(whereQuery)
I cannot use parameter in the select function.
In the above case, I am wondering how to change it.
Is it ok to not have to modify the select code?
Code example
// Creates an Objection query.
// I have no control over the creation of the query. I can only modify the query after it has been created.
// Example: "select `todos`.* from `todos` where `text` = ?"
const objectionQuery = thirdPartyService.createQuery(userControlledInput);
// Adds an access check. Example "select `todos`.* from `todos` where `text` = ? and `userId` = ?"
objectionQuery.andWhere("userId", currentUser.id);
The above example has a security bug. If the thirdPartyService generates a query like this:
select `todos`.* from `todos` where `text` = ? or `id` = ?
Then after adding the access check we will get the following query:
select `todos`.* from `todos` where `text` = ? or `id` = ? and `userId` = ?
And this query can return data that doesn't belong to the current user.
To fix this bug, we need to enclose the user-controlled conditions in parentheses:
select `todos`.* from `todos` where (`text` = ? or `id` = ?) and `userId` = ?
But how do I do this with the Objection query builder? I imagine something like this:
const objectionQuery = thirdPartyService.createQuery(userControlledInput);
wrapWhereClauses(objectionQuery);
objectionQuery.andWhere("userId", currentUser.id);
From docs: You can add parentheses to queries by passing a function to any of the where* methods:
await Todo.query()
.where('userId', 1)
.where(builder => {
builder.where('text', 2).orWhere('id', 3);
});
will result in
select * from "todos" where "userId" = 1 and ("text" = 2 or "id" = 3)
One way could be to wrap the original query to be subquery / temporary table:
MyModel.query().from(thirdPartyService.createQuery(userControlledInput)).where(...)
(please let me know if this works at all, I haven't tested it)
I'm using the orientjs library to perform operations in the Orient Database. I read in the documentation that it's possible to use parameter-style queries like the following:
db.query(
'SELECT name, ba FROM Player '
+ 'WHERE ba >= :ba AND team = ":team"',
{params: {
ba: targetBA,
team: targetTeam }
}, limit: 20
).then(function(hitters){
console.log(hitters)
});
My question is: Is it enough to prevent SQL injection? Because I didn't find information about that in the NodeJS API. In the case of Java, there is a 'Prepared Query' concept, I'm not sure if they are refering to the same thing.
Seems to be secure, I'm trying with this code (yours taken from the wiki is a bit buggy):
var name='admin';
db.open().then(function() {
return db.query(
"SELECT * FROM OUser "
+ "WHERE name = :name",
{params:{
name: name
}
});
}).then(function(res){
console.log(res);
db.close().then(function(){
console.log('closed');
});
});
First of all, the query is parsed as SELECT * FROM OUser WHERE name = "admin" (observed with the Studio Query Profiler).
As expected, I get the admin user record.
Since the params are evaluated directly as String, there's non need quote them (e.g. :name not ':name'). So there is no way to inject something like ' OR '1'='1 or any ; drop something;
Here are some test I did:
var name='; create class p;';
returns no records;
evaluated by orient as: SELECT * FROM OUser WHERE name = "; create class p;"
var name="' OR '1'='1";
returns no records;
evaluated as: SELECT * FROM OUser WHERE name = "' OR '1'='1"
var name='" OR "1"="1';
returns no records;
evaluated as: SELECT * FROM OUser WHERE name = "\" OR \"1\"=\"1"
quoting the param name in the query: "WHERE name = ':name'"
evaluated as: SELECT * FROM OUser WHERE name = ':name'
Feel free to try more combinations, in my opinion seems quite safe.
hi I am currently developing a geo location based app which updates the user's location and displays the shops around him, I am using ordinary sql queries in sql database .My php code to select the shops around the user is :
/*
* Following code will list all the products
*/
// array for JSON response
$response = array();
// include db connect class
require_once __DIR__ . '/db_connect.php';
// connecting to db
$db = new DB_CONNECT();
if (isset($_POST['code']) && isset($_POST['lat']) && isset($_POST['lng'])) {
$code = $_POST['code'];
$lng = $_POST['lng'];
$lat = $_POST['lat'];
// get all data from table this is my code to fetch data where i need change
$result = mysql_query("SELECT *, ( 3959 * acos( cos( radians($lat) ) * cos( radians( lat ) ) * cos( radians(lng) - radians($lng) ) + sin( radians($lat) ) * sin( radians(lat)))) AS distance
FROM maintable
HAVING distance < 25
ORDER BY distance
") or die(mysql_error());
// check for empty result
if (mysql_num_rows($result) > 0) {
// looping through all results
// products node
$response["people"] = array();
while ($row = mysql_fetch_array($result)) {
// temp user array
$people = array();
$product["_id"] = $row["_id"];
$product["name"] = $row["name"];
$product["distance"] = $row["distance"];
$product["lat"] = $row["lat"];
$product["lng"] = $row["lng"];
$product["image_bit"] = $row["image_bit"];
$product["security"] = $row["security"];
$product["status"] = $row["status"];
$product["code"] = $row["country_code"];
$product["phone"] = $row["phone"];
// push single product into final response array
array_push($response["people"], $people);
}
// success
$response["success"] = 1;
// echoing JSON response
echo json_encode($response);
} else {
// no products found
$response["success"] = 0;
$response["message"] = "No people found";
// echo no users JSON
echo json_encode($response);
}
}
else{
//required field is missing
$response["success"] = 0;
$response["message"] = "Required field missing";
// echoing JSON response
echo json_encode($response);
}
?>
i store the user's latitude and longitude values as lat and lng respectively.
But i recently heard about spatial datatype in sql,which will is more efficient, what i need to know is if i need to use spatial queries what change should be done in my lat and lng columns in sql table and can please anyone modify mysql query as a spatial query .any help would be appreciable
You can try a quadkey. Translate the points to a binary and interleave it. Treat it as base-4 number. The quadkey is similar to a quadtree but also it has interesting properties. It is often use for tiling.
I am updating the db table using below code but it does not seem to working fine.
$model = new Admin_Model_DbTable_SmsTemplate();
$where = $model->getDbTable()->getAdapter()->quoteInto('id = ?', $id);
$model->getDbTable()->update(array('content'=>$content), $where);
what is the error in this code as it is giving affected rows zero.
Thanks.
When using Zend_Db_table IN ZF1.
You can achieve it like this:-
$db=Zend_Db_Table::getDefaultAdapter();
$model = new Admin_Model_DbTable_SmsTemplate($db);
$where = 'id = ' . $id;
$model->update(array('content'=>$content), $where);
OR
$db=Zend_Db_Table::getDefaultAdapter();
$where = 'id = ' . $id;
$db->update('YourTableName', array('content = ?' => $content,),
$where
);
And the adapter will do quote work for you.