자격/SW보안약점진단원

구현단계 보안약점 제거 기준-Public 메소드부터 반환된 Private 배열

Ignatius Heo 2023. 7. 6. 15:50

작성일: 230704

 

※ 본 게시글은 학습 목적으로 행정안전부·KISA의 소프트웨어 보안약점 진단 가이드, 소프트웨어 개발보안 가이드를 참고하여 작성하였습니다.

 

정리 내용: 소프트웨어 보안약점 진단 가이드(481~486p)

구분 - 캡슐화
설계단계  
개요 private로 선언된 배열을 public으로 선언된 메소드로 반환(return)하면, 그 배열의 레퍼런스가 외부에 공개되어 외부에서 배열수정과 객체 속성변경이 가능해진다.
진단 세부사항
(설계단계)
 
보안대책
(구현단계)
private로 선언된 배열을 public으로 선언된 메소드로 반환하지 않도록 해야 한다. private 배열에 대한 복사본을 반환하도록 하고 배열의 원소에 대해서는 clone() 메소드로 복사된 원소를 저장하도록 하여 private 선언된 배열과 객체속성에 대한 의도하지 않게 수정되는 것을 방지한다.

만약 배열의 원소가 String 타입 등과 같이 변경이 되지 않는 경우에는 Private 배열의 복사본을 만들고 이를 반환하도록 작성한다.
진단방법
(구현단계)
① private 배열이 선언되어 있는지 확인하고,

② 해당 배열이 public 메소드에서 반환될 경우 취약하다고 판단한다

이때 선언된 private 배열의 원소가 일반 객체일 경우 각 원소별로 객체를 생성하고 객체 내부의 값을 복사하는지 확인한다.

 

다. 코드예제

 

ㅇ 분석

1: // private 인 배열을 public인 메소드가 return한다.
2: private Color[] colors;
3: public Color[] getUserColors(Color[] userColors) { return colors; }

ㅇ 내용

1. Colors를 private으로 선언했는데, public 메소드에서 리턴을 하네요

2. 꼭 참조를 해야하면 배열을 복사해서 참조하고 지우거나 중요도에 따라 배열 자체를 퍼블릭으로 바꾸거나 메소드를 프라이빗으로 해야함. 안그러면 private의 배열이 바뀔 수 있음

 

ㅇ 수정

1: private Color[] colors;
2: //메소드를 private으로 하거나, 복제본 반환, 수정하는 public 메소드를 별도로 만든다.
3: public void onCreate(Bundle savedInstanceState) {
4: super.onCreate(savedInstanceState);
5: Color[] newColors = getUserColors();
6: ......
7: }
8: public Color[] getUserColors(Color[] userColors) {
9: //배열을 복사한다.
10: Color[] colors = new Color [userColors.length];
11: for (int i = 0; i < colors.length; i++)
12: //clone()메소드를 이용하여 배열의 원소도 복사한다.
13: colors[i] = this.colors[i].clone();
14: return colors;
15:}

ㅇ 내용

1. clone을 사용해서 private 복제본을 만들고 해당 복제본을 참조해서 사용함

 


ㅇ 분석

1: // private 인 배열을 public인 메소드가 return한다.
2: private String[] colors;
3: public String[] getColors() { return colors; }

ㅇ 수정

1: private String[] colors;
2: // 메소드를 private으로 하거나, 복제본 반환, 수정하는 public 메소드를 별도로 만든다.
3: public void onCreate(Bundle savedInstanceState) {
4: super.onCreate(savedInstanceState);
5: String[] newColors = getColors();
6: ......
7: }
8: public String[] getColors() {
9: String[] ret = null;
10: if ( this.colors != null ) {
11: ret = new String[colors.length];
12: for (int i = 0; i < colors.length; i++) { ret[i] = this.colors[i]; }
13: }
14: return ret;
15: }

ㅇ 내용

1. 여기서는 스트링 참조해서 ret 만들고, ret를 반환함

 

 


ㅇ 분석

1: // private 인 collection을 public인 메소드가 return한다.
2: private List<Color> colors;
3: public List<Color> getUserColors() { return colors; }

ㅇ 수정

1: private List<Color> colors;
2: //메소드를 private으로 하거나, 복제본 반환, 수정하는 public 메소드를 별도로 만든다.
3: public List<Color> getUserColors() {
4: //배열을 복사한다.
5: List< ICloneable> newList = new List< ICloneable>(colors.Count);
6: //Clone()메소드를 이용하여 collection의 원소도 복사한다.
7: colors.ForEach((item) =>
8: {
9: newList.Add((ICloneable)item.Clone());
10: });
11: return newList;
12:}

ㅇ 내용

1. 저렇게 클론하는 방법도 있구나

 

 

 

 

 

 

끝.