Tải bản đầy đủ - 0 (trang)
10  Track Element Attributes Dynamically

10  Track Element Attributes Dynamically

Tải bản đầy đủ - 0trang

Figure 3-16. Appending a child node triggers this alert

Next, create a function displaying the element attributes you’d like to detect:

function display_attribute() {

alert("New Element! \n ID:" + test_element.lastChild.id +

"\n HTML:" + test_element.lastChild.innerHTML); }

Add an event listener for any event which could change this attribute:


Initiate the event (via the application logic or manually):

new_element = document.getElementById('some_other_element')


Running these steps on a page at oreilly.com, we get the results in Figure 3-16.


This recipe is only really helpful when you have a JavaScript-driven application and

requires a good bit of JavaScript familiarity. It may not be appropriate for your application. However, for many AJAX-enabled websites, the outcome of JavaScript events

is determined by the server, not the client. This method remains one of the primary

tools for testing such event-driven sites. And if it can help debug your AJAX code, it

can help debug your AJAX-based attacks too.

This is a rather flexible method. There are many options for both the type of event and

test output. For instance, when running many such event listeners, you may prefer to

create a debug output area and instead append text to that node. For instance:

function debug_attribute() { debug_node.innerHTML += "

New Element ID: " + test_element.lastChild.id }

In a very complex application, you may have many actions tied to any number of nodes.

JavaScript supports an unlimited number of event listeners per node. There are also

many, many types of events. All the Firefox events can be found at http://www.xulplanet


If programming your own event listeners is overkill for your web application, Firebug

also includes a very good JavaScript debugger that can watch and log specific function

calls as well as set break points.

52 | Chapter 3: Basic Observation

Keep an eye out for dynamic JavaScript functions that initiate other AJAX requests or

run evaluated (via the eval() function) code. If your web application evaluates what it

receives from the server, it may be particularly vulnerable to JavaScript injection attacks.

This is even true if it’s just loading data, such as JavaScript Object Notation (JSON)

data, which is evaluated by the client.

3.11 Conclusion

Web applications deliver much more information, more output, than just the user

interface. Not only are many layers necessary for deploying a web application, but more

of these layers are under the direct control of the application’s developers. In security

terminology this is known as a large attack surface. Much of an application’s complexity, security functionality, and business logic are directly exposed to the entire

world. Modern additions such as AJAX, Flash, and mash-ups only increase this attack

surface. Protecting a greater area requires spreading your efforts and facing a higher

risk that at least one weakness will surface.

Verifying the correct behavior among all these layers requires efforts beyond the scope

of traditional testing, but still fits well within the capabilities of a software tester. These

extra efforts are necessary, as security vulnerabilities can be hidden from normal

interaction but plainly visible with the right tips and tools.

Correct testing requires not just observing application behavior, but carefully crafting

input as well. In later chapters, we’ll discuss techniques for crafting malicious test cases.

Yet for all of these later tests, the verification step will depend primarily on these few

basic observation methods. The pattern will almost always be as follows: observe normal output, submit malicious input, and check the output again to determine what

made it past your application’s defenses. Correct, detailed observation is crucial to both

the first and last steps.

3.11 Conclusion | 53


Web-Oriented Data Encoding

In the field of observation, chance favors only the

prepared mind.

—Louis Pasteur

Even though web applications have all sorts of different purposes, requirements, and

expected behaviors, there are some basic technologies and building blocks that show

up time and again. If we learn about those building blocks and master them, then we

will have versatile tools that can apply to a variety of web applications, regardless of

the application’s specific purpose or the technologies that implement it.

One of these fundamental building blocks is data encoding. Web applications ship data

back and forth from the browser to the server in myriad ways. Depending on the type

of data, the requirements of the system, and the programmer’s particular preferences,

that data might be encoded or packaged in any number of different formats. To make

useful test cases, we often have to decode the data, manipulate it, and reencode it. In

particularly complicated situations, you may have to recompute a valid integrity check

value, like a checksum or hash. The vast majority of our tests in the web world involve

manipulating the parameters that pass back and forth between a server and a browser,

but we have to understand how they are packed and shipped before we can manipulate


In this chapter, we’ll talk about recognizing, decoding, and encoding several different

formats: Base 64, Base 36, Unix time, URL encoding, HTML encoding, and others.

This is not so much meant to be a reference for these formats (there are plenty of good

references). Instead, we will help you know it when you see it and manipulate the basic

formats. Then you will be able to design test data carefully, knowing that the application

will interpret your input in the way you expect.

The kinds of parameters we’re looking at appear in lots of independent places in our

interaction with a web application. They might be hidden form field values, GET parameters in the URL, or values in the cookie. They might be small, like a 6-character

discount code, or they might be large, like hundreds of characters with an internal

composite structure. As a tester, you want to do boundary case testing and negative


testing that addresses interesting cases, but you cannot figure out what is interesting if

you don’t understand the format and use of the data. It is difficult to methodically

generate boundary values and test data if you do not understand how the input is

structured. For example, if you see dGVzdHVzZXI6dGVzdHB3MTIz in an HTTP header, you

might be tempted to just change characters at random. Decoding this with a Base-64

decoder, however, reveals the string testuser:testpw123. Now you have a much better

idea of the data, and you know how to modify it in ways that are relevant to its usage.

You can make test cases that are valid and carefully targeted at the application’s


4.1 Recognizing Binary Data Representations


You have decoded some data in a parameter, input field, or data file and you want to

create appropriate test cases for it. You have to determine what kind of data it is so that

you can design good test cases that manipulate it in interesting ways.

We will consider these kinds of data:

• Hexadecimal (Base 16)

• Octal (Base 8)

• Base 36


Hexadecimal data

Hexadecimal characters, or Base-16 digits, are the numerical digits 0–9 and the letters

A–F. You might see them in all uppercase or all lowercase, but you will rarely see the

letters in mixed case. If you have any letters beyond F in the alphabet, you’re not dealing

with Base 16.

Although this is fundamental computer science material here, it bears repeating in the

context of testing. Each individual byte of data is represented by two characters in the

output. A few things to note that will be important: 00 is 0 is NULL, etc. That’s one of

our favorite boundary values for testing. Likewise, FF is 255, or −1, depending on

whether it’s an unsigned or signed value. It’s our other favorite boundary value. Other

interesting values include 20, which is the ASCII space character, and 41, which is ASCII

for uppercase A. There are no common, printable ASCII characters above 7F. In most

programming languages, hexadecimal values can be distinguished by the letters 0x in

front of them. If you see 0x24, your first instinct should be to treat it as a hexadecimal

number. Another common way of representing hexadecimal values is with colons between individual bytes. Network MAC addresses, SNMP MIB values, X.509 certificates, and other protocols and data structures that use ASN.1 encoding frequently do

56 | Chapter 4: Web-Oriented Data Encoding

this. For example, a MAC address might be represented: 00:16:00:89:0a:cf. Note that

some programmers will omit unnecessary leading zeros. So the above MAC address

could be represented: 0:16:0:89:a:cf. Don’t let the fact that some of the data are single

digits persuade you that it isn’t a series of hexadecimal bytes.

Octal data

Octal encoding—Base 8—is somewhat rare, but it comes up from time to time. Unlike

some of the other Bases (16, 64, 36), this one uses fewer than all 10 digits and uses no

letters at all. The digits 0 to 7 are all that are used. In programming, octal numbers are

frequently represented by a leading zero, e.g., 017 is the same as 15 decimal or 0F

hexadecimal. Don’t assume octal, however, if you see leading zeroes. Octal is too rare

to assume just on that evidence alone. Leading zeroes typically indicate a fixed field

size and little else. The key distinguishing feature of octal data is that the digits are all

numeric with none greater than 7. Of course, 00000001 fits that description but is probably not octal. In fact, this decoding could be anything, and it doesn’t matter. 1 is 1 is

1 in any of these encodings!

Base 36

Base 36 is rather an unusual hybrid between Base 16 and Base 64. Like Base 16, it begins

at 0 and carries on into the alphabet after reaching 9. It does not stop at F, however. It

includes all 26 letters up to Z. Unlike Base 64, however, it does not distinguish between

uppercase and lowercase letters and it does not include any punctuation. So, if you see

a mixture of letters and numbers, and all the letters are the same case (either all upper

or all lower), and there are letters in the alphabet beyond F, you’re probably looking

at a Base-36 number.


Finding encoders and decoders for Base 16 and Base 8 are easy. Even the basic calculator

on Windows can do them. Finding an encoder/decoder for Base 36, however, is somewhat rarer.

What Do You Really Need to Know About Base 36?

The most important thing to know about Base 36, like all other counting systems, is

that it’s just a number, even though it looks like data. If you want to look for problems

with predictable and sequential identifiers (e.g., like we discuss in Recipe 9.4), remember that the next thing after 9X67DFR is 9X67DFS and the one before it is 9X67DFQ.

We have found online shopping carts where manipulating a Base-36 parameter in the

URL ultimately led to a 90% discount!

4.1 Recognizing Binary Data Representations | 57

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

10  Track Element Attributes Dynamically

Tải bản đầy đủ ngay(0 tr)