(UseModWiki소스수정/위키스팸막기 페이지로부터 자동으로 이동)

[첫화면으로]UseModWiki소스수정/Comments와Thread매크로스팸막기

마지막으로 [b]

1. comments 와 thread 매크로 스팸막기
1.1. 아이디어
1.2. 장단점이랄까, 암튼 생각해볼 문제
1.3. wiki.pl 수정
1.4. action/comments.pl 수정
2. 스팸 트랙백 막기
2.1. 부작용
2.2. wiki.pl 수정
2.3. action/tb.pl 수정
3. 페이지를 통채로 수정해 버리는 WikiSpam 막기
3.1. wiki.pl 수정
4. comments 와 thread 매크로 스팸막기 (구버전)
5. 추가 업데이트 내역
6. 로그 남기기
7. 사용자 의견

1. comments 와 thread 매크로 스팸막기

/Comments매크로, /Thread매크로를 사용하여 쉽게 커멘트를 달 수 있게 했더니만 스팸이 기승을 부리는 터라...

이미 2006년8월에 ext1.97에서 구현을 한번 했었지만, 이 구현은 정상적인 사용자들이 매번 "NOSPAM"등의 문자열을 필드에 추가러 넣어줘야 하니 아무래도 불편하다. 그래서 새로 고쳐보았다. (2007년1월8일. ext1.101)

기본 아이디어는 [스팸 코멘트, 트랙백을 막기 위한 CCode 와 TCode 플러그인 from AlogBlog]에 있는 CCode에서 얻었다. 그런데 주인장은 그 CCode 루틴을 분석해서 똑같이 적용할 만한 내공이 안 되는 터라, 좀 간단하게 바꿔 보았다.

1.1. 아이디어

코멘트 입력 폼에 히든 필드(필드 이름은 ccode) 하나를 추가하여, 정상적으로 웹브라우저를 통해 코멘트를 입력할 때는 그 필드값이 그대로 전송이 되므로 문제가 없지만, 스팸 봇이 POST를 시도할 때는 그 필드가 누락되었기 때문에 스팸으로 간주하여 무시하도록 한다.

이 ccode의 값은 어떻게 결정되느냐 하면, 그 페이지 이름과 그 날의 날짜를 crypt 함수에 넣어서 만든다. 좀 더 정확히는 "페이지 이름 문자열의 길이"와 "월-일" 형태의 문자열을 이어서 (ex. "Test"페이지, 2007년 1월 9일에 해당하는 문자열은 "41-9") 사용한다.

그러니 스팸 봇이 웹페이지를 읽고 소스코드를 분석해서 ccode값을 얻어내는1 수고를 한다 하더라도, 그 값은 그 페이지(와 이름의 길이가 같은 페이지들)에 대해서만 그날 하루와 다음날까지만 유효하다. (다음날은 왜 유효하냐 하면... 정상적인 이용자가 23:55에 웹페이지를 띄운 후에 코멘트를 작성하고 다음날 00:05에 확인 버튼을 누를때 스팸으로 취급되는 것을 막기 위해서이다2)

1.2. 장단점이랄까, 암튼 생각해볼 문제

1.3. wiki.pl 수정

이미 아래 있는 구버전의 구현을 수작업으로 적용한 사이트가 있다면, 다시 원래대로 되돌려 놓고 다음의 수정을 적용해야 합니다. -.-;

