웹/웹 보안

try2hack

비니화이팅 2018. 7. 20. 12:42

LEVEL 1

소스코드를 확인해보면 패스워드를 비교하는 로직에 패스워드가 하드코딩되어있음을 알 수 있습니다.

 

 

LEVEL 2

우클릭을 하면 아래와 같은 메시지가 뜹니다.

 

LEVEL 2에 접속하고 Response 패킷을 Paros로 잡아 body부분의 html코드에서 위의 메시지를 찾아봅니다.

그러면 아래와 같이 if문을 확인할 수 있습니다.

 

우클릭을 우회하는 방법은 두가지가 있습니다.

1. if문 자체를 없앤다.

2. if문은 그대로 return 값을 true로 바꾼다.

 

저는 2번 방법으로 진행할 건데 값을 true로 바꿔야 하니 paros에서 아래와 같이 트랩을 잡아줍니다.

 

paros로 들어온 response패킷에서 return값을 true로 바꿔주고 alert는 없애고 continue합니다.


그러면 아래와 같이 우클릭이 가능해집니다.


사실 이렇게 안하고 개발자 도구에 들어가서 소스를 확인하면 됩니다.

그러면 아래와 같은 swf(플래시)파일을 발견할 수 있습니다.


http://www.try2hack.nl/levels/level2.swf파일을 다운받아줍니다.

또, 다운 받은 level2.swf파일을 열기 위해 Sothink SWF Decompiler도 설치해줍니다.

참고로 Sothink SWF Decompiler은 플래시 파일에 있는 이미지, 사운드, 스크립트 등을 추출할 수 있는 프로그램입니다. 아래의 링크에서 다운로드받을 수 있습니다.

http://www.sothink.com/product/flashdecompiler/download.htm


설치한 Sothink SWF Decomplier로 level2.swf를 열어보면 아래와 같이 username과 password를 얻을 수 있습니다.



LEVEL 3

LEVEL3으로 넘어가면 바로 password를 입력하는 창이 나타납니다.


여기에 틀린 password를 입력하면 바로 디즈니랜드 홈페이지로 넘어갑니다~



paros로 확인해보았습니다. PASSWORD="AbCdE"라는 부분이 보입니다. 그러나 이것은 거짓말!

아래에 보이는 src 속성은 외부 스크립트 파일의 URL을 지정하는 속성입니다. 


그렇다면 위에서 지정한 JavaScript파일을 확인해보기 위해 다운받아봅시다.

http://www.try2hack.nl/levels/JavaScript


여기서 PASSWORD를 얻을 수 있었습니다.


 

LEVEL 4

원래는 LEVEL4페이지에 들어가면 아이디와 패스워드를 입력받는 폼이 보여야하지만 저는 안보였습니다.


소스코드를 살펴보니 object태그가 보입니다.

object태그는 문서안에 html, audio, video, 플러그인(Flash, Java Applets)등을 삽입하는 태그입니다

classid 속성은 URI을 나타냅니다.

PassdLeve4.class라는 자바클래스 파일이 보입니다. 이 파일이 뭔지 살펴보기 위해 다운받아봅시다.

http://www.try2hack.nl/levels/PasswdLevel4.class


class파일은 이미 컴파일되어진 파일이기 때문에 이것을 디컴파일 해야합니다.

그래서 저는 JD-GUI를 다운받았습니다.

http://jd.benow.ca/#jd-gui-download


실행을 시키면 아래와 같은 창이 뜹니다.


여기서 아까 다운받은 PasswdLevel4.class파일을 열어줍시다.


아래와 같이 뭔가 아이디와 패스워드를 비교하는 듯한 구문은 찾았으나 아이디랑 패스워드는 발견할 수 없었습니다.ㅠ

어짜피 아이디와 패스워드 폼도 안보였기 때문에 다른 방법을 찾아보기로 했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import java.applet.Applet;
import java.applet.AppletContext;
import java.awt.Button;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.Label;
import java.awt.TextComponent;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.EventObject;
 
