$24
WEB SERVICES
In the following exercises, we will try consuming a web service.
E x e r c i s e 1 8 . 1— D I S P L A Y I N G A G O O G L E M A P
Examine lab18-exercise1.html.
You will be adding JavaScript in a separate file to consume the web service.
You will need a Google Map API key to do this next exercise. If you do not already have one, visit the following URL:
https://developers.google.com/maps/documentation/javascript/get-api-key
Modify the script tag in the head to use your Google map API key.
<script type='text/javascript' src='https://maps.googleapis.com/maps/api/js?key=your key here'
Add the following code to exercise1.js and then test.
$(function () { $('.animLoading').show();
var url =
"http://www.randyconnolly.com/funwebdev/services/travel/cities.php";
var param = "iso=CA";
make request for list of cities for specified country $.get(url, param)
.done(function (data) {
loop through returned array of cities $.each(data, function(index,city) {
create new empty list item
var item = $('<li');
add lat and long info from web service to each
list item using HTML5 data- attributes item.attr( "data-lat", city.latitude); item.attr( "data-long", city.longitude); item.html('<a href="#"' + city.name + '</a');
add list item to UL
$("#cities").append(item);
});
})
.fail(function (jqXHR) {
alert("Error: " + jqXHR.status);
})
.always(function () {
all done so now hide the animated loading GIF $('.animLoading').fadeOut("slow");
});
});
Fundamentals of Web Development
3
This should display a list of cities from Canada. If the list works, then the next step will display a map of the city when it is clicked.
Add the following code to the done() function in exercise1.js.
$(function () {
...
add lat and long info from web service to each
list item using HTML5 data- attributes item.attr( "data-lat", city.latitude); item.attr( "data-long", city.longitude); item.html('<a href="#"' + city.name + '</a');
add list item to UL
$("#cities").append(item);
});
add handler for clicking on list items $("#cities li").on("click", function () {
displayMap($(this));
});
Add the following nested function to exercise1.js and test.
display map for selected city
function displayMap(selectedCity) {
the lat and long of city is contained within
the clicked <li element
var ourLatLong = {lat: Number(selectedCity.attr("data-lat")) ,
lng: Number(selectedCity.attr("data-long"))};
var ourMap = new google.maps.Map(document.getElementById('map'), { center: ourLatLong,
scrollwheel: false,
zoom: 13
});
}
Lab 18: Web Services and Security
Figure 18.1 – Finished Exercise 18.1
AUTHENTICATION
E x e r c i s e 1 8 . 2 — B U I L D B E T T E R A U T H E N T I C A T I O N
Execute the database commands in lab18-exercise2.sql. This will create a database named Login and a table to store user credentials.
Open, examine, and test lab18-exercise2.php. You will see that it contains a functioning authentication script for a user with the name "testuser" and password of "funwebdev". Unfortunately, if you look at the database records, those fields are stored in plaintext, and so they are easily compromised by anyone with access to the database or database backup as illustrated in Figure 18.2.
Fundamentals of Web Development
5
Figure 18.2 Credentials table and a record structure before changes
Modify the database table to hold an extra field, which should be a string and named seed. This can easily be done in phpMyAdmin.
Modify any records already in the table so that they store a unique seed and then use that unique seed when calculating the password. For the record with username password, the seed might be abcd1234 so you'd update the password to store md5(funwebdevabcd1234) as shown in Figure 18.3.
Figure 18.3 More secure database schema after modifications
Modify the validLogin function that checks for a valid login so that it also uses the seed in the validation check. Note that you only have to change the SELECT statement to make use of the seed in a sub query.
function validLogin(){
$pdo = new PDO(DBCONNSTRING,DBUSER,DBPASS); //updated query to use the seed in checking login.
$sql = "SELECT * FROM Credentials WHERE Username=:user and Password=MD5(CONCAT(:pass,(SELECT Seed FROM Credentials WHERE Username=:user)))";
$statement = $pdo-prepare($sql);
$statement-bindValue(':user',$_POST['username']); $statement-bindValue(':pass',$_POST['pword']);
$statement-execute();
echo $sql;
if($statement-rowCount()0){
return true;
}
return false;
}
Note: To see if your PDO queries are operating correctly, you need to access your MySQL log file which will have the "final" query after all bindings in PDO have occurred. Check my.cnf for the location of that file.
Lab 18: Web Services and Security
Now you have the basis for a secure authentication storage system. You should be able to log in as before, but now you are using the salted hash to validate logins. If you have any scripts to allow registrations, be sure to update them as well to include random seed creation, storage and usage as well.
WHITE HAT SECURITY TESTING
The exercise below make use of techniques that hackers use to compromise your sites. Therefore, you should exercise caution that you are only using these techniques on websites and systems that you own. These skills are necessary to understand and protect your sites, but can land you in prison if used for illegal purposes.
E x e r c i s e 1 8 . 3 — I N J E C T I O N T E S T S
Open, examine, and test lab18-exercise3.php. Like Exercise 18.2 it is a simple login form. Unlike Exercise 18.2 it passes user input directly to the database making SQL injection possible.
Since you have likely modified your database to handle authentication more securely in Exercise 18.2 you will have to revert to the previous, bad way of storing credentials as defined in the file lab18-exercise2.sql
Now to ensure the form is working properly log in with testuser and password funwebdev. If successful the page is working as expected.
Now try to create a SQL query which will exploit the fact that the query values are being passed on in an unsanitized format.
In the username field type a username and in the password field enter
'; DROP TABLE Credentials;#
This results in two queries, the first to test for login and the second to drop the table.
If you run this query you will have dropped the Credentials table form the database altogether, thereby breaking logins for everyone, and possibly losing the data for good if the site was not backed up!
Since you just lost your table you will have to run lab18-exercise2.sql to recreate it.
Now to fix the SQL injection vulnerability you have to handle the potentially bad user input by either sanitizing your user inputs or using prepared statements. Since we have illustrated prepared statements elsewhere, we will illustrate sanitized inputs. Modify the
Fundamentals of Web Development
7
SQL statement provided in the file to the following:
function validLogin(){
$pdo = new PDO(DBCONNSTRING,DBUSER,DBPASS);
//very simple (and insecure) check of valuid credentials.
$sql = "SELECT * FROM Credentials WHERE Username='"
.$pdo-quote($_POST['username'])."' and Password='"
.$pdo-quote($_POST['pword'])."'";
echo $sql;
$statement = $pdo-prepare($sql);
//The solution with prepared statements prevents injection as well! //$statement-bindValue(':user',$_POST['username']); //$statement-bindValue(':pass',$_POST['pword']); $statement-execute();
if($statement-rowCount()0){
return true;
}
return false;
}
If you add an echo statement to output the SQL command being run you will see that the attempt was escaped and so the query did not drop the table. Instead that DROP query was tested as the password as is appropriate.
SELECT * FROM Credentials WHERE Username=''testUser'' and Password=''\'; DROP TABLE Credentials;#''
SUBMIT YOUR COMPLETED LAB FILES
Open lab 18 report.doc and answer the questions. Save your lab report as lab18_yourname and submit your report via dropbox in elearning.
Each lab is worth 1.5% of your total grade.