1. Trang chủ
  2. » Công Nghệ Thông Tin

Applied Oracle Security: Developing Secure Database and Middleware Environments- P51 pdf

10 285 1
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 400,32 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The following examples demonstrate a SQL query and an insert statement as a developer would use them in APEX: -- This query is used in a report region select first_name,last_name from e

Trang 1

Kochhar - 17000

De Haan - 17000

Hunold - 9000

Ernst - 6000

Austin - 4800

Pataballa - 4800

Gietz - 8300

107 Rows Returned

Now we can see all 107 rows! How did this happen?

1 By including the single quote after Grant, the where predicate has the correct syntax.

2 Adding or 1 = 1 essentially negates the where predicate and returns every row since 1

will always equal 1

3 The at the end of the statement is the comment operator in Oracle SQL, which comments

out the trailing single quote that is in the original procedure Remember that we already closed the quote in step 1

The addition of this predicate completely changes the result set of the query Instead of simply passing different last names to the procedure, we are able to construct parameters that will modify the structure of the query

The more an attacker knows about a system, the more effectively he can plan an attack In the next example, we will pass a more sophisticated parameter to the same procedure to start investigating the data dictionary views

hr@aos> exec sql_injection(q'!ZZZ' union select null,null,

table_name last_name,null,null,null,null,null,null,null,null

from user_tables !');

COUNTRIES

DEPARTMENTS

EMPLOYEES

JOBS

JOB_HISTORY

LOCATIONS

REGIONS

-7 Rows Returned

Here’s the breakdown of this attack:

1 The first part of the parameter is ZZZ’ This simply returns no rows from the employees

table and closes the first quote This was intentional since we already have all of the rows

in the preceding example

2 Next, we union in our own query The syntax of a union operator is such that both queries

need to have the same number and type of columns, so an attacker would need to keep adding null columns until he received a result

3 Once again, we comment out the trailing single quote since we already closed it in step 1.

A variation on this attack might be to query the USER_TAB_COLUMNS table to find all the columns in the employees table We could then union in our own query of the employees table

Trang 2

to select columns that we were not intended to see, such as Social Security Number or Government Identification Number

Example 2: The Right Way

The fatal flaw with the procedure in the preceding example is that instead of using bind variables,

it glues a query together based on values passed in by the user, allowing an attacker to change the structure and the semantics of the query Bind variables prevent SQL injection by allowing the values of predicates to change at runtime, yet the structure of the query cannot change

The following example is a modified version of the preceding example implemented using bind variables:

create or replace procedure sql_injection_prevented(

p_last_name in varchar2)

is

type employee_record is table of employees%ROWTYPE;

emp_rec employee_record := employee_record();

x varchar2(32767);

begin

x := q'!select *

from employees

where last_name = :last_name !';

execute immediate x bulk collect into emp_rec using p_last_name;

for i in emp_rec.first emp_rec.last loop

dbms_output.put(emp_rec(i).last_name||' - ');

dbms_output.put_line(emp_rec(i).salary);

end loop;

dbms_output.put_line(emp_rec.count||' Rows Returned');

end sql_injection_prevented;

/

Take a close look at the query string defined in the variable X Because it uses a bind variable, :last_name, the query is first parsed without the actual value of p_last_name substituted for the bind variable last_name The SQL parser knows during the parse phase that this query has only one predicate and that the only acceptable value for last_name is a character string that represents a value It is impossible to add any structures such as an OR predicate that changes

structure of the query To prove this, let’s use a few of the tests from our previous example This procedure works as expected when we call it with a last name:

hr@aos> exec sql_injection_prevented(q'!Grant!');

Grant - 2600

Grant - 7000

2 Rows Returned

Now let’s try one of our SQL injection techniques:

hr@aos> exec sql_injection_prevented(q'!Grant' or 1 = 1 !');

BEGIN sql_injection_prevented(q'!Grant' or 1 = 1 !'); END;

*

Trang 3

ORA-06502: PL/SQL: numeric or value error

ORA-06512: at "HR.SQL_INJECTION_PREVENTED", line 1

ORA-06512: at line 1

This time we receive a “numeric or value error” since the string we passed in is not a valid string when searching for LAST_NAME

Now that you fully understand the concept of SQL injection, let’s talk about how it applies to APEX Bind variables are remarkably easy to use in APEX since you do not have to write extra code to bind the values of those variables You can simply reference the APEX items using bind variable syntax The following examples demonstrate a SQL query and an insert statement as a developer would use them in APEX:

This query is used in a report region

select first_name,last_name

from employees

where instr(upper(last_name),upper(nvl(:P1_SEARCH,last_name))) > 0

This insert statement is used in a page process

insert into employees (first_name,last_name)

values (:P2_FIRST_NAME,:P2_LAST_NAME)

returning employee_id into :P2_NEW_EMPLOYEE_ID;

Note that in both examples, bind variable syntax is used to reference items It is possible to

reference APEX items using &ITEM_NAME syntax, which treats them as a string, not a bind variable For example, in the first query, we could have used &P1_SEARCH instead of :P1_SEARCH In that

case, a nefarious user could inject carefully constructed code, through either the URL or the search box, which would modify the semantics of the query at runtime The documentation, tutorials, and examples used throughout the APEX community encourage bind variable syntax However, it is still possible for a developer who does not understand the difference to use the wrong syntax Fortunately, the wrong syntax is substantially more complex than the right syntax when you add in the

concatenation operators, so the secure way is actually the easy way

Cross-site Scripting

Cross-site scripting (XSS) is a type of web exploit that affects every web development technology

by attempting to execute client-side code, typically JavaScript, in a user’s browser that was not included by the original developers of the application For example, suppose a JavaScript function was executed on the Accounts page of your online banking application that searched for your account numbers on that page, and then posted those account numbers to some other web server controlled by a hacker Obviously, the developers of the banking application would never create such a function, but if someone else were able to “inject” this function into your browser session

or the page itself, the consequences could be catastrophic

Of the several different types of XSS attacks, the most obvious one in the context of APEX is called “persistent.” The persistent attack takes advantage of applications that have a database backend and that allow end users to save text that includes JavaScript, that will then be displayed

by another user (as shown in Figure 12-5) Let’s look at another example in an effort to clarify the vulnerability

Imagine a timecard system or reporting application written in APEX that allowed users to enter the number of hours they worked along with some comments about those hours and a display of their year-to-date earnings A newly submitted timecard would be routed to a person’s manager

Trang 4

for approval The manager could see all of her employees’ hours, comments, and salaries So far, the application works as intended Now imagine that in my comments for this week, I include JavaScript that sends all the data displayed on a page to a web server that I control When my manager views my timecard and my comments, she is unknowingly executing my JavaScript stored in the comments field, which sends the salary of everyone in my group to a server that I control If I knew that the business rules of the system were such that overtime of more than 20 hours goes up to our group vice president for approval, I could wait for a week when I had more than 20 hours of overtime to inject my code, thus gaining access to the salaries of everyone in the whole organization Who would have thought that a simple comments field could do so much damage?

Hopefully, you’re now asking yourself, What can I do to prevent this? Fortunately, APEX includes features to help developers mitigate the risk of XSS To summarize, the behavior we are trying to prevent is the ability for one user to submit JavaScript that will be displayed and therefore executed by other users The most common APEX objects that display data are regions

of type Report and APEX page items When a new Standard Report is created based on a SQL query

in APEX 3.2, the default column type for every column is called Standard Column Unfortunately, this type of column is vulnerable to XSS To prevent XSS, a developer must change this column type to Display as Text (escape special characters, does not save state) Future versions of APEX will likely change the default column type to the more secure version The new type of APEX reports, called Interactive Reports, use the secure column type by default

This same concept applies to APEX page items If a developer chooses an item of type Display

As Text, any JavaScript code that is stored in session state for that item will be executed when the page is displayed To prevent this, a developer should choose items of type Display As Text (escape special characters, does not save state), as shown in Figure 12-6 In the case of the Report Column type and the APEX page item type, the “escape special characters” aspect is key, because

it will send the HTML character codes for the less-than and greater-than signs—< and >,

respectively—to the browser, not the characters < and > The escaping of such markup-sensitive characters will cause the browser to render the actual characters, rather than interpret them as

HTML Using this technique will prevent data containing <script>…</script> from being

interpreted as executable JavaScript

One of the best ways for a developer to understand a security vulnerability is to intentionally create an example that is vulnerable, and then re-create the same example in a secure way To that end, the following is a simple two-page APEX application that demonstrates the insecure and secure report column types and page item types The following code, saved in a database table, simply writes a line of text onto a web page The message is written in Unicode character codes

so that it is unreadable unless the JavaScript function is executed:

<script type="text/JavaScript">

document.write(String.fromCharCode(88,83,83,32,86,117,108,110,101,114,97,98,108,101));

FIGURE 12-5 Persistent XSS

Trang 5

The report on the page has two comments columns that display the previous JavaScript function The first column, Comments - Secure, is set to the secure type of Display as Text (escape special characters, does not save state) The second column, Comments - Insecure, is set to the type Standard Column As you can see in Figure 12-7, the first column shows the JavaScript function

in its entirety, but does not execute it, while the second column is actually executing the JavaScript

as you can read the phrase “XSS Vulnerable” in the comments The developer of this application anticipated that users would enter only comments about an employee However, it was trivial to add a bit of JavaScript that is now executed by any other user who views the report

URL Tampering

In the earliest days of the internet web pages were primarily, a static, read-only medium used to share information The most interaction a user had with a web application was clicking a link Today, modern web applications have evolved to the point that there is an almost continuous two-way stream of information between a user’s web browser and the application server I’d like to emphasize “almost continuous” because it’s important to understand the true nature of the HTTP Protocol as it relates to modern web applications HTTP is a stateless protocol as a persistent connection is not maintained between the client web browser and the HTTP server In contrast, traditional client-server applications maintain a persistent connection between the client and the server The actions of the HTTP protocol are often defined in terms of request, response I like to add a third term and describe it as request, response, disconnect The emphasis on “disconnect” helps developers understand the true nature of the technology they are working with Consider the impact of removing the network connection would have on a web application compared to

a client-server application The stateful client-server application would know immediately if the

FIGURE 12-6 Report column types

Trang 6

connection were severed whereas the web application would have no knowledge of this action Obviously, the end user in the web scenario would know when they clicked a link or posted a form and received no response, but the HTTP Server would have no knowledge of this

Now that we have a better understanding of the stateless nature of a web application, let’s talk about how APEX maintains session state When a user requests a page from an APEX application, the APEX engine checks to see if this is the first request from this user in this browser session If it

is the first request, APEX assigns a new, unique number for this session For brevity, we’ll refer to this unique user session identifier as the Session ID When you are using an APEX application, including the APEX Development Environment, notice the third parameter in the colon delimited list in the URL is a long seemingly random number This number is also stored in a hidden form field on every page called pInstance APEX also passes variables, such as search criteria, as parameters in the URL when the operation is an HTTP GET One of the most convenient aspects

of APEX for developers is that this session state is automatically managed for them in database tables Once a value is set for an APEX Page or Application Item, the value of this item is maintained for the duration of the user’s session One simple, yet security-friendly benefit to this is realized when passing data between pages If you as a developer set the value of an item on page 1, you can refer to it on any other page in the application without the need to constantly pass it through the URL

FIGURE 12-7 XSS example report output

Trang 7

A classic example of passing session state through the URL is the “Report and Form on a Table” generated by a wizard within APEX The wizard builds a report page that shows the rows

in a database table with an edit link next to each row When users click on the edit link they are taken to the form page where they can edit the data in that row, as shown in Figure 12-8 The primary key of the table is passed as a parameter in the URL The query on the form page uses that primary key as a query predicate to select the desired row

In our example, what would happen if a user simply changed the value of the primary key

in the URL (aka URL tampering)? If the user chose a value that matched another row in the table, that row would appear in the form This raises an obvious security concern as end users are able

to change the value used in the query predicate at will Imagine now that the developer in this example wanted to limit the rows a user could edit by simply limiting the rows shown on the report page If there is no row to click, how can a user edit that row? This false assumption by

a developer could easily allow a user to gain access to data he or she is not supposed to see

The first instinct of many developers is to make the request an HTTP POST instead of a GET,

as the value is not passed through the URL The reality is that this technique is simply “security through obscurity.” Many web developer tools are available that allow an end user to view and

manipulate post data or simply turn the POST into a GET To address these concerns, APEX offers

several new features that let developers easily protect their applications against such threats

Restricted Items

In many scenarios, certain application- or page-level items should never be set by an end user Suppose, for example, that the end user’s role, such as Administrator or Guest, is stored in an application-level item If an end user can change the value of this item, she could gain access

FIGURE 12-8 Primary Key Passed Through the URL

Trang 8

to pages or data to which she is not entitled Each application or page item now has an attribute called Session State Protection Setting this attribute to Restricted - May Not Be Set From Browser will prevent end users from tampering with the value of the attribute The only way to change a Restricted item’s value is through constructs inside the application, such as computations or processes at the application or page level This technique enables the developer to store values

in items with the confidence that an end user cannot change their values

Checksum

Completely blocking the ability to set an item from a URL is the most secure option and works well for application-level roles or attributes that are typically static for the session However, in many scenarios, this technique simply won’t work, such as the “Report and Form on a Table” discussed earlier in this section

When a user clicks a row, we must have a way of determining which row was clicked to edit the proper row on the form page The most common technique for this in APEX, as well as many other popular technologies, is to pass the value in the URL Unfortunately, this gives the end user the opportunity to change the value In response to this potential security threat, the concept of a URL checksum was built into APEX When this feature is enabled, APEX uses a cryptographically strong Message Authentication Code or “MAC” to generate a checksum based on the parameters and their values in the URL APEX then appends this checksum to the URL This process occurs when APEX generates links to pages that require a checksum When a link is clicked that sets the value of one or more items, APEX runs the items and values through the same function Any change of a value in the URL will result in a different checksum when the request is received, thus allowing APEX to detect URL tampering

A great example of this is the Report and Form on a Table Once we require a checksum for the ID item on the form page, APEX automatically generates the checksum for each link on the report page Clicking a link works exactly as it did before, except you will now see a checksum appended to the URL If you try to change the value of ID in the URL, APEX will simply return an error If this checksum were a simple hash based on a well-known algorithm, it would be easy to spoof However, since the algorithm also takes in a key or “salt” that is known only internally to the APEX engine, a nefarious user would need to determine the algorithm or algorithms used as well as the key

Suggested Session State Protection Scenario

Session State Protection is extensively documented in the APEX Application Builder Users Guide Many permutations of settings are possible for Session State Protection Instead of dedicating a large portion of this chapter to all possible scenarios, I’ll provide some guidelines that cover the most common ones, which fall into two categories: items that should never be changed by a user, such as an application item storing the user’s role, and items that must be set through the URL; however, allowing the user to change item values is a security risk

Items That Should Never Change To ensure that the value of an item is never set by an end

user using URL parameters, set the item-level Session State Protection attribute to Restricted - May Not Be Set From Browser This is applicable to application- and page-level items

Sensitive Items Set Through the URL The scenario described earlier using the Report and

Form example is a perfect candidate for URL checksums To enable this feature, navigate to the Application Level Attributes | Security | Session State Protection Section, and click Page Select the target page of a URL that requires a checksum, in this case the form page Change the Page Access Protection attribute to Arguments Must Have Checksum You must also set the session

Trang 9

state protection level for key items on the page, typically items that store the primary key of the row Checksum Required - Session Level is the most secure setting Application and User Level Checksums are used when sharing URLs or bookmarking is desirable It is not necessary to require checksums for items that are not passed through the URL, as the values of those items will

be overwritten by the process that returns the row into the page items Figure 12-9 shows an APEX URL in which Session State Protection is enabled The cs= parameter appended to the URL is the checksum

Password Items Items of type Password have always obscured the value from appearing on

the screen so that someone watching over a user’s shoulder cannot read the password However, password values are stored in the APEX session state table, which is accessible to anyone with a privileged database account Any login page generated by APEX clears this session state as soon

as the user logs in, but that value could persist in online redo log files or archive log files It is also easy for a developer inadvertently to alter the process that clears session state for the login, leaving the password in the session state table

To address these situations, two new item types were introduced in APEX 3.2: Password (does not save state) and Password (submits when ENTER pressed, does not save state) Both item types insure that a user’s password is never written to a persistent store Developers who upgrade applications or instances from previous versions of APEX to APEX 3.2 should verify that all password fields use these new item types

Encrypted Session State

In addition to protecting passwords, a developer may want to protect other sensitive data from system administrators or anyone else who has a privileged account or access to the online redo or archive log files Even if the data is stored in a table using programmatic or transparent encryption, any data element used in an APEX item is stored in the application session state table in clear text Starting with APEX 3.2, developers can set an item-level attribute to store session state encrypted

To illustrate this point, the following example in Figure 12-10 sets the Store Value Encrypted In Session State attribute of the P11_SALARY item to Yes and leaves it set to No for the P11_EMAIL item After submitting the page to make sure their values were stored in session state, I queried the WWV_FLOW_DATA table used to store APEX session state:

APEX_030200@AOS> select item_name,item_value

from wwv_flow_data

where flow_instance = 3574272250559947

and flow_id = 107

and item_name in ('P11_EMAIL','P11_SALARY');

ITEM_NAME ITEM_VALUE

-

-P11_EMAIL JWHALEN

P11_SALARY 948F90BDC554FBB74305B2AFA6E44102

FIGURE 12-9 Checksum added to URL

Trang 10

As you can see, P11_EMAIL is in clear text, while the value of P11_SALARY that was a four-digit number on screen is now stored in the session state table as an encrypted value This value can be decrypted only internally by APEX and is thus protected from scenarios such as this It’s very important to note that this setting affects how the data is stored only in APEX session state—it has nothing to do with how the value is stored in application tables In this example, the value of the EMPLOYEES.SALARY column is not encrypted, only the value stored in the APEX item P11_ SALARY So enabling encryption on this item does not encrypt data in the EMPLOYEES table It is the developer’s responsibility to make sure that the application tables used to store sensitive data

do so using technologies such as DBMS_CRYPTO or Transparent Data Encryption at the column

or tablespace level

Leveraging Database Security Features

One key benefit to the APEX architecture is that every database feature is available to APEX developers In this section, we will explore the integration of VPD to implement row-level security We’ll then leverage fine-grained auditing (FGA) to provide silent alarm for our most sensitive data Both scenarios take advantage of the context information that APEX provides to better determine who the user is and where they are in a given application

FIGURE 12-10 Store Value Encrypted In Session State attribute

Ngày đăng: 06/07/2014, 23:20

TỪ KHÓA LIÊN QUAN