I have PHP generating an HTML form and I'm trying to write a script that will update the information in the database. For some reason it works on some of the fields and not others.
Code which won't work:
PHP-Form that users can change details within
echo"<form name='details'>";
echo"<p>Surname: <input type='text'id='surname' value='".$row['Surname']."'/></p>;
<p>Telephone: <input type='text'id='phone' value='".$row['Telephone']."'/></p>;
<p>Postcode: <input type='text' id='postcode' value='".$row['Postcode']."'/></p>;
<p>House/Flat Number: <input type='text' id='number' value='".$row['Number']."'/></p>";
AJAX - sends changes to server via querystring
var sname = document.getElementById('surname').value;
var tel = document.getElementById('phone').value;
var num = document.getElementById('number').value;
var pcode = document.getElementById('postcode').value;
var queryString = "?username=" + username +"&email="+email....";
ajaxRequest.open("GET", "url" + queryString, true);
ajaxRequest.send(null);
PHP - execute update command
//connect to server
...
//get variables
$sname = $_GET['sname'];
$pcode = $_GET['pcode'];
$tel = $_GET['tel'];
$num=$_GET['num'];
//process update
$update ="UPDATE User SET Surname='$sname',Telephone='$tel',Number='$num',
Postcode='$pcode' WHERE Username='$username'";
//if query, display success
if(mysqli_query($update))
{
echo"success";
}
else
{
echo"error";
}
//else display error
The query executes fine, but the values aren't displaying within the database. My other variables (username, password etc) all update fine. All database fields are type VARCHAR(80).
EDIT: I do have the query being executed. This still results in the surname, postcode, number and telephone field not being updated.
Ignoring for the moment all the other issues with this code and approach (SQL injection issues, GET vs. POST issue, etc.), and dealing with the update not changing things as expected, there are a couple of things to check.
Try outputing the update query in your logs and make sure that it actually looks like what your expecting. It could be that the values you're meaning to push across the wire are not making it into the query or that.
Verify that running the query by hand in an standalone SQL client (mysql, squirrel, etc...) Actually updates a record. It's entirely possible that a valid update query may not match any records. (Say the username value you're looking for does not match one that's in the database.
Not knowing your infrastructure, I'd suggest some sanity checks: Are you actually pointing at the right database? Do you have a your update wrapped in a transaction that's rolling back? etc ...
A few other tips:
I would suggest looking at PDO, in particular how Prepared Statements work. The kind of query you're building above is someone to run off with all your data or worse. While not a panacea, prepared statements are a solid first step.
Take a look at Jquery's Ajax functions. In particular the post method. It provides a simple interface for making ajax calls without having to construct special url strings. Plus, switching to a POST will avoid your data showing up in webserver logs files.
Related
I am just wondering, if possible, the best way to go about allowing users to actually input an SQL query from within a web application.
I have so far got a very simple web application that allows users to view the database tables and manipulate them etc etc..
I wanted to give them an option to actually type queries from within the web app too (SELECT * FROM).. and then display the results in a table. (Exactly the same as a search bar, but I don't think that would cut it, would it?).
I am only using PHP at the moment, is what I'm looking to do possible with just HTML/PHP or will I need the help of other languages?
This may be too complex for me, but if someone could give me a starting point that would be great, thank you.
UPDATE:
From my understanding to answer my question, i need something like:
<form action= Search.php method="POST">
<input type="text" name="Search">
<input type="submit" name"">
Search.php
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$SEARCH = $_POST['Search'];
if (!isset($_POST)) {
$sql = "'%".$_POST['$SEARCH']."%'";
$results = mysqli_query($con, $sql);
echo "<table border ='2'>";
if (mysqli_num_rows($results) !=0) {
while ($row=mysqli_fetch_array($results)) {
echo "<tr><td></td></tr>";
}
echo "</table>";
}else {
echo "Failed! Try another search query.";
}
}
}
?>
At the moment in returns one error:
Undefined index: Search
It's talking about the $SEARCH = $_POST['Search'];
But I thought I am defining that Search, as that's the Search in the form?
Sounds like you're building your own minimalistic version of phpMyAdmin. That's perfectly doable with just PHP and HTML.
A very basic implementation would be a standard HTML form with a textarea, which submits to a PHP script that executes the query and renders a table of the results. You can get the required table column headers from the first result row's array keys if you fetch the results as an associative array.
You may (or perhaps I should say "will") run into situations where users provide a query that returns millions of results. Outputting all of them could cause browsers to hang for long periods of time (or even crash), so you might want to implement some sort of pagination and append a LIMIT clause to the query.
Since the user is providing the SQL query themselves, they need to know what they did wrong so they can correct it themselves as well so you'll want to output the literal error message from MySQL if the query fails.
Allowing users to provide raw SQL queries opens the door to a lot of potential abuse scenarios. If it were my application, I would not want users to use this feature for anything other than SELECT queries, so I would probably have the user-provided queries executed by a MySQL-user that only has SELECT privileges on the application database and not a single other privilege -- that way any user that tries to DROP a table will not be able to.
Undefined index: Search
This error will show only when the PHP is executed for the first time as it's simply expecting "Search" in $_POST.
$_SERVER['REQUEST_METHOD'] checks if the request method is POST it does not check if $_POST have any post data in it.
(Source :$_POST vs. $_SERVER['REQUEST_METHOD'] == 'POST')
But the page is being loading for the first time so it wouldn't have anything in POST.
You can simply avoid it by check if the page is loading for first time, using the "isset()" method.
If its loading for the first time just ignore the further execution of php code and simply show the form to enter the query.
<?php
if(isset($_POST['Search']))
{
`// Query execution code`.
}
?>
<form action= Search.php method="POST">
<input type="text" name="Search">
<input type="submit" name"">
So if the search index is not set in the $_POST it wont execute the php code and will not generate any error.
I was wondering if code I have written is open to attack.
$.ajax({
url: site_url+"/customer/update",
type: 'POST',
dataType: "json",
async: true,
data: {
'id':$('#id').val(),
'cuFirstname':$('#firstname').val(),
'cuLastname':$('#lastname').val(),
'cuPersonalnr':$('#personalnr').val(),
},
});
On the server it looks like this:
$this->db->where('cuID = '.$customerid);
$this->db->update('customers',$_POST);
So I'm thinking that maybe if someone could change the variables (cuFirstname, cuLastname, cuPersonalnr) in the data part of the ajax post, that they would be able to write sql-code there.
"update customers set cuFirstname = 'charlie', cuLastname = 'brown', cuPersonalnr = '7012230303' where cuID = 1000"
So if they changed cuLastname to something else it could look like this:
update customers set cuFirstname = 'charlie', [cuShouldnotbechanged] = 'brown', cuPersonalnr = '7012230303' where cuID = 1000
So my question is: Is it possible for an attacker to change those variable names, and if so, how?
The client can change any aspect of the AJAX call, simply by making their own HTTP request to your URL with their own parameters. So, yes, they could conceivably change any part of the request.
In your code, the question really boils down to "how does my database library handle the update?". You're doing the following:
$this->db->where('cuID = '.$customerid);
$this->db->update('customers',$_POST);
which is, presumably, building a query like:
UPDATE customers SET column1='some value', column2='some other value', ... WHERE cuID='whatever';
based on the keys and values of the $_POST array. To address your specific question about what happens if a client changes the keys n the $_POST array, it seems to me there are two possibilities:
if they enter a column name that does not exist, the database library is either going to ignore it (and update the stuff it is able to) or throw an error (because an UPDATE statement with a non-existent column name is an SQL error).
if they enter a column name that exists but that you did not intend to update, then that new column name will probably be used and updated (unless your database library has protection in place for that - some require you to explicitly state which columns can be updated in this way).
Can a user write SQL code into those variabiles? The answer is yes.
Is it open to attack? That entirely depends on your method of sanitization/SQL input.
You can use prepared statements such as PDO (properly) to prevent the possibility.
Otherwise sanitize/check the sent data:
It looks as the cuPersonalnr, should be numeric? check to make sure:
if (!is_numeric ($_POST['cuPersonalnr']))
exit(); //script stops, not a number
first name and last name, im assuming need to be alphanumeric only?
well create a check, or sanitize any other values that are not alphanumeric:
if(!ctype_alnum($_POST['cuFirstname'])) {
exit(); //script stops, contains unsafe characters
}
instead of exit() you can create an error variable, and return the error.
Basically i have a form where a studentID is inputted, i then want to check id the inputted studentID is in the database, if it is post the form to the next page. If not then display an error on the page where you input studentID
Don't really know where to start
Cheers
is this what you want?
<form id = "form" action = "./?page=markandfeedback" method = "post">
<br>
Mark for:
<INPUT id="stud" onkeypress="return isNumberKey(event)" type="text" name="stud" value="Enter Student Number">
<input type="submit" value = 'Continue'>
<?
$studID = $_POST['stud'];
$module2 = $_SESSION['module'];
$ex = $_POST['exer'];
$studerr = array();
$sql = 'SELECT * FROM `student`, `modules` WHERE `studentID` = '.$studID.' AND `moduleCode` = '.$_SESSION['module'];
$result = mysql_query ($sql);
// echo $_SESSION['module'];
if ($result == NULL) { // nothing found
echo "the student id you entered is not in the database";
}
else {
$_SESSION['student'] = $studID;
Header("Location: http://www.whereever.com/"); // send the browser where you want
exit();
}
?>
EDIT:
I went over the other answers. I assume you check for mysql injection properly. I recommend implementing AJAX AFTER everything works and is secure. The idea behind my solution was to solve the problem as simple as possible. If you want to make something fancy out of it you could:
generate the whole form via php and tell the user in the input field, that the id wasn't found
tell your Javascript to present the information in some fancy way
Use AJAX. Everybody loves forms with AJAX.
You could, as suggested, assume that the user entered a valid id. You would check on the "whereever" page wether the id is actually valid. If it weren't, you would simply send the user back to the form and tell the php to output an error message (maybe via get). This possibility is not usual, I am not sure if it has any advantages.
the mysql_num_rows hint is nice, too, if you don't want any data from the user. I thought you wanted to do something with the data because of the SELECT *.
Make a seperate controller that does the checking of the username.
Use ajax to check if user input is valid or not.
So you'll have something like this:
<input id="stud" onchange="checkStudentId(this)" />
<script>
function checkStudentId(inputElement) {
var id = inputElement.value();
$.ajax({
url: "test.html",
context: {id:id}
}).done(function() {
// Check the return result
});
}
</script>
Here is a reference to jquery ajax
http://api.jquery.com/jQuery.ajax/
You actually have to connect to the server in some fashion to figure out of the student exists. What you'd normally do in this situation is submit the form to the server and do validation server-side. If the student exists, you return the "next" page. If the student doesn't exist, then you return (or redirect to using a Location header) the same form again with an error message.
Another popular method would be to use an AJAX request to check asynchronously (which I see many other people are recommending). I'd only recommend this way if you're actually doing validation right as they've finished entering the student id and are showing an error message in real-time, effectively. In this way, AJAX is a nice-to-have to provide quick user feedback, but not a real solution. Keep in mind that regardless of this, you need to check for and handle this when the form is submitted anyway, or at the least, consider what will happen when the form is submitted with an invalid id.
People can bypass this check (EVERY request from the client side is considered hostile, you can't implicitly trust anything)
Another user may have deleted the student ID between the time the check was done and the form was submitted
There could be an error in your code that causes validation to falsely pass or not to recognize a negative response
Doing AJAX onsubmit makes no sense, because effectively you're doubling the amount of work by making the server handle two separate requests in a row. It's simply the wrong answer to the problem.
The biggest trouble with this implementation is the PHP code can quickly get quite hairy and hard to follow as you have everything mixed together.
This is where you probably start to tip over using PHP like a templating language (mixed php code and html markup) and start getting into using a framework where your views (the HTML) are decoupled from your PHP code (if you're using the very-populate MVC pattern, this code is called your controller -- precisely because it controls how the server responds). This is how any professional developer will work. Kohana, CakePHP, and Zend are all examples of fairly popular MVC frameworks, all of which are used professionally.
You can do this in two different ways
AJAX - make ajax call to your server and check the ID if its exist display the error else go to the next page
PHP - put a hidden input in your form and make the action of the form to the same page and check everything their and keep the values of the input fields is the $_POST['field_name'];
And you can make the action into another page and return back variable or make a session to hold the error message
Try this:
<?
if(isset($_POST['stud'])){
$studID = $_POST['stud'];
$module2 = $_SESSION['module'];
$ex = $_POST['exer'];
$studerr = array();
$host="hostname";//your db host
$user="user";//your db user
$pass="pass";//your db pass
$conn=mysql_connect($host,$user,$pass);
$sql = 'SELECT * FROM `student`, `modules` WHERE `studentID` = '.$studID.' AND `moduleCode` = '.$_SESSION['module'];
$result = mysql_query ($sql,$conn);
if(mysql_num_rows($result)>0){//the id was found in the DB, do whatever here...
echo $_SESSION['module'];
$_SESSION['student'] = $studID;
Header("Location: http://www.whereever.com/");//redirect to wherever
$error=false;
}
else{//id was not found
$error=true;}
}//end of isset
?>
<? if($error===true){?> <div> The id was not found.... </div> <?}?>
<form id = "form" action = "<? echo $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']; ?>" method = "post">
<br>
Mark for:
<INPUT id="stud" onkeypress="return isNumberKey(event)" type="text" name="stud" value="Enter Student Number">
<input type="submit" value = 'Continue'>
So what this does is: When the user hits submit, conects to the DB, and checks if the ID exists...if it does, then it redirects it to wherever.com (see comments) and if it don't an error messege will show up. Be sure to change the db variable values to your own ($host, $user, $pass).
For a while I am more and more confused because of possible XSS attack vulnerabilities on my new page. I've been reading a lot, here on SO and other googled sites. I'd like to secure my page as best as it is possible (yes, i know i cant be secure 100%:).
I also know how xss works, but would like to ask you for pointing out some vulnerable places in my code that might be there.
I use jquery, javascript, mysql, php and html all together. Please let me know how secure it is, when i use such coding. Here's idea.
html:
<input name="test" id="id1" value="abc">
<div id="button"></div>
<div id="dest"></div>
jQuery:
1. $('#id').click (function() {
2. var test='def'
3. var test2=$('#id1').val();
4. $.variable = 1;
5. $.ajax({
6. type: "POST",
7. url: "get_data.php",
8. data: { 'function': 'first', 'name': $('#id').val() },
9. success: function(html){
10. $('#dest').html(html);
11. $('#id1').val = test2;
12. }
13. })
14. })
I guess it's quite easy. I have two divs - one is button, second one is destination for text outputted by "get_data.php". So after clicking my button value of input with id 'id1' goes to get_data.php as POST data and depending on value of this value mysql returns some data. This data is sent as html to 'destination' div.
get_data.php should look like this:
[connecting to database]
switch($_POST['function']) {
case 'first':
3. $sql_query = "SELECT data from table_data WHERE name = '$_POST[name]'";
break;
default:
$sql_query = "SELECT data from table_data WHERE name = 'zzz'";
}
$sql_query = mysql_query($sql_query) or die(mysql_error());
$row = mysql_fetch_array($sql_query);
echo $row['data']
For now consider that data from mysql is free from any injections (i mean mysql_real_escaped).
Ok, here are the questions:
JQuery part:
Line 2: Can anybody change the value set like this ie. injection?
Line 3 and 11: It's clear that putting same value to as was typed before submiting is extremely XSS threat. How to make it secure without losing functionality (no html tags are intended to be copied to input)
Line 4: Can anybody change this value by injection (or any other way?)
Line 8: Can anybody change value of 'function' variable sent via POST? If so, how to prevent it?
Line 10: if POST data is escaped before putting it into database can return value (i mean echoed result of sql query) in some way changed between generating it via php script and using it in jquery?
PHP part:
Please look at third line. Is writing: '$_POST[name]' secure? I met advice to make something like this:
$sql_query = "SELECT data from table_data WHERE name = " . $_POST['name'];
instead of:
$sql_query = "SELECT data from table_data WHERE name = '$_POST[name]'";
Does it differ in some way, especially in case of security?
Next question to the same line: if i want to mysql_real_escape() $_POST['name'] what would be the best solution (consider large array of POST data, not only one element like in this example):
- to mysql_real_escape() each POST data in each query like this:
$sql_query = "SELECT data from table_data WHERE name = " . mysql_real_escape($_POST['name']);
to escape whole query before executing it
$sql_query = "SELECT data from table_data WHERE name = " . $_POST['name'];
$sql_query = mysql_real_escape($sql_query);
to write function that iterates all POST data and escapes it:
function my_function() {
foreach ( $_POST as $i => $post ) {
$_POST[$i] = mysql_real_escape($post)
}
}
What - in your opinion is best and most secure idea?
This post became quite large but xss really takes my sleep away :) Hope to get help here dudes once again :) Everything i wrote here was written, not copied so it might have some small errors, lost commas and so on so dont worry about this.
EDIT
All right so.. if I understand correctly filtering data is not necessery at level of javascript or at client side at all. Everything should be done via php.
So i have some data that goes to ajax and further to php and as a result i get some another kind of data which is outputted to the screen. I am filtering data in php, but not all data goes to mysql - part od this may be in some way changed and echoed to the screen and returned as 'html' return value of successfully called ajax. I also have to mention that I do not feel comfortable in OOP and prefering structural way. I could use PDO but still (correct me if i am wrong) i have to add filtering manually to each POST data. Ofcourse i get some speed advantages. But escaping data using mysql_real_escape looks to me for now "manual in the same level". Correct me if i am wrong. Maybe mysql_realescape is not as secure as PDO is - if so that's the reason to use it.
Also i have to mention that data that doesnt go to database has to be stripped for all malicious texts. Please advice what kind of function I should use because i find a lot of posts about this. they say "use htmlentities()" or "use htmlspecialchars()" and so on.
Consider that situation:
Ajax is called with POST attribute and calls file.php. It sends to file.php POST data i.e. $_POST['data'] = 'malicious alert()'. First thing in file.php I should do is to strip all threat parts from $_POST['data']. What do you suggest and how do you suggest I should do it. Please write an example.
XSS is Cross-site scripting. You talk about SQL injection. I will refer to the latter.
JQuery Part
It's possible to change every single JavaScript command. You can try it yourself, just install Firebug, change the source code or inject some new JavaScript code into the loaded page and do the POST request. Or, use tools like RestClient to directly send any POST request you like.
Key insight: You cannot control the client-side. You have to expect the worst and do all the validation and security stuff server-side.
PHP Part
It is always a good idea to double-check each user input. Two steps are usually mandatory:
Validate user input: This is basically checking if user input is syntactically correct (for example a regex that checks if a user submitted text is a valid email address)
Escape database queries: Always escape dynamic data when feeding it to a database query. Regardless where it's coming from. But do not escape the whole query string, that could yield in unexpected results.
Maybe (and hopefully) you will like the idea of using an ORM solution. For PHP there are Propel and Doctrine for instance. Amongst a lot of other handy things, they provide solid solutions to prevent SQL injection.
Example in Propel:
$result = TableDataQuery::create()
->addSelectColumn(TableDataPeer::DATA)
->findByName($_POST['name']);
Example in Doctrine:
$qb = $em->createQueryBuilder();
$qb->add('select', 'data')
->add('from', 'TableData')
->add('where', 'name = :name')
->setParameter('name', $_POST['name']);
$result = $qb->getResult();
As you can see, there is no need for escaping the user input manually, the ORM does that for you (this is refered as parameterized queries).
Update
You asked if PDO is also an ORM. I'd say PDO is a database abstraction layer, whereas an ORM provides more functionality. But PDO is good start anyway.
can firebug any malicious code in opened in browser page and send
trash to php script that is somwhere on the server?
Yes, absolutely!
The only reason you do validation of user input in JavaScript is a more responsive user interface and better look & feel of your web applications. You do not do it for security reasons, that's the server's job.
There is a firefox addon to test your site for XSS, it called XSS Me
Also you can go to
http://ha.ckers.org/xss.html
for most XSS attacks
and go to
http://ha.ckers.org/sqlinjection/
for most sql injection attacks
and try these on your site
table person
"person_id"
"person_name"
table email
"email_id"
"email"
"person_id"
What is the sql comment for insert data form a web form into these tables?
In the web form I have a text box for name and dynamic text box for email
Read the form values into variables, securely insert into MySQL database: http://www.php.net/manual/en/function.mysql-query.php
If you want to do this by only SQL queries, you need to code a procedure like
INSERT INTO person (person_name) VALUES ('PERSON_NAME')
INSERT INTO email (email_id,email,person_id) VAUES ('EMAIL_ID','EMAIL',(SELECT LAST_INSERT_ID()))
I assumed that you can post PERSON_NAME, EMAIL_ID, EMAIL from your web form.
I think it's easy to send both EMAIL_ID, EMAIL from your autocomplete like box.
Well assuming you are using POST and you set up your connection to the db i'd do it like this (i omit validation and so on, just the sript to insert data :
$person_name = mysql_real_escape_string($_POST['person_name']);
$email= mysql_real_escape_string($_POST['email']);
$query = sprintf("INSERT INTO person ('person_name') VALUES ('%s')'",$person_name);
$result = mysql_query($query);
// always set your variables to a default value
$success = false;
// did the query execute successfully?
if($result){
$success = true;
}
if($success){
$person_id = mysql_insert_id();
$query = sprintf("INSERT INTO email ('email','person_id') VALUES ('%s','%s')",$email,$person_id);
$resultSecond = mysql_query($query);
}
There are a few steps involved. You will first need to validate the user's input - don't just put it directly into the database. Validation should be done on the server. You can perform client-side validation with Javascript too, but this should only be done to enhance the user experience - it must not replace server-side validation. To start, you could look at PHP's Filter methods, or perhaps look for a form validation library.
When you come to insert it into the database, I highly recommend using prepared statements instead of messing around with horrible escaping.
The example given on the PHP site is quite good, and should get you started. You could also checkout:
PHP PDO prepared statements
Why you Should be using PHP’s PDO for Database Access