sub MacroComments {
    ...
    my $submit_button;

# CCode - 이 줄 추가
    my $ccode = &simple_crypt(length($id).substr(&CalcDay($Now),5));

    if ($long) {
    ...
        &GetHiddenValue("up","$up") .
# 아래 줄 추가
        &GetHiddenValue("ccode","$ccode") .
        (($threadindent ne '')?&GetHiddenValue("threadindent",$threadindent):"") .
    ...
}

아래 함수는 통채로 추가
# 인자를 $HashKey를 salt로 하여 crypt하고, 앞의 두 바이트 제외하여 반환
sub simple_crypt {
    my ($orig) = @_;

    my $encrypt = crypt($orig, $HashKey);

    return substr($encrypt, 2);
}

1.4. action/comments.pl 수정

sub action_comments {
    ...
    my $anchor;
    my $match = 0;

# 이 줄은 스팸과는 관계없는데 덩달아 수정
    return if (!&ValidIdOrDie($id));

# ccode - 이 단락 추가
    my $ccode = &GetParam("ccode", "");
    my ($code_today, $code_yesterday);
    $code_today = &simple_crypt(length($id).substr(&CalcDay($Now),5));
    $code_yesterday = &simple_crypt(length($id).substr(&CalcDay($Now - 86400),5));

    if (($ccode ne $code_today) && ($ccode ne $code_yesterday)) { # spam
        &ReportError("SPAM comment");
        return;
    }
# 여기까지

# 금지단어 처리는 여기서 먼저
    if (my $bannedText = &TextIsBanned($newcomments)) {
        print &GetHeader("", T('Editing Denied'),"");
        print Ts('Editing not allowed: text includes banned text');
        print " [$bannedText]";
        print "\n<br><hr noshade size=1><p><strong>". T('This is the text you submitted:').
                "<br>". T('(Copy the text, go back with your browser, paste the text, and edit again please)').
                "</strong><p>".
                &GetTextArea('text', $newcomments, &GetParam("editrows", 20), &GetParam("editcols", 65)).
                "<p>\n";
        print &GetCommonFooter();
        return;
    }

    # 블로그 지원을 위한 꽁수
    ...
}

2. 스팸 트랙백 막기

TrackBack의 경우도 동일한 아이디어로 처리한다. 트랙백 주소에 "tc=******" 라는 항목이 추가되었고, 이 tc의 값은 페이지 이름과 그 날의 날짜에 의해 달라진다. 트랙백 주소는 당일날과 그 다음날까지 유효하므로, 봇이 페이지를 읽어서 트랙백 주소를 얻어내더라도, 그 페이지에 한해서 그 다음날까지만 보낼 수 있다. (봇이 스팸 테러를 하기에는 충분히 넉넉한 기간이긴 하다 -_-;)

2.1. 부작용

이제는 특정 페이지의 트랙백 주소가 날짜에 따라서 달라진다는 얘기고, 따라서 페이지의 메타 정보에 트랙백 주소를 넣거나 하는 경우에 문제가 됩니다. (2007.1.8 현재 이곳의 위키에는 그런 기능이 없습니다만) 즉 그런 메타정보를 읽어서 자동으로 트랙백을 쏴줄수 있는 그런 프로그램을 통해서 트랙백을 보내는 것은 힘들어진다는 거죠. alogblog에서도 언급하고 있고, 거기서는 일단 트랙백을 받아서 DB에만 저장하고 웹페이지에는 반영을 하지 않은 다음에, 관리자가 직접 판단해서 반영 여부를 결정하게 하였더군요. 여기서는... 그때가 되면 생각하기로 합시다. :-)

2.2. wiki.pl 수정

