[ Apache Struts ] Apache Struts 2 프레임워크 보안취약점 조치 전 간단 톮아보기

duck-ach·2024년 10월 9일
0

보안취약점

목록 보기
1/1

회사에서 다음주부터 Apache Struts2 프레임워크에서 발견된 원격코드 실행 관련 보안취약점을 해결해야해서 프로젝트 투입 전 간단히 Apache Struts 프레임워크에서 사용하는 문법과 종속 라이브러리 정보 등을 톮아보자.

※ 톮아보다 : 샅샅히 톮아 나가면서 살피다. (순우리말)

Apache Struts

Apache Struts는 Apache 사에서 만들어진 Java EE 애플리케이션을 개발하기 위한 MVC 아키텍처 기반 오픈 소스 프레임워크다.

Apache Struts의 특징으로는 POJO(Plain Old Java Object) 기반의 Actions를 사용하여 HTML Form 이나 다른 리소스들에 대한 요청들을 처리한다.

보안취약점

  • CVE-2019-0230
    설명 : 사용자 입력 데이터 검증이 미흡하여 발생하는 원격코드 실행 취약점
    영향 받는 버전 : Struts 2.0.0 ~ 2.5.20

  • CVE-2020-17530
    설명 : CVE-2019-0230의 보안패치를 우회한 원격코드 실행 취약점
    영향 받는 버전 : Struts 2.0.0 ~ 2.5.25

해결책으로는 권고사항인 Apache Struts 프레임워크를 업그레이드 하는 방안으로 진행하기로 했다.

문법 및 용어

Actions

Struts 2 Web Application에서 하이퍼링크를 클릭하거나 HTML Form을 Submit하면 Struts 내의 자바 클래스로 전송된다. 이런 요청을 받는 클래스를 Actions라고 한다.
Action이 실행된 후, Result는 응답을 렌더링할 리소스(Java, html, jsp, file 등)를 선택할 수 있고, 실행 결과에 따라 SUCCESS, ERROR, INPUT 과 같은 result-name 을 반환할 수 있다.

struts.xml 파일

struts.xml 이라는 xml 파일을 통해 모든 연결관계를 확인할 수 있다.

struts.xml

<action name="index" class="com.struts.MainAction">
    <result name="index">/index.jsp</result>
</action>
<action name="login" class="com.struts.LoginAction">
    <result name="login">/login/login.jsp</result>
    <result name="success" type="redirect">index</result>
</action>

LoginAction.java

public class LoginAction extends ActionSupport {
    public String execute() {
        return SUCCESS;
    }
}

사용자가 만약 http://www.myStruts.com/strutsproject/login 로 요청을 시도하면 Struts에 의해 액션클래스로 지정해놓은 LoginAction 의 execute() 메소드가 호출된다.

excute()의 return 값은 String 형태로 되어있으며, 실행결과에 문제가 없다면 "success"를 돌려주며, index 페이지로 지정된 MainAction을 호출하여 index.jsp로 보낸다.

위와 같이 각각의 동작에 해당되는 자바 클래스를 별도로 작성하고, 웹 페이지와의 관계를 xml로 지정하여 Struts 가 애플리케이션의 동작을 통제한다.

HTML, jsp 에서의 데이터 렌더링

Apache Struts에서는 Java단에서 Getter/Setter를 작성한 후 이에 대한 변수 이름을 Form 필드에 지정만 해주면 HTML이나 jsp의 Form 에서 값을 넘겨줄 때나 받아올 때 추가 코드를 작성할 필요가 없이 Struts가 자동으로 이 메소드들을 호출해서 값을 받아오거나 넘겨준다.

Users.java

@Getter
@Setter
public class Users {
	private String id;
    private String name;
    private int age;

UsersInfoAction.java

public class UsersInfoAction extends ActionSupport {
    private Users users;

    public String execute() {
        users = new Users() ;
        
        return SUCCESS;
    }

