Chapter 4. Developing Successful Interfaces

Applications rely on interfaces to interact with the user. When the interface is flawed, the user’s opinion of the application diminishes and user satisfaction suffers. Every security solution you can conceive of depends on the goodwill of the user to make it a reality. Yes, you can attempt Draconian measures to force user participation, but often these measures result in the user constantly finding ways to overcome security, rather than work with it. In most cases, you receive the best results when the user is on your side, which means making an effort to create an interface the user can appreciate (in that it makes the application so easy to use that the application almost disappears from view). Of course, you do need to ensure the application enforces policies. Therefore, this chapter looks at both the carrot (user cooperating) and the stick (enforced policies) of application security from the interface perspective.

It’s important to make the carrot part of the equation obvious. A user sees various kinds of eye candy, helpful tips, and a clear interface as signs that the developer really cares about the application and how the user views it. Making the user experience pleasant is essential.

The stick part of the equation is usually hidden and subtle. For example, instead of asking the user to type the name of a state, the application prevents unauthorized entries by creating a state list and having the user select from the list. Although the user’s choices are constrained, what the user sees is ease-of-use.

Some interface decisions are mistakes before you even code them. For example, some validation techniques tell the user that the input is unacceptable without telling the user why the input won’t work. More importantly, when the feedback lacks useful tips and examples, the user becomes frustrated. This chapter also discusses techniques you can use to refine the interface. It isn’t a matter of some techniques working, while others don’t—it’s more a matter of some techniques creating less user angst.

Note

It’s important to understand that few people would handcode a website any longer. Fewer still would code a website without using libraries, APIs, frameworks, microservices, and any of a number of other third-party offerings. However, all of these third-party sources rely on the technologies described in this chapter. All that you’re getting from a third-party source is prepackaged code that you could have created yourself. Viewing the code in the way shown in this chapter helps you understand the underlying techniques used by third-party sources so that you can better tell whether these sources are secure. With this in mind, the code in this chapter is designed to help you understand security principles, rather than something you’d actually employ on your website.

Assessing the User Interface

Most organizations need to spend time assessing the user interface of their applications because these interfaces create clear opportunities for hackers to gain access to your network. The section “Specifying Web Application Threats” in Chapter 1 describes a number of common exploits that hackers use. A surprising number of those exploits rely on some user interface element to help things along. The tighter you can make your interface without inhibiting user interaction, the better. The following sections describe some of the techniques you can use to assess the user interface.

Note

The best way to work with the examples described in this chapter is to use the downloadable source, rather than type it in by hand. Using the downloadable source reduces potential errors. You can find the examples for this chapter in the \S4WD\Chapter04 folder of the downloadable source.

Creating a Clear Interface

An essential part of creating workable interfaces today is making them clear. The complex interfaces of old create security problems because the user isn’t sure what to do or possibly has too much to do. The libraries available today make it possible to create clear interfaces that focus on one issue at a time in many situations. For example, the tabbed interface shown in Figure 4-1 provides an example of a clear interface that only does one thing at a time as part of the Tabs.html file.

A clear interface focuses on one issue in a manner the user can understand
Figure 4-1. A clear interface focuses on one issue in a manner the user can understand

This interface is quite clear. It asks a simple question, provides a limited number of responses, and makes it more difficult for the user to enter bad data. The user selects a color, clicks the button, and moves on to the next tab. A number of web applications now make use of this sort of interface. You often see it used for signup sheets. The example relies on the jQuery UI library to perform its task. Here’s the source code for this example:

<!DOCTYPE html>

<html>
<head>
   <script
      src="https://code.jquery.com/jquery-latest.js">
   </script>
   <script
      src="https://code.jquery.com/ui/1.9.2/jquery-ui.js">
   </script>
   <link
      rel="stylesheet"
      href="https://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
   <title>Using the Tabs Widget</title>
   <style>
      #Configuration
      {
         width: 90%;
         text-align: center;
      }
      #Configuration div
      {
          text-align: left;
      }
   </style>
   <script language="JavaScript">
      $(function()
        {
            $("#Configuration").tabs();
        });
   </script>
</head>

