1580, 5/79 회원가입  로그인  
   twinz
   - [보안팁] 프로그래밍 코드보호 (1)

http://www.hackerschool.org/HS_Boards/zboard.php?id=Free_Lectures&no=844 [복사]


보안은 다차원적인 문제입니다. 어디에서나 보안상 위험이 발생할 수 있습니다. 사용자가 오류 처리 코드를 작성하거나 너무 많은 권한을 제공하는 경우, 서버에서 실행하고 있는 서비스가 무엇인지 잊어 버리는 경우, 모든 사용자 입력을 허용하는 경우 등이 있습니다. 그 밖에도 여러 가지 경우가 있습니다. 다음과 같은 안전한 네트워크 전략에 대한 10가지 주의 사항에 따라 시스템, 네트워크, 코드를 순조롭게 보호할 수 있습니다.

1. 사용자 입력 신뢰의 위험성
이 기사의 나머지 부분을 읽지 않더라도 한 가지 주의해야 할 사항은 "사용자 입력을 믿지 말아야 한다"는 것입니다. 데이터가 항상 올바르게 구성되고 제대로 되어 있다고 생각한다면 문제에 직면하게 됩니다. 대부분의 보안상 취약점은 서버 시스템에 잘못된 데이터가 제공하는 공격자로 인해 발생합니다.
입력이 올바른 형식이라고 무조건 신뢰하는 것은 버퍼 오버런, 사이트 간 스크립트 공격, SQL 주입 공격 등과 같은 문제를 일으킬 수 있습니다.
이러한 잠재적인 공격 문제에 대해 자세히 살펴보겠습니다.
2. 버퍼 오버런 방지
버퍼 오버런은 공격자가 필요 이상으로 규모가 큰 데이터를 응용 프로그램에 제공할 때 발생하는 것으로서 내부 메모리 공간으로 오버플로됩니다. 버퍼 오버런은 C/C++에서 주로 발생하며 일반적으로 쉽게 해결할 수 있습니다. 버퍼 오버런은 명확하지 않은 버퍼 오버런과 수정하기 어려운 버퍼 오버런 두 가지 유형이 있습니다. 개발자는 내부 버퍼보다 큰 데이터가 외부에서 제공되리라고는 생각하지 못했습니다. 오버플로는 메모리의 다른 데이터 구조에 손상을 일으키기 때문에 공격자가 유해한 코드를 실행할 수 있는 경우가 있습니다. 또한 버퍼 언더플로 및 버퍼 오버런은 배열 인덱싱 문제를 유발시키지만 일반적인 것은 아닙니다.
아래의 C++ 코드를 살펴봅시다.
void DoSomething(char *cBuffSrc, DWORD cbBuffSrc) {
    char cBuffDest[32];
    memcpy(cBuffDest,cBuffSrc,cbBuffSrc);
}

이 코드에서 잘못된 점은 무엇일까요  사실, cBuffSrc 및 cbBuffSrc가 데이터를 신뢰하지 않은 코드  신뢰하는 원본에서 나온 것이고 데이터의 형식과 크기가 올바른지 확인한 것이라면 이 코드에는 잘못된 점이 없습니다. 하지만 해당 데이터가 신뢰되지 않은 원본에서 나온 것이고 유효성 검사를 하지 않은 경우에는 공격자(신뢰되지 않은 원본)가 cBuffDest보다 큰 cBuffSrc를 작성할 수 있으며 cbBuffSrc를 cBuffDest보다 크게 설정할 수도 있습니다. memcpy가 데이터를 cBuffDest에 복사할 때, cBuffDest가 함수의 스택 프레임의 반환 주소 옆에 있고 공격자로 인해 코드가 유해한 작업을 실행하므로 DoSomething에서 반환된 주소에 나쁜 영향을 미칩니다.
이 문제를 해결하는 방법은 사용자 입력과 cBuffSrc 및 cbBuffSrc의 데이터를 신뢰하지 않는 것입니다.
void DoSomething(char *cBuffSrc, DWORD cbBuffSrc) {
    const DWORD cbBuffDest = 32;
    char cBuffDest[cbBuffDest];
#ifdef _DEBUG
    memset(cBuffDest, 0x33, cbBuffSrc);
#endif
    memcpy(cBuffDest, cBuffSrc, min(cbBuffDest, cbBuffSrc));
}

