Security_Analysis

진단 Tool 제작_5 (결과 모델링 및 학습) 본문

현업/[dev]_Python

진단 Tool 제작_5 (결과 모델링 및 학습)

Positivie 2024. 7. 11. 21:09
728x90
반응형

직접 진단한 결과를 DB에 저장까지 했으니, 이 결과들을 가지고 취약점 예측 모델을 만들어야 한다.

진단 Tool 제작_4 (데이터 저장)

 

내가 생각한 학습 모델은 다음과 같다. 

    1). DB에 저장된 현황과 결과를 학습하여 각 "양호", "취약", "N/A", "인터뷰" 등의 결과를 내야 하고   

    2). 진단 시 오탐률은 최대한 적어야 한다. 

 

 맨 처음글에서도 썼지만, 취약점 자동화 솔루션들은 특정 설정값 존재여부에 대해 확인하고 

 존재하는 경우 : 양호 / 존재하지 않는 경우 : 취약 

   => 즉 설정값 과 기준 값의 1 : 1 Mapping 을 통한 진단 이라는 것

그럼 기준에는 적합하지 않지만 양호의 결과가 존재한다면..? 

예를 들어 이런 항목이다. 

========================================================================================

항목명 : [접근IP 제한 및 포트 설정]

========================================================================================

   양호) 자체방화벽, TCP Wrapper 등을 통해 접근 가능한 사용자에 대해 설정이 되어있는 경우 

   취약) 자체방화벽, TCP Wrapper 등을 통해 접근 가능한 사용자에 대해 설정이 되어있지 않은 경우

========================================================================================

[진단기준]

  RHEL 7 이하 : /etc/hosts.deny, /etc/hosts.allow 파일에 접근 가능한 사용자가 설정이 되어있거나, iptables를 활용하여 접근가능한 사용자 혹은 포트에 대해 설정되어 있어야 함

  RHEL 8 이상 : firewalld 를 통해서 접근 가능한 IP, 포트 대역에 대해 allow 설정이 되어있어야 함

  혹은 해당 서버의 상단 방화벽 내 정책을 통하거나, 접근제어 솔루션을 통해서 설정되어 있어야 함 

========================================================================================

 

서버 자체 방화벽 혹은 TCP Wrapper, Iptables 등에 설정이 되어있다면 더 확인할 것 도 없이 바로 "양호" 처리가 가능하다 

하지만 설정이 안되어 있다면 

 1). 상단 방화벽, 접근제어 솔루션 등과 같은 별도의 인터뷰가 필요하다

 

이 때에, 스크립트 결과에는 포함이 안되어있다고 취약으로 줄 수는 없고, 인터뷰를 해야 하지만 취약점 자동화 솔루션에서는 "인터뷰" 가 나오지 않는다.

물론 모든 취약점 자동화 솔루션에서 안나오는 것은 아니다.

인터뷰 기능이 있다면 나올 것이다. 

없으면 아래와 같다. 

========================================================================================

 사전예외 처리를 했으면 => 양호, 대체, 예외 등  사전예외 처리를 하지 않으면 => 취약

========================================================================================

 

특히 자동화 솔루션들은 보고서까지 자동으로 써주는데 사전 예외처리를 하지 않았거나 최초 진단하거나 했을 때 해당 항목이 취약으로 나온다면

시스템 운영자 입장에서 볼 때 "오탐" 이다. 

 

오탐은 막고, 수많은 데이터를 통해 학습 해서 제대로된 결과를 만들어야 한다. 

 

그렇다면 DB 내 Content와 Label을 긁어와서 결측치와 이상치를 제거해야 하지만, 

이상치 제거는 현실적으로 불가능하다.

아니 코드적으로는 가능한데, 하면 안된다. 

# 텍스트 벡터화
vectorizer = TfidfVectorizer(max_features=5000)
X_vectorized = vectorizer.fit_transform(X)

 

이유는 오래된 서버일 수록 데이터가 많이 있고, 하나의 파일에 계정이 몇백개 이상 있을 수도 있다.