<body>
   <h1>Using the Tabs Widget</h1>
   <form id="ConfigForm" method="get" action="Tabs.html">
      <div id="Configuration">
         <ul>
            <li><a href="#Tab1">Foreground Color</a></li>
            <li><a href="#Tab2">Background Color</a></li>
            <li><a href="#Tab3">Options</a></li>
         </ul>
         <div id="Tab1">
            <input id="FGRed"
                   type="radio"
                   name="Foreground"
                   value="Red"
                   checked="checked" />
            <label for="FGRed">Red</label><br />
            <input id="FGOrange"
                   type="radio"
                   name="Foreground"
                   value="Orange" />
            <label for="FGOrange">Orange</label><br />
            <input id="FGGreen"
                   type="radio"
                   name="Foreground"
                   value="Green" />
            <label for="FGGreen">Green</label><br />
            <input id="FGBlue"
                   type="radio"
                   name="Foreground"
                   value="Blue" />
            <label for="FGBlue">Blue</label>
         </div>
         <div id="Tab2">
            <input id="BGRed"
                   type="radio"
                   name="Background"
                   value="Red"
                   checked="checked" />
            <label for="BGRed">Red</label><br />
            <input id="BGOrange"
                   type="radio"
                   name="Background"
                   value="Orange" />
            <label for="BGOrange">Orange</label><br />
            <input id="BGGreen"
                   type="radio"
                   name="Background"
                   value="Green" />
            <label for="BGGreen">Green</label><br />
            <input id="BGBlue"
                   type="radio"
                   name="Background"
                   value="Blue" />
            <label for="BGBlue">Blue</label>
         </div>
         <div id="Tab3">
            <input id="Sounds"
                   type="checkbox"
                   name="Sounds"
                   value="SpecialSounds" />
            <label for="Sounds">Use Special Sounds</label><br />
            <input id="Effects"
                   type="checkbox"
                   name="Effects"
                   value="SpecialEffects" />
            <label for="Effects">Use Special Effects</label>
         </div>
      </div>
      <input id="ChangeConfig"
             type="submit"
             value="Change Configuration" />
   </form>
</body>
</html>

In order to create this interface, you import the jQuery and jQuery UI libraries, and the associated jQuery UI stylesheet. The tab information appears in a <div> with an id of Configuration. The magic used to create the interface is the result of making the $("#Configuration").tabs() call.

Making Interfaces Flexible

Reducing the user’s ability to enter invalid data, making the interface clear and concise, and keeping things simple all restrict the user in various ways. They’re forms of constraints that help you keep data safe while making the user’s task of interacting with the application simpler. However, interfaces also require flexibility. The user will use the application on a number of devices, not all of which will accept the initial organization you provide. The act of letting the user organize the screen as needed provides the user with a sense of power without leaving any security holes open. Whenever possible, an interface should let the user:

Drag
Moving items around on screen can provide the user with a better view of the interface and potentially reduce errant inputs. At a minimum, reorganizing the interface lets a user interact with the application in a manner that best suits the user.
Resize
There are many reasons the user may need to resize an interface element. Perhaps the text is too small. Combining the resize action with the ability provided by most browsers of making the text smaller or larger as needed helps the user see the information better.
Select
Creating positive feedback for selections is essential. You should assume nothing about the user’s ability to see. The selection should provide multiple means of feedback, such as using a thicker border, presenting the selection in a whiter (brighter) color, relying on changing textual attributes, and providing feedback in the form of color. This is one time where having someone on staff check the effects of selections using accessibility aids such as screen readers is important.
Sort
The user should see the data in an order that makes sense to the user—not necessarily to you. With this in mind, provide multiple ways to sort data whenever possible so that the user can perform required analysis and make selections with greater ease.

The jQuery and jQuery UI libraries provide the means to perform all the essential interface flexibility tasks and a host of other tasks (such as allowing drag-and-drop data entry). Figure 4-2 shows an example of using these libraries to move items around on the screen.

Make it possible to move items around
Figure 4-2. Make it possible to move items around
Warning

A library can help you create an appropriate environment for user data entry. However, it can’t remove the need to validate every piece of data you receive. Hackers like it when developers make assumptions about inputs based on the interface. Always assume that a hacker will find a way around the interface aids you provide to honest users and validate every piece of data no matter what source it comes from.

Creating an interface with moveable elements is relatively easy. The following code shows you how (you can also see this code in the DragContent.html file):

<!DOCTYPE html>

<html>
<head>
   <script
      src="https://code.jquery.com/jquery-latest.js">
   </script>
   <script
      src="https://code.jquery.com/ui/1.9.2/jquery-ui.js">
   </script>
   <link
      rel="stylesheet"
      href="https://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
   <style>
      #MoveMe
      {
         border: solid;
         width: 200px;
         height: 5em;
         text-align: center;
         line-height: 5em;
      }
   </style>
   <script language="JavaScript">
      $(function()
        {
            $("#MoveMe").draggable();
        });
   </script>
   <title>Creating a Draggable Element</title>
</head>