    public Users getUsers() {
        return users;
    }
}

userinfo.jsp
여기서 중요한점은 3번째 line의 Tag 라이브러리 <%@ taglib prefix="s" uri="/struts-tags" %> 를 지정해주는 것이다.

<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>User Info</title>
  </head>
  <body>
  	<h1>사용자 정보</h1>
  	<h3>사용자 아이디</h3>
    <li><s:property value="users.id" /></li>
    <h3>사용자 이름</h3>
    <li><s:property value="users.name" /></li>
    <h3>사용자 나이</h3>
    <li><s:property value="users.age" /></li>
  </body>
</html>

URL 태그 (Forward, Redirect)

HTML은 하이퍼링크를 만드는 간단한 a 태그를 제공하지만, HTML은 종종 중복된 정보를 포함해야하거나 프레임워크에서 제공하는 동적 데이터에 쉽게 Access 하지 못한다.

Struts에서는 이를 해결하기 위해 Struts 2 url 태그를 제공한다.

사용자가 버튼 또는 링크를 클릭하면 Struts 프레임워크 클래스의 실행 메소드를 실행하고 뷰를 렌더링하는 예제를 작성해보았다.

매개변수가 없는 URL 태그

jsp 맨 위에 taglib 지시문 추가
<@ taglib prefix="s" uri="/struts-tags"%>

예제용 jsp 파일 작성

<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Basic Struts 2 Application - Welcome</title>
    </head>
    <body>
        <h1>Welcome To Struts 2 - Let's Join</h1>
        <p><a href="<s:url action='join'/>">Sign Up</a></p>
    </body>
</html>

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
		"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
		"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
    <constant name="struts.devMode" value="true" />

    <package name="basicstruts2" extends="struts-default">
        <action name="index">
            <result>/index.jsp</result>
        </action>
		
        <action name="join" class="org.apache.struts.strutsproject.action.JoinAction" method="execute">
            <result name="success">/join.jsp</result>
        </action>
    </package>
</struts>

Struts url 태그는 join Action으로 URL을 생성한다. 사용자가 "Sign Up" 링크를 클릭하면 join Action은 클래스 JoinAction의 execute() 메소드를 호출하고, success 문자열을 반환하고, join.jsp 파일이 렌더링된다.

매개변수가 있는 URL 태그

<s:url action="hello" var="helloLink">
  <s:param name="userName">Heera</s:param>
</s:url>

<p><a href="${helloLink}">Click me! Heera</a></p>

url 태그를 <a> 태그의 href 속성의 값으로 넣는 대신, <s:url> 태그를 별도의 코드 블록으로 분리했고, 내부에 <param> 태그를 지정함으로써 파라미터를 지정해줄 수 있다.


문법은 대충 전체적으로 JSTL이나 Thymeleaf 처럼 jsp에 taglib 들을 지정해서 사용하는 문법이 많은 것같고, 문법에 대한 내용이 너무 많아서 더 깊고 자세한 내용들은 그때그때 필요한것 위주로 문서를 찾아봐야겠다.

혹시나 이 글을 보고 struts를 공부하고 있는 사람이 있다면 struts 공식문서를 보고 따라해보길 바란다. 생각보다 쉽고 간단하게 설명이 되어있어 기존에 다른 프레임워크를 사용해본 사람이라면 금방 따라할 것 같다.

Struts 문서 링크 - Getting Started

핵심 라이브러리 Dependency

보통 Maven 기준으로 Apache Struts 버전을 바꿔주면 자동으로 모두 Depedency 된다고 한다.
하지만 기업내부에 배포되어 있는 소스라 알 수 없어 정보 볼 수 있는 곳 링크 걸어놓기
핵심 라이브러리 Dependency 정보

Struts 2 필수 라이브러리 로는

  • commons-logging-1.0.4.jar
  • freemarker-2.3.8.jar
  • ognl-2.6.11.jar
  • struts2-core-2.0.11.jar
  • xwork-2.0.4.jar

다섯가지가 있고,
버전마다 다르게 추가적으로 에러문구를 보면서 아래 라이브러리도 점검해주고 교체해주면 될 것같다.

  • commons.beanutils.1.x.x.jar
  • commons.fileupload-1.2.x.jar
  • commons.io-1.x.x..jar
  • commons-lang3-....jar
  • javassist-3....GA.jar
  • struts.core1.....jar

다른 블로그를 참고해보니 기존버전의 라이브러리와 업그레이드 할 버전의 라이브러리를 비교하여 이름이 같은것들만 버전을 덮어쓰기하여 맞춰주었더니 해결했다는 글도 있었다. 한번 시도해보면서 trace 해봐야겠다.

profile
자몽 허니 블랙티와 아메리카노 사이 그 어딘가

0개의 댓글