이 함수는 제대로 작성된 함수의 세 가지 속성을 보여줍니다. 이 함수는 버퍼 오버런을 완화시킵니다. 첫째, 버퍼 길이를 제공하는 호출자가 필요합니다. 물론 이 값을 무조건 신뢰하지는 말아야 합니다. 둘째, 디버그 빌드에서 소스 버퍼를 포함할 수 있는 충분한 크기인지 확인하기 위해 해당 코드가 버퍼를 검색합니다. 그렇지 않을 경우, 액세스 위반이 발생하며 코드를 디버거에 throw합니다. 이 작업을 실행하는 중에 많은 버그를 볼 수 있습니다. 마지막으로, 가장 중요한 사항으로서 memcpy에 대한 호출은 방어적이기 때문에 버퍼가 소유할 수 있는 데이터만큼만 복사합니다.
Microsoft의 Windows Security Push에서는 C 프로그래머를 위해 안전한 문자열 처리 함수 목록을 만들었습니다. Strsafe.h: Safer String Handling in C (US) 에서 확인하십시오.
3. 사이트 간 스크립팅 방지
사이트 간 스크립팅 취약점은 웹 관련 문제점으로서 단일 웹 페이지의 결함으로 인해 클라이언트의 데이터에 손상을 입힐 수 있습니다. 다음과 같은 ASP.NET 코드 단편이 있다고 가정해 봅시다.
<script language=c#>
    Response.Write("안녕하세요, " + Request.QueryString("name"));
</script>

이러한 코드를 본 적이 있습니까  이 코드는 잘못된 코드입니다. 일반적으로 다음과 같은 URL을 사용하여 이 코드에 액세스합니다.
http://explorationair.com/welcome.aspx?name=Michael

C# 코드에서는 해당 데이터가 항상 올바른 형식이며 이름만 포함한다고 가정합니다. 하지만 공격자는 이 코드를 악용하여 스크립트 및 HTML을 이름으로 제공합니다. 다음 URL을 입력하면
http://northwindtraders.com/welcome.aspx?name=<script>alert('안녕!');
</script>

"안녕!"이라고 표시된 대화 상자가 있는 웹 페이지에 연결됩니다. 사용자가 이와 같은 링크를 클릭하면 어떻게 될까요  쿼리 문자열에 좋지 않은 스크립트 및 HTML이 있어 사용자의 쿠키를 공격자가 가져가 공격자의 사이트에 게시하게 되면 사용자의 개인 쿠키 정보를 공격자가 갖게 되거나 더 나쁜 상황이 발생하게 됩니다.
이것을 방지할 수 있는 두 가지 방법이 있습니다. 첫째, 입력 내용을 신뢰하지 않고 사용자의 이름이 무엇으로 되어 있는지 신중히 살펴야 합니다. 예를 들어, 일반 식을 사용하여 이름에 일반적인 문자 하위 집합만 포함되어 있으며 크기가 너무 크지 않은지 확인합니다. 다음 C# 코드 조각을 사용하여 이러한 작업을 할 수 있습니다.
Regex r = new Regex(@"^[w]{1,40}$");
        
if (r.Match(strName).Success) {
    // 좋습니다! 올바른 문자열입니다.
} else {
    // 좋지 않습니다! 잘못된 문자열입니다.
}