<body>
   <h1>Creating a Draggable Element</h1>
   <p id="MoveMe">
      Moveable Paragraph
   </p>
</body>
</html>

In this case, the MoveMe paragraph (<p> element) is the target. Notice that making the paragraph moveable doesn’t affect the heading (<h1> element). All you need to do is call $("#MoveMe").draggable() when the form loads in order to make the paragraph element moveable.

Providing User Aids

Creating an environment in which even the least capable user is able to function well is hard for most developers because most developers can’t even imagine not being able to relate well to a computer. Many of the people a developer supports with an application are quite smart—they simply aren’t smart about computers or the way in which applications work, so it’s important to give them a hand with various types of aids.

The one help item you should always provide is explanatory text. You add explanatory text as part of the HTML tag associated with an element. Here are the attributes most commonly used for explanatory text:

title
The title attribute makes it possible to add explanatory information to just about any textual or control element on the page. When a user hovers the mouse over the top of an element that has the title attribute defined, the browser displays the additional information in a text balloon. It’s important not to make the text too long or to use anything but text within the title attribute because screen readers rely on these attributes to describe an element to someone with special visual needs.
alt
Use the alt attribute to provide a short description of an image element. When the browser can’t display the image, it displays the description instead. In addition, when someone with special needs can’t see the picture, the accessibility aid they use will typically use the alt attribute text to introduce the image. The point is that the alt attribute provides a description of the image and also acts as a substitute for it as needed.
longdesc
Many browsers ignore the longdesc attribute. This attribute provides a much longer description of an image than an alt attribute does. In most cases, you limit the description to about a paragraph of text. The point is to provide enough information so that someone with special needs can create a reasonable mental version of the image—at least the salient points of the image (rather than background).

User help information can appear in many other forms. A kind of help that most sites miss is to provide a sample of what you want as input for textboxes and other typed data as part of the input. You often see textboxes that contain a description of the desired content, rather than a sample of the desired content. (When the user types something in the textbox, the sample text disappears.) For example, instead of providing Last Name as the text within the textbox, provide an actual name, such as Doe (as in John Doe) or something along those lines.

Any input field should also provide a help link. When the user clicks the link, the application displays a help page with additional information. The point is to make it as easy as possible for the user to provide correct information. Any mistakes you can prevent at the outset will reduce user frustration, make data entry more accurate, and most importantly, avoid the mistakes that often lead to security issues.

Defining the Accessibility Issues

Accessibility can be a tricky issue to deal with, especially when working with modern tools. However, it’s an important issue to consider because according to Web Accessibility In Mind (WebAIM), about 20% of the people visiting your site have a special need of some sort: visual, hearing, motor skills, or cognitive. As the world’s population continues to age, the percentage will grow larger. In fact, you have a high likelihood of eventually needing some sort of assistance for a special need.

You may wonder what accessibility has to do with security. When people don’t understand an interface, they make mistakes. However, training usually helps with this problem because you can instruct people on the proper use of the software (and sometimes they actually listen). When people can’t understand an interface because of a special need, they still make mistakes, but no amount of training will ever solve the problem. Even if the user is positively motivated to use the software correctly, unmet accessibility needs will prevent them from doing so. Mistakes often translate into security holes of the worst sort. The unexpected input—the one you never imagined anyone would provide, often creates the biggest problems. An application that lacks accessibility features is more likely to create an environment where security busting mistakes occur on a regular basis.

Fortunately, many vendors design libraries, APIs, frameworks, and microservices with some level of accessibility in mind. They avoid uses of tables as a formatting aid, for example, which causes problems with the screen readers used by those who have visual needs. However, none of these tools is perfect and some of them are less perfect than others. Consequently, it’s important to test your site to determine just what level of accessibility it provides. Most of these testing tools also provide tips on how to fix the accessibility issues found on your site. Table 4-1 provides a listing of testing tools and a description of how you can use them.

