취약한 코드
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
package java_contents;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.soap.Node;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
public class SecurityController extends HttpServlet
{
private final String GET_USER_INFO_CMD = "get_user_info";
private final String USER_ID_PARM = "user_id";
private final String USER_TYPE = "user_type";
private final String ADMIN_USER = "admin_user";
private final String NORMAL_USER = "normal_user";
protected void doPost(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws
letException, IOException
{
String command = request.getParameter("command");
UserInfo info = getUserInfo();
if( info == null ) return;
if (command != null && command.equals(GET_USER_INFO_CMD))
{
response.getOutputStream().print(info.getUserId());
response.getOutputStream().print(info.getUserName());
response.getOutputStream().print(info.getUserHomepage());
if(getCookie(USER_TYPE).equals(ADMIN_USER))
{
response.getOutputStream().print(info.getUserAddress());
response.getOutputStream().print(info.getUserPhoneNumber());
}
}
}
}
취약점 분석
1
if(getCookie(USER_TYPE).equals(ADMIN_USER))
해당 코드에서 쿠키를 이용하여 관리자 여부를 검사하고 있다. 공격자는 ADMIN_USER로 설정된 쿠키를 조작하거나 존재하지 않는 쿠키를 사용하여 어드민 권한을 획득할 수 있는 취약점이 존재한다.
중요한 정보는 쿠키가 아닌 세션을 이용하여 공격자가 임의로 조작하는 것을 방지할 수 있다.
안전한 코드
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
package java_contents;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.soap.Node;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
public class resource extends HttpServlet
{
public class UserInfoPool extends HttpServlet
{
private final String GET_USER_INFO_CMD = "get_user_info";
private final String USER_ID_PARM = "user_id";
private final String USER_TYPE = "user_type";
private final String ADMIN_USER = "admin_user";
private final String NORMAL_USER = "normal_user";
protected void doPost(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws
letException, IOException
{
String command = request.getParameter("command");
UserInfo info = getUserInfo();
if( info == null ) return;
if (command != null && command.equals(GET_USER_INFO_CMD))
{
response.getOutputStream().print(info.getUserId());
response.getOutputStream().print(info.getUserName());
response.getOutputStream().print(info.getUserHomepage());
// 사용자 Role(역할) 정보는 서버의 저장소에 저장해서 사용하는것이 안전합니다.
if((session.getAttribute(USER_TYPE)).equals(ADMIN_USER))
{
response.getOutputStream().print(info.getUserAddress());
response.getOutputStream().print(info.getUserPhoneNumber());
}
}
}
}