I have this code
http://www.nomorepasting.com/getpaste.php?pasteid=22580
which is part of a small ajax application. I would like to know a better, more efficient way to assign $query, instead of copying the sql each time with a different query or a bunch of if clauses. Basically the query will be dependant on the link clicked, but I am not sure how to show that in the logic. I am also unsure why my SQL query in $result fails.
UPDATE: I integrated Eran's function into the refactored code. NOTE: I corrected it by passing the $table variable into it and renamed it since it doesn't search the query text only but mainly returns the needed rows!
MAIN MISTAKES:
mistake 1: you overwrite query with query2 in all cases which breaks the code.
mistake 2: LIKE'%$query%' there is a space missing between LIKE and ' => LIKE '%... this most probably breaks your code too
OTHER ISSUES
security problem: sql injection danger, use mysql_real_escape_string
\n not platform independent: use PHP_EOL
alternative way of writing short if blocks
use curly brackets for normal if structures and all such structures for the matter
here is your code with some changes, look at the comments:
<?php
session_start(); //ommit, no session var used
//use braces, always!
//you may write such statements with the short form like
if (isset($_GET['cmd'])) : $cmd = $_GET['cmd']; else : die (_MSG_NO_PARAM); endif;
$query = '';
//escpae your input - very important for security! sql injection!
if ( isset ($_GET["query"]))
{
$query = mysql_real_escape_string($_GET["query"]);
}
//no need for the other part you had here
$con = mysql_connect("localhost", "root", "geheim");
if (!$con) : die ('Connection failed. Error: '.mysql_error()); endif;
mysql_select_db("ebay", $con);
if ($cmd == "GetRecordSet")
{
$table = 'Auctions';
$rows = getRowsByArticleSearch($searchString, $table);
//use PHP_EOL instead of \n in order to make your script more portable
echo "<h1>Table: {$table}</h1>".PHP_EOL;
echo "<table border='1' width='100%'><tr>".PHP_EOL;
echo "<td width='33%'>Seller ID</td>".PHP_EOL;
echo "<td width='33%'>Start Date</td>".PHP_EOL;
echo "<td width='33%'>Description</td>".PHP_EOL;
echo "</tr>\n";
// printing table rows
foreach ($rows as $row)
{
$pk = $row['ARTICLE_NO'];
echo '<tr>'.PHP_EOL;
echo '<td>'.$row['USERNAME'].'</td>'.PHP_EOL;
echo '<td>'.$row['ACCESSSTARTS'].'</td>'.PHP_EOL;
echo '<td>'.$row['ARTICLE_NAME'].'</td>'.PHP_EOL;
echo '</tr>'.PHP_EOL;
}
}
mysql_free_result($result);
//mysql_close($con); no need to close connection, you better don't
function getRowsByArticleSearch($searchString, $table)
{
$searchString = mysql_real_escape_string($searchString);
$result = mysql_query("SELECT ARTICLE_NO, USERNAME, ACCESSSTARTS, ARTICLE_NAME FROM {$table} WHERE upper ARTICLE_NAME LIKE '%" . $searchString . "%'");
if($result === false) {
return mysql_error();
}
$rows = array();
while($row = mysql_fetch_assoc($result)) {
$rows[] = $row;
}
return $rows;
}
// ?> ommit closing php tag
"SELECT ARTICLE_NO, USERNAME, ACCESSSTARTS, ARTICLE_NAME
FROM {$table} WHERE upper ARTICLE_NAME LIKE'%$query%'"
You need to put brackets around the parameters of your upper function. change your query to this, and it should work:
"SELECT ARTICLE_NO, USERNAME, ACCESSSTARTS, ARTICLE_NAME
FROM {$table} WHERE upper(ARTICLE_NAME) LIKE'%$query%'"
for a feature use:
$result = mysql_query($sql_query) or die(mysql_error());
To see what kind of mysql error you get.
you should do like nickf said.
and you are definitely prone to SQL-Injection:
wikibooks: http://en.wikibooks.org/wiki/Programming:PHP:SQL_Injection
long article: http://www.securiteam.com/securityreviews/5DP0N1P76E.html
You can abstract your query in a function that accepts the search text as a parameter. Something like:
function searchQuery($text) {
$text = mysql_real_escape_string($text);
$result = mysql_query("SELECT ARTICLE_NO, USERNAME, ACCESSSTARTS, ARTICLE_NAME FROM {$table} WHERE upper ARTICLE_NAME LIKE '%" . $text . "%'");
if($result === false) {
return mysql_error();
}
$rows = array();
while($row = mysql_fetch_assoc($result)) {
$rows[] = $row;
}
return $rows;
}
Note that you should escape user input to prevent SQL injection attacks (here I used mysql_real_escape_string() to do that). This function also returns the error code if the query fails, so you should check the result to see if it's an array or not:
$result = searchQuery($_GET['query']);
if(!is_array($result) ) {
echo 'An error has occurred:' . $result;
} else {
//iterate over rows
}
Wrap your logical structures (IF/ELSE) with curly brackets {. It's better for readability and helps avoid unnecessary mistakes.
You haven't enclosed the statements in your IF/THEN/ELSE constructions in accolades so only the first statement in every block is conditionally executed, the rest allways is.
In most cases you'd be assigning $query2 to $query while $query2 probably hasn't been defined.
As another tip: sanitize your input, don't go pasting user input into your SQL like that, it's dangerous.
You may need a space between LIKE and '%$query%'. Also, you should look into the mysql_error() function - let MySQL tell you exactly what the error is.
Related
I am very new to the whole PHP/MSSQL coding and need assistance with SQL Injection prevention.
I am adding a simple search feature to a website that uses a MSSQL database.
The code works as I want it to but it is vulnerable to SQL Injection.
Any other way to secure it except for prepare statements?
I am also not that familiar with stored procedures.
I have tried prepare statements with no luck(unless I'm doing something wrong, that's most likely)
Stored procedures I'm not familiar with.
<?PHP
$tech = (isset($_POST['Technician'])? $_POST['Technician'] : null);
$sql = "SELECT * FROM Errors WHERE Error LIKE '%$tech%' or Description LIKE '%$tech%'";
$name = trim($_POST['Technician']);
if(empty($name)){
print '<script type="text/javascript">alert("Please enter an Error Code or Error Description")</script>';
exit;
}
$stmt = sqlsrv_query($conn, $sql);
if ($stmt) {
$rows = sqlsrv_has_rows( $stmt );
if ($rows === true) {
echo "";
} else{
echo '<script type="text/javascript">alert("Please enter a valid Term")</script>';
}
}
while($db_field = sqlsrv_fetch_array($stmt)){
print '<table align="center" style="position: relative; width:250px; text-align: center;">';
print '<tr>';
print '<td>'.$db_field['Error']."</td></tr>";
print "<tr>";
print '<td>'.$db_field['Description'].'</td></tr>';
//print "<tr><th>"."Cause"."</th>";
//print "<td>".$db_field['Cause']."</td></tr>";
//print "<tr><th>"."Resolution"."</th>";
//print "<td>".$db_field['Resolution']."</td></tr>";
print "</table><br>";
}
sqlsrv_close($conn);
?>
I expect SQL Injection to fail when attempted.
Pretty simple to use a parameterized query, notice only ?:
$sql = "SELECT * FROM Errors WHERE Error LIKE ? OR Description LIKE ?";
Then build an array of parameters adding the LIKE wildcards %:
$params = array("%$tech%", "%$tech%");
Execute with parameters:
$stmt = sqlsrv_query( $conn, $sql, $params);
Alternatively, for flexibility with other queries, for the parameters you could do:
$tech = "%$tech%";
$params = array($tech, $tech);
Prepared statements are the simplest way to inject raw input into SQL. You can skip them altogether if you want but it comes at the price of greater complexity and lower security (and you need to write the alternative code yourself). The only reason why you can find escape() functions in other extensions (or no mechanism at all!) is because they're legacy libraries, sometimes very old ones. SQLSRV is reasonably modern.
Additionally, you may want to:
User filter functions to simply input checks.
Escape wildcard characters.
Resulting code would look like this:
$tech = filter_input(INPUT_POST, 'Technician');
if ($tech !== null) {
$sql = "SELECT *
FROM Errors
WHERE Error LIKE ? or Description LIKE ?";
$find = '%' . escapeLike($tech) . '%';
$params = [$find, $find];
$res = sqlsrv_query($conn, $sql, $params);
}
function escapeLike($value)
{
return strtr($value, [
'%' => '[%]',
'_' => '[_]',
'[' => '[[]',
]);
}
I'm currently learning php and am testing around with sqli queries.
I want to have an input field where a number can be entered. This number is used in the sql-query. Unfortunately it doesn't work the way I want.
The text field is stored in index.php as this:
<form method="post" action="handler.php">
<input type="text" name="idEingabe">
<input type="submit" value="Abfrage für eingegebene ID starten">
</form>
In handler.php, I'm using
$stridEingabe = $_POST["idEingabe"];
And the query contains:
$query = 'SELECT name, beschreibung FROM uebersicht WHERE id = "$stridEingabe"';
$result = mysqli_query($con, $query);
if ($result = mysqli_query($con, $query)) {
/* Array ausgeben */
while ($row = mysqli_fetch_assoc($result)) {
printf ("<b>%s</b> <br>%s<br> <br>", $row["name"], $row["beschreibung"]);
}
/* free result set */
mysqli_free_result($result);
}
mysqli_close($con);
?>
Unfortunately I don't get any results when I enter the number into the text box and click the submit-button. But if I write the number in the query without using $stridEingabe, I'm getting the results.
Where is the mistake?
Thanks a lot
Seeing that an answer's been submitted before this, thought I'd put one in too and based on a comment I left under the question.
One of the problems here is, you're querying twice which is a major issue, resulting in a syntax error that MySQL is throwing in the background, but you're not listening for it. Plus, your quoting method which I've modified below, just in case it is a string; which we don't know at this time.
$query = 'SELECT name, beschreibung FROM uebersicht WHERE id = "$stridEingabe"';
$result = mysqli_query($con, $query);
^^^^^^^^^^^^
if ($result = mysqli_query($con, $query)) {
^^^^^^^^^^^^
/* Array ausgeben */
while ($row = mysqli_fetch_assoc($result)) {
printf ("<b>%s</b> <br>%s<br> <br>", $row["name"], $row["beschreibung"]);
}
what you want is to remove = mysqli_query($con, $query) and add error checking:
$query = "SELECT name, beschreibung FROM uebersicht WHERE id = '".$stridEingabe."'";
$result = mysqli_query($con, $query);
if ($result) {
/* Array ausgeben */
while ($row = mysqli_fetch_assoc($result)) {
printf ("<b>%s</b> <br>%s<br> <br>", $row["name"], $row["beschreibung"]);
}
} // brace for if ($result)
// else statement for if ($result)
else{
echo "There was an error: " .mysqli_error($con);
}
Or, better yet using mysqli_real_escape_string().
$stridEingabe = mysqli_real_escape_string($con,$_POST["idEingabe"]);
Although prepared statements are best.
Plus, in regards to SQL injection which is something you're open to, should be using mysqli with prepared statements, or PDO with prepared statements, they're much safer.
Footnotes:
Make sure you are indeed using mysqli_ to connect with and not another MySQL API such as mysql_ or PDO to connect with. Those different APIs do not intermix with each other.
I say this because, the connection method is unknown in your question.
Plus, if you're using your entire code inside the same file, then you should be using a conditional statement for your POST array, otherwise it will thrown a notice immediately on page load; assuming error reporting is enabled on your system.
The notice would be "Undefined index idEingabe..."
I.e.:
if(!empty($_POST['idEingabe'])){...}
Another thing; if your inputted value is an integer, you can use the following functions to make sure they are integers and not a string, if that is what the ultimate goal is:
http://php.net/manual/en/function.is-int.php - is_int()
http://php.net/manual/en/function.is-numeric.php - is_numeric()
and using a conditional statement in conjunction with those.
Add error reporting to the top of your file(s) which will help find errors.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// rest of your code
Sidenote: Error reporting should only be done in staging, and never production.
Two things, first your quotes are wrong, and second, with your code you are vulnerable to sql code injection attacks, try this instead:
$stridEingabe = mysql_real_escape_string($_POST["idEingabe"]);
$query = "SELECT name, beschreibung FROM uebersicht WHERE id='$stridEingabe'";
The problem is that you are not concatenating the $string to the query
Use something like
$query = 'SELECT name, beschreibung FROM uebersicht WHERE id = ''.$stridEingabe.'';
Or use double quotes which is way more acceptable
$query = "SELECT name, beschreibung FROM uebersicht WHERE id = '$stridEingabe'";
And try to use only the $results declared in the if statement to avoid double queries.
You are using wrong quotes. try this:
$query = "SELECT name, beschreibung FROM uebersicht WHERE id = '$stridEingabe'";
I have a successful connection made in PDO to my MySQL database and I am currently trying to get it to query the database for itmes LIKE the search query.
<?php
include ('connection.php');
function doSearch() {
$output = '';
if(isset($_POST['search'])) {
$searchq = $_POST['search'];
$searchq = preg_replace ("#[^0-9a-z]#i","",$searchq);
$sql = "SELECT * FROM entries WHERE name LIKE :searchq or description LIKE :searchq or content LIKE :searchq";
global $conn;
$stmt = $conn->prepare($sql);
$stmt->bindParam(":searchq",$searchq,PDO::PARAM_STR);
$stmt->execute();
$count = $stmt->rowCount();
if($count == 0) {
$output = 'No results found, buddy.';
} else {
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$eName = $row['name'];
$eDesc = $row['description'];
$eCont = $row['content'];
$id = $row['id'];
$elvl = $row['level'];
$ehp = $row['hp'];
$output .= '<tr><td>'.$eName.'</td><td>'.$eDesc.'</td><td>'.$elvl.'</td><td>'.$ehp.'</td></tr>';
}
}
return $output;
}
}
?>
I am struggling to get it to search. Unless the query exactly matches only the name, it doesn't show any results.
The LIKE operator does not do partial matches unless specifically instructed to. Perhaps you meant to prepend/append a % wildcard symbol to the search string:
$searchq = '%' . $searchq . '%';
I don't see anything wrong in the SQL text of the query.
The simplest explanation is that the SQL you are expecting to be sent to the database isn't what is being sent.
I suggest you give this a try:
use unique bind variable names in the statement, use each bind variable only once.
There used to be a bug in PDO with named bind variables (not sure if that's fixed of not. Under the covers, the named bind parameters were getting converted to positional notation, and when the same bind variable two or more times, the query being sent to MySQL wasn't what we expected.
For example:
$sql = "SELECT e.*
FROM entries e
WHERE e.name LIKE :searchq1
OR e.description LIKE :searchq2
OR e.content LIKE :searchq3";
$stmt = $conn->prepare($sql);
$stmt->bindParam(":searchq1",$searchq,PDO::PARAM_STR);
$stmt->bindParam(":searchq2",$searchq,PDO::PARAM_STR);
$stmt->bindParam(":searchq3",$searchq,PDO::PARAM_STR);
When we encountered the problem, we weren't using server side prepared statements, just regular client side prepares; the SQL sent to the server included literals, not placeholders. Turning on the general_log in MySQL allowed us to see the actual SQL statements that were being sent to the database.
You might be encountering the same problem. But I'd recommend this as a step in debugging the problem, at least to verify it isn't the problem.
I want to get some data from sql server using php but the sql doesn't seem reading the php variable
<?php
$q = $_POST["fl"];
echo $foo;
if ($_POST["fl"] == true);
{
$conn1=odbc_connect('SQLDB','','');
if (!$conn1)
{exit("Connection Failed: " . $conn1);}
$sql1= "SELECT * FROM dbo.Audit WHERE Details = '$q'";
$rs1=odbc_exec($conn1,$sql1);
if (!$rs1)
{exit("Error in SQL");}
while (odbc_fetch_row($rs1))
The best way to do that is:
$stmt = odbc_prepare($conn1, "SELECT * FROM dbo.Audit WHERE Details = ?");
$success = odbc_execute($stmt, array(PDO::quote($_POST["fl"])));
You're testing for the presence of your $q incorrectly. You should have something more like:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['fl'])) {
$q = $_POST['fl'];
$sql = "SELECT ... WHERE Details = '$q'":
etc..
} else {
die("No fl value was passed");
}
}
Also note that I have not corrected your SQL injection vulnerability. Your code, even if it was working, is just begging to get your database trashed.
To avoid the apparent downvote party I'm not going to post any SQL, but yadda yadda SQL injection, yadda yadda input validation, etc.
Your problem is:
if ($_POST["fl"] == true); //<-- this semicolon, get rid of it
{
$conn1=odbc_connect('SQLDB','','');
Aside from that your code is syntactically fine, though you should be using if(isset($_POST['f1'])) in place of if ($_POST["fl"] == true).
You can use PDO object for making a select query to the database....
$q = $_POST['fl'];
$pdo=new PDO('mysql:host=localhost;dbname=databasename','username','password');
$query="select * from dbo.Audit WHERE Details = :q;";
$result=$pdo->prepare($query);
$result->bindValue(':q',$q);
$result->execute();
First things first, please sanitize the post before you put it inside an SQL query.
You have to use htmlentities or even better, PDO.
Second, you can try this if your current one doesn't work:
$sql1 = "SELECT * FROM dbo.Audit WHERE Details = '".$q."'";
Hi i am too new too php and mysql and i want to count the member number due to the search made by user. However, mysql_num_rows doesnt work.
mysql_num_rows(mysql_query("SELECT * FROM members WHERE $title LIKE '%$_POST[search]%' LIMIT $start,$member_number"));
It says "mysql_num_rows(): supplied argument is not a valid MySQL result resource in ..."
NOTE: $title is a select menu which user choose where to search. LIMIT is, as you know :), number of member which is shown in a page.
And also $start= ($page-1)*$member_number; in order to set the first entry in that page. I think the problem is here but i cant solve it. :(
Your query probably has an error, in which case mysql_query will return false.
For this reason, you should not group commands like this. Do it like this:
$result = mysql_query("...");
if (!$result)
{ echo mysql_error(); die(); } // or some other error handling method
// like, a generic error message on a public site
$count = mysql_num_rows($result);
Also, you have a number of SQL injection vulnerabilities in your code. You need to sanitize the incoming $search variable:
$search = mysql_real_escape_string($_POST["search"]);
... mysql_query(".... WHERE $title LIKE '%$search%'");
if $start and $end come from outside, you also need to sanitize those before using them in your LIMIT clause. You can't use mysql_real_escape_string() here, because they are numeric values. Use intval() to make sure they contain only numbers.
Using a dynamic column name is also difficult from a sanitation point of view: You won't be able to apply mysql_real_escape_string() here, either. You should ideally compare against a list of allowed column names to prevent injection.
you have to use GET method in your form, not POST.
mysql_num_rows doesn't make sense here.
If you're using limit, you already know the number*.
If you want to know number, you shouldn't use limit nor request rows but select number itself.
// get your $title safe
$fields = array("name","lastname");
$key = array_search($_GET['title'],$fields));
$title = $fields[$key];
//escape your $search
$search = mysql_real_escape_string($_GET['search']);
$sql = "SELECT count(*) FROM members WHERE $title LIKE '%$search%'";
$res = mysql_query($query) or trigger_error(mysql_error()." in ".$sql);
$row = mysql_fetch_row($res);
$members_found = $row[0]
in case you need just 5 records to show on the page, no need for mysql_num_rows() again:
// Get LIMIT params
$member_number = 5;
$start = 0;
if (isset($_GET['page'])){
$start = abs($_GET['page']-1)*$member_number;
}
// get your $title safe
$fields = array("name","lastname");
$key = array_search($_GET['title'],$fields));
$title = $fields[$key];
//escape your $search
$search = mysql_real_escape_string($_GET['search']);
$sql = "SELECT count(*) FROM members
WHERE `$title` LIKE '%$search%'
LIMIT $start, $member_number";
$res = mysql_query($query) or trigger_error(mysql_error()." in ".$sql);
while($row = mysql_fetch_assoc($res){
$data[] = $row;
}
Now you have selected rows in $data for the further use.
This kind of error generally indicates there is an error in your SQL query -- so it has not been successful, and mysql_query() doesn't return a valid resource ; which, so, cannot be used as a parameter to mysql_num_rows().
You should echo your SQL query, in order to check if it's build OK.
And/or, if mysql_query() returns false, you could use mysql_error() to get the error message : it'll help you debug your query ;-)
Typically, your code would look a bit like this :
$query = "select ..."; // note : don't forget about escaping your data
$result = mysql_query($query);
if (!$result) {
trigger_error(mysql_error()." in ".$query);
} else {
// use the resultset
}