본문 바로가기

CTF

[LINE CTF 2023] old pal(미해결)

<문제>

 

<풀이>

1. 시작

링크로 들어가면 나오는 첫 화면이다. 주소창을 확인해보면 password 파라미터에 아직 값이 입력되지 않은 상태인 것을 확인할 수 있다.

 

my $pw = uri_unescape(scalar $q->param("password"));

코드를 확인해보면 password 파라미터의 값을 $pw 변수가 받고 있는 것을 확인할 수 있다. password 파라미터에 올바른 패스워드 값을 입력하면 되는 것으로 보인다.

 

2. 코드 분석

if (eval("$pw == 20230325")) {
    print "Congrats! Flag is LINECTF{redacted}"
} else {
    print "wrong password :(";
    die();
};

FLAG와 직접적으로 관련된 코드부터 살펴보면, 패스워드가 20230325일 때 FLAG를 출력해주는 것을 확인할 수 있다.

 

그 외의 코드들에서는 패스워드가 만족해야할 조건들을 확인할 수 있다.

 

if (length($pw) >= 20) {
    print "Too long :(";
    die();
}

패스워드의 길이가 20보다 길면 안 된다.

 

if ($pw =~ /[^0-9a-zA-Z_-]/) {
    print "Illegal character :(";
    die();
}

패스워드에 0~9 사이의 숫자, 영문 대소문자, 특수기호 '_', '-' 외의 문자가 들어가면 안 된다.

 

if ($pw !~ /[0-9]/ || $pw !~ /[a-zA-Z]/ || $pw !~ /[_-]/) {
    print "Weak password :(";
    die();
}

패스워드는 반드시 0~9 사이의 숫자, 영문 대소문자, 특수기호 '_' 또는 '-' 를 포함해야 한다.

 

if ($pw =~ /[0-9_-][boxe]/i) {
    print "Do not punch me :(";
    die();
}

확실하지는 않지만 패스워드에 영문자 b, o, x, e가 들어가면 안 되는 듯하다.

 

if ($pw =~ /AUTOLOAD|BEGIN|CHECK|DESTROY|END|INIT|UNITCHECK|abs|accept|alarm|atan2|bind|binmode|bless|break|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|connect|cos|crypt|dbmclose|dbmopen|defined|delete|die|dump|each|endgrent|endhostent|endnetent|endprotoent|endpwent|endservent|eof|eval|exec|exists|exit|fcntl|fileno|flock|fork|format|formline|getc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|goto|grep|hex|index|int|ioctl|join|keys|kill|last|lc|lcfirst|length|link|listen|local|localtime|log|lstat|map|mkdir|msgctl|msgget|msgrcv|msgsnd|my|next|not|oct|open|opendir|ord|our|pack|pipe|pop|pos|print|printf|prototype|push|quotemeta|rand|read|readdir|readline|readlink|readpipe|recv|redo|ref|rename|require|reset|return|reverse|rewinddir|rindex|rmdir|say|scalar|seek|seekdir|select|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|state|study|substr|symlink|syscall|sysopen|sysread|sysseek|system|syswrite|tell|telldir|tie|tied|time|times|truncate|uc|ucfirst|umask|undef|unlink|unpack|unshift|untie|use|utime|values|vec|wait|waitpid|wantarray|warn|write/) {
    print "I know eval injection :(";
    die();
}

eval injection에 이용되는 명령어들을 필터링하고 있는 코드이다.

 

if ($pw =~ /[Mx. squ1ffy]/i) {
    print "You may have had one too many Old Pal :(";
    die();
}

코드의 의미를 파악하지 못했다.

 

3. 익스플로잇

패스워드가 충족해야 하는 조건들을 만족시키며 20230325라는 의미로 쓰일 수 있는 문자열을 만들어보려고 시도해봤지만 답을 찾지 못했다.