Table 4-1. Accessibility testing sites
Site URL Description
Lynx http://www.delorie.com/web/lynxview.html This is a text-only browser that comes in versions for Linux, OS X, and Windows. It helps you check your site by displaying it in text only. This check helps you see your site as a screen reader will see it—making it possible to detect and correct problems with greater ease. Learn more about this product at http://lynx.browser.org/.
NIST Webmetrics Tool Suite http://zing.ncsl.nist.gov/webmet A group of tools from the National Institute of Standards and Technology (NIST) helps you test the usability and accessibility of a site. For example, Web Static Analyzer Tool (WebSAT) ensures your page meets specific usability goals. The Web Variable Instrumenter Program (WebVIP) helps track user interaction so you know how well users are finding site features. There are more tools on this site and NIST updates them regularly.
Opera http://www.opera.com Like Lynx, this browser enables you to see your site as a screen reader will see it. However, unlike Lynx, this product also helps you turn certain features on and off as needed for comparison. For example, you can toggle images off so you can see how <ALT> tags will look (see the instructions at http://help.opera.com/Windows/12.10/en/images.html). Opera is available for a number of platforms including Windows, OS X, and Linux.
O’Reilly XML.com http://www.xml.com/pub/a/tools/ruwf/check.html This site provides an XML syntax checker that also validates XHTML. You can provide the XML input directly or supply an URL containing the XML. The test run by this tool will check that the XML is well formed—it doesn’t verify that the XML actually means anything. In most cases, you’ll want to use the W3C HTML Validation Service for a final check of your web page. However, this website does perform fast checks of intermediate and test XML.
W3C HTML Validation Service http://validator.w3.org This site checks the HTML on your web page for conformance to World Wide Web Consortium (W3C) recommendations and standards. An error on this site means that the coding for your page is incorrect, even if most browsers will read it, so this tester goes beyond usability and accessibility requirements. Don’t get the idea that passing the test on this site automatically makes your site accessible. Passing on this site means that your code is correct. However, making sure your code is correct is a good first step to ensuring you can add accessibility features.
Web Design Group HTML Validator http://www.htmlhelp.com/tools/validator/ This site checks the HTML on your page or, as an alternative, on your computer. It also provides an option to validate a single page or the entire site. You may also find that this site is a little less picky than the W3C HTML Validation Service about which pages it will check and seems to output about the same information, but may not provide complete validation of your site.
WebAIM http://webaim.org You can find all sorts of interesting tools for verifying that your site is accessible on this site. For example, you can use the WAVE Web Accessibility Evaluation Tool to determine whether your site has any major accessibility problems. A serious problem for many sites is the use of color. The Color Contrast Checker helps you verify that people with color deficiencies can actually see your site.

Testing tools are helpful in verifying that your development team has done a great job in creating an application that everyone can use. However, the actual development effort will often require a checklist of tasks to perform and issues to check. The Section 508 checklist at http://webaim.org/standards/508/checklist helps you create such a list for your application development efforts. Interestingly enough, as hard as this checklist might be to read, the government documentation at http://www.section508.gov/ is a lot harder. The point of these requirements is to ensure that anyone, no matter what special needs they might have, can actually use your application as you intend. Without these features in place, you may find that up to 20% of your users have problems that they really shouldn’t be having.

Note

If you have worked through accessibility issues in applications long enough, you know about the Bobby Approved icon that used to appear on some sites. Unfortunately, Bobby isn’t available any longer—at least, not as a free service. You can read the history of Bobby at http://www.bobby-approved.com/. The important thing to note is that accessibility is such an important issue and Bobby did such a terrific job at helping people add it to their sites that IBM eventually bought the product. Bobby is still around—it simply isn’t free.

Providing Controlled Choices

Security is about exercising control. The application must maintain control over the manner in which it interacts with data. Managing data, without damaging it or causing a data leak, is the essential basis for creating a secure interface. One of the best ways to exercise control is to use techniques to ensure the user choices are limited to only the choices you expect. The use of specific entry controls limits user choices, but also makes the user more efficient because the user has to think less about the available options. Here are the common specific entry control choices:

Radio buttons
Lets the user choose one choice out of a number of choices. Selecting a new choice always deselects the previous choice. The most common error developers make is not setting one of the choices as a default. When the data is sent to the server after the user fails to select an option, the server encounters a blank data entry and could potentially experience problems.
Checkboxes
Lets the user choose anywhere between none and all of the available options by checking the desired options. The most common error developers make is allowing conflicting choices to occur. When working with checkboxes, each of the options is mutually exclusive.
List boxes
Depending on the configuration, a list box can act like a radio button or checkbox entry. An advantage of list boxes is that you can set them to hide the choices when the user hasn’t selected the list box control. In addition to the issues that developers often experience with radio buttons and checkboxes, list boxes can suffer from issues in populating the list of choices. The user must have at least one choice available for the list box to act as a control. Inaccessible data sources can prove fatal for this control.
Menus
Depending on the configuration, menus can allow complex combinations of radio button and checkbox behavior. Of course, menus are also used to make client-side application choices. Many developers fail with menus by making them too complicated. A user won’t search long for a particular option, so making the menu too complex leads to errors when the user becomes frustrated.

In addition to standard input types (including older types, such as password), you can also use special HTML5 functionality in creating a controlled choice environment. However, in this case, the alternative is to provide the user with a text input box, which means that these options aren’t as secure as you might think they are. Here are the HTML5-specific controls:

color
Acts as a button with most supporting browsers. Clicking the button displays the platform’s color picker. When the user chooses a new color, the color appears on the button so the user can see the current choice. Newer versions of Firefox, Chrome, and Opera all support this control.
date
Displays a date picker that the user can use to select a specific date. The min and max attributes let you set the range of allowable dates. Newer versions of Chrome, Safari, and Opera all support this control.
datetime
This input type isn’t currently supported by any browser, so you shouldn’t use it even though the specifications tell you that it’s available.
datetime-local
Provides a combination of the date and time controls so that a user can choose both a date and a time (with the restrictions of those controls in place). When specifying the min and max attributes, supply both date and time values as input. Newer versions of Chrome, Safari, and Opera all support this control.
email
Displays a standard text input control. However, the control automatically validates the input to ensure the user supplies an email address. Newer versions of Internet Explorer, Firefox, Chrome, and Opera all support this control.
month
Displays a date picker that the user can use to select a specific month and year. The min and max attributes let you set the range of allowable dates (even though you’re working with months, you must enter dates for these attributes). Newer versions of Chrome, Safari, and Opera all support this control.
number
Permits a user to type any numeric value, but not an alphabetic or special symbol value. Setting the min and max attribute values controls the range of input. Newer versions of Internet Explorer, Firefox, Chrome, Safari, and Opera all support this control.
range
Appears as a slider with most browsers. Setting the min and max attribute values controls the range of input. Use the value attribute to control the initial range setting. The step attribute controls the amount the slider moves for each change in position so that a user can only select specific values. Newer versions of Internet Explorer, Firefox, Chrome, Safari, and Opera all support this control.
search
There isn’t much point in using this HTML5 control because it behaves like a standard <input> tag. Newer versions of Chrome and Safari support this control.
tel
Displays a standard text input control. However, the control automatically validates the input to ensure the user supplies a properly formatted telephone number. Newer versions of Safari support this control.
time
Displays a time picker that the user can use to select a specific time (but not a time zone). The min and max attributes let you set the range of allowable times. Newer versions of Chrome, Safari, and Opera all support this control.
url
Displays a standard text input control. However, the control automatically validates the input to ensure the user supplies a properly formatted URL. Newer versions of Internet Explorer, Firefox, Chrome, and Opera all support this control.
Note

The url input control is the only control that currently provides special support on smartphones (not found on other computer types). On some smartphones, the browser adds a special .com key when it senses the url input control.

week
Displays a date picker that the user can use to select a specific week and year. The min and max attributes let you set the range of allowable dates (even though you’re working with months, you must enter dates for these attributes). Newer versions of Chrome, Safari, and Opera all support this control.
Warning

It’s important to remember that a hacker doesn’t play by the rules or feel constrained by your forms in any way. It’s possible to bypass the protections provided by these controls and submit data directly to the server in some other format. The ability to bypass protections is the reason that you must also range check and data type check any data received from the client at the server.

To use these controls, you use the <input> tag. For example, to create a number input type you might use (see the InputTag.html file for details):

<input id="NumberInput" type="number" min=1 max=5 value=1 />

In this case, the user sees a text input control, but this one includes an up/down arrow control as shown in Figure 4-3. In addition, the value attribute provides a default value. The user can easily change the value by typing a new value or simply using the up/down arrow control.

A number input features an up/down arrow control
Figure 4-3. A number input features an up/down arrow control

The number input doesn’t prevent the user from typing an unwanted value. However, it does perform automatic validation. Depending on the browser, an incorrect entry receives some form of highlight. For example, in the case of Firefox, the border becomes heavier and the box appears in red, as shown in Figure 4-4. The point is that HTML5 additions reduce the work you need to do for honest users, but it’s possible for a determined hacker to overcome them.

HTML5 controls provide automatic validation
Figure 4-4. HTML5 controls provide automatic validation
Note

Some HTML5 controls are safer to use than others. For example, the range input type normally appears as a slider, so the user doesn’t actually enter a value. You should never depend on any of the controls providing absolute safety, however.

Choosing a User Interface Solution Level

When working with web-based applications, you have a choice of which level to use for implementing the user interface. In fact, most web-based applications rely on multiple levels of interface controls. Some part of the page appears using HTML tags, another part is a manipulation of the interface using Cascading Style Sheets (CSS), and a third part relies on JavaScript. It’s important to remember that you can use JavaScript both at the client and at the server, so really, there are four levels of solutions that you can exercise, as described in the following sections.

