ECE4112 Internetwork Security Lab X: Web Application Attacks Group Number: ____________ Member Names: _______________________ _______________________ Date Assigned: Due Date: Last Edited on: December 11, 2007 Lab Authored By: Zafeer Khan and Simmon Yau Please read the entire lab and any extra materials carefully before starting. Be sure to start early enough so that you will have time to complete the lab. Answer ALL questions and be sure you turn in ALL materials listed in the Turn-in Checklist ON or BEFORE the Date Due. Goal: The goal of this lab is to introduce different kinds of web application attacks and how to secure your web applications to prevent being the victims of such attack. Summary: The Lab will cover URL Interpretation Attacks which includes SQL injection and Cross-Site Scripting, Impersonation attacks, Buffer Overflow attacks and finally Remote Code Execution, divided into their own individual sections. Background: The lab requires a basic understanding of web based applications, a combination of SQL, Apache servers and PHP and how they all work together. Appendix A has information on PHP, Appendix B on MySQL and Appendix C on setup of MySQL database and Apache Server. If you have no previous knowledge on web applications it is highly recommended you read those appendices before starting the lab. Other than that basic web browsing skills are required to complete this lab. Below is a diagram of a typical web application setup. It shows where the different applications sit within the whole system. We will see during the lab that there are vulnerabilities in almost all the components in a web application. 1 SQL Database Firewall HTTP request (cleartext or SSL) Web App DB Web App Web Client Web Server Web App Web App HTTP reply (HTML, JavaScript, VBscript, etc) Apache IIS Netscape, etc Plugins: Perl C/C++ JSP, etc DB Database connection: ODBC JDBC, etc Typical Web Application Setup Requirements: VMWare with 1 – Windows XP image XAMPP on XP image Any web browser Prelab Questions: None. Section 0: Setup Get the installer for XAMPP from the NAS server. Install XAMPP on your Windows XP image. Once installed go to the XAMPP folder and look for a folder named htdocs. This is the directory where your Apache server finds all the files to display under localhost. There should be a default index.html file, which is displayed when you open a browser. So basically if you have a file named test.html in the htdocs folder, opening a browser and typing in localhost/test.html will display your page. Inside xampp->apache->conf>httpd.conf file is the settings for your server. You can open and modify this file to 2 change your directory root to point to a different location if you want to. If you don’t have any previous experience with Apache servers you can leave this file alone, however, the file is well commented and self explanatory so it is worthwhile going through it once. Inside xampp->php->php.ini is the settings for PHP. This is where you can turn Magic Quotes on/off and enable or disable other security features for PHP. Once again, refer to the appendices for more information. Section 1: URL Interpretation Attacks Section 1.1 – HTTP response splitting/Cross-Site Scripting This attack targets applications that use parameters to indicate redirects. For example, here is a potentially vulnerable URL: http://localhost/ECE%204112/redirect.php?page=http://localhost/ECE%204112/welcome .html A good input validation routine would ensure that the value for the page parameter consists of a valid URL. Yet if arbitrary characters can be included, then the parameter might be rewritten with something like this: http://localhost/ECE%204112/redirect.php?page=0d%0aContentType:%20text/html%0d%0aHTTP/1.1%20200%20OK%0d%0aContentType:%20text/html%0d%0a%0d%0a%3chtml%3eHello, world!%3c/html%3e The original value of page has been replaced with a series of characters that mimic the HTTP response headers from a web server and includes a simple HTML string for “Hello, world!” The malicious payload is more easily understood by replacing the encoded characters: Content-Type: text/html HTTP/1.1 200 OK Content-Type: text/html <html>Hello, world!</html> The end result is that the web browser displays this faked HTML content rather than the HTML content intended for the redirect. The example appears innocuous, but a malicious attack could include JavaScript or content that appears to be a request for the user’s password, social security number, credit card information, or other sensitive information. The point of this example is not how to create an effective phishing attack, but to demonstrate how a parameter’s content can be manipulated to produce unintended effects. Let’s try out this for ourselves. In the source directory for your Apache server create these files with the following code: 3 welcome.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <link rel="stylesheet" href="style.css" type="text/css" /> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Welcome Page</title> </head> <body> <h1>Welcome Page</h1> <p>Welcome member!</p> </body> </html> login.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <link rel="stylesheet" href="style.css" type="text/css" /> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Sample Web Page</title> </head> <body> <h1>Sample Login Page</h1> <p>Basic URL interpretation attack. </p> <p> <label>Username </label><input name="username" type="text" id="username" /> </p> <p> <label>Password </label><input name="password" type="password" id="password" /> </p> <p> <a href="http://localhost/ECE%204112/redirect.php?page=http://localhost/ECE%204112/w elcome.html">Click Here to Login</a><br /> </p> </body> </html> redirect.php 4 <?php if( (isset($_GET['page'])) ) { $page = $_GET['page']; header("Location: $page"); exit(); } ?> hacked.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <link rel="stylesheet" href="style.css" type="text/css" /> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Welcome Page</title> </head> <body> <h1>Welcome member!</h1> <p>Please provide credit card number for validation</p> <script type="text/javascript" src="nasty.js"></script> <script>disp_prompt()</script> </body> </html> nasty.js function disp_prompt() { var num=prompt("Please enter your Credit Card Number"); if (num!=null && num!="") { document.write("<h1>You have just been hacked. Sucker!!!</h1>"); } } style.css body {background-color: #000000; font-family: "Times New Roman"; color: #4444CC; font-size: 12pt;} 5 a {color: #A20000} a:hover {color: #A27700} a:active {color: #17A200} a:visited {color: #00CDD8} table {border: #FF8800 2px solid;} td {border: white 1px solid;} h3 {font-weight: bold; font-size: 14pt} If you look closely at the codes you will see that all redirect.php does is get the header information from the url, and redirects to the welcome page. The login page does nothing other than take you to the script redirect.php with the page information for welcome.html. Since login.html is a static html page it does nothing with the username and password typed in, you can leave them empty and just click the login link. We don’t really care about that, the purpose of this is to show how by not validating information passed between pages we can expose ourselves to attacks. style.css is just the stylesheet for the html pages. To carry out the attack we first load login.html and view page source. If you scroll down you will see the link for the login button. As you can see all you have to do is change the page value to an address you want the user to be redirected to when they click on the login link. Let’s try this now, type the following link into your browser’s URL address bar: http://localhost/ECE%204112/redirect.php?page=http://localhost/ECE%204112/hacked.h tml Q1.1.1 What happens once you do this? Q1.1.2 How could you have prevented such an attack? We ran the whole attack on localhost server but you can easily see how we can accomplish the same thing on any site. The only difference would be instead of localhost the URL would be something like: http://website/redirect.php?page=http://website/welcome.php where website is the actual website we are trying to attack. Section 1.2 – SQL Injection This attack targets the encoding of the URL. An attacker can take advantage of the multiple ways of encoding an URL and abuse the interpretation of the URL. An URL may contain special character that need special syntax handling in order to be interpreted. Special characters are represented using a percentage character followed by two digits 6 representing the octet code of the original character (%HEX-CODE). For instance USASCII space character would be represented with %20. This is often referred as escaped ending or percent-encoding. Since the server decodes the URL from the requests, it may restrict the access to some URL paths by validating and filtering out the URL requests it received. An attacker will try to craft an URL with a sequence of special characters which once interpreted by the server will be equivalent to a forbidden URL. It can be difficult to protect against this attack since the URL can contain other format of encoding such as UTF-8 encoding, Unicode-encoding, etc. The attacker could also subvert the meaning of the URL string request by encoding the data being sent to the server through a GET request. For instance an attacker may subvert the meaning of parameters used in a SQL request and sent through the URL string. Attack Execution Flow 1- The attacker accesses the server using a specific URL. 2- The attacker tries to encode some special characters in the URL. The attacker finds out that some characters are not filtered properly. 3- The attacker crafts a malicious URL string request and sends it to the server. 4- The server decodes and interprets the URL string. Unfortunately since the input filtering is not done properly, the special characters may have harmful consequences. We will try this out for ourselves. First create the following files in your Apache htdocs directory: process_login.asp <HTML> <BODY bgcolor='000000' text='ffffff'> <FONT Face='tahoma' color='ffffff'> <STYLE> p { font-size=20pt ! important} font { font-size=20pt ! important} h1 { font-size=64pt ! important} </STYLE> <%@LANGUAGE = JScript %> <% function trace( str ) { if( Request.form("debug") == "true" ) Response.write( str ); } function Login( cn ) 7 { var username; var password; username = Request.form("username"); password = Request.form("password"); var rso = Server.CreateObject("ADODB.Recordset"); var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql ); rso.open( sql, cn ); if (rso.EOF) { rso.close(); %> <FONT Face='tahoma' color='cc0000'> <H1> <BR><BR> <CENTER>ACCESS DENIED</CENTER> </H1> </BODY> </HTML> <% Response.end return; } else { Session("username") = "" + rso("username"); %> <FONT Face='tahoma' color='00cc00'> <H1> <CENTER>ACCESS GRANTED<BR> <BR> Welcome, <% Response.write(rso("Username")); Response.write( "</BODY></HTML>" ); Response.end } } function Main() { //Set up connection var username var cn = Server.createobject( "ADODB.Connection" ); cn.connectiontimeout = 20; cn.open( "localhost", "root", "" ); 8 username = new String( Request.form("username") ); if( username.length > 0) { Login( cn ); } cn.close(); } Main(); %> loginform.html <HTML> <HEAD> <TITLE>Login Page</TITLE> </HEAD> <BODY bgcolor='000000' text='cccccc'> <FONT Face='tahoma' color='cccccc'> <CENTER><H1>Login</H1> <FORM action='process_login.asp' method=post> <TABLE> <TR><TD>Username:</TD><TD><INPUT type=text name=username size=100% width=100></INPUT></TD></TR> <TR><TD>Password:</TD><TD><INPUT type=password name=password size=100% width=100></INPUT></TD></TR> </TABLE> <INPUT type=submit value='Submit'> <INPUT type=reset value='Reset'> </FORM> </FONT> </BODY> </HTML> Open a browser and goto http://localhost/loginform.html Now try logging in with any username and password. It should redirect you to process_login.asp if you typed in a valid username and password from the users table. Now go to the URL address bar of your browser and type in the following: http://target/process_login.asp?userid=bob%27%3b%20update%20logintable%20set%20 passwd %3d%270wn3d%27%3b--%00 Q1.2.1 What happens once you do this? Q1.2.2 Can you figure out what SQL query gets executed? Q1.2.3 How can you protect yourself from such an attack? 9 Section 2: Impersonation Attacks In this section of the lab, you will learn about impersonation attacks or how people pretend to be another person or a popular and known organization and attempt to gain access to their private account information. These impersonation attacks are becoming more popular due to the large amount of money that hackers and organized crime can make off of them. There are many kinds of impersonation attacks, but we will only cover the ones people would encounter on the web. This section will show you an impersonation attack of an attacker pretending to be another person as a result of some poorly coded session management. Http is basically a stateless protocol and has no way to track or remember information. However, web developers can use something called sessions which are similar to cookies to track information. Sessions and cookies are different in the way that sessions only exist until they are destroyed. Once a session is destroyed, the browser will not keep track of any information until a new session is created again on the same webpage. Let’s take a look at an example of a session. First, install apache, mySQL, and PHP onto your hard drive if you have not already done so in your previous lab(s). If you do not know how to do this, please look in Appendix A of this lab on further instructions in doing so. Mount the nas onto your hard drive and then proceed to download “session.php” from the LabX folder on the nas onto your RedHat WS 4.0 host machine. Save this file onto your …/apache2/htdocs/ folder so that we can view it in a web browser. Next, go to http://57.35.6.x/session.php where x corresponds to the last byte of the IP of your RedHat WS 4.0 host machine. You could also do http://127.0.0.1/session.php or http://localhost/session.php. Q2.1. What do you see displayed on the webpage? Q2.2. Click the refresh button on the browser. What do you see displayed on the webpage now? Q2.3. Close the web browser(NOT just the tabbed window!) and open a new one. Go back to the site. What do you see displayed on the webpage now? Why? Q2.4. Take a look at the source code for session.php below and explain what it is doing. 10 Session.php Source Code <?php session_start(); if ($PHPSESSID) { echo $PHPSESSID; } else { print('This is your first time visiting this site. A session has been created to track your information.'); session_register('PHPSESSID'); $PHPSESSID=rand(); } ?> Now that you know what the sessions are doing, let’s take a look at how someone could easily hijack sessions. In a web browser, go to your http://57.35.6.x/session.php page again and click the refresh button so you can see your session ID printed on the webpage. Take this session copy and replace the X in this url and go to it in a NEW web browser: http://57.35.6.x/session.php?PHPSESSID=X . Now that you have seen an example of session creation on the web, let’s take a look at how someone could take advantage of sessions to gain another person’s account information. Let us look at a poorly coded session management webpage. Mount the nas onto your hard drive and then proceed to download “badsession.php” from the LabX folder on the nas onto your RedHat WS 4.0 host machine. Save this file onto your …/apache2/htdocs/ folder so that we can view it on our webpage. Before you access the webpage, we must create the database for which our webpage will be pulling information out of. Under a mySQL prompt, do the following commands: mysql> create database ebank; mysql> use ebank; Next, we create the users table: mysql> CREATE TABLE `users` ( `id` int(10) NOT NULL auto_increment, `username` varchar(100) NOT NULL default '', `password` varchar(100) NOT NULL default '', `balance` varchar(100) NOT NULL default '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; 11 mysql> INSERT INTO `users` VALUES (1, 'henry', 'owen', ‘$1’); mysql> INSERT INTO `users` VALUES (5, 'bill', 'gates', ‘$10000000000’); In the previous step, you created a database called ebank and a table called users. For the users table, you inserted the entries for two people and their account information. We will now try to log in to one of the accounts and see what happens. Open a web browser and go to http://57.35.6.x/badsession.php. Use the username “henry” with the password “owen”. Your screen should look like the figure below. Q2.5. After logging in with the username “henry” and the password “owen”, what do you see? 12 Q2.6. Try adding ?PHPSESSID=5 to the end of the url, what happens? Q2.7. Obviously, what happened in the previous question is a very unsafe method of coding a website. Explain why this can occur and what you could do to as the web designer to prevent this from happening. The code in badsession.php is not only bad, but there were also some other reasons that allowed this session hijacking. One of the reasons is because the options for global variables was turned on in the php.ini file. Also, the PHPSESSID variable was also enabled to be passed around in a cookie. This can be seen in the code below: Php.ini php.ini changes ; Option of whether or not to use cookies session.use_cookies = 1 session.cookie_secure = 0 ; This option enables administrators to make their users invulnerable to ; attacks which involve passing session ids in URLs; defaults to 1. session.use_only_cookies = 0 ; Name of the session (used as cookie name). session.name = PHPSESSID register_globals=on Badsession.php <?php if(!$PHPSESSID){ $username = $_POST["username"]; // grab username from form $password = $_POST["password"]; // grab password from form $dbuser="root"; // database username $dbpassword="password"; // database password $database=" ebank"; // database name mysql_connect(localhost,$dbuser,$dbpassword); // connect to database @mysql_select_db($database) or die( "Unable to select database"); $login = mysql_num_rows(mysql_query("SELECT * FROM users WHERE username='$username' AND password='$password'")); // sql query to see if user and password exist together if($login){ 13 $sql_pass_get = "SELECT * FROM users WHERE username='$username'"; $user_info = mysql_fetch_array(mysql_query($sql_pass_get)); session_register('PHPSESSID'); session_register('username'); session_register('password'); session_register('balance'); $PHPSESSID = $user_info['id']; // store id as session variable $username = $user_info['username']; // store username as a session variable $password = $user_info['password']; // store password as a session variable $balance = $user_info['balance']; // store balance as a session variable echo "ID: "; echo $PHPSESSID; echo "<br>Username: "; echo $username; echo "<br>Password: "; echo $password; echo "<br>Balance: "; echo $balance; } else{ ?> <form method="post" action="badsession.php"> Username:<input type="text" size="12" name="username"><br /> Password:<input type="password" size="12" name="password"><br /> <input type="submit" value="Log In" name="submit"> </form> <? } } else{ echo "ID: "; echo $PHPSESSID; $dbuser="root"; // database username $dbpassword="password"; // database password $database="ebank"; // database name mysql_connect(localhost,$dbuser,$dbpassword); // connect to database @mysql_select_db($database) or die( "Unable to select database"); 14 $sql_pass_get = "SELECT * FROM users WHERE id='$PHPSESSID'"; $user_info = mysql_fetch_array(mysql_query($sql_pass_get)); $PHPSESSID = $user_info['id']; // store id as session variable $username = $user_info['username']; // store username as a session variable $password = $user_info['password']; // store password as a session variable $balance = $user_info['balance']; // store balance as a session variable echo "<br>Username: "; echo $username; echo "<br>Password: "; echo $password; echo "<br>Balance: "; echo $balance; } ?> What you saw in the previous section is due to poor session management and led up to someone’s account information seen by the wrong eyes. This could happen at any time if a web developer is not careful in the code he creates. What’s worse is that if this example was a real bank webpage, someone could have transferred off all the money from one account to another. The other way for someone to gain information is creating a false popup that appears to be a legitimate webpage and has the user fill out information like his or her account number and pin number. Due to the complexity and the time it would take to create this code, we will not be covering this. Section 3: Buffer Overflow A buffer overflow attack can occur when a user inputs more data in a buffer than it can handle. As a result, this code flows over into other buffers and can corrupt or overwrite data in them. Although it is hard to find such vulnerabilities while probing for attacks on a system, it is usually easy to see and easily exploitable by anyone once the source code is reviewed. This is a security risk for many web applications because someone could overflow a buffer with code that makes someone’s computer run a program or expose information on their computer. 15 The majority of buffer overflow attacks are on programs that have already been made in languages like C. However, it is possible for buffer overflows to occur on web applications and structures as well. An example would be the incident which occurred in July 2000 where a buffer overflow exploit was found in Microsoft Outlook and Outlook Express. A flaw in the code made it possible for an attacker to take over someone’s computer by simply sending an e-mail to that person. The user did not even have to open the message because the header of the e-mail could be overflowed with extraneous data that allowed the attacker to execute whatever code they wish on the receiver’s computers. Of course, Microsoft made a patch which has fixed this vulnerability. In this lab, we will look at an example of a simple buffer overflow attack in C. Download the file demo.tar from the LabX folder of the nas to your RedHat WS 4.0 machine. Next, type the following commands: tar –xvf demo.tar cd demo make Q3.1. Type the command “demo –n 3 garotinho”. What happens? Why? Section 4: Remote Code Execution Remote code execution is a vulnerability in which an attacker could run an arbitrary, system level code on a vulnerable server to retrieve any information they wish that may be on the system. Go to http://www.securityfocus.com/infocus/1864/1 and read up more information on this topic. This kind of attack could basically happen in various kinds of protocols like SMTP, HTTP, and others. It is usually a result of poor coding just like how most exploits occur. Q4.1. Give an example of a remote code section you found on the web. 16 Answer Sheet Lab X Group Number:_____________ Member Names: ______________________ _______________________ Section 1.1 – HTTP Response Splitting/Cross Site Scripting Q1.1.1 What happens once you do this? Q1.1.2 How could you have prevented such an attack? Section 1.2 – SQL Injection Attack Q1.2.1 What happens once you do this? Q1.2.2 Can you figure out what SQL query gets executed? Q1.2.3 How can you protect yourself from such an attack? 17 Section 2 - Impersonation Attacks Q2.1. What do you see displayed on the webpage? Q2.2. Click the refresh button on the browser. What do you see displayed on the webpage now? Q2.3. Close the web browser(NOT just the tabbed window!) and open a new one. Go back to the site. What do you see displayed on the webpage now? Why? Q2.4. Take a look at the source code for session.php below and explain what it is doing. Q2.5. After logging in with the username “henry” and the password “owen”, what do you see? Q2.6. Try adding ?PHPSESSID=5 to the end of the url, what happens? 18 Q2.7. Obviously, what happened in the previous question is a very unsafe method of coding a website. Explain why this can occur and what you could do to as the web designer to prevent this from happening. Section 3 – Buffer Overflow Q3.1. Type the command “demo –n 3 garotinho”. What happens? Why? Section 4 – Remote Code Execution Q4.1. Give an example of a remote code section you found on the web. 19 References http://searchsoftwarequality.techtarget.com/searchAppSecurity/downloads/Hacking_Exp osed_ch06.pdf, Hacking Exposed http://capec.mitre.org, CAPEC (Common Attack Pattern Enumeration and Classification) http://www.securityfocus.com/infocus/1774, Security Focus http://www.pcmag.com/article2/0,1759,34074,00.asp, PC Magazine http://www.weberdev.com/ViewArticle/Exploring-Session-Security-In-PHP-WebApplications, weberdev.com http://www.tizag.com/mysqlTutorial/mysqltables.php, tizag.com http://phpsec.org/projects/guide/4.html, PHP Security Consortium http://www.ic.unicamp.br/~stolfi/urna/buffer-oflow/, Institute of Computing, UNICAMP Appendix A & B from Web Security Lab from Spring 2007 20 Appendix A PHP REFERENCE The following is a brief reference of the PHP language. It is in no means a complete reference and only contains the relevant functions that you need for this lab. A more complete reference can be found at: http://www.php.net/manual/en/ PHP is a popular scripting languages that enable developers to make dynamic web pages. Some important points include: All PHP code must be contained within <?php <php code goes here> ?> tags. A shorthand for this is simply <? <php code goes here> ?>. All variables in PHP are referred to by using the “$” symbol. For example, a variable called foo would be references as $foo. - Every line of code in PHP must end with a “;” The following is a list of PHP functions that you will see in the lab: int print ( string arg ) Outputs arg. Returns 1, always. Works without the parenthesis. void echo( string arg ) Same as the print() function 21 resource mysql_connect( server, username, password ) Opens a connection to a mysql database and returns as a resource object a reference to the connection. bool mysql_select_db ( string database_name ) Sets the current active database on the server that’s associated with the specified database name. Every subsequent call to mysql_query() will be made on the active database. resource mysql_query ( string query ) Sends a specified SQL query to the currently active database which is set by mysql_select_db(). Results of the query are returned in a resource object. array mysql_fetch_assoc ( resource result ) Fetch a result row as an associative array. Returns an associative array that corresponds to the fetched row and moves the internal data pointer ahead. bool isset ( mixed var ) Determine whether the specified variable is set (ie if the variable exists). string htmlentities ( string text ) Convert all applicable characters to HTML entities. This function is identical to htmlspecialchars() in all ways, except with htmlentities(), all characters which have HTML character entity equivalents are translated into these entities. 22 The $_GET, $_POST, and $_COOKIE are global PHP arrayvariables that refer to a web requests get, post and cookie variable’s respectively. To get a specific value from each one of these, use the [] notation. Example: $_GET[“foo”] returns the HTTP get variable called foo. HTTP get variables are the same as variables that are passed onto the URL string. Appendix B SQL TUTORIAL Included are excerpts from the w3schools SQL Tutorial. The full text may be found at http://www.w3schools.com/sql/sql_where.asp Reproduced here are the Introduction, SQL The SELECT Statement, SQL The WHERE Clause, and SQL Functions sections. The full SQL language is much more complicated and even these excerpts are more than is strictly necessary to know for this lab. These are provided as a reference and as a launching point for those who want to learn more about SQL. Introduction to SQL SQL is a standard computer language for accessing and manipulating databases. What is SQL? SQL stands for Structured Query Language SQL allows you to access a database SQL is an ANSI standard computer language SQL can execute queries against a database 23 SQL can retrieve data from a database SQL can insert new records in a database SQL can delete records from a database SQL can update records in a database SQL is easy to learn SQL is a Standard - BUT.... SQL is an ANSI (American National Standards Institute) standard computer language for accessing and manipulating database systems. SQL statements are used to retrieve and update data in a database. SQL works with database programs like MS Access, DB2, Informix, MS SQL Server, Oracle, Sybase, etc. Unfortunately, there are many different versions of the SQL language, but to be in compliance with the ANSI standard, they must support the same major keywords in a similar manner (such as SELECT, UPDATE, DELETE, INSERT, WHERE, and others). Note: Most of the SQL database programs also have their own proprietary extensions in addition to the SQL standard! SQL Database Tables A database most often contains one or more tables. Each table is identified by a name (e.g. "Customers" or "Orders"). Tables contain records (rows) with data. Below is an example of a table called "Persons": LastName FirstName Address City Hansen Ola Timoteivn 10 Sandnes Svendson Tove Borgvn 23 Sandnes Pettersen Kari Storgt 20 Stavanger The table above contains three records (one for each person) and four columns (LastName, FirstName, Address, and City). 24 SQL Queries With SQL, we can query a database and have a result set returned. A query like this: SELECT LastName FROM Persons Gives a result set like this: LastName Hansen Svendson Pettersen Note: Some database systems require a semicolon at the end of the SQL statement. We don't use the semicolon in our tutorials. SQL Data Manipulation Language (DML) SQL (Structured Query Language) is a syntax for executing queries. But the SQL language also includes a syntax to update, insert, and delete records. These query and update commands together form the Data Manipulation Language (DML) part of SQL: SELECT - extracts data from a database table UPDATE - updates data in a database table DELETE - deletes data from a database table INSERT INTO - inserts new data into a database table SQL Data Definition Language (DDL) The Data Definition Language (DDL) part of SQL permits database tables to be created or deleted. We can also define indexes (keys), specify links between tables, and impose constraints between database tables. 25 The most important DDL statements in SQL are: CREATE ALTER DROP TABLE - alters (changes) a database table TABLE - deletes a database table CREATE DROP TABLE - creates a new database table INDEX - creates an index (search key) INDEX - deletes an index SQL The SELECT Statement The SELECT Statement The SELECT statement is used to select data from a table. The tabular result is stored in a result table (called the result-set). Syntax SELECT column_name(s) FROM table_name Select Some Columns To select the columns named "LastName" and "FirstName", use a SELECT statement like this: SELECT LastName,FirstName FROM Persons "Persons" table LastName FirstName Address Hansen Ola City Timoteivn 10 Sandnes 26 Svendson Tove Borgvn 23 Sandnes Pettersen Kari Storgt 20 Stavanger Result LastName FirstName Hansen Ola Svendson Tove Pettersen Kari Select All Columns To select all columns from the "Persons" table, use a * symbol instead of column names, like this: SELECT * FROM Persons Result LastName FirstName Address Hansen Ola City Timoteivn 10 Sandnes Svendson Tove Borgvn 23 Sandnes Pettersen Kari Storgt 20 Stavanger The Result Set The result from a SQL query is stored in a result-set. Most database software systems allow navigation of the result set with programming functions, like: Move-To-FirstRecord, Get-Record-Content, Move-To-Next-Record, etc. 27 Programming functions like these are not a part of this tutorial. To learn about accessing data with function calls, please visit our ADO tutorial. Semicolon after SQL Statements? Semicolon is the standard way to separate each SQL statement in database systems that allow more than one SQL statement to be executed in the same call to the server. Some SQL tutorials end each SQL statement with a semicolon. Is this necessary? We are using MS Access and SQL Server 2000 and we do not have to put a semicolon after each SQL statement, but some database programs force you to use it. The SELECT DISTINCT Statement The DISTINCT keyword is used to return only distinct (different) values. The SELECT statement returns information from table columns. But what if we only want to select distinct elements? With SQL, all we need to do is to add a DISTINCT keyword to the SELECT statement: Syntax SELECT DISTINCT column_name(s) FROM table_name Using the DISTINCT keyword To select ALL values from the column named "Company" we use a SELECT statement like this: SELECT Company FROM Orders "Orders" table 28 Company OrderNumber Sega 3412 W3Schools 2312 Trio 4678 W3Schools 6798 Result Company Sega W3Schools Trio W3Schools Note that "W3Schools" is listed twice in the result-set. To select only DIFFERENT values from the column named "Company" we use a SELECT DISTINCT statement like this: SELECT DISTINCT Company FROM Orders Result: Company Sega W3Schools Trio Now "W3Schools" is listed only once in the result-set. 29 SQL The WHERE Clause The WHERE clause is used to specify a selection criterion. The WHERE Clause To conditionally select data from a table, a WHERE clause can be added to the SELECT statement. Syntax SELECT column FROM table WHERE column operator value With the WHERE clause, the following operators can be used: Operator Description = Equal <> Not equal > Greater than < Less than >= Greater than or equal <= Less than or equal BETWEEN Between an inclusive range LIKE Search for a pattern Note: In some versions of SQL the <> operator may be written as != 30 Using the WHERE Clause To select only the persons living in the city "Sandnes", we add a WHERE clause to the SELECT statement: SELECT * FROM Persons WHERE City='Sandnes' "Persons" table LastName FirstName Address City Year Hansen Ola Timoteivn 10 Sandnes 1951 Svendson Tove Borgvn 23 Sandnes 1978 Svendson Stale Kaivn 18 Sandnes 1980 Pettersen Kari Storgt 20 Stavanger 1960 LastName FirstName Address City Year Hansen Ola Timoteivn 10 Sandnes 1951 Svendson Tove Borgvn 23 Sandnes 1978 Svendson Stale Kaivn 18 Sandnes 1980 Result Using Quotes Note that we have used single quotes around the conditional values in the examples. SQL uses single quotes around text values (most database systems will also accept double quotes). Numeric values should not be enclosed in quotes. For text values: 31 This is correct: SELECT * FROM Persons WHERE FirstName='Tove' This is wrong: SELECT * FROM Persons WHERE FirstName=Tove For numeric values: This is correct: SELECT * FROM Persons WHERE Year>1965 This is wrong: SELECT * FROM Persons WHERE Year>'1965' The LIKE Condition The LIKE condition is used to specify a search for a pattern in a column. Syntax SELECT column FROM table WHERE column LIKE pattern A "%" sign can be used to define wildcards (missing letters in the pattern) both before and after the pattern. Using LIKE The following SQL statement will return persons with first names that start with an 'O': SELECT * FROM Persons 32 WHERE FirstName LIKE 'O%' The following SQL statement will return persons with first names that end with an 'a': SELECT * FROM Persons WHERE FirstName LIKE '%a' The following SQL statement will return persons with first names that contain the pattern 'la': SELECT * FROM Persons WHERE FirstName LIKE '%la%' SQL Functions SQL has a lot of built-in functions for counting and calculations. Function Syntax The syntax for built-in SQL functions is: SELECT function(column) FROM table Types of Functions There are several basic types and categories of functions in SQL. The basic types of functions are: Aggregate Scalar Functions functions 33 Aggregate functions Aggregate functions operate against a collection of values, but return a single value. Note: If used among many other expressions in the item list of a SELECT statement, the SELECT must have a GROUP BY clause!! "Persons" table (used in most examples) Name Age Hansen, Ola 34 Svendson, Tove 45 Pettersen, Kari 19 Aggregate functions in MS Access Function Description AVG(column) Returns the average value of a column COUNT(column) Returns the number of rows (without a NULL value) of a column COUNT(*) Returns the number of selected rows FIRST(column) Returns the value of the first record in a specified field LAST(column) Returns the value of the last record in a specified field MAX(column) Returns the highest value of a column MIN(column) Returns the lowest value of a column STDEV(column) STDEVP(column) 34 SUM(column) Returns the total sum of a column VAR(column) VARP(column) Aggregate functions in SQL Server Function Description AVG(column) Returns the average value of a column BINARY_CHECKSUM CHECKSUM CHECKSUM_AGG COUNT(column) Returns the number of rows (without a NULL value) of a column COUNT(*) Returns the number of selected rows COUNT(DISTINCT column) Returns the number of distinct results FIRST(column) Returns the value of the first record in a specified field (not supported in SQLServer2K) LAST(column) Returns the value of the last record in a specified field (not supported in SQLServer2K) MAX(column) Returns the highest value of a column MIN(column) Returns the lowest value of a column STDEV(column) STDEVP(column) SUM(column) Returns the total sum of a column 35 VAR(column) VARP(column) Scalar functions Scalar functions operate against a single value, and return a single value based on the input value. Useful Scalar Functions in MS Access Function Description UCASE(c) Converts a field to upper case LCASE(c) Converts a field to lower case MID(c,start[,end]) Extract characters from a text field LEN(c) Returns the length of a text field INSTR(c) Returns the numeric position of a named character within a text field LEFT(c,number_of_char) Return the left part of a text field requested RIGHT(c,number_of_char Return the right part of a text field requested ) ROUND(c,decimals) Rounds a numeric field to the number of decimals specified MOD(x,y) Returns the remainder of a division operation NOW() Returns the current system date FORMAT(c,format) Changes the way a field is displayed 36 DATEDIFF(d,date1,date2) Used to perform date calculations Appendix C I. Setting up Apache Apache should already be installed on your Red Hat WS 4.0 Machine. If it is not, please follow the directions given in Lab 2. Make sure you have a directory called apache2 somewhere on your machine. Possible locations for this folder are /home/apache2, /usr/local/apache2 or /var/local/apache2. In order to use php, we must modify our server’s configuration file. This file called httpd.conf is located under the apache2 directory (/conf/httpd.conf). The following lines must be added. The best way to add these lines is to search for them in the config file and place them below the commented examples. LoadModule php4_module modules/libphp4.so DirectoryIndex index.html index.html.var index.php (this replaces existing line) AddType application/x-httpd-php .php For reference, an httpd.conf file is placed on nas4112/Lab9/Examples II. Setting up PHP Now that we have our apache server configured, we need to make sure we can interpret a php file located in .../apache2/htdocs. First, locate php.ini (use the locate command; you may have to updatedb before you can). More than likely php.ini is located in /etc/. Open php.ini and set the document root to the path of your htdocs directory. For example, if apache2 is located in /usr/local, then find the line in php.ini starting with doc_root and type the following: doc_root = “/usr/local/apache2/htdocs/” Remember, depending on the location of the apache2 directory, the above line may be different. Once you have completed this task, test out php by creating a sample file in apache2/htdocs called test.php; <?php phpinfo(); ?> 37 Now, restart apache by typing #/apache2/bin/apachectl restart. If you receive an error about libphp4.so module not found, locate the libphp4.so file and copy to /apache2/modules (probably located in /usr/lib/httpd/modules/) Open up a web browser, and type http://localhost/test.php. If you see a page with a lot of information formatted in a nice table, you have succeeded. III. Setting up MySQL To configure MySQL, open a terminal as root and do the following: #service mysqld start #mysqladmin –u root password password In this lab, we will be using three databases. One will be used to store captured cookie information, one will be used for a message board, and the third one will be used to store login information. To create each of these databases, we will need to execute the following commands. First get a myslq> prompt by typing mysql –u root –h localhost –p and then password for your password. Type the following commands : NOTE: All sql commands are provided in commands.sql under /Lab9 for your copying pleasure. mysql> create database ece4112; mysql> use ece4112; To create the cookies table: mysql> CREATE TABLE `cookies` ( `id` int(11) NOT NULL auto_increment, `username` varchar(100) NOT NULL default '', `password` varchar(100) NOT NULL default '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; mysql> INSERT INTO `cookies` VALUES (6, 'testertest', 'hilohilo'); To create the message board table: mysql> CREATE TABLE `messages` ( `msg_id` int(11) NOT NULL auto_increment, `title` varchar(50) NOT NULL default '', `body` text NOT NULL, 38 PRIMARY KEY (`msg_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ; mysql> INSERT INTO `messages` VALUES (1, 'Test Message 1', 'This is a test.'); mysql> INSERT INTO `messages` VALUES (2, 'Test Message 2', 'This is another test.'); mysql> INSERT INTO `messages` VALUES (3, 'We love 4112', 'What a great message.'); mysql> INSERT INTO `messages` VALUES (4, '42', 'Meaning of life the universe and everything.'); mysql> INSERT INTO `messages` VALUES (5, 'Hello', 'Hey everyone!'); mysql> INSERT INTO `messages` VALUES (6, 'We need more messages', 'Here is yet another message!'); mysql> INSERT INTO `messages` VALUES (7, 'Yo dude', 'Jeff should type more of these.'); mysql> INSERT INTO `messages` VALUES (8, 'Lalala', 'Typing messages for people.'); mysql> INSERT INTO `messages` VALUES (9, 'Yet another message', 'Here is a hint. Post a message.'); To create the users table: mysql>CREATE TABLE `users` ( `user_id` int(11) NOT NULL auto_increment, `first_name` varchar(50) NOT NULL default '', `last_name` varchar(50) NOT NULL default '', `address` varchar(50) NOT NULL default '', `city` varchar(50) NOT NULL default '', `state` char(2) NOT NULL default '', `zip` varchar(5) NOT NULL default '', `phone` varchar(10) NOT NULL default '', `email` varchar(50) NOT NULL default '', `password` varchar(8) NOT NULL default 'password', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ; mysql>INSERT INTO `users` VALUES (1, 'Jeff', 'Jo', '1008 State Street', 'Atlanta', 'GA', '30318', '4041234567', 'jeff.jo@ece.gatech.edu', 'password'); INSERT INTO `users` VALUES (2, 'Tim', 'Jackson', '342 Hempill Avenue', 'Atlanta', 'GA', '30318', '7704325543', 'tim.jackson@ece.gatech.edu', 'password'); INSERT INTO `users` VALUES (3, 'Unsuspecting', 'User', '10 Hackme Place', 'San Diego', 'CA', '45443', '3153332222', 'hackme@vulnerable.com', 'password'); INSERT INTO `users` VALUES (4, 'Henry', 'Owen', '10 Professors Place', 'New York', 'NY', '07321', '2124432345', 'henry.owen@professors.com', 'goodbye'); To create the login database. mysql> create database my_database; 39 mysql> use my_database; mysql> CREATE TABLE users ( id int(10) NOT NULL auto_increment, username varchar(40), password varchar(50), regdate varchar(20), email varchar(100), website varchar(150), location varchar(150), show_email int(2) DEFAULT '0', last_login varchar(20), PRIMARY KEY(id)); After executing these commands, you should have two databases: ece4112 and my_database. ece4112 has three tables: cookies, messages, and users. my_database has one table: users. Refer to Appendix B for more information about mysql statements. Hopefully, everything has gone smoothly. Installing these three components are often quite tricky. We have just done the basic configurations; however, all three can be customized for various uses. 40