public class PasswdLevel4
  extends Applet
  implements ActionListener
{
  private URL finalurl;
  String infile;
  String[] inuser = new String[22];
  int totno = 0;
  InputStream countConn = null;
  BufferedReader countData = null;
  URL inURL = null;
  TextField txtlogin = new TextField();
  Label label1 = new Label();
  Label label2 = new Label();
  Label label3 = new Label();
  TextField txtpass = new TextField();
  Label lblstatus = new Label();
  Button ButOk = new Button();
  Button ButReset = new Button();
  Label lbltitle = new Label();
  
  void ButOk_ActionPerformed(ActionEvent paramActionEvent)
  {
    int i = 0;
    for (int j = 1; j <= this.totno / 2; j++) {
      if ((this.txtlogin.getText().trim().toUpperCase().intern() == this.inuser[(2 * (j - 1+ 2)].trim().toUpperCase().intern()) && (this.txtpass.getText().trim().toUpperCase().intern() == this.inuser[(2 * (j - 1+ 3)].trim().toUpperCase().intern()))
      {
        this.lblstatus.setText("Login Success, Loading..");
        i = 1;
        String str1 = this.inuser[1].trim().intern();
        String str2 = getParameter("targetframe");
        if (str2 == null) {
          str2 = "_self";
        }
        try
        {
          this.finalurl = new URL(getCodeBase(), str1);
        }
        catch (MalformedURLException localMalformedURLException)
        {
          this.lblstatus.setText("Bad URL");
        }
        getAppletContext().showDocument(this.finalurl, str2);
      }
    }
    if (i == 0) {
      this.lblstatus.setText("Invaild Login or Password");
    }
  }
  
  void ButReset_ActionPerformed(ActionEvent paramActionEvent)
  {
    this.txtlogin.setText("");
    this.txtpass.setText("");
  }
  
  public void actionPerformed(ActionEvent paramActionEvent)
  {
    Object localObject = paramActionEvent.getSource();
    if (localObject == this.ButOk) {
      ButOk_ActionPerformed(paramActionEvent);
    } else if (localObject == this.ButReset) {
      ButReset_ActionPerformed(paramActionEvent);
    }
  }
  
  public void destroy()
  {
    this.ButOk.setEnabled(false);
    this.ButReset.setEnabled(false);
    this.txtlogin.setVisible(false);
    this.txtpass.setVisible(false);
  }
  
  public void inFile()
  {
    new StringBuffer();
    try
    {
      this.countConn = this.inURL.openStream();
      this.countData = new BufferedReader(new InputStreamReader(this.countConn));
      String str;
      while ((str = this.countData.readLine()) != null) {
        if (this.totno < 21)
        {
          this.totno += 1;
          this.inuser[this.totno] = str;
          str = "";
        }
        else
        {
          this.lblstatus.setText("Cannot Exceed 10 users, Applet fail start!");
          destroy();
        }
      }
    }
    catch (IOException localIOException1)
    {
      getAppletContext().showStatus("IO Error:" + localIOException1.getMessage());
    }
    try
    {
      this.countConn.close();
      this.countData.close();
    }
    catch (IOException localIOException2)
    {
      getAppletContext().showStatus("IO Error:" + localIOException2.getMessage());
    }
  }
  
  public void init()
  {
    setLayout(null);
    setSize(361191);
    add(this.txtlogin);
    this.txtlogin.setBounds(1567213224);
    this.label1.setText("Please Enter Login Name & Password");
    this.label1.setAlignment(1);
    add(this.label1);
    this.label1.setFont(new Font("Dialog"112));
    this.label1.setBounds(413628024);
    this.label2.setText("Login");
    add(this.label2);
    this.label2.setFont(new Font("Dialog"112));
    this.label2.setBounds(75723624);
    this.label3.setText("Password");
    add(this.label3);
    add(this.txtpass);
    this.txtpass.setEchoChar('*');
    this.txtpass.setBounds(15610813224);
    this.lblstatus.setAlignment(1);
    this.label3.setFont(new Font("Dialog"112));
    this.label3.setBounds(751085721);
    add(this.lblstatus);
    this.lblstatus.setFont(new Font("Dialog"112));
    this.lblstatus.setBounds(1413234424);
    this.ButOk.setLabel("OK");
    add(this.ButOk);
    this.ButOk.setFont(new Font("Dialog"112));
    this.ButOk.setBounds(1051565923);
    this.ButReset.setLabel("Reset");
    add(this.ButReset);
    this.ButReset.setFont(new Font("Dialog"112));
    this.ButReset.setBounds(2041565923);
    this.lbltitle.setAlignment(1);
    add(this.lbltitle);
    this.lbltitle.setFont(new Font("Dialog"112));
    this.lbltitle.setBounds(121433624);
    String str = getParameter("title");
    this.lbltitle.setText(str);
    this.ButOk.addActionListener(this);
    this.ButReset.addActionListener(this);
    this.infile = new String("level4");
    try
    {
      this.inURL = new URL(getCodeBase(), this.infile);
    }
    catch (MalformedURLException localMalformedURLException)
    {
      getAppletContext().showStatus("Bad Counter URL:" + this.inURL);
    }
    inFile();
  }
}
 
cs


일단 아이디와 패스워드를 비교하여 일치하면 "Login Success, Loading.."이라는 문구를 보여주는거 같습니다. 그 후 finalurl 변수에 URL객체를 생성하여 넣고  getAppletContext().showDocument로 무언갈 하고 있습니다. 무슨 역할을 하나 구글링했더니 해당 URL로 보내주는거 같습니다.

그렇다면 finalurl변수에는 다음 레벨의 url이 들어가는 것이겠군요!


getCodeBase()메서드와 str1을 이용하여 URL객체를 생성했습니다. getCodeBase()메서드가 무엇인지 찾아봤습니다. 애플릿 코드가 있는 URL객체를 반환한다고 합니다.

그렇다면 http://www.try2hack.nl/levels/ 을 반환하겠군요.


소스코드를 살펴보니 inURL변수를 발견했습니다. 마찬가지로 getCodeBase()메서드와 infile변수를 이용하여 어떠한 URL을 생성하고 있었습니다. infile변수에는 어떤 값이 담기나 보았더니 level4가 담겼습니다. 따라서 inURL은  http://www.try2hack.nl/levels/level4 이라는 URL을 생성한다는 것을 알아내고 직접 들어가봤습니다.

그랬더니 파일이 다운받아졌고 그 파일에 아래와 같은 내용이 담겨져 있었습니다.


맨 윗줄은 inuser배열에 담겨 str1에 들어가서 finalurl변수를 만들어내고 있었습니다. 

따라서 http://www.try2hack.nl/levels/level5-fdvbdf.xhtml이 다음 단계 URL임을 알 수 있었습니다.

밑에는 아이디와 패스워드 같습니다.


해결 끝!