블로그 구성 요소 중 태그 목록이라는 좋은 기능이 있지만,
블로그 테마에 어울리지 않거나, 이쁘지 않아 쓰지 않는 사람이 있다.

태그 목록의 기능은 그대로 유지하면서, 미적 업그레이드를 한 플러그인으로 WP-Cumulus가 있다.

WP-Cumulus
외국에서 공개한 플로그로서, 워드 프레스용 전용 플러그인이다.
그래서 티스토리 블로그에는 한계가 있다.
가장 기본적으로 글꼴이 한글 글꼴은 없다. 영문 글꼴만 포함되어 있다.
그리고 워드 프레스용으로 개발되었기에 블로그 적용을 위해 수작업이 많이 들어간다.

하지만, 티스토리 전용 태그 클라우드가 공개됐다.
우선 적용하는 방법을 적어보겠다.

아래의 링크를 다운받아 압축을 풀면 swfobject.js 파일과 tagcloud.swf 두개 파일이 있을 것이다.
두 파일을 스킨 올리기 기능을 이용해서 업로드시킨다.


이제 스킨을 수정해야 하는데, 아래와 같은 내용을 우선 찾는다.

<div id="tagbox" class="module">
  <h3>태그목록</h3>
  <div class="tagboxWrap">
  <ul>
    <s_random_tags>
    <li>
      <a href="[##_tag_link_##]" class="[##_tag_class_##]"> [##_tag_name_##]</a>
    </li>
    </s_random_tags>
  </ul>
  </div>
</div>

블로그 스킨이 조금씩 다르겠지만, 비슷한 형식이라 금방 찾을 수 있을 것이다.
<s_random_tags> 태그 상단에 보면 <ul>태그를 찾을 수 있는데
<ul>에서 </ul>로 닫기는 부분까지 아래 코드로 수정하면 된다.


<div id="tags">
<div id="htags" style="display:none;">
    <tags>
        <s_random_tags>
            <a href="[##_tag_link_##]" class="[##_tag_class_##]">[##_tag_name_##]</a>
        </s_random_tags>
    </tags>
</div>
<div id="TiCumulus"><p>Tistory Cumulus Flash tag cloud by <a href="http://zoc.kr">BLUEnLIVE</a> requires Flash Player 9 or better.</p></div>
<script type="text/javascript" src="./images/swfobject.js"></script>
<script type="text/javascript">
  var t = new SWFObject("./images/tagcloud.swf", "tagcloud", "100%", "200", "7", "#ffffff");
  t.addVariable("tcolor", "0x222222");
  t.addVariable("mode", "tags");t.addVariable("distr", "true");t.addVariable("tspeed", "100");t.addParam("allowScriptAccess", "always");
  t.addVariable("tagcloud", document.getElementById('htags').innerHTML.replace(/class=([\w]+)/gi, 'class="$1"').replace(/\"\"/gi, '"').replace(/class=\"/gi, 'style=\"font-size:').replace(/:cloud([\d])/gi, ':1$1pt;').replace(/TAGS\>/gi, 'tags>').replace(/\<A\s/gi, '<a ').replace(/\<\/A\>/gi, '</a>').replace(/\"/g, "'"));
  t.write("TiCumulus");
</script>
</div>

중간쯤에 있는 스크립트 소스를 보면,
new SWFObject("./images/tagcloud.swf", "tagcloud", "100%", "200", "7", "#ffffff");라고 되어 있는데
"100%" 이라고 표기된 부분이 가로 길이이고, "200" 부분이 세로 길이를 나타낸 것이다.
그리고 #ffffff는 배경 색상을 나타낸다.


새로운 SQL 잘라내기 공격 및 대처 방법
Baka Neerumalla

SQL 주입을 이용하는 공격은 방화벽과 침입 검색 시스템을 통과해서 데이터 계층을 손상시킬 수 있다는 점 때문에 많은 관심을 끌었습니다.

기본 코드 패턴을 보면 1차 또는 2차 주입 모두 문을 생성할 때 신뢰할 수 없는 데이터를 사용한 경우에 발생하는 다른 주입 문제와 비슷합니다.
대부분의 개발자는 백 엔드에서 매개 변수가 있는 SQL 쿼리를 저장 프로시저와 함께 사용하여 웹 프런트 엔드의 취약점을 완화하고 있지만, 사용자 입력 기반의 DDL(데이터 정의 언어) 문을 생성하는 경우 또는 C/C++로 작성된 응용 프로그램의 경우에는 동적으로 생성된 SQL을 여전히 사용하고 있습니다.
이 기사에서는 구분 문자가 이스케이프된 코드일지라도 SQL 문을 수정하거나 SQL 코드를 주입할 수 있는 몇 가지 새로운 아이디어에 대해 설명합니다.
구분 식별자SQL 리터럴을 생성하는 유용한 방법을 몇 가지 살펴본 다음 응용 프로그램을 보호하는 데 도움이 될 수 있도록 공격자가 SQL 코드를 삽입할 때 사용하는 새로운 방법을 설명합니다.


 

식별자 및 문자열 구분
SQL Server™에는 테이블, 뷰 및 저장 프로시저와 같은 SQL 개체를 고유하게 식별하는 SQL 식별자데이터를 나타내는 리터럴 문자열이라는 두 가지 문자열 변수가 있습니다.
SQL 식별자를 구분하는 방법은 데이터 문자열을 구분하는 방법과는 다릅니다.
이러한 데이터 변수를 사용해야 하는 동적 SQL을 생성하는 유용한 방법을 살펴보겠습니다.
SQL 개체 이름에 키워드가 사용되거나 개체 이름에 특수 문자가 들어 있는 경우 구분 식별자를 사용해야 합니다.
my_dbreader라는 이름의 로그인을 삭제한다고 가정해 봅시다.
이 경우 다음 문을 실행하여 작업을 수행할 수 있습니다.
 
DROP LOGIN my_dbreader
 
키워드이기도 한 DROP을 이름으로 사용하는 로그인을 삭제하려는 경우에는 어떻게 해야 합니까?
다음 SQL 문을 사용하면 SQL Server에서 잘못된 구문 오류가 반환됩니다.
 
DROP LOGIN DROP
 
my][dbreader라는 이름의 로그인을 삭제하려는 경우에는 어떻게 합니까?
이 경우에도 잘못된 구문 오류가 반환됩니다.
두 예제 모두 로그인 이름이 키워드이거나 로그인 이름에 특수 문자가 들어 있기 때문에 SQL Server에서 SQL 문에 있는 개체 이름을 식별할 수 있도록 시작 및 끝 표시를 입력해야 합니다.
큰따옴표대괄호를 SQL 식별자의 구분 기호로 사용할 수 있지만 연결 기반 설정인 QUOTED_IDENTIFIER 설정을 사용하도록 설정한 경우에는 큰따옴표만 사용할 수 있습니다.
복잡하지 않도록 하기 위해 항상 대괄호를 사용하는 것도 좋은 방법입니다.
로그인 이름인 DROP을 삭제하기 위해 다음과 같이 대괄호를 사용하여 SQL 문을 생성할 수 있습니다.
 
DROP LOGIN [DROP]
 
그러나 다음 문은 어떻게 처리되겠습니까?
 
DROP LOGIN [my][dbreader]
 
이와 같은 특별한 경우에는 로그인 이름인 my][dbreader에 구분 문자가 들어 있으므로 SQL에서는 대괄호로 둘러싸인 [my]를 로그인 이름으로 간주합니다.
로그인 이름 뒤에 오는 [dbreader]는 올바른 SQL 문이 아니기 때문에 구문 오류가 발생합니다.
오른쪽 대괄호를 하나 더 사용하여 오른쪽 대괄호를 이스케이프하면 이 문제를 해결할 수 있습니다.
따라서 다음 문을 실행하면 SQL Server에서 로그인 my][dbreader가 삭제됩니다.
 
DROP LOGIN [my]][dbreader]
 
이스케이프 메커니즘은 간단히 오른쪽 대괄호를 두 번 표시하는 것입니다.
왼쪽 대괄호를 포함한 다른 어떤 문자도 변경할 필요가 없습니다.
구분 리터럴을 사용하는 것은 구분 SQL 식별자를 사용하는 것과 비슷하지만 사용해야 하는 구분 문자가 다르다는 데 기본적으로 차이가 있습니다.
비슷한 규칙을 사용하여 구분 문자열 리터럴을 만들기 전에 몇 가지 예제를 살펴보겠습니다.
암호가 P@$$w0rd인 로그인 이름 dbreader를 만든다고 가정해 봅시다.
이 경우 다음 SQL 문을 사용할 수 있습니다.
 
CREATE LOGIN [dbreader] WITH PASSWORD = 'P@$$w0rd'
 
이 문에서 P@$$w0rd는 작은따옴표로 구분된 문자열 데이터이므로 SQL에서 문자열의 시작과 끝이 인식됩니다.
그러나 문자열 데이터에 작은따옴표가 들어 있다면 어떻게 되겠습니까?
문이 유효하지 않기 때문에 SQL Server에서 오류가 발생합니다.
 
CREATE LOGIN [dbreader] WITH PASSWORD = 'P@$$'w0rd'
 
유효한 SQL 문을 만들려면 문자열에 있는 모든 작은따옴표를 이스케이프해야 합니다.
 
CREATE LOGIN [dbreader] WITH PASSWORD = 'P@$$''w0rd'
 
이 문을 실행하면 SQL Server에서 암호가 P@$$'w0rd인 로그인 dbreader가 만들어집니다.
큰따옴표를 구분 기호로 사용할 수도 있지만 앞에서 설명했듯이 이 방법의 성공 여부는 전적으로 QUOTED_IDENTIFIER 설정의 사용 여부에 달려 있습니다.
결과적으로 항상 작은따옴표를 문자열 리터럴의 구분 기호로 사용하는 것이 좋습니다.


 

T-SQL 함수
지금까지 살펴본 것처럼 식별자문자열을 다루는 규칙은 비교적 간단하며 문자열을 미리 알고 있으면 수동으로 구분할 수 있습니다.
그러나 사용자 입력 기반의 동적 T-SQL 문을 생성할 경우에는 어떻겠습니까?
자동으로 이 작업을 수행할 수 있는 방법이 있어야 합니다.
구분 문자열을 준비하는 데 도움이 되는 QUOTENAMEREPLACE라는 2개의 T-SQL 함수를 사용할 수 있습니다.
QUOTENAME입력 문자열을 유효한 식별자로 만들기 위해 구분 기호가 추가된 유니코드 문자열을 반환합니다.
QUOTENAME 함수는 다음 구문을 사용합니다.
 
QUOTENAME ( 'string' [ , 'delimiter' ] )
 
QUOTENAME의 인수는 구분할 문자열구분 기호로 사용할 한 문자로 된 문자열입니다.
구분 기호로 대괄호, 작은따옴표 또는 큰따옴표를 사용할 수 있습니다.
이 함수는 주로 구분 SQL 식별자를 사용하기 위한 것이므로 SQL Server에서 nvarchar(128) 형식인 sysname만 받습니다.
또한 이 함수를 사용하여 구분 SQL 리터럴 문자열을 준비할 수 있지만 인수 길이 제한 때문에 128자 이하의 문자열에만 사용할 수 있습니다.
즉, 이러한 제한 때문에 REPLACE 함수를 사용하게 됩니다.
그림 1에서는 sp_addlogin이 QUOTENAME을 사용하여 구분된 로그인 이름 및 암호 문자열을 만드는 방법을 보여 줍니다.
그림에서 볼 수 있듯이 @loginname과 @passwd가 모두 sysname이므로 QUOTENAME 함수를 사용하여 구분 SQL 식별자와 구분 리터럴을 준비할 수 있습니다.
따라서 @loginname = 'my[]dbreader'와 @passwd = 'P@$$''w0rd'가 전달된다고 하더라도 QUOTENAME이 구분 문자를 올바르게 이스케이프하므로 SQL 주입 기회가 발생하지 않습니다.
 
create login [my[]]dbreader] with password = 'P@$$''w0rd' 
 
Figure 1 QUOTENAME으로 문자열 구분
create procedure sys.sp_addlogin
    @loginame       sysname
   ,@passwd         sysname = Null
   ,@defdb          sysname = ‘master’     
   ,@deflanguage    sysname = Null
   ,@sid            varbinary(16) = Null
   ,@encryptopt     varchar(20) = Null
AS
    -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --
    -- some code ----
    set @exec_stmt = ‘create login ‘ + quotename(@loginame, ‘[‘)

    if @passwd is null
        select @passwd = ‘‘

    if (@encryptopt is null)
        set @exec_stmt = @exec_stmt + ‘ with password = ‘ +
            quotename(@passwd, ‘‘‘‘)
    else
    -- some code
GO
 
REPLACE 함수는 지정된 문자열을 모두 지정된 대체 문자열로 바꿉니다.
QUOTENAME과는 달리 받는 인수에 대한 길이 제한은 없습니다.
 
REPLACE ( 'string1' , 'string2' , 'string3' )
 
REPLACE는 3개의 문자열을 받습니다.
즉, string1은 편집할 식이고 string2는 바꿔야 하는 string1 내의 항목이며 string3은 string2 대신 사용할 항목입니다.
모든 문자열 식은 문자 또는 이진 데이터일 수 있습니다.
구분 SQL 리터럴을 준비하기 위해 REPLACE를 사용하여 작은따옴표 수를 2배로 만들 수 있습니다.
그러나 이 경우 시작 및 끝 작은따옴표를 사용하는 것처럼 구분 기호를 수동으로 추가해야 합니다.
그림 2에서는 sp_attach_single_file_db에서 이 함수를 사용하여 이스케이프된 물리적 파일 이름을 준비하는 방법을 보여 줍니다. @physname은 nvarchar(260)이므로 QUOTENAME을 구분 리터럴을 준비하는 데 사용할 수 없습니다.
바로 이 점 때문에 REPLACE를 사용하는 것입니다.
따라서 작은따옴표가 있는 문자열을 전달한다고 하더라도 SQL 문을 수정하거나 SQL 코드를 주입할 수 없습니다.
이제 현재 암호의 유효성을 확인한 후 사용자 계정의 암호를 변경하는 저장 프로시저를 살펴보겠습니다(그림 3 참조).
CREATE PROCEDURE sp_setPassword
    @username varchar(25),
    @old varchar(25),
    @new varchar(25)
AS

DECLARE @command varchar(100)

SET @command=
    ‘update Users set password=‘‘‘ + @new +
    ‘‘‘ where username=‘‘‘ + @username +
    ‘‘‘ AND password=‘‘‘ + @old + ‘‘‘‘

EXEC (@command)
GO
 
저장 프로시저를 간단하게 살펴보면 작은따옴표에 대해 이스케이프된 매개 변수가 없어서 SQL 주입 공격에 취약하다는 것을 알 수 있습니다.
공격자는 몇 가지 특정 인수를 전달하여 SQL 문을 다음과 같이 수정할 수 있습니다.
 
update Users set password='NewP@ssw0rd'
where username='admin' --' and password='dummy'
 
결과적으로 실제 암호가 없어도 admin 계정(또는 알려진 계정)의 암호가 설정됩니다.
T-SQL에서는 REPLACE 또는 QUOTENAME을 사용하여 이 코드를 수정할 수 있습니다.
그림 4에서는 REPLACE 함수를 사용하여 수정한 코드를 보여 줍니다.
CREATE PROCEDURE sp_setPassword
    @username varchar(25),
    @old varchar(25),
    @new varchar(25)
AS

-- Declare variables.
DECLARE @command varchar(100)

-- Construct the dynamic SQL
SET @command=
    ‘update Users set password=‘‘‘ + REPLACE(@new, ‘‘‘‘, ‘‘‘‘‘‘) + ‘‘‘‘ +
    ‘ where username=‘‘‘ + REPLACE(@username, ‘‘‘‘, ‘‘‘‘‘‘) + ‘‘‘‘ +
    ‘ AND password = ‘‘‘ + REPLACE(@old, ‘‘‘‘, ‘‘‘‘‘‘) + ‘‘‘‘

-- Execute the command.
EXEC (@command)
GO
그림에서 볼 수 있는 것처럼 REPLACE는 매개 변수에 있는 모든 작은따옴표 수를 2배로 만듭니다.
따라서 공격자가 동일한 인수를 전달하는 경우 다음과 같은 문이 만들어집니다.
 
update Users set password='NewP@ssw0rd'
where username='admin''--' and password='dummy'
 
따라서 일반적인 SQL 주입 문제에 취약하지 않게 됩니다.


 

잘라내기를 통한 수정
앞에서 본 저장 프로시저를 자세히 살펴보면 @command 변수의 길이 제한이 100자임을 알 수 있습니다.
그러나 25자로 된 각 변수에 대한 REPLACE 함수는 모든 문자가 작은따옴표일 경우 50자를 반환할 수 있습니다.
SQL Server 2000 SP4 및 SQL Server 2005 SP1에서는 변수의 버퍼가 충분하지 않으면 데이터가 자동으로 잘립니다.
공격자는 이러한 기회를 틈타 명령 문자열을 자를 수 있습니다.
이 예제에서 누군가가 username='username' 식의 바로 뒤에 있는 명령을 자를 수 있다면 알려진 사용자 계정의 현재 암호를 알지 못하더라도 해당 암호를 변경할 수 있습니다.
웹 응용 프로그램에 administrator라는 이름의 사용자가 있다는 것을 공격자가 알고 있다고 가정합니다.
이 경우 모든 사용자 계정이 대상이 될 수 있습니다.
명령이 너무 길어서 적절하게 잘리도록 하기 위해서는 공격자가 41자 길이의 새 암호를 제공해야 합니다.
즉, 전체 길이가 100자인 명령에서 27자는 update 문에 사용되고 17자는 where 절에 사용되고 13자는 "administrator"에 사용되며 2자는 새 암호를 둘러싸는 작은따옴표에 사용되기 때문에 암호에는 41자가 필요합니다.
공격자는 새 암호로 25자만 전달할 수 있습니다.
그러나 REPLACE 함수에 의해 2배가 되는 작은따옴표를 전달하면 이 문제를 해결할 수 있습니다.
따라서 공격자는 작은따옴표 18개, 대문자 1개, 기호 1개 및 소문자 2개를 전달하여 where username='administrator' 식의 바로 뒤에 있는 명령을 자를 수 있습니다.
공격자가 @new 매개 변수에 대해 ''''''''''''''''''!Abb1을 전달하고 username 매개 변수에 대해 administrator를 전달하면 @command는 다음과 같이 됩니다.
 
update Users set password=
'''''''''''''''''''''''''''''''''''''!Abb1' where username='administrator'
 
그림 5에서는 REPLACE 대신 QUOTENAME을 사용합니다.
이전 예제에서는 개발자가 사용자 이름, 새 암호 및 기존 암호에 대해 작은따옴표를 구분 문자로 추가하지만 이 예제에서는 QUOTENAME 함수를 사용해서 작은따옴표를 추가한다는 점이 이전 예제와 이 예제의 유일한 차이점입니다.
사용자가 제공한 데이터는 변경되지 않기 때문에 이전 예제에 사용한 것과 동일한 공격 문자열을 이 예제에 사용할 수 있습니다.
그림 6에서는 동일한 기능을 수행하는 중간 계층 응용 프로그램에서 작성된 간략한 C/C++ 함수 버전을 보여 줍니다.
이 함수도 동일한 공격에 취약합니다.
DWORD ChangePassword(char* psUserName, char* psOld, char* psNew)
{
    char* psEscapedUserName = NULL;
    char* psEscapedOldPW = NULL;
    char* psEscapedNewPW = NULL;
    char szSQLCommand[100];
    HRESULT hr=0;
   
    // Input Validation
    ...

    // Calculate and allocate the new buffer with length
    // userdatalen*2 + 1
    // Escape all single quotes with double quotes
    ...

    //Construct the query
    hr = StringCchPrintf(szSQLCommand, sizeof(szSQLCommand)/sizeof(char),
        "Update Users set password=‘%s’ where username=‘%s’"
        "AND password=‘%s’,
        psEscapedNewPW, psEscapedUserName, psEscapedOldPW);
   
    if (S_OK != hr)
    {
        // handle error cases
    }

    // Execute and return
}

CREATE PROCEDURE sp_setPassword
    @username varchar(25),
    @old varchar(25),
    @new varchar(25)
AS
-- Declare variables.
DECLARE @command varchar(100)

-- In the following statement, we will need 43 characters
-- to set an administrator password without knowing its current password.
-- 100 - 26 - 16 - 15 = 43 (26 for update stmt, 16 for where clause,
-- 15 for ‘administrator’). But @new only takes 25 characters, which we
-- can get around by using single quotes. So one can pass the following
-- parametes and set admin password. @new = 18 single quotes, 1 Capital
-- letter, 1 symbol, 2 small case letters, 1 digit
-- @username = administrator
-- @command becomes
-- update Users set password=‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘!Abb1’
-- where username=‘administrator’
SET @command= ‘update Users set password=‘ + QUOTENAME(@new,’’’’) +
‘ where username=‘ + QUOTENAME(@username,’’’’) + ‘ AND password = ‘ + QUOTENAME(@old,’’’’)

-- Execute the command.
EXEC (@command)
GO


 

잘라내기를 통한 SQL 주입
그림 7에서는 개별 변수를 고정적으로 사용하는 동일한 코드의 여러 변형을 보여 줍니다.
이 코드에서는 이스케이프된 문자열을 개별 변수에 저장하고 @command의 버퍼는 전체 문자열을 저장할 수 있을 정도로 큽니다. @escaped_username, @escaped_oldpw 및 @escaped_newpw는 varchar(25)로 선언되었지만 @username, @old 및 @new의 모든 문자가 25개의 작은따옴표 문자일 경우 50자를 저장해야 합니다.
이 경우 이스케이프된 문자로 구성된 문자열이 잘릴 가능성이 있습니다.
CREATE PROCEDURE sp_setPassword
    @username varchar(25),
    @old varchar(25),
    @new varchar(25)
AS
-- Declare variables.
DECLARE @escaped_username varchar(25)
DECLARE @escaped_oldpw varchar(25)
DECLARE @escaped_newpw varchar(25)
DECLARE @command varchar(250)

SET @escaped_username = REPLACE(@username, ‘‘‘‘, ‘‘‘‘‘‘)
SET @escaped_oldpw = REPLACE(@old, ‘‘‘‘, ‘‘‘‘‘‘)
SET @escaped_newpw = REPLACE(@new, ‘‘‘‘, ‘‘‘‘‘‘)

SET @command =
    ‘update Users set password=‘‘‘ + @escaped_newpw + ‘‘‘‘ +
    ‘ where username=‘‘‘ + @escaped_username + ‘‘‘‘ +
    ‘ AND password = ‘‘‘ + @escaped_oldpw + ‘‘‘‘
EXEC (@command)
GO
 
공격자는 123...n'(여기서 n은 24번째 문자)을 새 암호로 제공하고 @escaped_newpw를 123...n'으로 만든 후(REPLACE 함수에서 반환된 두 번째 작은따옴표 문자가 잘림) 다음과 같은 마지막 쿼리를 만들 수 있습니다.
이 경우 공격자는 username 필드를 통해 코드를 주입하여 공격할 수 있습니다.
 
update users set password='123...n''
where username='<SQL Injection here using Username>
 
이 코드 패턴의 경우 기존 SQL을 단순히 자르는 것에 그치지 않고 SQL 코드를 삽입할 가능성이 열려 있기 때문에 더 위험합니다.
그림 8에서는 REPLACE 대신 QUOTENAME 함수를 사용하는 동일한 코드의 변형을 예제로 보여 줍니다.
QUOTENAME은 구분 기호를 추가하므로 페이로드는 다르지만 여전히 SQL 주입 공격에는 취약합니다.
ALTER PROCEDURE sp_setPassword
    @username varchar(25),
    @old varchar(25),
    @new varchar(25)
AS
-- Declare variables.
DECLARE @quoted_username varchar(25)
DECLARE @quoted_oldpw varchar(25)
DECLARE @quoted_newpw varchar(25)
DECLARE @command varchar(250)

-- In the following statements, all the variables can only hold
-- 25 characters, but quotename() will return 52 characters when all
-- the characters are single quotes.
SET @quoted_username = QUOTENAME(@username, ‘‘‘‘)
SET @quoted_oldpw = QUOTENAME(@old, ‘‘‘‘)
SET @quoted_newpw = QUOTENAME(@new, ‘‘‘‘)

-- By passing the new password as 123...n where n is 24th character,
-- @quoted_newpw becomes ‘123..n
-- Observe carefully that there is no trailing single quote as it gets
-- truncated.
-- So the final query becomes something like this
-- update users set password=‘123...n where username=‘ <SQL Injection
-- here using Username>
SET @command= ‘update Users set password=‘ + @quoted_newpw +
              ‘ where username=‘ + @quoted_username +
              ‘ AND password = ‘ + @quoted_oldpw
EXEC (@command)
GO
 
이 코드에서는 구분 문자열을 개별 변수에 저장하고 @command의 버퍼는 전체 명령 문자열을 저장할 수 있을 정도로 큽니다.
이전 예제와 마찬가지로 따옴표 붙은 변수 @quoted_username, @quoted_oldpw 및 @quoted_newpw에 문제가 있습니다.
이러한 변수는 varchar(25)로 선언되었지만 @username, @old 및 @new의 모든 문자가 25개의 작은따옴표 문자일 경우 52자가 필요합니다.
또한 QUOTENAME은 시작 및 끝 구분 기호를 추가합니다.
이 경우 공격자는 구분 문자로 구성된 문자열을 자를 기회를 얻게 됩니다.
공격자는 123...n(여기서 n은 24번째 문자)을 새 암호로 제공하고 @escaped_newpw를 '123...n으로 만든 후(QUOTENAME 함수가 시작 작은따옴표를 추가함) 다음과 같은 마지막 쿼리를 만들 수 있습니다.
이 경우 공격자는 username 필드를 통해 코드를 주입하여 공격할 수 있습니다.
 
update users set
password='123...n where
username=' <SQL Injection here using Username>
 
그림 9에서는 이 코드와 동일한 기능을 수행하면서 C/C++로 작성된 간단한 코드를 보여 줍니다.
이 코드 또한 동일한 공격 방식에 취약합니다.
 
DWORD ChangePassword(char* psUserName, char* psOld, char* psNew)
{
    char szEscapedUserName[26];
    char szEscapedOldPW[26];
    char szEscapedNewPW[26];
    char szSQLCommand[250];
   
    // Input Validation

    // Escape User supplied data
    Replace(psUserName, "’", "’’", szEscapedUserName,
            sizeof(szEscapedUserName));
    Replace(psPassword, "’", "’’", szEscapedOldPW,
            sizeof(szEscapedOldPW));
    Replace(psPassword, "’", "’’", szEscapedNewPW,
            sizeof(szEscapedNewPW));
   
    // Construct the query
    StringCchPrintf(szSQLCommand, sizeof(szSQLCommand)/sizeof(char),
        "Update Users set password=‘%s’ where username=‘%s’"
        "AND password=‘%s’,
        szEscapedNewPW, szEscapedUserName,szEscapedOldPW);

    // Execute and return
}
 
여기에서는 설명을 위해 T-SQL 코드를 사용하기는 했지만 실제로는 DML(데이터 조작 언어) 코드가 포함된 대부분의 응용 프로그램이 이러한 문제에 취약하지 않으므로 DML 문에 동적 SQL을 사용할 필요는 없습니다.
그림 10에서는 사용자 입력에 따라 동적 DDL 문을 생성하는 예제를 보여 줍니다.
앞서 살펴본 다른 예제와 마찬가지로 다음 문에는 잘라내기 문제가 있습니다.
 
set @escaped_oldpw = quotename(@old, '''')
set @escaped_newpw = quotename(@new, '''')
 
공격자는 @new = '123...'을 전달하여 이러한 문을 공격할 수 있습니다.
여기서 127번째 문자(작은따옴표 아님)는 @old = '; SQL Injection'을 시작하고 다음과 같은 SQL 문이 만들어집니다.
 
alter login [loginname]
with password = '123... old_password = '; SQL
Injection
 
create procedure sys.sp_password
    @old sysname = NULL,        -- the old (current) password
    @new sysname,               -- the new password
    @loginame sysname = NULL    -- user to change password on
as
    -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES --
    set nocount on
    declare @exec_stmt nvarchar(4000)
    declare @escaped_oldpw sysname
    declare @escaped_newpw sysname

    set @escaped_oldpw = quotename(@old, ‘‘‘‘)
    set @escaped_newpw = quotename(@new, ‘‘‘‘)

    set @exec_stmt = ‘alter login ‘ + quotename(@loginame) +
        ‘ with password = ‘ + @escaped_newpw + ‘ old_password = ‘ +
        @escaped_old

    exec (@exec_stmt)

    if @@error <> 0
        return (1)

    -- RETURN SUCCESS --
    return  (0)    -- sp_password
 
저장 프로시저에서 이러한 문제가 쉽게 발생할 수 있는 것처럼 보이기는 하지만 모든 저장 프로시저가 보안에 취약한 것은 아닙니다.
다음 내용을 주의 깊게 검토할 필요가 있습니다.
SQL Server에서는 모든 저장 프로시저가 기본적으로 호출자의 컨텍스트에서 실행됩니다.
따라서 프로시저에 SQL 주입 문제가 있다고 하더라도 프로시저에 대한 실행 권한을 갖고 있는 악의적 로컬 사용자가 자신의 권한을 높일 수 없기 때문에 주입된 코드는 해당 사용자의 컨텍스트에서 실행됩니다.
그러나 EXECUTE AS 기능을 통해 소유자 또는 다른 특정 사용자가 실행할 수 있는 내부 유지 관리 스크립트가 있는 경우에는 호출자가 다른 사용자 컨텍스트에서 코드를 실행하여 호출자의 권한을 해당 사용자의 권한으로 높일 수 있습니다.
모든 잘라내기 문제는 명백히 버그이지만 반드시 보안 취약점이라고 할 수는 없습니다.
그러나 향후 누가 이러한 문제점을 발견하여 악용할 가능성은 있기 때문에 문제를 해결해 두는 것이 좋습니다.
SQL 코드의 주입 취약점을 완화하기 위해 취할 수 있는 다른 방법이 있습니다.
첫 번째는 저장 프로시저에서 DML 문에 대해 동적 SQL을 사용하지 않는 것입니다.
불가피하게 동적 SQL을 사용해야 한다면 sp_executesql을 사용하십시오.
두 번째는 이 기사의 예제에서 설명한 것처럼 버퍼 길이를 올바르게 계산해야 합니다.
마지막으로 C/C++ 코드의 경우 문자열 연산 반환 값을 확인하여 문자열이 잘렸는지 여부를 확인합니다.
문자열이 잘렸으면 실패한 것입니다.
취할 수 있는 단계에 대한 요약을 보려면 "취약점 검색 방법" 보충 기사를 참조하십시오.


 

잘라내기를 통한 주입 검색
잘라내기를 이용한 SQL 주입 문제를 자동화된 도구로 검색하려면 잘라내기 공격의 가능성을 남기는 모든 코드 패턴을 잘 파악하고 있어야 합니다.
서로 다른 문자열 데이터를 사용하여 개별 특정 코드 패턴에 적용할 수 있습니다.
다음 시나리오에서는 n입력 버퍼의 길이라고 가정합니다.
QUOTENAME 구분 문제를 검색하기 위해 먼저 QUOTENAME(또는 C/C++ 응용 프로그램의 경우 비슷한 함수)을 사용해서 구분 식별자 또는 리터럴을 준비했고, 구분된 문자열 버퍼 크기가 2*n + 2보다 작다고 가정합니다.
구분된 문자열 버퍼 길이가 n일 경우 이러한 문제를 검색하려면 비구분 문자로 구성된 긴 문자열을 전달합니다.
후행 구분 기호는 잘리고 다른 입력 변수를 사용하여 주입할 수 있는 기회가 생깁니다.
구분된 버퍼 길이가 홀수일 때 이러한 문제를 검색하려면 작은따옴표(또는 오른쪽 대괄호나 큰따옴표) 문자로 구성된 긴 문자열을 전달합니다.
QUOTENAME은 모든 구분 기호 수를 2배로 만들고 시작 구분 문자를 추가하는 반면, 이스케이프된 문자열 버퍼에는 홀수 개의 문자만을 저장할 수 있으므로 후행 구분 기호는 잘립니다.
구분된 버퍼 길이가 짝수일 때 이러한 문제를 검색하려면 1', 1'', 1''', 1''''과 같이 각 반복에 대해 작은따옴표(또는 오른쪽 대괄호)의 수를 늘리는 방식으로 문자열을 전달합니다.
QUOTENAME은 모든 작은따옴표 수를 2배로 만들기 때문에 시작 구분 기호와 1이 포함된 짝수 개의 작은따옴표가 들어 있는 문자열이 반환되어 짝수 개의 문자를 받게 됩니다.
결과적으로 후행 구분 기호는 잘립니다.
또한 REPLACE(또는 C/C++ 응용 프로그램의 경우 유사한 함수)를 사용하여 이스케이프된 문자열을 준비하고 이스케이프된 문자열 버퍼 크기가 2*n보다 작은 경우에도 이러한 문제를 검색할 수 있습니다.
이스케이프된 문자열 버퍼 길이가 n과 같을 때 이러한 문제를 검색하려면 1', 12', 123' 및 123...n'과 같이 각 반복에 대해 입력 문자열의 길이를 늘리는 방식으로 문자열을 전달합니다.
이 경우 올바른 길이를 입력하면 REPLACE 함수에 의해 마지막 작은따옴표 문자가 2배로 됩니다.
이스케이프된 문자열 변수에는 충분한 버퍼 공간이 없으므로 마지막 작은따옴표가 잘린 채로 저장되어 전달되기 때문에 SQL 문을 수정할 수 있는 기회가 발생합니다.
이스케이프된 버퍼 길이가 홀수일 때 REPLACE를 사용하여 이러한 문제를 검색하려면 ', '', ''' 및 ''''...'와 같이 길이가 길어지는 작은따옴표 문자로 구성된 문자열을 전달하거나 작은따옴표 문자로 구성된 긴 문자열을 전달합니다.
이 경우 REPLACE는 모든 작은따옴표 수를 2배로 만듭니다.
그러나 버퍼 크기가 홀수이기 때문에 마지막 작은따옴표가 잘리면서 SQL 문을 수정할 수 있는 기회가 발생합니다.
이스케이프된 버퍼 길이가 짝수일 때 이러한 문제를 검색하려면 1', 1'', 1''', 1''''과 같이 각 반복에 대해 작은따옴표(또는 오른쪽 대괄호)의 수를 늘리는 방식으로 문자열을 전달합니다.
맨 앞의 1을 제외한 반환 값에는 짝수 개의 문자가 포함되므로 전체 반환 값의 문자 수는 홀수가 됩니다.
그러나 버퍼 길이가 짝수이기 때문에 후행 작은따옴표가 잘리면서 SQL 문을 수정할 수 있는 기회가 발생합니다.
 
 
취약점 검색 방법

코드 검토 사용
코드 검토를 수행할 때 다음과 같은 방법을 사용하여 SQL 문의 문제를 검색할 수 있습니다.

1차 또는 2차 SQL 주입 검색
  • 동적 SQL 문을 실행하는 데 사용한 API를 확인합니다.
  • 동적 SQL 문에 사용된 데이터에 대해 데이터 유효성 검사가 수행되었는지 검토합니다.
  • 데이터 유효성 검사가 수행되지 않은 경우 데이터의 구분 문자(문자열 리터럴의 경우 작은따옴표, SQL 식별자의 경우 오른쪽 대괄호)가 이스케이프되었는지 검토합니다.

잘라내기를 통한 SQL 수정 문제 검색
  • 마지막 동적 SQL 문을 저장하는 데 사용된 버퍼 길이를 검토합니다.
  • 입력이 최대값을 초과하고 SQL 문을 저장하는 데 사용할 버퍼가 충분히 큰 경우 SQL 문을 저장하는 데 필요한 최대 버퍼를 계산합니다.
  • QUOTENAME 또는 REPLACE 함수의 반환 값에 특히 주의합니다.
    이러한 함수는 입력 데이터의 길이가 n자일 때 모든 입력 문자가 구분 문자이면 2*n + 2 또는 2*n을 반환합니다.
  • C/C++ 응용 프로그램의 경우 SQL 문을 준비하는 데 사용한 StringCchPrintf와 같은 API의 반환 값에 대해 버퍼 부족 오류가 발견되었는지 확인합니다.

잘라내기를 통한 SQL 주입 문제 검색
  • 구분 문자열 또는 이스케이프된 문자열을 저장하는 데 사용된 버퍼 길이를 검토합니다.
  • n이 입력 문자열의 길이이면 QUOTENAME의 반환 값을 저장하는 데 2*n + 2가 필요하고 REPLACE의 반환 값을 저장하는 데 2*n이 필요합니다.
  • C/C++ 응용 프로그램의 경우 REPLACE에 상응하는 함수의 반환 값에 대해 버퍼 부족 오류가 발견되었는지 확인합니다.

블랙 박스 메서드 사용
자동화 도구나 지능형 퍼저(Fuzzer)가 있는 경우에는 다음과 같은 방법을 사용하여 SQL 문의 문제를 검색할 수 있습니다.

SQL 주입 문제 검색
  • 작은따옴표를 입력 데이터로 보내서 사용자 입력이 동적 SQL 문에서 문자열 리터럴로 관리 및 사용되지 않는 경우를 검색합니다.
  • 오른쪽 대괄호(] 문자)를 입력 데이터로 사용하여 정리되지 않은 사용자 입력이 SQL 식별자의 일부분으로 사용되는 경우를 검색합니다.

잘라내기 문제 검색
  • 버퍼 오버런 검색을 위해 문자열을 보내는 것처럼 긴 문자열을 보냅니다.

잘라내기를 통한 SQL 수정 문제 검색
  • 작은따옴표 문자(또는 오른쪽 대괄호나 큰따옴표)로 구성된 긴 문자열을 보냅니다.
    이 경우 REPLACEQUOTENAME 함수의 반환 값이 최대값을 초과하게 되어 SQL 문을 저장하는 데 사용되는 명령 변수가 잘릴 수 있습니다.

 

 

 

Bala Neerumalla는 Microsoft의 보안 소프트웨어 개발자이며 응용 프로그램 보안 취약점 조사를 전문적으로 담당하고 있습니다.

 

### 출처 : MSDN Magazine / 저작권자 : Microsoft Corporation ###

 


 
 

 
 인텔은 오늘 코어 i5와 코어 i3의 브랜드의 세부사항을 살짝 공개했습니다.

 요점은 아래와 같습니다.
 1) 새로운 브랜드는 인텔 코어. 이 브랜드는 3가지로 나뉘는데 코어 i7, 코어 i5, 코어 i3이다.
 2) 코어2 듀오와 코어2 쿼드 브랜드는 앞으로 사라질 것이다.
 3) 펜티엄, 셀러론, 아톰은 유지
 4) 센트리노는 인텔의 WiFI와 WiMAX제품명에 2010년 부터 적용.

 그런데 뭘로 코어 i7, 코어 i5, 코어 i3를 나눌까요? 제 생각에 따르면 데스크탑 프로세서는 이렇습니다.


 코어 i7은 오직 LGA-1366소켓만을 사용하지만 앞으로는 LGA-1156 소켓의 i7, i5, i3 CPU도 들어갈 겁니다. 더 이상 메모리 채널의 숫자와 QPI의 지원여부로 브랜드를 가르지 않습니다. 이 말은 곧, 린필드가 코어 i7과 코어 i5 두가지에 모두 속할 수 있다는 겁니다.

 LGA-1156 코어 i7은 8xx시리즈가 될 것이고, LGA-1366 i7은 9xx시리즈가 될 겁니다. 그리고 i5는 6xx시리즈가 되고 i3는 5xx시리즈가 될 겁니다.

 4개의 코어와 HT지원, 터보모드 지원을 한다면 코어 i7. 만약 최대 4개의 쓰레드만 지원한다면 코어i5. 터보모드까지 빠지면 i3 입니다.

 그러나 모바일의 경우는 약간 다릅니다


 모바일 i7에는 2개 또는 4개의 코어와 4개 또는 8개의 쓰레드를 지원하는 듀얼코어나 쿼드코어 모바일 프로세서가 속할겁니다. 나머지 제품군은 데스크탑의 규칙을 따르므로 i5와 i3는 4개의 쓰레드를 가지고 i3은 터보모드가 빠집니다.

출처: 아난드텍

 모질라는 차기 메이저 브라우저로 보이는 파이어폭스 3.5의 RC2 버전을 내놓았습니다. 겍코 1.9.1 렌더링 플렛폼에 기반한 이 RC2버전은 70여개의 언어를 지원하며 최종 릴리즈의 모든 기능- 즉 개인 브라우징모드, 트레이스몽키 자바스크립트 엔진, HTML5 지원, 네이티브 JSON과 웹 워커 쓰레드, 지오로케이션을 포함한 여러 기능을 자랑했습니다.

 차세대 파이어폭스의 기능을 당장 보고 싶은 분들은 여기에 들어가서 RC2를 다운로드 받으세요.

출처: tech connect magazine


웹 개발 중, 브라우저 크기에 따라 텍스트 길이가 길어질 경우가 있다.
그럴 경우 자동으로 "..." 처리 하는 방법이 있는데,
누구나 아는 방법이겠지만, 간단하게 설명하겠다.

table 태그 내에 style="TABLE-layout:fixed;"
td 태그 내에 nobr태그가 있을 경우 자동으로 ... 처리가 가능하다.

<HTML>
<HEAD>
<STYLE>
.longcut  { text-overflow : ellipsis;overflow : hidden; }
</STYLE>
</HEAD>
<TABLE style="TABLE-LAYOUT: fixed" border=1 width="100%"><TR><TD class=longcut><NOBR>안녕하세요 영어 숫자 아아앙 adfdfdd 1234 45777 아라앙아아앙아앙 1259800</NOBR></TD></TR><TR><TD class=longcut><NOBR>익스플로러 창 사이즈를 늘였다 줄였다 해보세요.<NOBR></NOBR></TD></TR>
</TABLE>

</HTML>

우선 아래 압축 파일을 푼 뒤,
스킨의 파일 업로드에 스크립트 텍스트 파일을 제외하고
두개의 파일을 업로드합니다.


그리고 다음 작업으로 스킨 페이지에 스크립트를 추가해야 하는데,
기존 스킨 소스에 보시면 [##_article_rep_title_##] 이라는 기존의 포스트 타이틀에 대한 치환 코드가 있을 것이다.
(Ctrl + F을 이용하여 검색하면 쉽게 찾을 수 있다.)

검색해보면 아래와 같은 코드를 찾을 수 있다.
<h2><a href="[##_article_rep_link_##]">[##_article_rep_title_##]</a></h2>

해당 코드를 지우고, 아래 스크립트 코드를 추가한다.
<script language="javascript"  src="./images/viewTitle.js" type="text/javascript"></script>
<script language="javascript">
     showTitle("./images/", "viewTitle.swf", 600, 30, "[##_article_rep_title_##]", "[##_article_rep_link_##]", "center", "0x00000");
</script>

위 스크립트 소스를 보면 showTitle 이라는 함수를 호출하는데,
해당 함수에 대한 옵션을 부가 설명하겠다.
showTitle("플래시 파일을 업로드한 주소", "플래시 파일명", "제목 가로 크기", "제목 세로 크기", "제목 치환자 코드", "제목 링크 치환자 코드", "정렬방법", "제목 색상");

정렬 방법은 center, left, right로 속성을 지정할 수 있으며,
제목 색상은 16진수 표기법으로 표현하여야 한다. (예: black => 0x00000)

마지막으로 여기서 주의할 점이 있다면, 
공개/보호/비밀글 마다 따로 서식을 따로 가지고 있는 스킨 같은 경우 해당 코드를 여러개 찾을 것이다.
그럴 경우 이 작업을 반복하시면 된다.

II 6.0 까지는
web.config에서
<httpRuntime executionTimeout="18000" maxRequestLength="2000000"/>
태그만 설정해주면 되었는데요.

IIS 7.0에서는 좀 추가 작업이 필요하네요.

<system.webServer>
  <security>
      <requestFiltering>
         <requestLimits maxAllowedContentLength="2147483648"/>
      </requestFiltering>
   </security>
</system.webServer>

그런데 컴퓨터에 따라
이 설정 적용 후 페이지를 띄우면 이런 메세지가 뜹니다.

이 아래와 같은 메세지가 뜨면
C:\Windows\System32\inetsrv\config\applicationHost.config
파일의 <section name="requestFiltering" overrideModeDefault="Deny" />를
<section name="requestFiltering" overrideModeDefault="Allow" />
로 변경해 주시면 됩니다.

* 이 적용을 web.config에서도 할수도 있는데요. 제가 아직 그 부분은 해보질 않아서...
   ^^;; 아시는 분은 좀 가르쳐 주세요.


HTTP 오류 500.19 - Internal Server Error
요청된 페이지와 관련된 구성 데이터가 잘못되어 해당 페이지에 액세스할 수 없습니다.

이 구성 섹션은 이 경로에서 사용할 수 없습니다. 섹션이 부모 수준에서 잠겨 있는 경우 이 오류가 발생합니다. 이러한 잠금은 기본적으로 설정(overrideModeDefault="Deny")되거나 overrideMode="Deny" 또는 레거시 allowOverride="false"와 함께 위치 태그를 사용하여 명시적으로 설정합니다.

MS-SQL 트리거(Trigger)에 대해서 간단하게 적어보았습니다.

트리거란?

비디오 대여 샵을 예로 들면 고객이 1번 테이프를 빌려갔는데 '대여중' 표시가 되어 있지 않으면 '대여가능' 이기 때문에 다른 고객에게 실수 할 수 있다.
이럴 때 대여를 해 갔다면 알아서 '대여중'으로 표시되고 다시 반납하면 '대여가능'으로 표시가 된다면 대여 관리가 편해 질것이다.
이처럼 트리거는 하나의 작업이 발생할 때마다 그작업의 발생과 동시에 작동하는 일련의 작업들이다.
한 테이블과 관련되어 존재하는데 Insert, Delete, Update 세가지 형태로 만들수 있다.

트리거 만들기
트리거 생성 구문

CREATE TRIGGER 트리거이름 ON { table | view }
[WITH ENCRYPTION]
{
{ {FOR | AFTER | INSTEAD OF }
{ [INSERT][,][UPDATE][,][DELETE]}

AS
SQL구문

트리거 사용 예제
A테이블의 INSERT 되는 내용을 B테이블에 자동으로 저장 할 때

CREATE TRIGGER tr_INSERT ON A
FOR INSERT
AS
 INSERT INTO B
  SELECT *,'INSERT' FROM INSERTED

A테이블의 DELETE 되는 내용을 B테이블에 자동으로 저장 할 때

CREATE TRIGGER tr_DELETE ON A
FOR DELETE
AS
 INSERT INTO B
  SELECT *,'DELETE' FROM DELETED

A테이블의 UPDATE 되는 내용을 B테이블에 자동으로 저장 할 때
(UPDATE할때는 INSERTED와 DELETED가 함께 발생 합니다.)

CREATE TRIGGER tr_UPDATE ON A
FOR UPDATE
AS
 INSERT INTO B
  SELECT *,'UPDATEINSERT' FROM INSERTED
 INSERT INTO B
  SELECT *,'UPDATEDELETE' FROM DELETED


블로그에 프로그램 소스를 적용시키려고 할때, 지져분할 때가 많다.
조금이나마 깔끔하게 작성하기 위해 외국에서 제공하는 Syntax Highlighter 2.0을 적용해 보기로 한다.

우선 아래 링크에서 zip파일을 다운 받아, 압축을 푼 뒤 스킨 올리기 기능을 이용하여 모든 파일을 올린다.
(적용시키고자 하는 프로그램 언어만 받아 올려도 상관없지만, 여기선 다 올리기로 한다.)


파일을 올렸다면, HTML/CSS 편집에 들어가 아래의 html 소스를 추가한다.
(추가할 소스는 html 페이지의 <head> 안에 넣으면 된다.)
 <head>
    ......(중략)......
    <script type="text/javascript" src="./images/shCore.js"></script>
    <script type="text/javascript" src="./images/shBrushCpp.js"></script>
    <script type="text/javascript" src="./images/shBrushCSharp.js"></script>
    <script type="text/javascript" src="./images/shBrushCss.js"></script>
    <script type="text/javascript" src="./images/shBrushDelphi.js"></script>
    <script type="text/javascript" src="./images/shBrushDiff.js"></script>
    <script type="text/javascript" src="./images/shBrushJScript.js"></script>
    <script type="text/javascript" src="./images/shBrushPlain.js"></script>
    <script type="text/javascript" src="./images/shBrushXml.js"></script>
    <script type="text/javascript" src="./images/shBrushMsx.js"></script>
    <script type="text/javascript" src="./images/shBrushAvs.js"></script>
    <script type="text/javascript" src="./images/shLegacy.js"></script> 
    <link type="text/css" rel="stylesheet" href="./images/shCore.css"/>
    <link type="text/css" rel="stylesheet" href="./images/shThemeDefault.css"/>
    <script type="text/javascript">
        SyntaxHighlighter.config.bloggerMode = true;
        SyntaxHighlighter.config.clipboardSwf = './images/clipboard.swf';
        SyntaxHighlighter.all();
    </script>
</head>

이렇게 해서 모든 작업은 완료 하였으며 이제는 적용한 화면을 보도록 하자.
적용하는 방법은 그리 어렵지 않다.

프로그램 코드 앞 부분에는 <pre>태그 뒷 부분에는 </pre>로 씌워주면 끝이다.
예시) <pre class="brush:c-sharp; highlight:[3,5];">소스 부분</pre>

brush:c-sharp 는 C#언어를 나타낸 것이며,  highlight 속성은 해당 라인를 강조하겠다는 표시이다.


마지막으로 결과 화면이다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace LinqToTerraServerProvider
{
    public class QueryableTerraServerData : IOrderedQueryable
    {
        #region Constructors
        /// 
        /// This constructor is called by the client to create the data source.
        /// 
        public QueryableTerraServerData()
        {
            Provider = new TerraServerQueryProvider();
            Expression = Expression.Constant(this);
        }

        /// 
        /// This constructor is called by Provider.CreateQuery().
        /// 
        /// 
        public QueryableTerraServerData(TerraServerQueryProvider provider, Expression expression)
        {
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            if (!typeof(IQueryable).IsAssignableFrom(expression.Type))
            {
                throw new ArgumentOutOfRangeException("expression");
            }

            Provider = provider;
            Expression = expression;
        }
        #endregion

        #region Properties

        public IQueryProvider Provider { get; private set; }
        public Expression Expression { get; private set; }

        public Type ElementType
        {
            get { return typeof(TData); }
        }

        #endregion

        #region Enumerators
        public IEnumerator GetEnumerator()
        {
            return (Provider.Execute>(Expression)).GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (Provider.Execute(Expression)).GetEnumerator();
        }
        #endregion
    }
}
css 수정으로 자기만의 스타일로 꾸밀수도 있다.

오라클이 1일 퓨전 11g 제품군을 출시했다고 미국 지디넷뉴스가 보도했다. 이 제품은 그동안 오라클이 인수한 애플리케이션 기술을 총 집결하고 있다. 클라우드컴퓨팅을 포함해 소프트웨어에서 과거에는 화제가 됐지만 이제는 관심 속에서는 사라져가고 있는 온디맨드 개념 등이 총 망라됐다.

 

오라클은 11g 제품군에서 다양한 영역의 신제품을 출시했으며 이들은 모두 통합 기능이 강화됐다. 이번 선보인 신제품은 미들웨어, SOA, 개발툴, 계정관리 등이다. 오라클은 데이터모델링 솔루션을 이용해 A애플리케이션 생명주기관리(ALM) 시장에 대한 공략까지도 강화한다.

 

제품명을 좀 더 구체적으로 살펴보면 오라클 퓨전 미들웨어 11g, 오라클 SOA 스위트, 웹로직 스위트, 웹센터 스위트, 아이덴티티 매니지먼트 등이다.

 

양기크룹 애널리스트인 다나 가드너는 퓨전 미들웨어 11g는 궁극적으로는 클라우드 개념을 추구하고 있는 것으로 분석했다.

 

오라클은 이번 제품에서 통합 기능을 강조하면서도 핫플러그인을 통해 제품을 꽂기만 하면 되는 조립하는 형식의 제품이라고 강조하고 있다.

 

가드너는 "11g를 통해 각 제품을 통합하는 게이트웨이 역할을 함으로써 '언제', '어떤 애플리케이션'이든 사용할 수 있는 미래를 추구하고 있다"고 설명했다. 이같은 점이 클라우드컴퓨팅 개념과 유사하다.

 

오라클 11g는 이번달 국내 출시도 앞두고 있다. 한국오라클은 오는 15일 11g 신제품들에 대한 국내 출시발표 행사를 계획하고 있다.


최근에 들은 소식인데, TmaxSoft 에서 토종 기술을 살려만든 OS를 공개한다는 소식이다.

TmaxSoft는 처음듣는 사람도 많지만,
기업용 솔루션 / 컨설팅 서비스 / 각종 기술 지원 / 교육 등 여러분야에서 힘쓰고 있는 대표적인 IT 기업이다.
(대기업 이름에만 익숙한 분들은 모를지도 모른다.)

1997년 회사설립후  꾸준히 발전하고 해외에도 지부가 있는 회사이다.

티맥스 소프트 홈페이지 : http://www.tmax.co.kr/


그런곳에서 그동안의 경험을 바탕으로 OS - 이름하여 Tmax Window를 개발했고, 7월 7일 공개한다고 한다.
들리는 말에 의하면, 작년 정도에 이미 말이 나왔었고, 이번년도 초 공개 예정이었는데 점점 미뤄저서 7월까지 왔다고 한다.
아무튼 7월7일 세미나식으로 진행되는 2009TmaxDay에서 그 실체를 "공개" 한다고 한다.[각주:1]


티맥스 윈도우 2009 TmaxDay 등록 :
http://tmaxday.tmaxwindow.co.kr/registration/
(행사자체가 무료이고, TmaxWindow 티셔츠도 준다고 한다. OS나 새로운 도전에 관심이 있다면 꼭 등록하자. 필자도 등록하였다.~!!!!)


또한 홈페이지에서는 홍보를 위해 여러 이벤트가 진행중이니, 경품을 원하시는 분들도 많이 참여하시기 바란다. 



온라인 이벤트 참여 : http://tmaxday.tmaxwindow.co.kr/event/event1/


T-Max Window 공개가 18일 남은 현재 시점에서
관련하여 공개된 것이라고는 티맥스윈도우폰트 2가지 밖에 없다.
OS(Operate System)의 수많은 기능중 공개된것이 없다.
뭐 7월 7일을 위해서 아껴둔 것일지 몰라도, 약간의 의구심이 든다.

T-Max Window에 대한 약간은 부정적인 글 : http://blog.naver.com/saltynut/120064925551
(읽다보면 맞는 말이다. - 아무것도 공개되지 않은 시점에서 너무 기대만하기에는 무언가 부족하다.)


하지만 역시 우리나라 순수기술이라는 점에 충분히 가치를 둘 수 있는 것이고,
나조차 혹시 세간을 뒤집을 만한 새로운 기술을 들고 나오는 것 아닌가 기대가 된다.

그러나 또한편으로는 유료 OS는 MS가 잠식했고, 무료 OS는 리눅스가 잠식한 상황에서
(그 상황에서도 리눅스는 조금씩 사용양이 증가하고 있는데)
T-Max Window가 유료 OS로서, 어떤 장점을 부각시키며 세상의 이슈로 떠오르느냐 하는 것이다.

또한 국산에서 발매가 되더라도 우리나라의 더러운 소프트웨어 문화 및 인식이 어떻게 평가해줄 것인지가 의문이다.
아마 처음에는 국산제품으로서 꼭 성공하세요! 라고 했던 사람들도 결국 T-Max Window를 외면할 지도 모른다.
(솔직히 굳이 돈들여 익숙하지 않은 제품을 살 필요는 없다.)

왠지 예전 심형래의 디워가 계속 떠오르는 이유는 뭘까?



덧 1. 혹시 사람들중 너무 부정적인 면으로만 보지 말라고 하는 분들도 있다. 맞는 말이다.
       하지만 그런사람들은 힘내라고만 하고 망하면, 소프트웨어를 사주기는 커녕 아예 잊을 사람들이고,
       차라리 단점을 말해주는 사람들이 오히려 회사를 더 생각해주고, 걱정해주는 거라고 본다. (억지인가 -.,-)
       적어도 난 발매되면 기념으로 하나 사줄 예정이니까 말이다.

덧 2. T-max Soft가 과연 이번 OS에 얼마나 투자할지가  궁금하다. 
      사의 존망을 뒤흔들만큼 올인 투자를 할것인가? 아니면 부수입 및 부 프로젝트형식으로 진행할것인가? (당연히 후자겠지...) 

T-Max Window 공식 BLOG : http://twinblog.tistory.com/
T-Max Window 공식 HomePage : http://tmaxday.tmaxwindow.co.kr/main.asp

 


[.NET REFERENCE]
명명 규칙 (Naming Rule)
개발 업무시 각 개발 요소에 대한 이름으로 명명 규칙(Naming Rule)을 준수함으로써 코드의 완전성과 가독성을 향상시키고 명확한 의미 부여를 생산성을 높힐 수가 있습니다.

1. 명명 규칙 준수를 통한 업무 생산성 효과
   - 일종의 규약을 설정하여 프로젝트 개발자 및 구성원 들간의 원활한 업무적 의사소통 가능
   - 업무 단계별 산출물 사이의 일관성 유지
   - 명확한 의미 부여로 산출물 사이의 연관성 및 코드 가독성을 높힘

2. 명명 규칙 준수시 공통 사항
   - 업무 영역에 적합하고 연관되게 정의된 용어를 사용
   - 같은 유형의 요소에 대해서는 혼동을 방지하기 위해, 유사 명칭이나 대소문자만 다른 같은 명칭 사용 금지

3. 대소문자 혼용
   - 여러 개의 단어로 이루어진 이름의 경우 대소문자를 적절히 혼용하여 코드의 가독성을 향상시킵니다.
     (예시) MemberInfo, ProductDetail, FlightReservation
   - 대소문자 혼용 기법
유   형 설     명 예   시 적용 대상
Pascal Case 모든 단어의 첫번째 글자를 대문자로 쓴다. ProductCatalog 클래스
열거형(Enum), 열거값
이벤트
읽기전용 정적 필드
인터페이스
메서드
네임스페이스
속성
Camel Case 맨 첫번째 글자는 소문자로, 나머지 각 단어의 첫번째 글자를 소문자로 쓴다. productCatalog 매개변수(parameter)
인스턴스 필드, 클래스 변수
Uppercase 모든 글자를 대문자로 쓴다. System.IO 2글자 정도의 단어
상수


4. 약어 사용을 자제
   - 가능한 한 단어 전체를 사용 ==> 코드의 가독성 및 의미 파악 명확
      (예시) ProCat --> ProductCatalog
   -  명칭이 지나치게 길어지는 경우, 일반적으로 통용되거나 사전에 정의된 약어를 적절히 사용
      (예시) Temporary --> Temp,  Information --> Info,  UserInterface --> UI,  Number --> No
   - 약어 사용시, 2글자 단어는 Uppercase을, 2글자 초과시는 Pascal 또는 Camel case을 적용하여 사용
      (예시) System.Web.Ui --> System.Web.UI,  HTMLButton --> HtmlButton,  UserControlCheck --> UCCheck

5. 단어 사용시 주의사항
   - 업무에 적합하고 연관된 단어를 선정, 정의
   - 같은 유형시 유사한 명칭이나 대소문자만 서로 다르게 한 명칭 사용 금지
   - .NET Framework의 네임스페이스와 중복되지 않아야 함
   - .NET Framework 및 각 언어 (C#, VB.NET)에서 미리 정의된 키워드(keyword) 이름과 중복되지 않아야 함

6. 네임스페이스(Namespace) 명명 규칙
   - 네임스페이스 이름은 Pascal case을 적용
     (기본 구조) 회사명.도메인/부서.애플리케이션/시스템명.하위시스템.논리적계층
                 (예시) Microsoft.Windows.WindowsServer.IIS
   - 필요에 따라서는 업무 시스템에 맞게 '도메인/부서', '하위 시스템', '논리적 계층' 등의 부분 이름은 생략이 가능  
수   준 내   용 고정값 / 예제 생략가능
1 회사명 COMPANY X
2 도메인 / 부서 Development O
3 애플리케이션 / 시스템 이름 MessengerApp X
4 하위 시스템 InstantChatting O
5 논리적 계층 Biz O
      
   (예시) 회사명.부서.애플리케이션 --> COMPANY.Development.MessengerApp

7. 클래스(Class) 명명 규칙
   - 명사 / 명사구 사용
   - Pascal case 적용
   - C++ 에서의 MFC 스타일처럼 클래스를 나타내는 C 등의 접두사를 사용하지 않음
      (예시) CMessengerInfo --> MessengerInfo
   - 클래스의 성격에 따라 접두사 또는 접미사를 적절히 사용
   - 권장되는 클래스 명명 규칙
구  분 명명 표준 예  시
Base Class 공통기능명 + Base RuleBase, DacBase
Business Facade [Use Case Group명] + System/Facade/Service ProductSystem, OrderService
Business Rule 트랜잭션 사용 : [Use Case Group명] + _Tx EmployeeInfo_Tx
트랜잭션 미사용 : [Use Case Group명] + _NTx EmployeeInfo_NTx
Data Access [Table명] + _Dac Members_Dac
Type Dataset ds + [Table명] dsMembers
Exception Class [사용자정의예외명] + Exception BusinessRuleException


8. 인터페이스(Interface) 명명 규칙
   - 대문자 I 를 접두사로 사용하여 인터페이스임을 표시
      (예시) IServiceProvider, IComponent
   - 다른 내용은 클래스 명명 규칙과 동일

9. 메서드(Method) 명명 규칙
   -  동사 / 동사구(동사 + 명사) 사용
   - Pascal case 적용
   - Business Logic, Data Access 계층의 클래스 메서드는 사전에 약속된 동사 사용
      * Business Logic : 동사 + 명사 (조합)
      * Data Access : 동사
   - Business Logic과 Data Access 계층 클래스 메서드 명명 비교
작업구분 Business Facade / Rule Data Access
추가 Add / AddNew / Append / Register + 명사
   (예시) AddNewMemberInfo
Insert
수정 Modify / Change / Update + 명사
   (예시) UpdateMemberInfo
Update
삭제 Remove / Delete + 명사
   (예시) DeleteMemberInfo
Delete
조회 Get / Inquire + 명사
Get / Inquire + 명사 + By + 조건 (Optional)
   (예시) GetMemberInfo, GetMemberInfoByMemberID
Select / Inquire


10. 열거형(Enum) 명명 규칙
   - Pascal case 적용
   - 약어는 꼭 필요한 경우에만 사용
   - 열거형 type 이름에 Enum 접두사를 사용하지 않음
   - 열거형 type : 단수형 이름,  비트 필드 : 복수형 이름 사용
   - 비트 필드 열거형에는 항상 FlgAttribute를 추가

11. 변수(Variant) 및 필드(Field) 명명 규칙
   - 변수 이름은 짧으면서도 의미가 있는 단어 사용. 명사 / 명사구 사용
   - 헝가리안 표기법은 가급적 사용하지 않음
   - 루프 카운터(loop counter; 예 for문 등)를 제외하고는 모호한 이름(i, j, s, a 등)을 사용하지 않음
   - 메서드의 매개변수(parameter) : 매개변수의 이름과 type을 통해 매개변수의 의미를 확인할 수 있을 정도로 설명적이어야 함
   - 매개변수(parameter), 지역 변수, 인스턴스 필드(instance field) : Camel case 적용
   - 정적 필드(static field) : Pascal case 적용
   - 데이터 바인딩(data binding)시 데이터 바인딩 UI 컨트롤의 필드 이름과 데이터베이스의 필드 이름은 서로 동일하게 선언

12. 상수(Constants) 명명 규칙
   - Uppercase 적용 (모두 대문자 사용)
   - 단어와 단어 사이는 _ 로 연결
      (예시) int MAX_COUNT = 1000;

13. 속성(Property) 명명 규칙
   - 명사 / 명사구 사용
   - Pascal case 적용
   - 헝가리안 표기법을 사용하지 않음
   - 속성 : 내부 type (private)과 동일한 이름 사용 (단, VB.NET의 경우 내부 type 이름 앞에 m_ 접두사 사용, 예시 : m_Age)
   - Private 인스턴스 필드를 노출시, 속성명은 인스턴스 필드의 Camel case를 Pascal case로 전환
      (단, VB.NET의 경우 내부 type 이름 앞에 m_ 접두사 사용)
   (예시) C# 언어를 사용하여 속성 명명 규칙을 적용한 코드 예시

public class Hello {
  
// 내부 type인 경우, Camel case 적용
  
private int
itemCount;
  
  
// Private 인스턴스 필드를 외부에 노출하고자 하는 경우 또는 속성, Pascal case
  
public int
ItemCount {
      get { ... }
      set { ... }
   }
}



14. 이벤트(Event) 명명 규칙
   - Pascal case 적용
   - 헝가리안 표기법을 사용하지 않음
   - 이벤트 처리기 이름 : EventHandler 접미사 사용
      (예시) MouseEventHandler
   - 2개의 매개변수 지정 : sender, e
   - 이벤트 인수 클래스 이름 : EventArgs 접미사 사용
      (예시) MouseEventArgs
      (예시) public delegate void MouseEventHandler(object sender, MouseEventArgs e);
   - 시점을 나타내는 경우, BeforeXXX / AfterXXX 대신 ~ing / ~(e)d 형태를 사용
      (예시) BeforeClose, AfterClose  -->  Closing, Closed
정리 문서 

작업 그룹 이름을(를) 액세스할 수 없습니다. 이 네트워크 리소스를 사용할 권한이 없습니다.


원인
이 문제는 다음 조건 모두에 해당하는 경우에 발생할 수 있습니다.
작업 그룹에 있는 하나 이상의 컴퓨터에 TCP/IP에서 NetBIOS 사용 기능이 설정되어 있지 않습니다.
작업 그룹에 있는 하나 이상의 컴퓨터에서 컴퓨터 브라우저 서비스가 시작되지 않았거나 해제되어 있습니다.

해결 방법
이 문제를 해결하려면 작업 그룹 내의 각 컴퓨터에 TCP/IP에서 NetBIOS 사용 기능이 설정되어 있고 컴퓨터 브라우저 서비스가 실행 중인지 확인하십시오. 이렇게 하려면 다음 단계를 수행하십시오.

1단계: TCP/IP에서 NetBIOS 사용 설정
1. 시작, 제어판을 차례로 누른 다음 네트워크 및 인터넷 연결을 누릅니다.
2. 네트워크 연결을 누릅니다.
3. 로컬 영역 연결을 마우스 오른쪽 단추로 누른 다음 속성을 누릅니다.
4. 인터넷 프로토콜 (TCP/IP)을 누른 다음 속성을 누릅니다.
5. 일반 탭을 누른 다음 고급을 누릅니다.
6. WINS 탭을 누릅니다.
7. NetBIOS 설정에서 TCP/IP에서 NetBIOS 사용을 누른 다음 확인을 차례로 두 번 누릅니다.
8. 닫기를 눌러 로컬 영역 연결 속성 대화 상자를 닫습니다.
9. 네트워크 연결 창을 닫습니다.

2단계: 컴퓨터 브라우저 서비스 시작
1. 시작을 누르고 내 컴퓨터를 마우스 오른쪽 단추로 누른 다음 관리를 누릅니다.
2. 서비스 및 응용 프로그램을 두 번 누릅니다.
3. 서비스를 두 번 누릅니다.
4. 오른쪽 창에서 Computer Browser를 마우스 오른쪽 단추로 누른 다음 시작을 누릅니다.
5. 컴퓨터 관리 창을 닫습니다.


6월 25일 11회로 종영한 일본 드라마 "BOSS"
너무 잼있게 본 탓인지 너무 아쉽기만 하다.
미드 CSI와 스토리 흐름이 비슷하긴 하지만
일본 드라마만의 매력이 있는 드라마라고 할 수 있다.
戸田恵梨香、可愛いい。


일본 드라마 『BOSS』엔딩 주제곡

 My Best Of My Life

- sung by. Superfly


 今ここで息をしてみる

(이마 고코데 이키오 시테미루)
あたしがここにあるように

(아타시가 고코니 아루 요우니)
包まれて生きてるようで

(츠츠마레테 이키테루요우데)
確かなものを 探すのはなぜ

(타시카나 모노오 사가스노와 나제)


지금 여기 숨을 쉬어봐

내가 여기에 있는 것처럼

주위에 둘러싸여 있는데도

확실한 것을 찾는 건 왜일까


足早に過ぎてく日々も

(아시바야니 스기테쿠 히비모)

間違いではないのかな

(마치가이데와 나이노카나)
ちぎれそうな心を背負って

(치기레소우나 고코로오 세옷테)
それでも明日を追いかけていく

(소레데모 아스오 오이카케테이쿠)


서둘러 지나가는 날들도

잘못되어 있는 건 아닐까

부서질 듯한 마음을 안고

그래도 내일을 쫓으며 살아


めぐり逢いの中で見つける

(메구리아이노 나카데 미츠케루)
生きてく意味を 育ててみよう

(이키테쿠 이미오 소다테테미요우)
涙は拭い去って

(나미다와 누구이삿테)
今 始まる (my) best of my life

(이마 하지마루 (my) best of my life)

 

만남들 속에 찾아낸

삶의 의미를 잘 키워보자

눈물은 모두 닦아내

지금 시작될거야 (my) best of my life


幸せに浸ることさえ

(시아와세니 히타루 고토사에)
なんだか怖く感じて

(난다카 코와쿠 칸지테)
乾いてた心の悲鳴も

(카와이테타 고코로노 히메이모)
気づけないまま 犠牲にした

(키즈케나이마마 기세이니 시타)

 

행복에 빠지는 것조차

어쩐지 두려워서

메마른 내 마음의 비명도

듣지 못한 채 희생시켰지


優しさに包まれたとき

(야사시사니 츠츠마레타 토키)
全て美しく見えすぎるの

(스베테 우츠쿠시쿠 미에스기루노)
ただ 全力で生きてる

(타다 젠료쿠데 이키테루)

それだけなのに

(소레다케나노니)
どうして人は 後悔を重ねる…?

(도우시테 히토와 고카이오 카사네루…?)


부드럽게 안겼을 때

모든 게 너무나 아름다워보였지

그저 온 힘을 다해 살아갈

그 뿐인데

어째서 사람은 후회만 늘어갈까…?


幸せを恐れることなく

(시아와세오 오소레루 고토나쿠)
誰かの胸に飛び込めたら

(다레카노 무네니 토비코메타라)
涙は風に舞って

(나미다와 카제니 맛테)
愛せるような (my) best of my life

(아이세루 요우나 (my) best of my life)

 

행복을 두려워하지 말고

누군가의 품으로 뛰어들어

눈물은 바람에 날려버려

사랑해줄 수 있을 (my) best of my life


本当は誰かにすがりたくて

(혼토우와 타레카니 스가리타쿠테)
ただ 過ぎ去って消えてった

(타다 스기삿테 키에텟타)

足跡は無駄じゃないと

(아시아토와 무다쟈나이토)
確かに心の中で生きてる

(타시카니 고코로노 나카데 이키테루)
そんな言葉に

(손나 고토바니)

抱きしめられて 眠りにつきたいの

(다키시메라레테 네무리니 츠키타이노)


실은 누군가에 매달리고 싶어서

그저 스쳐지나 사라져버린

과거는 무의미한 게 아니라고

분명히 마음 속에 숨쉬는

그런 말들에

안겨 잠들고 싶어


信じながら 許し合いながら

(신지나가라 유루시아이나가라)
誰かの胸に飛び込めたら

(다레카노 무네니 토비코메타라)
ほほえみと溶け合って

(호호에미토 토케앗테)
あふれるような (my) best of my life

(아후레루요우나 (my) best of my life)

 

믿으며 용서하며

누군가의 품으로 뛰어들면

미소가 녹아들어

가득 넘치는 (my) best of my life

 

めぐり逢いの中で見つけた

(메구리아이노 나카데 미츠케타)
生きてく意味を育ててみよう

(이키테쿠 이미오 소다테테미요우)
涙は拭い去って

(나미다와 누구이삿테)
今 始まる (my) best of my life

(이마 하지마루 (my) best of my life)

 

만남들 속에 찾아낸

삶의 의미를 잘 키워보자

눈물은 모두 닦아내

지금 시작될거야 (my) best of my life

 

今 始める (my) best of my life

(이마 하지메루 (my) best of my life)

 

지금 시작할거야 (my) best of my life

 

+ Recent posts