sub GetTrackbackGuide {
    ...
    my $encoded = &EncodeUrl($id);
# TCode
    my $tcode = &simple_crypt(length($id).substr(&CalcDay($Now),5));

#   my $url = $FullUrl . &ScriptLinkChar() . "action=tb&id=$encoded";                이 줄 아래처럼 수정
    my $url = $FullUrl . &ScriptLinkChar() . "action=tb&tc=$tcode&id=$encoded";

    if (&PageCanReceiveTrackbackPing($id)) {
    ...
}

2.3. action/tb.pl 수정

sub action_tb {
    ...
    my $excerpt = &GetParam('excerpt');
# tcode - 이 아래 두 단락 추가
    my $tcode = &GetParam('tc',"");
    my ($code_today, $code_yesterday);
    $code_today = &simple_crypt(length($id).substr(&CalcDay($Now),5));
    $code_yesterday = &simple_crypt(length($id).substr(&CalcDay($Now - 86400),5));

    if (($tcode ne $code_today) && ($tcode ne $code_yesterday)) { # spam
        &SendTrackbackResponse("1", "SPAM trackback");
        return;
    }
# 여기까지

# UTF-8 -> EUC-KR 전환
    ...
}

3. 페이지를 통채로 수정해 버리는 WikiSpam 막기

UseMod:WikiSpam도 같은 방식으로 막을 수 있지 않을까 기대를 하며...

만일 수작업으로 페이지 수정을 들어가서 바꾸는 거라면 못 막고... 봇이 그 과정을 그대로 따라하는 거라면 역시 못 막는다. -_-;

3.1. wiki.pl 수정

페이지 편집 화면에 tcode 히든 필드를 삽입

sub DoEdit {
    ... 한참 아래로 내려가서
    if ($canEdit) {
###
###############
        print &GetHiddenValue("title", $id), "\n",
                    &GetHiddenValue("oldtime", $pageTime), "\n",
                    &GetHiddenValue("oldconflict", $isConflict), "\n";
        if ($revision ne "") {
            print &GetHiddenValue("revision", $revision), "\n";
        }
# ECode - 여기 두 줄 추가
        my $ecode = &simple_crypt(length($id).substr(&CalcDay($Now),5));
        print &GetHiddenValue("ecode","$ecode")."\n";
###
        print &GetTextArea('text', $oldText, $editRows, $editCols);
}

페이지를 저장할 때 코드 확인

sub DoPost {
    my $string = &GetParam("text", undef);
    my $id = &GetParam("title", "");
    my $summary = &GetParam("summary", "");
    my $oldtime = &GetParam("oldtime", "");
    my $oldconflict = &GetParam("oldconflict", "");
# ECode - 아래 두 단락 추가
    my $ecode = &GetParam("ecode","");
    my ($code_today, $code_yesterday);
    $code_today = &simple_crypt(length($id).substr(&CalcDay($Now),5));
    $code_yesterday = &simple_crypt(length($id).substr(&CalcDay($Now - 86400),5));

    if (($ecode ne $code_today) && ($ecode ne $code_yesterday)) { # spam
        &ReportError("SPAM editing");
        return;
    }
### 여기까지
    DoPostMain($string, $id, $summary, $oldtime, $oldconflict, 0);
    return;
}

4. comments 와 thread 매크로 스팸막기 (구버전)

5. 추가 업데이트 내역

ext1.101 - 완전히 내용이 바뀜. 사용자가 추가로 코드를 넣는 방식을 없애고, 자동으로 확인 필드를 삽입하도록 함.

ext1.102 - 트랙백 관련 코드에도 적용.

ext1.102a - ccode와 tcode를 생성할 때 사용하는 인자로, "페이지 이름의 길이"와 오늘 날짜를 나타내는 문자열 중 "월-일" 부분을 합쳐서 사용하도록 수정.

ext1.103 - 페이지 수정 관련 코드에도 적용.

ext1.103a - 커멘트의 중간에 등록 금지 단어가 있는 경우에, 커멘트 저장은 안 되면서 BlogRc 페이지는 고쳐지는 문제 수정

ext1.109c

6. 로그 남기기

이 패치로 얼마나 스팸을 막을 수 있는지 로그를 남겨서 보려고 코드를 수정해 보았습니다. 이건 배포용 소스에는 넣기가 그래서 여기에 수정 내용을 적어 둡니다. 제 위키와 조프위키, 바벨 셋 중에서 가장 스팸에 시달리던 곳이 바벨인지라, 바벨에 적용해 보고 일주일쯤 후에 로그파일을 한번 살펴보면 어떨까 싶어요.

코멘트와 트랙백의 경우는, 원래 있는 소스를 고치지 말고, action/ 디렉토리 아래 있는 comments.pl과 tb.pl을 myaction/ 디렉토리로 복사한 후에, myaction 아래 있는 걸 고치면 편하겠습니다. 아니면 그냥 아래 링크에서 다운로드해서 myaction 디렉토리에 넣으셔도 됩니다. 나중에 myaction 아래 있는 걸 지우면 원상복귀 되니까요. 페이지 수정의 경우는 wiki.pl 을 직접 고쳐야 하는 터라 그러지 못하겠네요.

코멘트는 myaction/comments.pl : Upload:comments.txt.txt (뒤의 .txt.txt 를 .pl로 바꿀것)
    if (($ccode ne $code_today) && ($ccode ne $code_yesterday)) { # spam
### begin of logging routine - 이 단락 추가
       my ($authorAddr) = $ENV{REMOTE_ADDR};
       my ($timestamp) = CalcDay($Now) . " " . CalcTime($Now);
       if (open (LogFile, ">>$DataDir/__spam__")) {
           printf (LogFile "C|%-19s|%-15s|%s\n", $timestamp, $authorAddr, $id);
           close LogFile;
       }
### end of logging routine
        &ReportError("SPAM comment");
        return;
    }

트랙백은 myaction/tb.pl : Upload:tb.txt.txt (뒤의 .txt.txt 를 .pl로 바꿀것)
    if (($tcode ne $code_today) && ($tcode ne $code_yesterday)) { # spam
### begin of logging routine
       my ($authorAddr) = $ENV{REMOTE_ADDR};
       my ($timestamp) = CalcDay($Now) . " " . CalcTime($Now);
       if (open (LogFile, ">>$DataDir/__spam__")) {
           printf (LogFile "T|%-19s|%-15s|%s\n", $timestamp, $authorAddr, $id);
           close LogFile;
       }
### end of logging routine
        &SendTrackbackResponse("1", "SPAM trackback");
        return;
    }

페이지 수정은 wiki.pl 수정
    if (($ecode ne $code_today) && ($ecode ne $code_yesterday)) { # spam
### begin of logging routine
       my ($authorAddr) = $ENV{REMOTE_ADDR};
       my ($timestamp) = CalcDay($Now) . " " . CalcTime($Now);
       if (open (LogFile, ">>$DataDir/__spam__")) {
           printf (LogFile "E|%-19s|%-15s|%s\n", $timestamp, $authorAddr, $id);
           close LogFile;
       }
### end of logging routine
        &ReportError("SPAM editing");
        return;
    }

세 군데 다 완전히 동일한 코드이고 딱 하나 printf 에 보면 따옴표 직후에 C, T, E만 다릅니다. 만일 스팸이 이 패치에 의해 걸러지게 되면 위키 데이타가 있는 디렉토리($DataDir)에 __spam__ 이란 파일에다가 아래와 같이 로그를 남길 겁니다.
T|2007-1-10 12:13 am |220.80.107.90  |연습장       <-- T는 트랙백을 의미, 그 다음은 날짜, IP주소, 페이지

7. 사용자 의견

트랙백에도 마찬가지로 응용해서, 트랙백 주소에 이 ccode값을 포함하면 될 것 같습니다. 그러나 스팸봇이 매번 페이지를 읽고 트랙백주소를 얻어간다면 무용지물이겠지요. 그래서 일단은 그제 올린 수정(트랙백 주소의 action값만 바꾼)이 얼마나 잘 통하는지를 관찰을 좀 해볼까 싶어요. 제일 스팸트랙백에 시달리던 바벨의 도서관이 마침 어제 그 수정을 했으니, 얼마나 오래 견디는지 좀 구경했으면 (^^;) 좋겠네요.

오후쯤에 트랙백에도 적용한 코드를 올리긴 하겠습니다만, 그 트랙백 패치는 바벨에 적용하는 건 며칠 미뤄주시면 좋겠습니다. 이 페이지에 있는 코멘트 패치는 바로 적용하셔도 될 듯. 딱히 부작용은 없을 것 같네요. 혹시 구현에 문제가 있다면 조프님이 보고 발견해줄거라 기대를... ^^;
-- Raymundo 2007-1-8 9:49 am

알겠습니다. 매번 감사~
-- Nyxity 2007-1-8 10:36 am

action/comments.pl 에서 저는
my $anchor;
my $match = 0;
이게 없던데, 이것도 추가해 줘야 하나요?
-- Nyxity 2007-1-8 10:47 am

comments.pl 전체에서 그 두 변수가 쓰이는 곳이 없다면 없어도 됩니다. anchor는 스레드 댓글을 달았을때 바로 그위치로 이동하는 것이고, match는 comment 매크로가 없는 페이지에 스팸봇이 코멘트를 달았을때 blogrc 페이지만 갱신되는 것을 막으려고 넣은 것이니 둘 다 있는 게 나을 듯 합니다. 그냥 comments.pl 은 그대로 가져다 쓰셔도 되지 않을런지. (따로 수정하신 게 있다면 그 부분은 옮겨 주셔야겠지만)
-- Raymundo 2007-1-8 10:42 am

으윽, 서버의 시계가 너무 빨라서 늦췄더니만, 코멘트 작성 시각이 엇갈렸군요. 뭐 별 문제 없겠지...
-- Raymundo 2007-1-8 10:50 am

아 걍 가져다 쓰면 되는군요. 그 방법을 생각못했네.
-- Nyxity 2007-1-8 11:45 am

나 원 -_-; 이 패치 적용하고 반나절도 안 되어서 스팸 코멘트가 TrackBack 페이지에 줄줄줄... 진짜 매번 웹페이지 가져오는겐가? -_-;;;
-- Raymundo 2007-1-8 1:19 pm

으윽, 바벨도 오늘 스팸트랙백이 하나 날라왔던데... 전에 비하면 양호한 것 같기도 하지만... 진짜 그 자바스크립트 써서 코드값을 감추기까지 구현해야 하려나요 =.=;
-- Raymundo 2007-1-8 4:10 pm

그렇긴 한데, 기존 시달리던 페이지랑은 다른 페이지라서..
-- Nyxity 2007-1-8 4:53 pm

네 사실 그래서 약간은 안도했어요. 아직 트랙백 패치를 안 하신 상태이니. 오히려 제 홈에 스팸 코멘트가 매우 불길하군요. :-)
-- Raymundo 2007-1-8 5:21 pm

맙소사.. -_- 날짜가 바뀌면서 code값이 바뀌는 걸 확인하려 했는데 바뀌지를 않더군요. 펄과 C에서 제공하는 crypt 함수는 스트링의 앞 8바이트만 가지고 결과를 만들어 낸다는 걸 방금 매뉴얼 보고 알았습니다. ㅠ,.ㅠ
-- Raymundo 2007-1-9 12:17 am

crypt의 인자가 8바이트 이하가 되도록 수정했습니다.
-- Raymundo 2007-1-9 1:47 am

그러고보니... 이거 페이지를 수정할 때도 적용하면 페이지를 통채로 수정하는 WikiSpam도 막을 수 있지 않을까 하는 생각이...
-- Raymundo 2007-1-10 12:09 pm

일단 반영해 보았고... 슬쩍 이 GyparkWikiEditAllowed 옵션 값을 바꿔서 로그인하지 않은 사람도 수정이 가능하도록 해 보았습니다. (이 한 몸 실험 대상으로 내어놓아...) 좀 지켜볼 예정인데, 워낙 인기없는 사이트라서 과연 :-)
-- Raymundo 2007-1-10 2:34 pm