Implementing Standard HTML Controls

The section “Providing Controlled Choices” tells you about the ways to control user choices. Many of those options appear as HTML controls. The advantage of HTML controls is that they work automatically for the most part. A browser does have to support the level of HTML that the control requires, but that’s the only requirement.

Unlike most other control solutions, the browser doesn’t have to support scripting in many cases to obtain an effect. Of course, if you want to perform detailed work, then you need some level of scripting support. As an example, if you want to use special controls to ensure a user fills out a form properly, you can actually perform that task and submit the form to the server for processing without using scripts. On the other hand, if you want to perform a client-side task, such as client-side validation, then you’ll need scripting support in most cases (some HTML5 controls do provide rudimentary validation support).

There are a few disadvantages to using HTML controls. The most obvious is that HTML controls are rudimentary. If you want to add pizzazz to your site, then HTML controls will probably disappoint you. In addition, you can’t go beyond the bare-bones basics. It’s impossible to create a good tabbed interface (like the one shown in Figure 4-1) using just HTML controls.

Working with CSS Controls

The essential purpose of CSS is to format page content in such a manner that it doesn’t rely on a specific browser, device, or platform. In addition, the formatting doesn’t affect accessibility needs because the user can normally replace the fancy CSS formatting with simpler formatting that works better with accessibility devices. That said, it’s possible to use CSS for all sorts of other tasks through clever programming techniques. One of those tasks is creating controls of various sorts using a combination of HTML, CSS, and JavaScript, with an emphasis on CSS. In other words, you create the actual control using CSS, rather than relying on either HTML or JavaScript to perform the task.

It helps to have tools available when using CSS to create controls. One place to look for the required tools is Dynamic Drive. When you visit the site, you see it provides access to all sorts of tools, including the focus of this particular example, Button Maker. Figure 4-5 shows how Button Maker appears when you first access it. You use the settings on this page to generate the CSS needed to create a micro-button. However, you could just as easily create other sorts of controls using other tools.

The Button Maker tool helps you create micro-buttons
Figure 4-5. The Button Maker tool helps you create micro-buttons

The output of the process, for this example, is a bit of CSS and a Graphic Interchange Format (GIF) file named MyButton.gif. The example code (found in TestButton.html) is relatively simple, as shown here:

<!DOCTYPE html>

<html>
<head>
    <title>Testing a Micro Button</title>
    <style type="text/css">
        #MicroTest
        {
            border: none;
            background-color: transparent;
        }
    </style>
</head>

<body>
    <h1>Testing a Micro Button</h1>
    <button id="MicroTest"
            onclick="alert('Clicked!')">
        <img src="MyButton.GIF">
    </button>
</body>
</html>

Notice how the code uses HTML and JavaScript for support. The button itself is a GIF file. The CSS code performs the required formatting tasks. Of course, formatting would be more complex in a real application. The result of this experiment is a button like the one shown in Figure 4-6.

The micro-button is fully functional and nice to look at
Figure 4-6. The micro-button is fully functional and nice to look at

The main advantage of creating CSS controls is that everything is generated locally, so they tend to look nice, but the application also performs well. In addition, CSS lets you create applications with pizzazz, so they’re a lot more fun to use. The use of CSS can also provide visual hints to users, which means that you can use them to reduce mistakes—enhancing the security of your application.

CSS also presents some limitations when it comes to security. In order to obtain any level of validation, you must either employ HTML5 or JavaScript techniques. CSS doesn’t offer any sort of validation potential because it was never designed to perform this sort of support. Remember that the designers of CSS meant it to provide basic page formatting and nothing more. Only through clever programming do you get some of the interesting effects that CSS can provide.

Creating Controls Using JavaScript

When it comes to controls, JavaScript provides the options that most developers use to create complex applications. Yes, the developer also relies on HTML5 for placement support and CSS3 for formatting support, but the essential tasks of defining the interface rests with JavaScript. You have access to two levels of JavaScript support when creating an interface, and may implement both levels in a single application. The following sections describe both client-side and server-side controls.

Relying on client controls

This chapter contains a number of examples of using JavaScript in various ways to create client-side control setups. Normally, you won’t create the controls by hand, but will instead use a library setup such as jQuery and jQuery UI. When working with a client-side setup, the application loads the libraries from a local source or from a remote server, but once the libraries are loaded, everything happens locally. Later chapters in the book discuss the consequences of using in-process library support (see Chapter 6, Chapter 7, and Chapter 8 especially). The main benefit of client-side processing is that you gain a speed advantage and the application is more reliable in many cases because you have constant access to everything required to make the application run.

