I have an ordinary html table in which each cell contains a name. I've added a function to each of these cells, which turns the cells background color green, if it's white and the other way around. However, I would also like to update an mySql datebase, when a cell is clicked, but I can't seem to figure out a good way to do this, without reloading the page (which I would prefer not to do) or using javascript to connect to the server (which seems like a very bad practice). The page has already been loaded at this point. Does anybody have any good suggestions?
<script type="text/javascript">
var tbl = document.getElementById("table");
if (tbl != null) {
for (var i = 1; i < tbl.rows.length; i++) {
for (var j = 0; j < tbl.rows[i].cells.length; j++)
tbl.rows[i].cells[j].onclick = function () { getval(this); };
}
}
function getval(cel) {
if(cel.style.backgroundColor == "green")
{
cel.style.backgroundColor = "white";
// Here I would like to update my datebase with mySql
// query(UPDATE team SET attended=0 WHERE name = cel.innterText)
// (name associated with the cell)
}
else
{
cel.style.backgroundColor = "green";
// Here I would like to update my datebase with mySql
// query(UPDATE team SET attended=1 WHERE name = cel.innterText)
// (name associated with the cell)
}
}
</script>
In broad terms, you need to turn part of your application into a service and have calls to it made by an asynchronous HTTP request from your page (this falls under the "AJAX" denomination).
That service can be written as an extra PHP script on your server, which may not necessarily return an HTML document, but possible XML or JSON (the latter is probably more popular these days), which will be handled by your JavaScript script in the browser for further actions if necessary (e.g. turning the background white only if this request has succeeded).
It is this PHP script that should handle the SQL queries.
As a general guideline, don't prepare or handle any SQL at all on the client side (in your JavaScript script), and make sure you use prepared statements when running your SQL queries. (I'm just saying that because you're obviously new to this and you'll inevitably find snippets of code here or on various blogs where people just put the variables they in into their SQL statements by using the variable in the query strings. This is extremely bad practice.)
EDIT:
I actually need to go no further than W3Schools to have a bad example of MySQL query that is vulnerable to SQL injection (the problem is in $sql="SELECT * FROM user WHERE id = '".$q."'";). DO NOT USE THIS EXAMPLE. I'd avoid W3Schools, see http://www.w3fools.com/
SQL is server side, not client side. You need to use AJAX to send data to your server and then the server will use SQL to save.
Related
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.
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
I've built mini content management system. In my page add form i'm using ckeditor. for text are named content
<textarea id="content" style="width:100%" name="content"></textarea>
Adding all data from form into db table with following php code. (Function filter used for sanitizing data)
<?php
require '../../core/includes/common.php';
$name=filter($_POST['name'], $db);
$title=filter($_POST['title'], $db);
$parentcheck=filter($_POST['parentcheck'],$db);
if(isset ($_POST['parent'])) $parent=filter($_POST['parent'],$db);
else $parent=$parentcheck;
$menu=filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);
if(isset($_POST['submit'])&&$_POST['submit']=='ok'){
$result=$db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')") or die($db->error);
$new_id = $db->insert_id;
$result2=$db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')") or die($db->error);
header("location:".$wsurl."admin/?page=add");
}
?>
FUNCTION FILTER (data sanitization)
function filter($data, $db)
{
$data = trim(htmlentities(strip_tags($data)));
if (get_magic_quotes_gpc())
$data = stripslashes($data);
$data = $db->escape_string($data);
return $data;
}
I got questions about it. (I'm newbie to ajax.)
Currently i'm submitting data with standart php (page refreshes
every time). How to modify code for ajax submission?
I have only one button for submitting data. I want to create second
button "save" which will update db fields via ajax
How can i create autosave function (which periodically saves form in the background and informss user about it, just like on Stackoverflow) via ajax?
Thx in advance
Let's suppose you want to use jQuery to do the ajax business for you, you need to setup a periodic POST of the data in the textarea (note that in some browsers GET requests have a limit).
On the first POST, you need to tell the PHP script "this is the first POST" so that it knows to INSERT the data, it should then return to you some identifying characteristic. Every other time you POST data, you should also send this identifying characteristic, let's just use the primary key (PK). When you POST data + PK, the PHP script should run an update query on the SQL.
When constructing these, the thing to think about is sending data from the browser using JavaScript to a PHP script. The PHP script gets only whatever packet of data you send, and it can return values by producing, for instance, JSON. Your JavaScript code can then use those return values to decide what to do next. Many beginners often make the mistake of thinking the PHP can make calls to the JS, but in reality it's the other way around, always start, here, with the JS.
In this instance, the PHP is going to save data in the database for you, so you need to ship all the data you need to save to the PHP. In JS, this is like having some magic function you call "saveMyData", in PHP, it's just like processing a form submission.
The JavaScript side of this looks something like this (untested):
<script type="text/javascript">
var postUpdate = function(postKey){
postKey = postKey || -1;
$.post("/myscript.php",
/* note that you need to send some other form stuff
here that I've omitted for brevity */
{ data: $("#content").value(), key: postKey },
function(reply){
if(reply.key){
// if we got a response containing the primary key
// then we can schedule the next update in 1s
setTimeout(function(){postUpdate(reply.key);}, "1000");
}
}
});
};
// first invocation:
postUpdate();
</script>
The PHP side will look something like this (untested):
Aside: your implementation of filter should use mysql_real_escape_string() instead of striptags, mysql_real_escape_string will provide precisely the escaping you need.
<?php
require '../../core/includes/common.php';
$name = filter($_POST['name'], $db);
$title = filter($_POST['title'], $db);
$parentcheck = filter($_POST['parentcheck'],$db);
if(isset($_POST['parent'])){
$parent = filter($_POST['parent'],$db);
}else{
$parent = $parentcheck;
}
$menu = filter($_POST['menu'], $db);
$content = $db->escape_string($_POST['content']);
$pk = intval($_POST['key']);
if($pk == -1 || (isset($_POST['submit']) && $_POST['submit']=='ok')){
$result = $db->query("INSERT INTO menu (parent, name, showinmenu) VALUES ('$parent', '$name', '$menu')")
or die($db->error);
$new_id = $db->insert_id;
$result2 = $db->query("INSERT INTO pages (id, title, content) VALUES ('$new_id', '$title', '$content')")
or die($db->error);
$pk = $db->insert_id;
echo "{\"key\": ${pk}}";
// header("location:".$wsurl."admin/?page=add");
}else if($pk > 0){
$result2 = $db->query("UPDATE pages SET content='$content' WHERE id='$pk')")
or die($db->error);
echo "{\"key\": ${pk}}";
}
For AJAX, you can use jQuery's ajax API. It is very good and is cross-browser.
And for saving and auto-saving: you can use a temporary table to store your data. When the user presses the save button or when your data is auto-saved, you save your data to the table using AJAX and return a key for the newly created row. Upon future auto-save/save button events, you update the temporary table using AJAX.
And one word of advice, use a framework for your PHP and Javascript. I personally use Symfony and Backbone.js. Symfony checks for CSRF and XSS automatically and using Doctrine prevents SQL-injection too. There are other frameworks available (such as CodeIgniter, CakePHP and etc.) but I think Symfony is the best.
Edit: For the auto-save functionality, you can use Javascript SetTimeout to call your AJAX save function, when the page loads for the first time.
With regard to security issues:
Your silver bullet function is fundamentally flawed, it does not work, will never work and can never work.
SQL has different escaping needs than hmtl.
The functions you use counteract each other. escape_string adds \, stripslashes removes them.
Never mind the order of the functions, you need to use a specialized escape function for one and only one purpose.
On top of that you are using depreciated functions.
For MySQL this is mysql_real_escape_string. Note that escape_string (without the real) is depreciated, because it is not thorough enough. Use real_escape_string instead. On mysqli escape_string is an alias for real_escape_string.
See:
How does the SQL injection from the "Bobby Tables" XKCD comic work?
The ultimate clean/secure function
We have some problems with users performing a specific action twice, we have a mechanism to ensure that users can't do it but somehow it still happens. Here is how our current mechanism works:
Client side: The button will be disabled after 1 click.
Server side: We have a key hash in the URL which will be checked against the key stored in SESSIONS, once it matches, the key is deleted.
Database side: Once the action is performed, there is a field to be flagged indicating the user has completed the action.
However, with all these measures, still there are users able to perform the action twice, are there any more safer methods?
Here is the partial code for the database side:
$db->beginTransaction();
// Get the user's datas
$user = $db->queryRow("SELECT flag FROM users WHERE userid = {$auth->getProperty('auth_user_id)}");
if ($user['flag'] != 0) {
$db->rollback();
// Return with error
return false;
}
// Proceed with performing the action
// --- Action Here ---
// Double checking process, the user data is retrieved again
$user = $db->queryRow("SELECT flag FROM users WHERE userid = {$auth->getProperty('auth_user_id)}");
if ($user['flag'] != 0) {
$db->rollback();
// Return with error
return false;
}
// --- The final inserting query ---
// Update the flag
$db->query("UPDATE users SET flag = 1 WHERE userid = {$auth->getProperty('auth_user_id)}");
$db->commit();
return true;
It is good to see that you have taken all measures to defeat the bad guys. Speaking in terms of bad guys:
Client side: This can easily be bypassed by simply disabling javascript. Good to have anyways but again not against bad guys.
Server side: This is important, however make sure that you generate a different hash/key with each submission. Here is a good tutorial at nettutes on how to submit forms in a secure fashion.
Database side: Not sure but I suspect, there might be SQL injection problem. See more info about the SQL Injection and how to possibly fix that.
Finally:
I would recommend to you to check out the:
OWASP PHP Project
The OWASP PHP Project's goal (OWASP PHP Project Roadmap) is to enable developers, systems administrators and application architects to build and deploy secure applications built using the PHP programming language.
Well the JS method and Hash method may be cheated by some notorious guy, but 3rd method seems to be very good in order to protect the redundancy. There must be some programming flaw to get passed this.
Why don't u just check the flag field on the page where you are inserting the values rather than where user performing the action (if you are doing it now)
Pseudocode follows:
<?
$act_id; // contains id of action to be executed
$h = uniqid('');
// this locks action (if it is unlocked) and marks it as being performed by me.
UPDATE actions SET executor = $h WHERE act_id = $act_id AND executor = '';
SELECT * FROM actions WHERE executor = $h;
//
// If above query resulted in some action execute it here
//
// if you want to allow for executing this exact action in the future mark it as not executed
UPDATE actions SET executor = '' WHERE act_id = $act_id;
Important things:
First query should be update claiming
the action for me if it is yet
unclaimed.
Second should be query
grabbing action to execute but only
if it was claimed by me.
A project of mine involves a flash movie (.swf) in a webpage, where the user has to pick from a number of items, and has the option to thumbs up or thumbs down (vote on) each item.
So far I have gotten this to work during each run of the application, as it is currently loading the data from an XML file - and the data is still static at the moment.
I need to persist these votes on the server using a database (mySQL), such that when the page is reloaded, the votes aren't forgotten.
Has anyone done this sort of thing before?
The two mains methods that I have found on the 'net are
either direct communication between AS3 and the SQL using some sort of framework, or
passing the SQL query to a PHP file, which then executes the SQL query and returns the SQL to AS3.
Which of these methods is the better option?
For the latter method (involving PHP), I have been able to find resources on how to acheive this when attempting to retrieve information from the database (i.e. a read operation), but not when attempting to send information to the database (i.e. a write operation, which is needed when the users vote). How is this done?
Thank you!
Edit: Implemented solution
Somewhere in the PHP file:
if ($action == "vote")
{
$id = $_POST['id'];
$upvotes = $_POST['upvotes'];
$query = "UPDATE `thetable` SET `upvotes` = '$upvotes' WHERE `thetable`.`id` = '$id' LIMIT 1 ;";
$result = mysql_query($query);
}
Somewhere in the ActionsScript:
public function writeToDb(action:String)
{
var loader:URLLoader = new URLLoader();
var postVars:URLVariables = new URLVariables();
var postReq:URLRequest = new URLRequest();
postVars.action = action;
postVars.id = id;
postVars.upvotes = upvotes;
postReq.url = <NAME_OF_PHP_FILE>;
postReq.method = URLRequestMethod.POST;
postReq.data = postVars;
loader.load(postReq);
loader.addEventListener(Event.COMPLETE, onWriteToDbComplete);
}
I am not aware of any framework that supports method-1.
I would use method-2 - but instead of making the query within Flash and passing it to PHP, I would rather pass the related data and construct the query in PHP itself. This is safer because it is less susceptible to SQL injection attacks.
This answer has an example of sending data from flash to the server - it talks about ASP, but the method is same for PHP (or any technology) - just change the URL.
Within the php code, you can read the sent data from the post $_POST (or $_GET) variable.
$something = $_POST["something"]
Many different options:
AMFPHP - binary messaging format between PHP and Actionscript/Flash.
LoadVars - for POSTing and GETing values to a PHP script.
JSON - Using the AS3Corelib you can post JSON formatted data to your web site (just like an AJAX script does).