아 제 바벨에서 코멘트를 달려고 하니 금지단어가 있어서 수정불가라고 하는데 금지단어는 페이지에 없는 단어이거든요. 근데 모노로그 코멘트란에 보면 다양한 스팸코멘트들이 달려고 했던 시도들이 보이더군요. 그래서 그런 기록이 남아서 그런게 아닐까 멋대로 추측을 하는데, 꽤 당황했어요.
-- Nyxity 2007-1-10 3:36 pm

바벨에 오늘도 스팸이 보이던데...

알록블록의 구현처럼 자바스크립트를 써서 code를 감추는 방법을 추가로 구현한다 하더라도,
1) 스팸이 줄어도 정말 그 감추기 덕분에 스팸이 주는 것인지 확인하기 힘들고
2) 결정적으로 페이지 편집이나 트랙백은 몰라도, 횡설수설 같이 한 페이지 내에 코멘트창이 수십개 들어있는 곳에서는 매번 서버 쪽에서 감추기 코드를 생성하고 클라이언트 쪽에서는 자바스크립트가 그 계산을 해야 한다는 게 참 성능에 저하가 될 것 같습니다.

이래저래 고민이네요.
-- Raymundo 2007-1-10 10:59 pm

그 로그파일에 뭐 좀 남는게 보이면 그나마 기분이라도 좋을텐데 제 홈의 경우는 몇 시간이 지나도 전혀 없군요 흐...
-- Raymundo 2007-1-10 11:00 pm

