엄마보고싶다(3) - CTF 문제로 뜯어보기

By choirish | December 11, 2016

엄마보고싶다(3) - CTF 문제로 뜯어보기





으아으아으아으아 안녕안녕? 안녕하세요? ㅎㅎㅎㅎ



아 시작부터 글쓴이의 상태가 헤롱헤롱한게 느껴지네요 ㅋㅋㅋ

오늘은 특별히 오글거리는 프롤로그가 없어영(하지만 감격적인 오글토글 에필로그가 있을 예정…)


지난 시간에 뭘 했나 구경하면~!


  • SetUID야 너의 존재의 이유는 뭐니?

  • Command Injection아 안녕? 너랑 친해지고 싶어! ( ; || && 활용법을 배웠음!!)

  • 냠냠 맛보기당 FTZ 3번 문제를 풀어보자~


이렇게 끝이 났어요 ㅎㅎㅎㅎㅎㅎㅎ


그럼 오늘은~!


  • Command Substitution아 이리와, 너에 대해 알고 싶어졌어! (backquote(`) 활용법을 배울 거임!!)

  • 알았으니 이제 써먹어 주겠다, 문제 뽀개기! - Defcon2015 babycmd


지난 시간에 Command Injection의 방법으로 < ; || && > 요로코롬 세 가지를 살짝 구경해봤다면,

오늘은 하나 더! < ` command ` or $( command ) > 활용법을 배울 거에요 ㅎㅎㅎ

이것도 엄청 많이 쓰는 방법이랍니다!!


그리고 오늘 이걸 이용해서 문제도 뽀갤거라능 ㅎㅎㅎ


그럼! 바로바로 들어가볼게요~




Command Substitution, 넌 뭐니?


갑자기 또 Command 뭐시기 배운다고 하니까 새로운 공격 방법인가?! 우리 갑자기 딴 거 또 배우는 건가?! 싶을 수도 있어요 ㅎㅎ

하지만 논노 그거 아니라는 ㅎㅎㅎ

이것도 ; 나 | (pipe line)처럼 리눅스 쉘에서 사용하는 문법입니다! 어떤 녀석인지 알아봅시다 ㅎㅎ


< 표현 방식 >


우선 Command Substitution의 표현법은 두 가지입니다!

(앞으로 두 방법을 언급 시 back quote와 dollar라고 하겠습니다)


  1. ` command ` : back quote(back tick)

  2. $( command ) : dollar


둘 다 완전히 똑!같!은! 기능을 수행하기 때문에 아무거나 골라 써도 되긴 하는데….

nesting을 할 때는 dollar 표시를 쓰는 게 헷갈리지 않고 편한 것 같습니다 ㅎㅎ

여기서 nesting 이라 함은 겹겹이! 즉, echo $( echo $( ls ) ) 요로코롬 밖에 쓰고 안에 또 쓰고 할 때입니다 ㅎㅎ


만약에 같은 명령에 back quote을 쓴다면 echo `echo\ `ls\ `` 요로코롬 써줘야 합니다 ㅎㅎ

안쪽 back quote에는 앞에 backslash()를 붙여줘서 ` 형태로 써야! 나는 `를 쓸 거야! 하고 명확히 밝혀 줄 수 있습니다ㅎㅎ

그냥 무심코 echo `echo `ls`` 요로코롬 쓰면 안되는!!! 거죠 ㅎㅎㅎ 조심!!


보기 쉽게 뙇 정리해보면?!


echo $( echo $( ls ) )        [ O ]  
echo `echo \`ls\``            [ O ]  
echo `echo `ls``              [ X ]


이런 이유로…. $( command )를 많이 쓴다고도 하는데… 이건 뭐 사람따라 다른 것 같습니돠!

왜냐면 저는 ` command `를 주로 사용하거든요 ㅋㅋㅋ

그래서 앞으로 Command Substitution을 쓸 때는 대표로 back quote를 사용할게여 ㅎㅎ


< 하는 일 >


Command Substitution이 뭘 하는 애인지!!!!!가 가장 중요하졍 ㅎㅎㅎ


먼저 Command Substitution의 단어를 뜯어서 해석하면, “명령어를 치환해준다”인데….

음… 명령어를 그 결과값으로 치환해준다! 바꿔준다! 뭐 요정도로 이해하면 되겠네요!!?! ㅎㅎ


간단히 한 줄로 요약하면 이렇습니다!!


`command` : command가 실행된 결과의 출력값  


즉 다음과 같은 명령어를 쉘에 입력해 주면??!


command1  `command2`  


command2를 실행한 결과값을 command1의 인자로 넘겨주겠다~는 뜻이 됩니다ㅎㅎ


근데 어떻게 command2를 먼저 실행시켜서 그 값을 가져올 수 있는 거지? 궁금할 수 있죠! ㅎㅎ

설명에 따르면, `command2`라는 부분을 subshell( 하위 쉘??! 본 쉘 뒤에서 스윽 실행되는 쉘! 그런 쉘! )에서 실행시킨 다음에

그 결과를 본 쉘로 가져와 사용하는 거라고 합니다 오홍 역시 그냥 막 되는 일이란 없고, 다 체계적으로 진행되고 있었네요! 아항


그럼 이제 Command Substitution!! backqoute!! 사용법을 잘 터득하셨나요?  제가 참고한 곳은 아래 두 곳입니다!


Bash Hackers Wiki - Command Substitution

고급 Bash 스크립팅 가이드: Bash를 이용한 쉘 스크립팅 완전 가이드 - 명령어 치환




Defcon 2015 예선에 출제된 Babycmd 문제를 뽀개 보자!


지난 시간… Command Injection에 대해 좀 더 알게 되었고, 핵 간단 ftz 3번 문제를 뽀개보았고,

그리고 방금 전에… Command Substitution이란 걸 또 하나 배웠습니다 ㅎㅎ

그럼 이제 학습 경험치 좀 쌓으셨으리라 믿고…!!!?


지난 시간 예고한대로 CTF에 출제되었던 Command Injection 관련 문제를 풀어보도록 하여요.

Defcon!!!!!! 2015 예선(Qualification Round)의 문제가 되겠습니다 우아우아우앙…사실 롸업은 이곳저곳에 많지만… 그래도 나름대로 설명 해보겠습니다!


크게 어렵지 않은 문제이니, 풀어볼까요?


[띠링] choirish님이 Command Substitution을 알게 되었습니다.

[띠링] choirish님께 새로운 과제가 주어졌습니다. 열어보시겠습니까?


[수락] choirish님이 “Babycmd 뽀개기” 과제를 수락하셨습니다.


…..ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 문제 풀러 기기!!

먼저! 문제 바이너리 파일을 다운받습니다 ㅎㅎ

요기 로들어가서 View Raw를 클릭하시면 손쉽게 바이너리를 다운 받으실 수 있습니다 헤헿


아 들어가기 전에 당부말씀!! ㅎㅎ (콘치 선원의 멘트를 벤치마킹함!ㅋㅋ)


본래 이 Babycmd 문제는 대회에서 출제할 당시 리모트 문제였어요! 즉 대회 측에서 제공한 서버에 접속하여 프로그램을 실행하고 입력값을 넣는 형태였습니다 ㅎㅎ 그래서! 그러한 리모트 환경까지 세팅하여 문제를 풀어보면 더 완벽하겠으나~ 우리의 주된 목적은 문제를 통해 Command Injection!! 공격을 직접 해보는 것!!일 뿐~ ㅎㅎ


과감히 리모트 환경을 포기하기로 하였습니다 하하하하하하핳!! 그러니 저는 64bit Ubuntu 환경에 Babycmd 파일을 가져오고, 셀프로 직접 flag 파일을 만들어서! Babycmd를 통해 flag를 읽는!!!! 작업을 성공시켜보도록 하겠사옵니다!


그리하여…. 저는 요로코롬 Babycmd 파일을 Ubuntu에 옮기고, flag 파일도 만들어주었어용



간단한 메시지를 flag 파일에 담아뒀는데! 그 내용은!! 이따가 문제 뽀개기를 통해 읽어보는 걸로~ ㅎㅎ

실행하면 요로코롬 Welcome! 환영해주면서 ping, dig, host, exit 명령어를 쓸 수 있다고 알려줍니당



시험 삼아 ping, dig, host 명령어를 사용해보아요 ㅎㅎ



일반적으로 여러분들이 알고 있는 ping, dig, host 명령어와 똑!같!은 기능을 가졌어요 ㅎㅎ

ping, dig, host가 뭐하는 아이들인지 난 몰랐다! 하시면 밑의 링크를 참고하여 후다닥 보고 오시는걸로!


ping / dig / host


문제 푸는데 각 기능이 아주 중요하지는 않으니까… 지금 막 공부해오실 필요는 없어요ㅎㅎ

ping에는 IP주소, dig와 host에는 도메인 주소를 인자값으로 넣으시면 실행 테스트에 별 무리 없을 거니까! 잘 모른다고 걱정 노노해~


Why??! 우리에겐 IDA가 있으니까! 마법같은 HexRay!

그럼 문제 해결에 필요한 핵심 정보들을 Get!!하기 위해 IDA 분석하러 기기!!


IDA를 켜고 헥스레이느님[F5]을 실행하였더니 코드가 뙇!

64bit ELF 파일이니까 IDA도 64bit 버전으로 잘 실행해주어요~


왼쪽의 함수 목록에 여러 개의 함수들이 있는데…



그 중 분석해 볼만한 함수 다섯(main을 제외한!)을 뽑고, 함수 이름도 알아보기 쉽게 바꿔줍니다.


  • check1_D65

  • check2_DCC

  • ping_E35

  • dig_F5C

  • host_10BD


이제 main을 포함해서 요 여섯 가지 함수를 뜯어보아요 헿




< main >


우선 main 함수 아래쪽을 보면~


    if ( !strcasecmp(dest, "ping") )
    {
      ping_E35(v7);
    }
    else if ( !strcasecmp(dest, "dig") )
    {
      dig_F5C(v7);
    }
    else if ( !strcasecmp(dest, "host") )
    {
      host_10BD(v7);
    }
    else
    {
      puts("Unknown command");
    }


요로코롬 ping! dig! host! 하는 녀석이구나~ 요 명령어들을 실행시켜주는 애구나~ 딱 보입니다 ㅎㅎㅎ

사용자가 입력한 명령어가 ping!이면 ping_E35, dig!이면 dig_F5C, host!면 host_10BD를 실행하여

각자 본래의 역할을 수행하는 함수를 호출하네용~


요 각각의 함수들도 하나씩 살펴봐야 하는데~ 그 전에 더 신경쓰이는 녀석!! 핵심같아보이는 녀석!!

check1_D65check2_DCC을 먼저 뜯어보기로 합시다.

(딱 보니까 사용자의 입력값을 검사하는 함수인 거 같아서 check1/2로 이름 지어줬습니다 데헿)




< check1_D65 >


check1_D65 함수입니다.


signed __int64 __fastcall check1_D65(char *a1, _BYTE *a2)
{
  char v2; // al@1

  v2 = *a1;
  if ( !*a1 )
  {
LABEL_10:
    *a2 = 0;
    return 1LL;
  }
  while ( v2 == ' ' )          // 공백문자(' ') 금지
  {
LABEL_9:
    v2 = *++a1;
    if ( !*a1 )
      goto LABEL_10;
  }
  if ( (unsigned __int8)(v2 - '&') <= 1u )          // &와 ' 금지
    return 0LL;
  if ( v2 == ('|') )          // 파이프라인( | ) 금지
    return 0LL;
  if ( v2 == '*' )          // * 금지
    return 0LL;
  if ( (v2 & 0xFD) == '!' )          // ! 금지
    return 0LL;
  if ( (unsigned __int8)(v2 - ':') > 1u )          // :와 ; 금지
  {
    *a2++ = v2;
    goto LABEL_9;
  }
  return 0LL;
}


제가 분석한 대로 주석을 달아보았어요 ㅎㅎ 사실 원래는 지금 주석 달아놓은 & * 같은 문자가 십진수로 표현이 되어있는데!

마우스를 갖다 대니까 char!!(character)라고 알려줘서! 요로코롬 문자 형태로 바꿔준 겁니다 ㅎㅎ

(해당 십진수를 클릭하고 키보드에서 r을 눌리면 자동으로 char형으로 바꿔줘용 핵친절 IDA느님!)


코드 해석에 조금이나마 도움이 되시라고 제가 아스키 테이블에 금지 문자를 뙇! 표시해보았습니다 ㅎㅎ


# 출처 : 위키피디아



정리하면 이 함수는 요로코롬 금지 문자를 정해서 해당 문자가 입력값에 포함되어 있으면

0을 return 하여 if문 안으로 못 들어가게 하는 녀석입니다!!

요 함수를 ping_E35, dig_F5C, host_10BD 에서 모두 호출하는데! 이 함수에서 1이 return돼야만이 if문의 조건을 만족시켜서

그 다음 단계(입력한 명령어를 실행시켜주는 단계)로 진행할 수 있는 겁니다 ㅎㅎㅎ


즉!!! 여기에 있는 (공백문자) ! & ' * : ; |는 입력값에 사용할 수 없습니다… 뚜둔

근데… 딴 건 왜 막는지 솔직히 아직 잘 모르겠는데… & ; | 요런 거 보니까……ㅎㅎ

Command Injection을 막아보겠다 뭐 이런 의도가 살짝 보입니다??! ㅎㅎㅎㅎㅎㅎㅎㅎㅎ

이전 시간 내용까지만 학습했다면… 포기하고 넘어갔을 수도 있겠지만! 우린 이걸 대비해서 오늘!! 배운 것이 있죵 ㅎㅎㅎ


어머어머  backquote를 안 막네~?? 이거 써먹어야지~??!! 뙇 생각하셨다면 오늘 이제 거의 다 하신 겁니다 ㅎㅎ




< check2_DCC >


check1_D65에서 핵심포인트를 무사히 획득하였으니 두 번째로 check2_DCC 함수도 뜯어봅니다.


signed __int64 __fastcall check2_DCC(const char *a1)
{
  unsigned __int64 v1; 
  signed __int64 result;
  char v3; // dl@4

  v1 = strlen(a1) + 1;          // v1 = ( dig, host 명령의 인자값 길이 ) + 1
  result = 0LL;
  if ( v1 - 4 <= 60 )          // 즉 명령어의 인자값은 63글자 이하여야 한다!
  {
    // 인자값의 첫 번째 글자는 알파벳이거나 숫자(0~9)여야 한다!
    if ( (unsigned __int8)((*a1 & 0xDF) - 'A') <= 25u || (result = 0LL, (unsigned __int8)(*a1 - '0') <= 9u) )
    {          
      v3 = a1[v1 - 2];
      result = 1LL;
      // 인자값의 마지막 글자는 알파벳이거나 숫자(0~9)여야 한다! (check!)
      if ( (unsigned __int8)((v3 & 0xDF) - 'A') > 25u )     
        result = (unsigned __int8)(v3 - '0') <= 9u;
    }
  }
  return result;
}


처음에 이 부분을 이해하느라 좀 걸렸지마능…. ㅎㅎㅎㅎ

*a1이 입력한 인자값의 첫 번째 글자! v3이 마지막 글자!라는 걸 깨닫고 나면

A, 25, 0, 9 요 숫자들에서 감이 뙇뙇!!

아 A부터 알파벳 만족해야 되는구나~ 아 0부터 숫자 만족해야 되는구나~ 알아챌 수 있습니다 (야매기운스믈스믈흐흐)


자아 요로코롬 우리가 ping, dig, host 명령어를 쓸 때 주의해야 할 점들을 뙇 파악했으니!

Command Injection을!! `(back quote)를!! 어디에! 사용하면 좋을까~ 생각하면서 ping / dig / host 를 하나씩 뒤져봅시다 ㅎㅎ




< ping_E35 >


주요한 부분만 퇗퇗 봅니당


if ( a1 )
{
// 금지 문자가 포함되었는지 검사합니다
if ( (unsigned int)check1_D65(a1, &cp) )          
{
  // inet_aton 함수를 이용해 ping의 인자값이 올바른 IP주소 형태인지 확인하고 
  // 맞으면 if문 안으로 들어갑니다
  if ( inet_aton(&cp, &v4) )          
  {
    v1 = inet_ntoa(v4);
    __sprintf_chk(&command, 1LL, 384LL, "ping -c 3 -W 3 %s", v1);
    v2 = popen(&command, "r");
    if ( v2 )
    {
      while ( fgets(&s, 512, v2) )
        __printf_chk(1LL, &s);
      pclose(v2);
    }


pingping이 요 아이는…. inet_aton 함수를 사용해서 IP주소 형태가 아닌 인자값은 걸러내 버려서….

우리가 Command Injection을 하기가 힘들어 보이네요 ㄷㄷ 그럼 패쓰패쓰 다음 걸 살펴보아요

( inet_aton 함수에 대한 설명은 여기를 참고하실 수 있습니다! )




< dig_F5C >


주요한 부분만 퇗퇗


if ( a1 )
{
// 금지 문자가 포함되었는지 검사합니다
if ( (unsigned int)check1_D65(a1, &cp) )         
{
  // 인자값이 IP주소 형태이면
  if ( inet_aton(&cp, &v4) )           
  {
    v1 = inet_ntoa(v4);
    // " dig -x %s " 요러한 형태로 명령을 실행합니다
    __sprintf_chk(&command, 1LL, 384LL, "dig -x %s", v1);          
  }
  else          // 인자값이 IP주소 형태가 아니면
  {
    // 첫 글자와 마지막 글자를 검사합니다
    if ( !(unsigned int)check2_DCC(&cp) )          
    {
      puts("Invalid hostname.");
      return *MK_FP(__FS__, 40LL) ^ v8;
    }
    // " dig '%s' " 요러한 형태로 명령을 실행합니다
    __sprintf_chk(&command, 1LL, 384LL, "dig '%s'", &cp);          
  }
  v2 = popen(&command, "r");


ping과 다르게 check1과 check2를 모두 사용해서 인자값을 검사합니다 ! 엄격한 것! ㅎㅎㅎ

그리고 주의 깊게 볼 점은?!!!!! dig '%s' 요로코롬 입력받은 인자값에 single quote(’ ‘)를 씌어준다는 것이죵!

와우와우와우 뭔가 달라 보인다 ㅎㅎ

입력받은 인자값을 하나로 묶어주려고 그러나….? 왜 저렇게 해놨지? ㅎㅎㅎㅎ


미리 스포합니다 ㅎㅎㅎ 우리는 dig로 Command Injection을 할 수 없습니다 ㅎㅎ host를 사용할거에요 헿

둘이 비교하면서 설명해도 좋은데… 그냥 복잡하니까 dig 다 뽀개고 host로 넘어가는 걸로 해요 ㅎㅎ


왜 dig를 못쓰냐?! 하면!! 우리가 쓰려고 했던 Command Injection에 사용하려 했던 back quote(`)…..가

single quote(’ ‘)안에 들어가면 제 힘을 못 발휘해요!! ㅎㄷㄷ??!! 중요한 내용이니 잠시 짚고 가도록 하죠~




< 짚고 가기 : Single vs Double Quotes in Bash >


우리가 원하는 back quote(`)의 기능은 ` `안에 든 값이 실행된 결과값을 출력해주는 것입니다.

그!런!데! bash 쉘의 명령어 문법에서 single quote는 double quote(” “)보다 stricter(strict : 엄격한)하다고 표현됩니다!

즉… single quote 안에 갇힌 특수 문자( $ ` \ ! 등 )들은… 본디 기능을 수행하지 못하고

그 문자 그대로 살아남아서 출력이 되는 겁니다 ㅎㅎ 물론 double quote 안에서는 제 기능을 고스란히 발휘하는데 말이죠!!


직접 눈으로 한번 확인해 봅시다.

원래 우리가 bash 쉘에서 echo `ls`를 쓰면 ls 명령어를 실행한 결과값(= 현재 디렉터리에 있는 파일(및 디렉터리) 목록)이 출력됩니다.



그럼 double quote를 ls에 씌어서 echo “ls“를 실행해 봅시다.



오오 “ ” 안에서 back quote(`)의 기능이 잘 보존되었어요 꺄꺄 ㅎㅎㅎ

그럼 이번엔 single quote를 사용해서 echo ‘ls‘를 실행해 봅시다. 둑흔둑흔



와우… 정말 입력한 그대로! `ls`가 echo 명령어의 인자값으로 들어가서

결론적으로 `ls`가 출력되었습니다!!!!!

눈으로 보니 딱딱이 이해가 되네요! ㅎㅎㅎㅎㅎ


( [Single vs Double Quote]에 대한 내용은 검색으로도 쉽게 찾을 수 있어요 ㅎㅎ 저는 아래 두 개의 링크를 참고하였습니다!


Stack Overflow - Difference between single and double quotes in Bash

Single vs. Double Quotes in Bash


즉… back quote(`)가 Command Substitution을 잘 수행하려면 ‘ ’ 속에 갇히면 안된다는 거!


즉!!! 우리는 dig를 `를 이용한 Command Injection에 활용할 수 없다는 겁니다 ㅎㅎ

명확하게 결론 났으니, 이제 대망의 Command Injection 시도를 기대하며 host 함수를 분석해봅시다.




< host_10BD >


코드 뙇뙇


if ( a1 )
{
// 금지 문자가 포함되었는지 검사합니다
if ( (unsigned int)check1_D65(a1, &cp) )          
{
  if ( inet_aton(&cp, &v4) )
  {
    v1 = inet_ntoa(v4);
    __sprintf_chk(&command, 1LL, 384LL, "host %s", v1);
  }
  else         // 인자값이 IP주소 형태가 아니면
  {
    // 첫 글자와 마지막 글자를 검사합니다
    if ( !(unsigned int)check2_DCC(&cp) )          
    {
      puts("Invalid hostname.");
      return *MK_FP(__FS__, 40LL) ^ v8;
    }
    // " host "%s" " 요러한 형태로 명령을 실행합니다
    __sprintf_chk(&command, 1LL, 384LL, "host \"%s\"", &cp);          
  }
  v2 = popen(&command, "r");


후훟 앞서 dig 설명할 때 밑밥을 다 깔아뒀으니 ㅎㅎ 요점 짚고 결론 내고 얼른 Command Injection 공격 실행!으로 갑시다 ㅎㅎ


host 명령어의 인자값이 IP주소 형태가 아니라면,

host는 인자값에 double quote(” “)를 씌워서

host "%s" 요러한 형태로 명령이 실행될 겁니다 wowowowowowow!!!


이제 거의 다 끝난 거네요 어서 마저 꼬꼬Go!!




< Command Injection 공격!!으로 flag 읽기 >


자 우리가 분석한 핵심포인트들을 총 종합하여 정리해봅시다.


  1. ` `(공백문자) ! & ' * : ; |를 쓸 수 없으니 `를 사용하여 Command Injection 공격을 하자.

  2. host 명령어를 사용하자.

  3. host 명령어에 전달하는 인자값은 첫 번째 글자와 마지막 글자는 알파벳이나 숫자여야 한다.


그리고… 마지막으로 안에 어떤 명령어를 넣어서 공격할지 정해야 합니다…

앞서 예고한 대로 이 문제는 flag를 읽어야 할 듯한 문제였는데…. cat flag를 ` `안에 넣어주자니…………..


check1 함수에서 공백문자를 금지!!한다는 사실을 놓칠 뻔했습니당 또륵…


그!래!서! 우리는 한 단계 더 돌아서 갑시다 ㅎㅎ 즉 sh 명령어를 host의 인자값에 삽입하고,

열린 쉘에서 cat flag를 입력하는 시나리오입니다 후후훟


끄아 떨려~ 바로 실행해볼까요??!!!

우선 `ls`를 삽입해봅시다


host abc`ls`abc



오호 ls 명령어의 결과값인 babycmd와 flag가 오류 메시지 속에 낑겨서 출력되네요! ㅎㅎ

그럼 이제 진짜 공격! sh을 삽입합시당!!


host abc`sh`abc



꺄꺄꺄 oh_baby_you_mastered_babycmd_yeah라는 메시지를 읽으셨나요??! ㅎㅎㅎ

여러분들을 위해 제가 준비한 flag에용 킼킼


보시다시피 host abc`sh`abc 명령어로 실행된 sh은!!! subshell 이잖아요!

host에 인자값으로 줘야되니까 우선적으로 `sh`을 실행한 거구! 그 결과를 받아가려고 딱 대기중이에요!


그래서 cat flag를 해도 stdout을 출력해주지 않아요….헐랭

근데 다행히 sh을 빠져나오면! 출력하지 않고 기다렸던 cat flag의 결과값을 host에 뙇! 전달!해주고


결과적으로 host abcoh_baby_you_mastered_babycmd_yeahabc라는 명령이 실행되어서…

그런 host는 없다고 오류가 뙇 떴습니다 ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ

(히히 back quote를 써서 Command Injection을 하면 요로코롬 내가 원하는 명령어의 결과값이

오류메시지에 담겨서 노출되는 방식으로 flag 등을 읽을 수 있게 돼요 ㅎㅎ 신기하죠? ㅎㅎㅎ)


근데…….. 제가 다른 사람들의 write-up도 살펴보다가…… 재!밌!는! 걸 발견해서 여러분들께도 알려드릴려고 해요 ㅎㅎ

제가 본 write-up은 바로 요겁니다!!!


github.com/TUCTF Writeup


마지막 문단에 제가 알려드리고 싶은 내용이 뙇! 있는데요!!



host abc`sh`abc 명령어로 실행된 sh에서 stdout은 출력되지 않지만 stderr는 잘 출력이 되었다는 것입니다!

그래서 표준출력(stdout = 1)을 표준에러(stderr=2)로 리다이렉션시키면!

우리가 원하는 cat flag의 결과값이 표준에러로 인식되어 출력이 뙇! 우리에게 뙇! 보일 수 있다는 것입니다 wowowowowow!!

설레는 것… 당장 저도 해봅니다ㅋㅋ



subshell의 첫 명령으로는 요로코롬 존재하지 않는 ffff 파일을 읽어달라고 요청했습니다!

그랬더니 그런 거 없다고 우리한테 에러메시지를 뙇뙇!! 보여주네요 오


그리고 위 write-up에서 시킨 대로 cat flag 1>&2 해주었더니…………. flag가 고대로 예쁘게!!!!! 출력되었습니다 훟

그리고 stdout에 저장된 값이 없어서 그런가 subshell을 빠져 나오고 나면

host 명령어에는 subshell에서 아무런 값도 전달되지 않았네요~ 으흐흠 심오한 것….


혹 1>&2 이 부분이 생소하신 분은 여기를 참고하쎄여!

IO Redirection 두 번째 회색 박스

Bash Hackers Wiki - Redirection


후자의 방법이 훨씬 깔끔하고 말끔하고 뿌듯하고 명쾌해 보이네요 ㅎㅎㅎㅎ

새로운 방법을 알게 되어 기분이 매우 좋아요 룰루!!


출처 : 여기


아 이렇게 허무한 듯 재밌는 듯 복잡한 듯 “Babycmd 문제뽀개기”에 성공하였습니다.


Defcon 예선 문제라고 겁먹을 뻔도 했으나 별 거 아니었죠? ㅎㅎ

거부감느껴지는 IDA 헥스레이 코드도 쉬어가며 차근차근 읽으면 잘 분석해낼 수 있습니다! (거부감… 제 얘깁니다 ㅋㅋ)




Epilogue


자 요로코롬….. 간단히 핵심만 설명하겠다더니 또 요러쿵저러쿵 잡소리 더해가며 긴 write-up을 작성해주시고….


끝날 것 같지않게 주저리주저리 끌어가던 “Command Injection과 친해지기 프로젝트”도 어느덧 마무리된 것 같네요 ㅎㅎ

(하지만 그저 조금 친해진 것 뿐… 아직도 나는 Command Injection과 나 사이의 거리가 매우매우 멀게 느껴진다…흙)


히히

이번 시리즈하면서……. 엄마보고싶다며 엄마언제보냐며…. 징징댔는데 ㅎㅎㅎㅎ

사실………..ㅋㅋㅋㅋㅋㅋ 가끔 엄마보고 왔다능 ㅋㅋㅋㅋ 헿


아 그리고!!!! 맨날 엄마보고싶다고 징징댔지만 저!! 아빠도!!! 매우매우 사랑한답니다 히히


아빠, 알지????!!!!


출처 : 여기


.

.

.


히히 원래 이러한 오글거림 선사하려던 에필로그가 아닌데 말이죠 ㅎㅎㅎㅎ

왜이렇게 됐징 아 새벽감성타나봐요ㅋㅋㅋㅋㅋ


저는 다시 돌아올 거에요

(ㅇㅂㅇ;; 밑도 끝도 없는 소리….ㄷㄷㄷ ㅋㅋㅋㅋㅋㅋㅋㅋ)


하 횡설수설이 심했네요… ㅈㅅ 그럼 저는 이만 얼른 떠날게요ㅋㅋㅋ


다시 만나요~ (제발~)

뿅!!


comments powered by Disqus