I searched before posting this but didn't find an answer to my question.
I have a table in a database which stores queries such as (with the php variable stored in the database):
select * from accounts where type = 'client'
select * from accounts where user_id = $userid
select * from accounts where name = '$name'
I assumed that when I pulled that particular query from the database that PHP would recognized the variable and replace it but it treats it as regular text.
Is there a way to have PHP replace the $__ with an actual variable that exists? I think maybe the eval() function perhaps??
What you might try is using it as a prepared statement. So instead, if your database stored queries looked like this:
select * from accounts where type = 'client'
select * from accounts where user_id = ?
select * from accounts where name = ?
and you use PDO prepared statements like this:
$pdo = new PDO($dsn, $user, $pass);
$statement = $pdo->prepare($secondOfTheAboveQueries);
$statement->execute(array($userId));
$account = $statement->fetch();
You could also use prepared queries with named variables like user_id = :userid instead of questions marks if you have to process a few statements at a time with various variables.
You may also want to consider stored procedures which work similarly. An explanation for both can be found here:
http://php.net/manual/en/pdo.prepared-statements.php
Assuming that you pull the query from a database:
$string = ''; // Assign the real userID
while ($fetch = mysql_fetch_array($query)) {
$newQuery = str_replace('$userid', $string, $fetch['your_row_name']);
}
I'm not sure if this will work, but this is what i would try first...
sprint seems to work well. instead of storing them as $variable, I can use %s, etc.
Related
$level_sql_switch = mysqli_query($conn, "SELECT course_period_id
FROM course_periods
WHERE school_id = '$campus'
AND short_name = '$level'");
$course_period_id = $level_sql_switch->fetch_assoc();
$course_period_id = $course_period_id['short_name'];
For Example, when the excel file is read, the variable $level stores the value "C1". I would like to return a C1-T from the database using a select statement. How would you do so while ruling out the other variants of C1 (C1-A, C1-B, C1-C, C1-T2 and etc). As you cannot simply set the short_name = '$level' or use a substring.
"SELECT course_period_id FROM course_periods WHERE school_id = '$campus' AND short_name = '$level'"
It's not 100% made clear, but presumably $level won't always contain C1. Assuming also that you always want to find the variant -T then you could simply set the parameter as
short_name = '$level-T'
In full:
SELECT course_period_id
FROM course_periods
WHERE school_id = '$campus' AND short_name = '$level-T'
It should also be noted that your code is vulnerable to SQL Injection attacks. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. Never insert unsanitised data directly into your SQL like the above.
As I said above, you can find examples of precisely how to write what you need, but a parameterised version of your query with mysqli would look like:
SELECT course_period_id
FROM course_periods
WHERE school_id = ? AND short_name = ?
Then elsewhere you'd assign your first parameter to be $campus and your second to be "$level-T" before passing them to the query.
I am quite new to PDO, and am trying to change my MySQLi procedurally structured php code to an Object Oriented PDO structure. I am just learning about preparing, executing, bindParam/bindValue and the like, to a degree of success.
My question is how do I prepare a query when the user submitted value is in a subquery of that query?
I have a variable used as a subquery in php (where $playerOne, $playerTwo are user submitted values).
$sqlPlayerOne = "(SELECT * FROM players WHERE Player_name = $playerOne)";
$sqlPlayerTwo = "(SELECT * FROM players WHERE Player_name = $playerTwo)";
This it to get all records for these players. I can then, as an example, compare what games they played against each other e.g.
$sqlWith = "SELECT * FROM $sqlPlayerOne s1
WHERE EXISTS (SELECT * FROM $sqlPlayerTwo s2 WHERE s1.Team_name = s2.Opposing_team)
Note: SELECT * is just used to make it more readable here.
Is it enough to do $pdoWith = $db->prepare($sqlWith) or should I be preparing the $sqlPlayerOne first, as this has the user submitted value?
I realise I could just copy/paste the subquery inside every single main query that needed it, but if I don't have to I'd rather not.
EDIT: Sorry for the lack of clarity. This was a section of my code before I changed it, as i wasn't sure how I would have to change it. It seems I will just have to do it similar to how #J-C FOREST pointed out:
$dsn = "mysql:host=localhost;dbname=database";
$username = "user";
$password = "pass";
$db = new PDO($dsn, $username, $password);
$stmt = $db->prepare("SELECT * FROM (SELECT * FROM players WHERE Player_name = :playerone)
s1 WHERE EXISTS (SELECT * FROM (SELECT * FROM players WHERE Player_name = :playertwo) s2
WHERE s1.Team_name = s2.Opposing_team)");
$stmt->bindValue(':playerone', $playerOne);
$stmt->bindValue(':playertwo, $playerTwo);
$stmt->execute();
You need to bind $playerOne, $playerTwo to your prepared statement as parameters. http://php.net/manual/en/mysqli.prepare.php
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
/* create a prepared statement */
$stmt = $mysqli->prepare("SELECT * FROM (SELECT * FROM players WHERE Player_name = ?) s1
WHERE EXISTS (SELECT * FROM (SELECT * FROM players WHERE Player_name = ?) s2 WHERE s1.Team_name = s2.Opposing_team)")
/* bind parameters for markers */
$stmt->bind_param("ss", $playerOne, $playerTwo);
/* execute query */
$stmt->execute();
The overall mechanism of prepared statements is the same in all database extensions that support it:
Replace number or string literals (and I mean that, literals, not random pieces of code) inside SQL with place-holders, either position-based ? or named :username (don't mix, pick one)
Prepare the query by calling the appropriate function that receives SQL as parameter
Execute the prepared query by calling the appropriate function(s) that receive values as paremeter
So if you're doing it right in mysqli, a switch to PDO will not require a change in your logic. Your code samples, though, suggest you are not using prepared statements at all: no place-holders, no data in a separate channel... I can see variable interpolation in double quoted strings, but that's a PHP feature, not a SQL feature. As such, it's totally useless to separate code and data and prevent SQL injection.
I suspect the root misunderstanding is not being fully sure of how PHP and SQL interact. The answer is that they don't: they are entirely different computer languages and they are executed by entirely different programs. The only relationship is that you use the former to generate the latter. No matter what you do, in the end you'll just submit a string (i.e. plain text) to the database server. How you generate that text is irrelevant because strings have no memory.
I'm using session variables in an SQL query that updates either wins or losses whenever called. I've looked over similar questions, but they are using mysql as opposed to mysqli. What is the correct manner for using php variables in a mysqli query?
Here's what mine looks like:
$sqlQuery = "UPDATE users SET wins=wins+1 WHERE username == $_SESSION['username']";}
the resulting sql query should look like this:
UPDATE users SET wins=wins+1 WHERE username = 'user_name';
so we need to prepare it correctly:
$sql = sprintf(
"UPDATE users SET wins=wins+1 WHERE username = '%s';",
$_SESSION['username']
);
but please, use a proper database connector (PDO, mysqli) and escape the username.
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 9 years ago.
I've below code in one of my php files to fetch data from DB:
$products = $this->db->get_rows('SELECT * from products WHERE shop_id='.$_SESSION['shop_id'].'AND tags,title,text LIKE \'%'.$_POST['search'].'%\'');
Is it problematic? I mean LIKE operator can be injected?
Edited
please provide examples of injecting in this way
Any operator can be injected without binding.
$_POST['search'] = "1%'; DROP TABLE myTable LIKE '%";
Would make
.... AND tags,title,text LIKE '%1%'; DROP TABLE myTable LIKE '%%'
Read on how to bind parameters.
Of course this can be injected, you need to sanitize your input. Right now you are taking raw post data and inserting it into your SQL statement.
You should run your POST data through some sort of data sanitization, something like mysql_real_escape_string or the like
Or at least prepared statements. let server side code do the work for you.
Never, ever, use database queries like that, don't construct a string with variables and use it for database activities.
Construct a string that will later on be prepared and executed, by inserting the variables into the string, making them not act like "commands" but as "values".
You can do it like this:
$query = "SELECT * from products WHERE shop_id = :shopId;"; // An example, you can finish the rest on your own.
Now, you can prepare the statement (I recommend using PDO for this).
$statement = $db->prepare($query); // Prepare the query.
Now you can execute variables into the prepared query:
$statement->execute(array(
':shopId' => $_SESSION['shop_id']
));
If you're inserting or updating, then you would have wanted to do:
$success = $statement->execute(array(
':shopId' => $_SESSION['shop_id']
));
which stores a boolean in $success, or you can fetch the values from a result if you're SELECTing:
$statement->execute(array(
':shopId' => $_SESSION['shop_id']
));
$result = $statement->fetch(PDO::FETCH_ASSOC);
if($result )
{
// You can access $result['userId'] or other columns;
}
Note that you should actually make that be a function, and pass $shopId into the function, but not the session itself, and check if the session actually exists.
I recommend googling on how to use PDO, or take a look on one of my examples: How to write update query using some {$variable} with example
This is really bad. Pulling vars into an SQL statement without cleaning or checking them is a good way to get pwnd. There are several things that people can inject into code. Another injection method to watch out for, 1=1 always returns true.
$products = $this->db->get_rows('SELECT * from products WHERE shop_id='.$_SESSION['shop_id'].'AND tags,title,text LIKE \'%'.$_POST['search'].'%\'');
//This example expects no result from the table initially so we would blind attack the DB to pull the admin record.
$_POST['search'] = "-1\'; union all select * from users limit 1;";
Someone call pull up the top account in the database (like the admin).
$user_id = $this->db->get_rows('SELECT * from users WHERE email="'.$_POST['email'].'" and password="'.$_POST['password'].'"');
//This always returns true so now I'm the admin again
$_POST['password'] = "x\' or 1=1 limit 1";
You also want to be careful what you print on screen.
$user_id = $this->db->get_rows('SELECT * from users WHERE email="'.$_POST['email'].'" and password="'.$_POST['password'].'"');
A message that you echo that says "No user name exists for $_POST['email']" could be replaced with something else.
$_POST['email']=";
$fp = fopen('index.php', 'w');
fwrite($fp, \"header('Location: http://badwebsite.com;');\";
fclose($fp);";
index.php could now people to a different website entirely where an infected page exists or an infected page on the site.
If you're checking IDs do something like:
if(preg_match('!^[0-9]$!',$_POST['id'])){
$id = $_POST['id'];
} else {
//flush
}
or count for the number of possible records... if you're only expecting one and you get all of the records in the DB then it's an injection attempt.
if(is_numeric($_POST['id'])){
$id = $_POST['id'];
$count = mysql_result(mysql_query("select count(*) from users where id='$id''),0);
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to prevent SQL Injection in PHP
I just found that my website is vunerable.
Since it's connected to a DB and have functions like: Register, Change Password, Notices, etc... and SUPOSING it's fully vulnerable.
What should I look for into the code in order to start making it safe?
I mean, I did some researches and everywhere, everyone says different things about security.
"Use PDO."
"Use mysql_real_escape_string."
"Use addslashes."
What exactly should I look for??
"$_POST" and "$_GET" variables??
"$_SESSION" variables?
SQL querys?
$sql = "select * from user";
$sql = "update user set user="new_user_name";
$sql = "insert into user (user) values ('userid')";
What should I do in each case?
Please, help me to know what and where I must go.
Thank you.
Following are the points to be considered for making safe php application.
USE PDO or mysqli
Never trust any inputs. Consider every variable viz $_POST, $_GET, $_COOKIE, $_SESSION, $_SERVER as if they were tainted. Use appropriate filtering measure for these variables.
To avoid XSS attack use php’s builtin functions htmlentities,
strip_tags, etc while inserting the user input data into the
database.
Disable Register Globals in PHP.INI
Disable “allow_url_fopen” in PHP.INI
Don’t allow user to input more data than required. Validate input to
allow max number of characters. Also validate each field for
relevant datatypes.
Disable error reporting after Development period. It might give
information about database that’ll be useful to hackers.
Use one time token while posting a form. If token exist and matches
the form post is valid otherwise invalid.
Use parametrized database queries
Use stored procedures
You can google for each point for more details.
HOpe this helps
What you should look for: Any data send from the client/user. Sanitize/escape this data.
PDO can sanitize queries (using PDO::prepare) and supports multiple SQL systems.
For MySQL, use MySQLi. mysqli_real_escape_string is the function to use for sanitizing data if you are using MySQL.
None of the SQL queries you provided are actually vulnerable to SQL injection.
SQL injection vulnerabilities happen because SQL input is not properly escaped.
For example:
$sql = "select * from users where user_id =" . $_GET['user_id'];
Consider if I passed in the following:
http://some_server.com/some_page.php?user_id=123%20or%201=1
The query when executed would end up being:
select * from users where user_id = 123 or 1=1
To fix this, use parameterized queries:
$query = "select * from users where user_id = ?"
When you bind the user_id value to the query, the data access layer will escape the input string properly and the following would be executed:
select * from users where user_id = '123 or 1=1' which would not return any rows, preventing the injection
If using PHP and the mysql extension:
$sql = "select * from users where user_id = '" . mysql_real_escape_string($_GET['user_id']) . "'";
Keep in mind you need to escape ALL input that is going into a SQL query:
$sql = "select id_column from some_table where id = 1";
$stmt = mysqli_query($conn, $sql);
if($stmt === false) die(mysqli_error($conn) . "\n");
while($row = mysqli_fetch_assoc($conn, $stmt) {
$sql = "update some_other_table set some_value = 'new value' where some_column = '" . mysqli_real_escape_string($conn, $row['id_column']) . "'";
....
}
This is because values you select from the database might include characters that are not safe for execution in a SQL statement, like the name "O'Hara" or example.
}
I've been using PDO.
An example for that in your case:
<?php
$stmt = $dbh->prepare("insert into user (user) values (?)");
$stmt->bindParam(1, $name);
$name = 'ValueHere';
$stmt->execute();
?>