출처1 : https://gs.saro.me/dev?tn=515





우선 사용자에게 Request를 받으면 항상 필터나 인터셉터에서 미리 해당 인젝션 문자열에

(이 부분은 아마도 주관적이지 않을까, 그리고 계속 추가될 것이다.) 대한 처리를 미리하고나서 DB에 넣는다.


같은 디비를 다른 시스템이 보고 있다고 한다면, 다른 시스템에서도 인젝션 문자열이 들어올 수 있다고 가정한다.

그래서 디비값은 그대로 표현하면 항상 인젝션의 위험이 있다고 가정하자.

(이건 나의 케이스일 뿐이지 웹으로만 디비를 접속한다면 디비자체가 털리지 않는 이상은 그럴 일은 없을 것이다.)


대충 아래와 같은 모델이 있다고 가정하자.



@Entity
@Getter
@Setter
@Table(name = "table_name")
@EntityListeners({SpecialCharacterListener.class})
public class TableName implements Serializable {

    @Id
    @Column(columnDefinition = "BINARY(16)", name = "Id")
    @GenericGenerator(name = "customUuid", strategy = "com.motolies.model.util.CustomUUIDGenerator")
    @GeneratedValue(generator = "customUuid")   
    private byte[] id;
    
    @Column(name="Name", nullable=false, length=64
    private String name;
}


EntityListeners로  SpecialCharacterListener 클래스를 사용하고 있다.


import java.lang.reflect.Field;
import java.util.Arrays;

import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;

public class SpecialCharacterListener {
    @PostLoad
    void postLoad(Object objectthrows IllegalArgumentExceptionIllegalAccessException {
        // 이런 식으로 Object 를 파라미터로 지정한 경우 모든 엔티티가 적용됩니다.
        // https://gs.saro.me/dev?tn=515

        for (Field field : object.getClass().getDeclaredFields()) {
        // annotation 만들었을 때의 처리
        //          RemoveSomeTagCharacter notHtmlTag = field.getAnnotation(RemoveSomeTagCharacter.class);
        //          if (notHtmlTag != null) {
        //              field.setAccessible(true);
        //              String text = (String) field.get(object);
        //              if (text != null) {
        //                  field.set(object, removeSomeTagCharacter(text));
        //              }
        //          }
            
            // 모든 스트링 클래스에 인젝션 처리를 한다
            if(field.getType() == String.class) {
                field.setAccessible(true);
                String testCase = (String) field.get(object);
                if (testCase != null) {
                    field.set(object, removeSomeTagCharacter(testCase));
                }               
            }
        }
    }
    
    @PrePersist
    @PreUpdate
    void original(Object objectthrows IllegalArgumentExceptionIllegalAccessException {

        for (Field field : object.getClass().getDeclaredFields()) {
            OriginalTextCharacter setHtmlTag = field.getAnnotation(OriginalTextCharacter.class);
            if (setHtmlTag != null) {
                field.setAccessible(true);
                String text = (String) field.get(object);
                if (text != null) {
                    field.set(object, changeSpecialCharacter(text));
                }
            }
        }
    }
    
    public static String injectionCheck(String str) {

        if (str == null)
            return null;

        String escapeStr = str;
        escapeStr = escapeStr.replace("<""&lt;");
        escapeStr = escapeStr.replace(">""&gt;");
        escapeStr = escapeStr.replace("|""&#124;");
        escapeStr = escapeStr.replace("$""&#36;");
        escapeStr = escapeStr.replace("%""&#37;");
        escapeStr = escapeStr.replace("'""&#39;");
        escapeStr = escapeStr.replace("&quot;""\"");
        escapeStr = escapeStr.replace("(""&#40;");
        escapeStr = escapeStr.replace(")""&#41;");
        
        return escapeStr;
    }
    
    public static String[] injectionCheck(String[] str) {

        if (str == null)
            return null;

        String escapeStr = str[0];
        escapeStr = escapeStr.replace("<""&lt;");
        escapeStr = escapeStr.replace(">""&gt;");
        escapeStr = escapeStr.replace("|""&#124;");
        escapeStr = escapeStr.replace("$""&#36;");
        escapeStr = escapeStr.replace("%""&#37;");
        escapeStr = escapeStr.replace("'""&#39;");
        escapeStr = escapeStr.replace("&quot;""\"");
        escapeStr = escapeStr.replace("(""&#40;");
        escapeStr = escapeStr.replace(")""&#41;");
        
        String[] rtn = Arrays.copyOf(str,  str.length);
        rtn[0] = escapeStr;
        return rtn;
    }
    
    public static String changeSpecialCharacter(String str) {
        if (str == null)
            return null;
        String escapeStr = str;
        escapeStr = escapeStr.replace("&lt;""<");
        escapeStr = escapeStr.replace("&gt;"">");
        escapeStr = escapeStr.replace("&#124;""|");
        escapeStr = escapeStr.replace("&#36;""$");
        escapeStr = escapeStr.replace("&#37;""%");
        escapeStr = escapeStr.replace("&amp;""&");
        escapeStr = escapeStr.replace("&#39;""'");
        escapeStr = escapeStr.replace("&quot;""\"");
        escapeStr = escapeStr.replace("&#40;""(");
        escapeStr = escapeStr.replace("&#41;"")");
        return escapeStr;
    }
    
    public static String removeSomeTagCharacter(String str) {
        if (str == null)
            return null;
        String escapeStr = str;
        escapeStr = escapeStr.replace("&lt;""<");
        escapeStr = escapeStr.replace("&gt;"">");
        escapeStr = escapeStr.replace("&#124;""|");
        escapeStr = escapeStr.replace("&#36;""$");
        escapeStr = escapeStr.replace("&#37;""%");
        escapeStr = escapeStr.replace("&amp;""&");
        escapeStr = escapeStr.replace("&#39;""'");
        escapeStr = escapeStr.replace("&quot;""\"");
        escapeStr = escapeStr.replace("&#40;""(");
        escapeStr = escapeStr.replace("&#41;"")");
        
        escapeStr = HtmlSanitizer.sanitize(escapeStr);
        
        return escapeStr;
    }

}


public class HtmlSanitizer {
    private static String tagsPattern;
    private static String attrsPattern;
    private final static String[] tagsTab = { "form""script""body""iframe""object" };
    private final static String[] attrsTab = { 
            "FSCommand""onAbort""onActivate""onAfterPrint""onAfterUpdate"
            , "onBeforeActivate""onBeforeCopy""onBeforeCut""onBeforeDeactivate"
            , "onBeforeEditFocus""onBeforePaste""onBeforePrint""onBeforeUnload"
            , "onBeforeUpdate""onBegin""onBlur""onBounce""onCellChange"
            , "onChange""onClick""onContextMenu""onControlSelect""onCopy"
            , "onCut""onDataAvailable""onDataSetChanged""onDataSetComplete"
            , "onDblClick""onDeactivate""onDrag""onDragEnd""onDragLeave"
            , "onDragEnter""onDragOver""onDragDrop""onDragStart""onDrop"
            , "onEnd""onError""onErrorUpdate""onFilterChange""onFinish"
            , "onFocus""onFocusIn""onFocusOut""onHashChange""onHelp"
            , "onInput""onKeyDown""onKeyPress""onKeyUp""onLayoutComplete"
            , "onLoad""onLoseCapture""onMediaComplete""onMediaError"
            , "onMessage""onMouseDown""onMouseEnter""onMouseLeave"
            , "onMouseMove""onMouseOut""onMouseOver""onMouseUp"
            , "onMouseWheel""onMove""onMoveEnd""onMoveStart""onOffline"
            , "onOnline""onOutOfSync""onPaste""onPause""onPopState"
            , "onProgress""onPropertyChange""onReadyStateChange""onRedo"
            , "onRepeat""onReset""onResize""onResizeEnd""onResizeStart"
            , "onResume""onReverse""onRowsEnter""onRowExit""onRowDelete"
            , "onRowInserted""onScroll""onSeek""onSelect""onSelectionChange"
            , "onSelectStart""onStart""onStop""onStorage""onSyncRestored"
            , "onSubmit""onTimeError""onTrackChange""onUndo""onUnload"
            , "onURLFlip""seekSegmentTime""href" };

    static {
        StringBuffer tags = new StringBuffer();
        for (int i = 0; i < tagsTab.length; i++) {
            tags.append(tagsTab[i].toLowerCase());
            if (i < tagsTab.length - 1) {
                tags.append('|');
            }
        }
        tagsPattern = "(?i)</?(" + tags.toString() + "){1}.*?/?>";
    }

    static {
        StringBuffer attrs = new StringBuffer();
        for (int i = 0; i < attrsTab.length; i++) {
            attrs.append(attrsTab[i].toLowerCase());
            if (i < attrsTab.length - 1) {
                attrs.append('|');
            }
        }
        attrsPattern = "(?i)\\s(?:" + attrs.toString() + ")\\s*=\\s*(([\\\"'\\s]?)[^>]*)\\2";
    }

    public static String sanitize(String input) {
        String rtn = input.replaceAll(tagsPattern, "");
        rtn = rtn.replaceAll(attrsPattern, "");
        return rtn;

    }
}



대충 이런식의 클래스를 만들어 두었다고 할 때 String.class 타입에만 removeSomeTagCharacter 함수를 사용해서 

인젝션 가능 문자열을 제거한다. 



















Posted by motolies

댓글을 달아 주세요