본문 바로가기

[Wargame Write-up]/WebGoat

[WebGoat] [Injection Flaws] LAB: SQL Injection

Stage 1


String SQL Injection을 이용해 인증을 우회해 Neville로 로그인해야 한다.




부분 query를 작성해야 하는데, 10글자까지만 작성할 수 있다.




개발자 도구에서 maxlength를 지워주면, 무한정 작성할 수 있다.




^^




가장 기본적인 testing query인 ' or '1'='1을 넣으면 될 것 같다. 




Stage 1 Clear~



Stage 2


공격이 동작하지 않도록 소스 코드를 수정해야 하는데, 수정 사항을 반영해 complete message를 보는건 

developer version에서만 가능하다.




~/.extracted/webapps/WebGoat/plugin_extracted/org/owasp/webgoat/plugin/sqlinjection 경로에 Login.java 파일이 있을 것이다.


그 파일을 수정하면 된다.


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
        try    // 124 라인
        {
            String query = "SELECT * FROM employee WHERE userid = " + userId + " and password = '" + password + "'";
            // System.out.println("Query:" + query);
            try
            {
                Statement answer_statement = WebSession.getConnection(s)
                        .createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                ResultSet answer_results = answer_statement.executeQuery(query);
                if (answer_results.first())
                {
                    setSessionAttribute(s, getLessonName() + ".isAuthenticated", Boolean.TRUE);
                    setSessionAttribute(s, getLessonName() + "." + SQLInjection.USER_ID, userId);
                    authenticated = true;
                }
            } catch (SQLException sqle)
            {
                s.setMessage("Error logging in");
                sqle.printStackTrace();
            }
        } catch (Exception e)
        {
            s.setMessage("Error logging in");
            e.printStackTrace();
        }
cs



query라는 문자열에 대입되던 인자를 모두 '?'로 바꾸고


PreparedStatement 객체를 생성해, setString method를 이용해 그 인자를 각각 넣는다.


그 후 executeQuery method를 실행하면 된다.


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
        try
        {
            String query = "SELECT * FROM employee WHERE userid = ? and password = ?";
            // System.out.println("Query:" + query);
            try
            {
                Connection connection = WebSession.getConnections(s);
                PreparedStatement statement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
                statement.setString(1, userId);
                statement.setString(2, password);
                ResultSet answer_results = statement.executeQuery();
                if (answer_results.first())
                {
                    setSessionAttribute(s, getLessonName() + ".isAuthenticated", Boolean.TRUE);
                    setSessionAttribute(s, getLessonName() + "." + SQLInjection.USER_ID, userId);
                    authenticated = true;
                }
            } catch (SQLException sqle)
            {
                s.setMessage("Error logging in");
                sqle.printStackTrace();
            }
        } catch (Exception e)
        {
            s.setMessage("Error logging in");
            e.printStackTrace();
        }
cs


Stage 3


이제 절반이 지났다.


이번에는 Larry로 로그인 후, View 함수의 인자에 SQL injection 공격을 해 Neville의 프로필을 보라는 문제이다.


 

 

Neville의 employee_id가 가장 마지막이다.


select query 결과는 가장 상위에 나타나는 것만 반영되기 때문에, 이처럼 마지막 부분이 필요한 상황에서는 order by를 이용해 역순으로 뒤집어야 한다. 

 

 

 

역시 입력값의 길이 제한은 

 

 

 

풀도록 하자. 

 

 

 

Larry로 로그인하는 것도 간단하다. 


' or 1=1--을 이용했다.

 

 

 

Larry로 로그인했는데, ViewProfile 버튼이 보인다. 

 

 

 

Burp Suite를 이용해, employee_id parameter의 값을

 

 

 

아래처럼 바꿨다.


이렇게 전송하면 Stage 3 Clear~

 

 

 

Stage 4

 

Stage 3의 취약점을 막기 위해 소스 코드를 수정하는 문제이다.


이 문제 역시 complete 표시에 목숨 걸고 있다면, developer version으로 진행해야 한다. 

 




이 카테고리의 ViewProfile.java이라는 파일을 찾아 vim editor로 열어보자.

 

 

 

Line 101~109을 수정해주면 된다.

 

 

 

수정 방법은 Stage 2와 비슷하다.


Query String을 먼저 정의해 놓은 후, PreparedStatement Object를 이용해 각 인자를 넣어 executeQuery Method를 이용해 실행하면 된다.


Stage 4 Clear~