JavaScript offers the best opportunities for client-side control validation. You can configure the validation to work precisely as you want it to. The validation can also provide more functionality than other sorts of validation do. However, because a hacker can see your code, it’s possible that the hacker will come up with a strategy to thwart whatever you have in place.

A significant security issue with using client-side controls is that you are incorporating someone else’s code into your application. This means that you have a trust relationship between your application and code that you may never actually see. Yes, you can look at the content of libraries such as jQuery and jQuery UI, but few developers have the time to do so and certainly not the patience to review essentially undocumented code. Client-side controls have potential risks associated with them that you need to consider as part of your security strategy for the application.

Relying on server controls

Server-side controls often start with a PHP or other script on the server. In many cases, you can call the script directly, pass it the data it needs, and view just the script output in a browser. The processing all takes place on the server. Because the script is out-of-process, it’s easier to keep your application separated from the third-party code, making your application more secure. However, you have reliability and speed issues to contend with when using server-side controls.

The client-side portion of this arrangement usually relies on JavaScript. In fact, you may embed the output from the server-side control in a page and update this content as needed using something like Asynchronous JavaScript and XML (AJAX). When using this setup, it’s possible to speed the application by sending only the data to the server and only updating the portion of the page that the data affects.

Validating the Input

Of all the things you can do to ensure your application remains secure, the most important is to assume that all the input you receive is bad. When you assume that every input you receive contains a virus or some exploit that will cause damage to your system, you begin to view the input in a new way. Yes, it reeks of paranoia, but this viewpoint is essential to keeping your data secure. Validating data in a manner that reflects the corrupted input viewpoint is essential in today’s application environment. Even with this viewpoint, you may find that you aren’t paranoid enough (hackers are quite creative in finding new ways to make bad data look good) and need to hire someone to exercise even more paranoia on your behalf. The following sections give you some ideas on how you can protect your application and its associated data by validating absolutely every input in every way that you can think of.

Allowing Specific Input Only

The problem you read about most often when it comes to data validation is that the application didn’t control input well enough. When you think about it, that’s the underlying problem of many of the existing exploits. You should never allow a hacker to pass a script or other unwanted content through your application to the server. Of course, no one sets out to allow such content, but the content manages to get on the server anyway. The following list provides you with some ideas on the sorts of checks you should perform on any data passed from the application to the server (and then checked a second time on the server):

Type
Always verify that the data type is correct. Strings are the hardest data type to check because they can contain anything by definition. Use stricter data types whenever possible. For example, when you need numeric input, use a number data type, rather than a string, to pass it.
Range
Validate the range of any data type that supports it. Numbers are an obvious data type in this regard. However, you can check dates and times for range as well.
Regular expressions
Determine that the form of the data is correct. In some cases, it’s possible to check strings using regular expressions that match the input string pattern to an anticipated pattern. For example, when you want a telephone number as input, make sure you actually get a telephone number.
Special characters
Users don’t typically need to send any special characters to your application. A hacker employs special characters in a number of ways—none of them particularly helpful to your application. So, weeding out content that includes special characters is a must.

The best possible input from the user is the kind of input that you expect at the outset. For example, if you want the user to choose between red, yellow, and green, then the only acceptable answers are red, yellow, and green. Any other choice is invalid and you should reject it. The more specific you can make input, the easier it is to keep your application and its associated data secure.

Looking for Sneaky Inputs

Hackers constantly look for ways of providing unexpected input data. The point of doing so is to cause the application to crash in specific ways or to force the application to react in an unexpected manner. For example, sneaky input is the root cause of SQL injection attacks. The hacker makes use of inputs on a form to create a situation where the application ends up behaving in an unexpected manner. The result of such an attack can range from corrupted data to executing scripts that shouldn’t even appear as part of the data. You can find some additional information about this particular kind of attack at http://blogs.msdn.com/b/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx and https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet.

Warning

It may actually seem like a good idea at the time, but you should never allow the user to supply data used to create dynamic scripts. In fact, it’s a good idea not to use dynamic scripts at all unless you can be sure of the source of the data used to create the dynamic script.

Requesting New Input

One of the favorite exploits that hackers employ is looking for situations where an application performs strict checks on input data during the first pass, but then relaxes those checks during subsequent passes. The situation is quite easy to create because of the way that many languages deal with loops. Only a careful developer will avoid the situation during second and subsequent input retries. Every code input pass should rely on the same code to check and verify the input. Whether the user is inputting data for the first or third time, the checks should provide equal protection.