오옷 어제 밤에 세 차례 스팸 코멘트 시도가 있었다가 이 패치에 의해 무산되었었군요. 헛되지 않았어.. ㅠ,.ㅠ
-- Raymundo 2007-1-12 8:50 am

제 모노르그에 함 커멘트 달아주시겠어요? 자꾸 등록금지단어 달었던 기록이 남아선지..
-- Nyxity 2007-1-12 6:15 pm

참. 적용은 했어요
-- Nyxity 2007-1-12 6:16 pm

아... 모노로그 하위 페이지인 BlogRc 페이지에 문제가 있었네요. 스팸트랙백을 예전에 받으면서 거기에 그 트랙백 내용이 적혔고, 그 이후에 금지단어 목록에 그게 추가되니까, 이후에는 정상적인 코멘트를 달 경우 코멘트는 제대로 저장이 되는데, BlogRc를 갱신하려고 하는데 이미 내용에 금지단어가 들어가 있으니 거기서 문제가 되었네요. 그 라인을 지워주었으니 이제 잘 될 겁니다 ^^ BlogRc 페이지도 종종 들여다보면서 스팸 찌꺼기를 지워주시면 좋을 듯 하네요. (애초에 블로그 흉내 내려고 편법으로 우겨넣은 거다보니 관리에도 좀 신경쓸게 많군요 ^^;)
-- Raymundo 2007-1-12 9:40 pm

