차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.


이전 판
guide:asp.net_개발_보안_가이드 [2024/04/04 05:12] (현재) – 바깥 편집 127.0.0.1
줄 1: 줄 1:
 +====== ASP.NET 개발 보안가이드 ======
  
 +===== SQL Injection 취약점 =====
 +
 +==== 취약점 상세 내용 및 보안 대책 ====
 +웹 사이트는 DBMS와 연동하므로 웹 어플리케이션에서 사용자의 입력값을 통하여 데이타 트랜잭션이 발생함. 만일 사용자 입력값에 대한 유효성 검증이 누락될 경우, 악의적인 사용자는 정상적인 입력값 대신 SQL 쿼리문이 포함된 조작된 입력값을 전송하여 서버측 쿼리문의 구조를 변경할 수 있으며, 이를 통해서 사용자 인증을 우회하거나 데이터베이스의 정보를 유출시키고 서버의 시스템 명령어를 실행시킬 수도 있음.
 +
 +==== 보안 대책 ====
 +
 +=== 입력제한 ===
 +유형, 길이, 형식 및 범위 ASP.NET 응용 프로그램에 대한 모든 입력을 확인. 데이터 액세스 쿼리에 사용되는 입력을 제한함으로써, SQL 인젝션에서 응용 프로그램을 보호 할 수 있음.
 +  * 참조 : 입력을 제한하면 허용 문자의 목록을 작성하고, 목록에 없는 모든 문자를 거부하는 ​​정규식을 사용.
 +
 +가. ASP.NET 웹 페이지 입력 제한
 +ASP.NET 웹 페이지에 대한 서버 측 코드를 입력을 제한함.
 +
 +예) SSN 값을 ASP.NET에 의해 캡처하여 텍스트 상자의 입력을 제한
 +  <%@ language="C#" %>
 +  <form id="form1" runat="server">
 +      <asp:TextBox ID="SSN" runat="server"/>
 +      <asp:RegularExpressionValidator ID="regexpSSN" runat="server"         
 +                                      ErrorMessage="Incorrect SSN Number" 
 +                                      ControlToValidate="SSN"         
 +                                      ValidationExpression="^\d{3}-\d{2}-\d{4}$" />
 +  </form>
 +예) SSN 입력이 같은 HTML 컨트롤과 같은 다른 소스, 쿼리 문자열 매개 변수 또는 쿠키의 경우에는 사용을 제한
 +  if (Regex.IsMatch(Request.Cookies["SSN"], "^\d{3}-\d{2}-\d{4}$"))
 +  {
 +      // access the database
 +  }
 +  else
 +  {
 +      // handle the bad input
 +  }
 +나. 데이터 액세스 코드 입력 제한\\ 데이터 접근 코드의 유효성 검사를 제공
 +  * 신뢰할 수없는 클라이언트\\ 신뢰할 수없는 소스에서 데이터가 올 수있다 또는 데이터의 유효성을 검사하고 제한될 수 있으므로, 데이터 액세스 루틴에 대한 입력을 제한 유효성 검사 논리를 추가.
 +  * 라이브러리 코드\\ 데이터 액세스 코드가 여러 응용 프로그램에서 사용하도록 설계된 라이브러리로 패키지화되어 있으면 클라이언트 응용 프로그램에 대한 더 안전한 가정을 만들 수 있기 때문에, 데이터 액세스 코드가 자신의 유효성 검사를 수행.
 +예) 데이터 액세스 루틴 전에 SQL 문에서 매개 변수를 사용하여 정규 표현식을 사용하여 입력 매개 변수의 유효성을 검사하는 방법
 +  using System;
 +  using System.Text.RegularExpressions;
 +  
 +  public void CreateNewUserAccount(string name, string password)
 +  {
 +      // Check name contains only lower case or upper case letters, 
 +      // the apostrophe, a dot, or white space. Also check it is 
 +      // between 1 and 40 characters long
 +      if ( !Regex.IsMatch(userIDTxt.Text, @"^[a-zA-Z'./s]{1,40}$"))
 +        throw new FormatException("Invalid name format");
 +  
 +      // Check password contains at least one digit, one lower case 
 +      // letter, one uppercase letter, and is between 8 and 10 
 +      // characters long
 +      if ( !Regex.IsMatch(passwordTxt.Text, 
 +                        @"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$" ))
 +        throw new FormatException("Invalid password format");
 +  
 +      // Perform data access logic (using type safe parameters)
 +      ...
 +  }
 +  
 +=== 저장 프로 시저의 매개 변수 사용 ===
 +저장 프로 시저를 사용하면 반드시 SQL 인젝션을 방지하지 않음. 중요한 점은 저장 프로 시저 매개 변수를 사용. 이 매개 변수를 사용하지 않는 경우가 필터링되지 않은 입력을 사용하는 경우이며, 저장 프로 시저가 SQL 인젝션에 취약함.
 +
 +예) 저장 프로 시저를 호출
 +  using System.Data;
 +  using System.Data.SqlClient;
 +  
 +  using (SqlConnection connection = new SqlConnection(connectionString))
 +  {
 +    DataSet userDataset = new DataSet();
 +    SqlDataAdapter myCommand = new SqlDataAdapter( 
 +               "LoginStoredProcedure", connection);
 +    myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
 +    myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
 +    myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
 +  
 +    myCommand.Fill(userDataset);
 +  }
 +
 +가. 매개 변수가있는 저장 프로 시저 응용 프로그램의 사용 검토
 +매개 변수가있는 저장 프로 시저를 사용하여도 반드시 SQL 인젝션을 방지하지 않기 때문에, 저장 프로 시저의 응용 프로그램의 사용을 검토함.
 +
 +예) 저장 프로 시저를 사용하는 응용 프로그램
 +  CREATE PROCEDURE dbo.RunQuery
 +  @var ntext
 +  AS
 +          exec sp_executesql @var
 +  GO
 +  
 +=== 동적 SQL의 매개 변수 사용 ===
 +저장 프로 시저를 사용할 수 없는 경우 동적 SQL 문을 생성 할 때, 매개 변수를 사용
 +
 +예) 동적 SQL 매개 변수 사용
 +  using System.Data;
 +  using System.Data.SqlClient;
 +  
 +  using (SqlConnection connection = new SqlConnection(connectionString))
 +  {
 +    DataSet userDataset = new DataSet();
 +    SqlDataAdapter myDataAdapter = new SqlDataAdapter(
 +           "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", 
 +           connection);                
 +    myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
 +    myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
 +    myDataAdapter.Fill(userDataset);
 +  }
 +  
 +가. 일괄 처리 매개 변수 사용
 +SQL 텍스트 연결시 고유 한 매개 변수 이름을 사용하는 것을 확인하여 작업을 수행함.
 +
 +예) 일괄 처리 매개 변수 사용
 +  using System.Data;
 +  using System.Data.SqlClient;
 +  . . .
 +  using (SqlConnection connection = new SqlConnection(connectionString))
 +  {
 +    SqlDataAdapter dataAdapter = new SqlDataAdapter(
 +         "SELECT CustomerID INTO #Temp1 FROM Customers " +
 +         "WHERE CustomerID > @custIDParm; SELECT CompanyName FROM Customers " +
 +         "WHERE Country = @countryParm and CustomerID IN " +
 +         "(SELECT CustomerID FROM #Temp1);",
 +         connection);
 +    SqlParameter custIDParm = dataAdapter.SelectCommand.Parameters.Add(
 +                                            "@custIDParm", SqlDbType.NChar, 5);
 +    custIDParm.Value = customerID.Text;
 +  
 +    SqlParameter countryParm = dataAdapter.SelectCommand.Parameters.Add(
 +                                        "@countryParm", SqlDbType.NVarChar, 15);
 +    countryParm.Value = country.Text;
 +  
 +    connection.Open();
 +    DataSet dataSet = new DataSet();
 +    dataAdapter.Fill(dataSet);
 +  }
 +  . . .
 +
 +===== XSS(Cross-Site Scripting) 취약점 =====
 +
 +==== 취약점 상세 내용 및 보안 대책 ====
 +Javascript, Vbscript 등 PC의 웹브라우저에서 실행되는 클라이언트 사이트 스크립트를 다른 사용자의 웹브라우저에서 실행하도록 함으로서 웹 브라우저를 제어하여 PC를 공격하는 취약점을 말함. 공격에 사용되는 유형은 크게 두가지로 분류.
 +\\
 +(1)  Reflected XSS
 +\\
 +이 유형의 XSS는 클라이언트 측에서 전송된 데이터가 서버측에서 즉시 처리된 후 사용자에게 응답으로 전송되는 돌아오는 경우에 해당함. 다음과 같은 상황에서 발생이 가능함.
 +\\
 +  * 검색 페이지에서 입력된 검색어가 검색 결과 페이지에 표시되는 경우
 +  * URL에 포함된 특정 파라미터가 응답 페이지에 hidden 속성으로 포함되어 있는 경우
 +위의 두가지 유형은 본질적으로는 동일한 내용임. 
 +이러한 유형의 XSS 는 사회 공학적 방법 등을 통해서 공격 스크립트가 포함된 URL을 타인이 실행하도록 유도함으로서 (예를 들면 메신저로 링크를 전송하거나, 게시판에 URL을 링크로 걸어놓고 클릭을 유도하는 방식 등) 공격에 이용될 수 있음. 다만, 공격자가 강제적으로 타 사용자의 PC에서 공격 스크립트가 실행되도록 할 수는 없으므로 일반적으로 심각한 취약점으로 분류되지는 않음.
 +그러나 공공기관이나 금융권과 같이 신뢰도가 중요한 대상인 경우에는 이 유형의 XSS도 모두 제거해야 하며, 그 외에도 대외에 공개된 웹사이트라면 일반적으로 제거하도록 하는 것이 좋음.
 +\\
 +
 +(2) Stored XSS
 +\\
 +게시판과 같이 사용자가 입력한 정보가 서버측 DB에 저장되어 있다가 타 사용자가 해당 정보를 열람할 때 DB에 저장되어 있는 정보를 가져와 화면에 출력하는 방식의 웹 애플리케이션에서 발생하는 취약점으로서, XSS의 가장 핵심적인 취약점이라고 할 수 있다. 불특정 다수를 대상으로 열람자의 웹브라우저에서 공격 스크립트를 실행할 수 있기 때문에 심각한 위협이 발생함.
 +공격자가 XSS를 목적으로 악성 스크립트를 삽입하여 둘 수 있는 위치는 비단 게시판의 글 본문 뿐만 아니라 제목, 작성자 이름, 날짜, 첨부파일 이름 등이 모두 가능하며, 또한 게시판 외에도 사용자 프로필의 닉네임, 주소, 전화번호, 등 사용자가 입력이 가능한 모든 데이터에 스크립트가 삽입될 수 있음.
 +  * 게시판 : 제목, 본문, 작성자, 날짜, 첨부파일 이름, 태그, 분류 등
 +  * 사용자 프로필 : 이름, 닉네임, 주소, 전화번호, 이메일, 직업, 기타 입력정보
 +  * 기타 사용자가 입력 가능한 모든 데이터
 +
 +==== 보안 대책 ====
 +
 +=== ASP.NET 요청 유효성 검사가 활성화되어 있는지 확인 ===
 +기본적으로 요청 유효성 검사는 Machine.config 파일에서 사용할 수 있음. 그 유효성 검사가 현재 서버의 Machine.config 파일에서 활성화되고 응용 프로그램의 Web.config 파일에서 설정을 무시하지 않는지 확인함.
 +
 +가. ASP.NET 유효성 검사가 활성화되어 있는지 확인하는 테스트 절차
 +
 +1. 유효성 검사를 비활성화 하여 ASP.NET 페이지를 만들 수 있음. 이렇게 하려면 설정 ValidateRequest를 = "false"를 다음 코드 예제와 같이 설정.
 +
 +  <%@ Page Language="C#" ValidateRequest="false" %>
 +  <html>
 +   <script runat="server">
 +    void btnSubmit_Click(Object sender, EventArgs e)
 +    {
 +      // If ValidateRequest is false, then 'hello' is displayed
 +      // If ValidateRequest is true, then ASP.NET returns an exception
 +      Response.Write(txtString.Text);
 +    }
 +   </script>
 +   <body>
 +    <form id="form1" runat="server">
 +      <asp:TextBox id="txtString" runat="server" 
 +                   Text="<script>alert('hello');</script>" />
 +      <asp:Button id="btnSubmit" runat="server"   
 +                  OnClick="btnSubmit_Click" 
 +                  Text="Submit" />
 +    </form>
 +   </body>
 +  </html>
 +
 +2. 페이지를 실행함. 그럴 경우 스크립트 때문에 메시지 상자에 txtString를 지나 브라우저에서 클라이언트 측 스크립트로 렌더링됨.
 +\\
 +3. 설정값이 ValidateRequest = "true" 또는 제거 ValidateRequest의 페이지 속성을 다시 페이지로 이동함. 다음과 같은 오류 메시지가 표시되어 있는지 확인함.
 +
 +  A potentially dangerous Request.Form value was detected from the client (txtString="<script>alert('hello...").
 +  
 +=== HTML 출력을 생성 검토 ASP.NET 코드 ===
 +예) HTML 출력을 생성 검토 ASP.NET 코드 예제
 +  Response.Write
 +  <% =
 +===  HTML 출력은 입력 매개 변수를 포함 여부 확인 ===
 +출력은 입력 매개 변수가 포함되어 있는지 여부를 확인하고 디자인 및 당신의 페이지 코드를 분석함. 이러한 매개 변수는 다양한 소스로부터 올 수 있음.
 +\\
 +
 +예)일반적인 입력 소스
 +
 +  * Form 필드
 +
 +  Response.Write(name.Text);
 +  Response.Write(Request.Form["name"]);
 +  Query Strings
 +  Response.Write(Request.QueryString["name"]);
 +
 +  * 쿼리문자열
 +
 +  Response.Write(Request.QueryString["username"]);
 +
 +  * 데이터베이스 및 데이터 액세스 방법
 +
 +  SqlDataReader reader = cmd.ExecuteReader();
 +  Response.Write(reader.GetString(1));
 +
 +  * 쿠키 컬렉션
 +
 +  Response.Write(
 +  Request.Cookies["name"].Values["name"]);
 +
 +  * 세션 및 응용 프로그램 변수
 +
 +  Response.Write(Session["name"]);
 +  Response.Write(Application["name"]);
 +
 +=== 잠재적으로 위험한 HTML 태그와 속성 검토 ===
 +동적으로 HTML 태그를 생성하고 잠재적으로 안전하지 않은 입력으로 태그 속성을 구성하는 경우, 악의적인 사용자가 사용하기 전에 태그 속성을 HTML로 인코딩해야함.
 +예) aspx 페이지에서는 <사용하여 리턴 페이지에 HTML을 직접 작성하는 방법
 +  <%@ Page Language="C#" AutoEventWireup="true"%>
 +  
 +  <html>
 +    <form id="form1" runat="server">
 +      <div>
 +        Color:&nbsp;<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
 +        <asp:Button ID="Button1" runat="server" Text="Show color" 
 +           OnClick="Button1_Click" /><br />
 +        <asp:Literal ID="Literal1" runat="server"></asp:Literal>
 +      </div>
 +    </form>
 +  </html>
 +  
 +  <script runat="server">
 +    private void Page_Load(Object Src, EventArgs e)
 +    {
 +      protected void Button1_Click(object sender, EventArgs e)
 +      {
 +        Literal1.Text = @"<span style=""color:" 
 +          + Server.HtmlEncode(TextBox1.Text)
 +          + @""">Color example</span>";
 +      }           
 +    }
 +  </Script>
 +
 +가. 잠재적으로 위험한 HTML 태그
 +\\
 +
 +예)악의적인 사용자가 스크립트 코드를 삽입 할 수 있는 일반적으로 사용되는 HTML 태그
 +  * <applet>
 +  * <body>
 +  * <embed>
 +  * <frame>
 +  * <script>
 +  * <frameset>
 +  * <html>
 +  * <iframe>
 +  * <img>
 +  * <style>
 +  * <layer>
 +  * <link>
 +  * <ilayer>
 +  * <meta>
 +  * <object>
 +
 +\\
 +예) HTML 특성을 사용하여 SRC , lowsrc , 스타일 및 HREF 크로스 사이트 스크립팅을 삽입
 +  <img src="javascript:alert('hello');">
 +  <img src="java&#010;script:alert('hello');">
 +  <img src="java&#X0A;script:alert('hello');">
 +\\
 +예) 사용할 수있는 스타일을 다음과 같이 MIME 타입을 변경하여 스크립트를 삽입하는 태그
 +  <style TYPE="text/javascript">
 +    alert('hello');
 +  </style>
 +=== 대책 평가 ===
 +몇 가지 입력을 사용하여 HTML을 생성하는 ASP.NET 코드를 찾을 때, 특정 응용 프로그램에 대한 적절한 대책을 평가
 +\\
 +
 +가. HTML 출력을 인코딩
 +\\
 +웹 페이지에 텍스트 출력을 작성하고 텍스트를 HTML 특수 문자 (예 : <,>, and & 포함 된 경우 모르는 경우 )를 사용하여 텍스트를 미리 처리
 +\\
 +예) 텍스트 사용자 입력, 데이터베이스 또는 로컬 파일에서 온 경우이 작업을 수행
 +  Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));
 +
 +나. URL의 출력 인코딩
 +\\
 +클라이언트 입력을 포함하는 URL 문자열을 반환
 +\\
 +예) URL 문자열을 인코딩하는 방법
 +  Response.Write(HttpUtility.UrlEncode(urlString));
 +
 +다. 필터 사용자 입력
 +\\
 +텍스트 입력 필드의 어떤 종류를 예를 들어 HTML 요소의 범위를 수락해야 페이지가 있다면, 페이지에 대해 ASP.NET 유효성 검사를 요청시 비활성화해야함. 이렇게 여러 페이지가있는 경우, 동의 할 경우에만 HTML 요소를 허용하는 필터를 만듬.
 +\\
 +  * 안전 제한된 HTML 입력
 +  - ASP.NET 유효성 검사를 요청시 비활성화 ValidateRequest="false"로 하는 특성을 @ Page로 지시.
 +  - 문자열 입력 인코딩 HtmlEncode 방법.
 +  - 사용되는 StringBuilder을 불러오고 교체 선택적으로 허용 할 HTML 요소에 인코딩을 제거하는 방법.