However, the issue takes on new meaning when you begin to question user motivations during data entry. For example, you need to consider just why a user would need 10 retries to get their name right on a form. You can probably assume that the user does know their name—that it’s not something they’ve suddenly forgotten. A constant need to resupply obvious data to the application may point to something other than a forgetful user. You need to question whether the form is clear enough. When you’re sure the form is clear and that you have the proper validation in place, you need to start looking at other sources for the issue, such as a hacker trying various methods to break your application. In short, most applications should allow a certain number of retries and then shut down pending an administrator’s attention.

Note

Never assume that users are fully trained. Some users require a lot of training time and never really get the complete idea of precisely what it is that they’re supposed to do. Unless you want to spend your days looking for hackers lurking in places where hackers never go, you need to consider user training as a primary security requirement. A large number of form retries may point to a need for more training time, rather than a potential hacker issue.

Using Both Client-Side and Server-Side Validation

Application speed is a primary concern when creating a web-based application. A user’s focus can wander in as little as one to five seconds—not a long time to perform much in the way of validation. However, it’s essential to perform validation and obtain the correct kind of input from the user. With this in mind, using client-side validation seems like the path to travel. A JavaScript routine can quickly check for errant input and tell the user about it before the data makes the round-trip to the server. The fact is that you really do want client-side validation. 

However, client-side validation causes its own set of problems. The data must leave the host system at some point and travel to the server. Between the time the browser sends the data and the server receives that data, a hacker has all sorts of opportunities to intercept the data and change it. In order to ensure that the data really is of the right type and content, you need to perform a second validation check at the server. If no one has tampered with the data, the second validation will go quite quickly and the user will have a response within a reasonable timeframe.

Some people would consider the use of both client-side and server-side validation checks overkill. However, you really do need both. In fact, sometimes you get both whether you want them or not. For example, when using certain HTML5 controls, you get automatic validation. It’s true that the validation isn’t always the most precise or complete, but it does provide a certain level of safety for the user. Always remember that client-side validation is for the user’s protection and you use it to keep the user happy. Anything you can do to reduce user frustration will also reduce application support costs and security concerns.

Server-side validation checks need to provide complete coverage of every input and output. It isn’t enough to check data when it comes from the client and then assume that no one will tamper with the server. Hackers are motivated to attack the server because the server makes it possible to affect a lot of people with a single intrusion. Consequently, you do need to provide validation checks for every input to every routine on the server to ensure that the application and its data remain secure.

The issue you fight most often with validation checks is application speed. It’s not just users that can experience problems when an application runs slow—server loading increases as well. Therefore, you must maintain a balance with validation checks. Security is often a matter of defining how much risk you’re willing to accept in the pursuit of specific goals. It’s important that management understand that you have to maintain a balance as part of the application design and development process.

Some developers also falsely assume that throwing additional hardware at a problem will solve it. Adding hardware reduces the reliability of the system as a whole. A reduction in reliability is also a security risk. If a hacker has five servers to attack instead of just one, the probability of finding a server that lacks the proper patches or is loaded just enough to crash becomes greater. Increasing the amount of hardware used to serve an application is part of the solution, but you must balance it with increases in application speed without leaving major security holes in  place.

Expecting the Unexpected

Users are amazing at times. They seem to find the one hole you didn’t think to patch. A boring day might turn into a session of seeing just what it takes to break an application. In fact, the user might not even set out to break the application; perhaps it’s all a matter of mindlessly doing things while talking on the phone. The point is that users will find problems with your application that you never expected to exist. These problems can lead to all sorts of issues in protecting the application and its associated data. Sometimes an issue can crash the application or perhaps even the server on which it’s running. You may marvel at what users come up with, but in the real world, bored users spell unexpected events.

Hackers will also perform the unexpected with your application. However, in this case, the unexpected is more thoughtful and methodical. A hacker will continue probing your defenses looking for a way in until another target comes into view, the hacker gets bored, or the hacker finds the way in. In most cases, the hacker will find a way in when truly determined to do so. It’s never a matter of if the hacker will gain access to your application, but the timing of when the hacker will succeed in the effort. The use of security measures slows hackers down and with proper monitoring, you can discover the hacker lurking about your system before it’s possible to do any real damage.

Many of the unexpected things that users and hackers do are associated with inputs. For example, you might expect a string as input but receive a script instead. Users can click unexpected key combinations that result in a corrupted string that causes the application or server to crash. Sometimes it’s simply a matter of assuming the user will do one thing, when quite another seems more appropriate. For example, a user might respond with a string when a number is required (or vice versa). Hackers, of course, are looking for all sorts of nefarious ways of providing input you didn’t expect and will purposely provide the input you didn’t expect.

Get Security for Web Developers now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.