이 코드에서는 일반 식을 사용하여 문자열에 1과 40 사이의 영숫자만 포함되는지 확인합니다. 이 방법만이 값이 올바른지 확인하는 안전한 방법입니다.
이 일반 식을 통해 HTML 또는 스크립트를 확인할 수 있습니다. 일반 식을 사용하여 잘못된 문자를 찾고, 잘못된 문자가 검색된 경우에는 요청을 거부하는 작업을 하지 말아야 합니다. 왜냐하면 이러한 작업은 실수로 빠뜨리는 경우가 있기 때문입니다.
두 번째 방법은 입력이 출력으로 사용될 때 모든 입력을 HTML 인코딩하는 것입니다. 이렇게 하면 위험한 HTML 태그를 줄일 수 있어 이스케이프 문자를 좀 더 안전하게 할 수 있습니다. Server.HTMLEncode가 있는 ASP 또는 HttpServerUtility.HtmlEncode가 있는 ASP.NET에서 문제가 될 수 있는 모든 스트링을 이스케이프할 수 있습니다.
4. sa 사용 권한 불필요
마지막 입력 트러스트 공격으로 SQL 주입을 설명하겠습니다. 많은 개발자들이 Microsoft SQL Server 또는 Oracle과 같은 백엔드 데이터 저장소와 통신하기 위해 입력이 필요한 코드를 작성하고 해당 입력을 사용하여 SQL 쿼리를 작성합니다.
아래의 코드를 살펴봅시다.
void DoQuery(string Id) {
    SqlConnection sql=new SqlConnection(@"data source=localhost;" +
            "user id=sa;password=password;");
    sql.Open();
    sqlstring= "SELECT hasshipped" +
            " FROM shipping WHERE id='" + Id + "'";
    SqlCommand cmd = new SqlCommand(sqlstring,sql);
  
이 코드는 세 가지 심각한 결함이 있습니다. 첫째, 시스템 관리자 계정인 sa로 Web Service에서 SQL Server로 연결이 되었습니다. 이 부분이 왜 결함이 있는지 곧 설명하겠습니다. 둘째, sa 계정에 대한 암호로 "password"를 사용했습니다.
그러나 이 코드에 결함이 있는 가장 중요한 원인은 SQL 문을 작성하는 스트링 연결입니다. 사용자가 1001이라는 ID를 입력하면 다음과 같은 올바른 형식의 유효한 SQL 문이 표시됩니다.
SELECT hasshipped FROM shipping WHERE id = '1001'

하지만 공격자는 이보다 훨씬 앞서 생각합니다. 즉, 공격자는 다음과 같은 질의를 실행하는 "'1001' DROP table shipping --" ID를 입력합니다.
SELECT hasshipped FROM
shipping WHERE id = '1001'
DROP table shipping --';

이렇게 하면 질의가 작동하는 방법이 변경됩니다. 이 코드는 전달된 사항이 있는지 확인할 뿐만 아니라 전달 테이블도 삭제합니다. -- 연산자는 SQL의 설명 연산자로서 공격자로 하여금 유효하지만 위험한 일련의 SQL 문을 작성하도록 합니다.
이제 SQL Server 데이터베이스에서 테이블을 삭제하는 방법을 알아보겠습니다. 관리자만이 테이블 삭제 작업을 할 수 있습니다. 하지만 여기에서는 sa로 데이터베이스에 연결하여 sa가 SQL Server 데이터베이스에서 어떤 작업도 할 수 있습니다. sa로 응용 프로그램에서 SQL Server로 연결하지 않아야 합니다. 대신 적합한 Windows 통합 인증을 사용하거나 적절히 제한된 권리가 있는 미리 정의된 계정으로 연결해야 합니다.
SQL 주입 문제를 쉽게 해결할 수 있습니다. 아래의 코드에서는 SQL 저장 프로시저 및 매개 변수를 사용하여 이러한 쿼리를 작성하는 방법을 보여줍니다. 또한 이 코드에서는 4자리와 10자리 사이의 숫자로 된 전달 ID만 검색하므로 일반 식을 사용하여 입력이 유효한지 확인하는 방법을 보여줍니다.
Regex r = new Regex(@"^d{4,10}$");
if (!r.Match(Id).Success)
    throw new Exception("잘못된 ID");

SqlConnection sqlConn= new SqlConnection(strConn);
string str="sp_HasShipped";
SqlCommand cmd = new SqlCommand(str,sqlConn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ID",Id);

버퍼 오버런, 사이트 간 스크립트, SQL 주입 공격은 입력 트러스트의 예입니다. 이러한 공격에서 모든 입력 사항이 올바른 것이라고 증명될 때까지는 잘못된 것이라고 믿어야 합니다.

출저 - songhs33 님의 블로그

  Hit : 9905     Date : 2007/08/28 10:54



    
1500   - [리눅스팁] 리눅스 자동실행     twinz
08/28 7587
  - [보안팁] 프로그래밍 코드보호 (1)     twinz
08/28 9904
1498   - [보안팁] 프로그래밍 코드보호 (2)     twinz
08/28 7491
1497   - [보안팁] 리눅스     twinz
08/28 7289
1496   - [보안노트] 쿠키[4]     twinz
08/28 8604
1495   - [보안노트] 포트스캐닝 (1)     twinz
08/28 7591
1494   - [보안노트] 포트스캐닝 (2)     twinz
08/28 9001
1493   - [보안노트] 봇[1]     twinz
08/28 7219
1492   - 컴퓨터 바이러스의 종류[1]     twinz
08/27 8224
1491   - 다이하드 4.0 파이어세일 현실 가능[2]     twinz
08/25 8214
1490   - 도청 , 해킹 불가능한 세상이온다     twinz
08/25 7560
1489   - 백업명령어의 종류     twinz
08/27 8663
1488   - 무시되는 오프 스탠더드보안     twinz
08/27 6624
1487   - 서버관리자를 위한 50가지 비법     twinz
08/27 8790
1486   - 시스템 보안     twinz
08/27 6638
1485   - 어셈블리어 1[1]     twinz
08/27 8532
1484   - 어셈블리어 2     twinz
08/27 8387
1483   - 어셈블리어 3[1]     twinz
08/27 6622
1482   0번섹터 베드섹터일경우..[2]     ROK.AF
03/02 7552
1481   1[1]     백민준천재
08/31 4346
[1][2][3][4] 5 [6][7][8][9][10]..[79]

Copyright 1999-2023 Zeroboard / skin by Hackerschool.org / Secure Patch by Hackerschool.org & Wowhacker.com