아 거기를 보면되는 것이었군요. 감사감사
-- Nyxity 2007-1-12 10:05 pm

로그파일을 보니 2월26일 이후에 막지 막지 못하는 듯 하군요.
-- Nyxity 2007-4-10 5:33 pm

뭐 이곳도 하루에 하나 이상 꼬박꼬박 받고 있다보니 -_-; 이거 영 잘 안 돌아가는 것 같기도하고... 한글 스팸들은 매일 사이트 직접 찾아와서 폼에 데이타 넣고 submit하는 것 같기도 하고... 저도 잘 모르겠어요, 딱히 날짜 때문에 제대로 동작하지 않는 건 아닌것 같은데.
-- Raymundo 2007-4-10 6:09 pm

역시 부지런히 등록금지단어 등록밖에..
-- Nyxity 2007-4-10 8:02 pm

언제부턴가 매일 여기에 걸리는 스팸 트랙백이 300여개에 달해서, 아주 뿌듯해하고 있었는데... 로그를 보니 이게 다 구글의 IP였다 -_-;;; 스팸을 남기려 한 게 아니라 URL이 있으니 그냥 크롤링 하려고 했었나본데, 트랙백 주소는 링크가 아니라 텍스트로 남아 있는데 이걸 왜....
-- Raymundo 2012-2-9 12:12 pm
이름:  
Homepage:
내용:
 

위키위키분류
각주:
1. 값 자체는 html코드에 그대로 드러나 있어서, 파싱만 하면 금방 얻어낼 수 있다. alogblog에서 하는 것처럼 자바스크립트를 써서 값을 흐트려놓지는 않았음
2. 코멘트를 작성하는데 24시간 이상을 들이는 사용자가 있다면... 정말 힘들게 작성한 코멘트가 스팸 취급 받아 날아가 버리겠지만... 설마 그런 경우는 없겠지.

마지막 편집일: 2012-2-9 12:12 pm (변경사항 [d])
5166 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기