그런 경우에 이상치 제거로 비이상적으로 데이터가 길거나, 짧은 것에 대해서 무시해버리면 특정 항목에 대해서 예측을 하지 못하는 경우가 생기거나 

1000대의 데이터를 넣어놨다하더라도, 비 이상적으로 길거나 짧은 데이터가 포함되서 이상치 제거를 하다보면 1000대가 아닌 900대 가지고 학습 할 수 있기 때문이다. 

# 레이블 인코딩
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)

# 학습 및 테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(X_vectorized, y_encoded, test_size=0.2, random_state=42)

# 모델 학습
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 모델 평가
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred, target_names=label_encoder.classes_))

이렇게까지 모델을 만들어서 학습하고, 평가까지 완료 하면 준비는 끝난다. 이제 각 Content 값에 대한 Label을 예측하도록 함수를 구현하고, 해당 결과를 DB에 업데이트 하도록 한다. 

 

이 결과는 Label 에 값이 없더라도, 기존에 학습된 데이터로 새로 예측하여 결과는 넣는 것이기 때문에1대의 결과를 넣어서 각 항목에 대한 현황으로 결과를 예측한다.

# 예측 함수
def predict_label(content):
    content_vectorized = vectorizer.transform([content])
    prediction = model.predict(content_vectorized)
    return label_encoder.inverse_transform(prediction)[0]

# 예측 및 결과 저장
            df['Predicted_Label'] = df['Content'].apply(predict_label)

            output_file_path = os.path.join(predict_output_dir, f'predicted_{file}')
            df.to_excel(output_file_path, index=False)
            print(f"Prediction completed and saved to {output_file_path}")

            update_db_with_predictions(df, os_dbs.get(file.split('_')[3].lower()),file)

 

그렇다면 지금 6대를 가지고 학습을 한 상태에서 학습에 사용된 특정 자산의 Label을 지우고 테스트 해보았다. 

결과는 꽤나 아이러니 하다..

 

6대 모두 Label이 작성된 엑셀파일에서 Label을 삭제하고 저장 후 예측을 시도했다. 

물론 DB에는 Label이 저장되어 있지만 지금은 엑셀 파일만 가지고 예측을 했기 때문에 기존 Label의 영향을 받지 않았다.

영향을 받았다면 데이터 모델 학습할 때 영향을 받았겠지..

 

6대를 모두 넣어보니 결과는 아래와 같았다. 

 

[ 예측 결과 ]

========================================================================================

모두 DB 내 업데이트 된 두개의 라벨을 가지고 비교했다. 

※ TRUE : Label = Predict_Label 

※ FALSE : Label ≠ Predict_Label

========================================================================================
※ 총 항목 개수 : 78개
1). TRUE : 72 / FALSE : 6  < 오탐률 : 8.3% >

2). TRUE : 71 / FALSE : 7  < 오탐률 : 9.8% >

3). TRUE : 68 / FALSE : 10  < 오탐률 : 14.7% >

4). TRUE : 69 / FALSE : 9  < 오탐률 : 13.0% >

5). TRUE : 74 / FALSE 4   < 오탐률 : 5.4% >

========================================================================================

 

단 6대를 가지고 진행했고, 이미 현황과 결과를 가지고 학습한 상태에서 동일한 현황을 넣었음에도 불구하고, 

최소 5.4% ~ 최대 14.7% 까지의 오탐이 발생했다. 

 

몇일간 삽질을 하면서 코드를 만들었지만

오탐률이 5 ~ 15퍼센트 까지 나오는게 참 아이러니 하면서도 흥미로웠다. 

 

일단 데이터를 계속 추가하면서 오탐률을 낮춰볼 생각이다. 만약, 오탐률이 더 늘어난다면 이 코드는 실패한 코드가 될 것이겠지만수백대에서 수천대에 대한 데이터를 가지고 학습해서 새로운 결과를 넣었을 때 내 개인적인 생각으로 오탐률이 2% 미만 이라면 꽤나 괜찮은 프로그램이 될 것이라고 본다. 

 

728x90
반응형