리눅스에서 데이터 압축에 필요한 도구인 'XZ Utils'에서 백도어가 발견되었습니다. CVE-2024-3094로 명명된 이 취약점은 현지 시간으로 2024년 3월 29일 발표되었습니다. 소프트웨어 공급망 공격의 일종으로, 5.6.0 ~ 5.6.1 버전에서 무단 원격 액세스를 허용하도록 하는 백도어가 심어져 있었다고 합니다. 이 백도어가 동작하면 공격자가 서버의 SSH에 인증 없이 로그인이 가능하다고 합니다. 이 취약점은 대부분 리눅스와 관련이 있지만 일부 macOS에서도 같은 문제가 있는 것으로 나타났습니다.
CVSS 점수라고 하는 취약점의 위험성을 표기하는 점수가 있습니다. 이 취약점은 CVSS 점수 10.0점으로, 부여할 수 있는 최대 점수를 받았습니다. 그만큼 IT 업계에서는 이 취약점을 심각하게 보고 있다는 것입니다. 한국인터넷진흥원 인터넷침해대응센터에서도 4월 1일 공지를 올리며 보안 조치를 적용할 것을 권고했습니다.
이번 사건이 다른 사건과 다른 점이 하나 있습니다. 이번 사건에서는 공격자가 GitHub에서 2021년부터 여러 오픈소스 프로젝트에 참여하면서 XZ 프로젝트 관련자로 등극한 이후 백도어를 심었고, 거의 2~3년 가까이를 공들이면서까지 이번 공격을 실행했다는 점입니다. GitHub에서는 XZ Utils 관련 깃허브를 폐쇄시켰습니다.
그렇다면, 이 취약점이 나에게도 해당되는지 궁금할 수도 있을 것 같습니다. 그래서 직접 확인해 보았습니다. 확인하는 방법은 간단합니다. 리눅스나 맥의 터미널에서 이 명령어를 입력해 봅니다.
xz --version
이 명령어의 결과값이 이 둘 중 하나라면 이 취약점에 해당된다는 겁니다.
xz (XZ Utils) 5.6.0 또는 5.6.1
liblzma 5.6.0 또는 5.6.1
만약에 이렇게 나온다면 다음 세 가지 조치 중 두 가지를 하면 된다고 합니다.
리눅스 배포판 또는 macOS를 업데이트한다.
XZ Utils를 다운그레이드하거나,
SSH 전체를 비활성화시킨다.
문제가 될 수 있는 리눅스 배포판은 다음과 같습니다.
레드햇: 페도라 41과 페도라 로하이드
수세: Tumbleweed, MicroOS
데비안: Stable 버전에서는 없음
칼리: 3월 26일~29일 사이 업데이트를 진행한 적이 있다면 해당
리눅스뿐만 아니라 맥에서도 XZ Utils를 일부 사용하고 있는 만큼 맥에서도 조치가 필요할 텐데요, brew update , brew upgrade xz 를 실행하면 XZ가 5.4.6으로 다운그레이드됩니다.
XZ Utils의 버전이 5.4.6으로 다운그레이드되었다.
다운그레이드한 버전에서도 취약점이 발견되지 않으리라는 보장은 없지만, 현 시점에서 공식적으로 확인된 바는 없다고 합니다. 공격자가 여러 프로젝트에 참여하면서 500회 이상의 커밋을 한 것으로 알려져 있어, 백도어가 심어진 다른 프로그램이 존재할 수도 있다고 합니다.
국내에서는 이 취약점으로 인한 피해는 아직 접수된 바가 없다고 하지만, 치명적인 취약점인 만큼 최신 버전으로의 업데이트를 하지 않을 것을 당부했습니다.
간단한 인터랙티브 문제였습니다. 그런데 저는 인터랙티브 문제를 풀어본 적이 아마도 없을 겁니다. 그래서 예상치 못한 결과를 받은 건가 싶네요.
사람은 최대 500명이고, 질문은 최대 1000번까지 가능하므로, 그냥 모든 사람에 대해 2번씩 질문을 던집니다. 생일인 사람에게 질문을 하면 두 번의 질문에 대해 인터랙터의 답이 모두 1이라면 걔가 정답이고, 최소 1번은 인터랙터의 답이 1이므로 그 값을 저장했다가 나중에 정답으로 출력하면 될 것 같은데...
여전히 시간 초과를 받습니다. 왜일까요...?
UPDATE: 드디어 맞았습니다!!를 받았습니다! 인터랙티브 문제에서는 출력을 하고 나서 개행 문자(\n)를 출력해야 하는데, 개행 문자를 쓰지 않아 시간 초과를 받았던 것입니다. 이제 저는 이 문제를 맞았습니다!
대회일 아침, 분명히 7시에 알람을 맞춰 놓았는데 제가 일어난 시각은 7시 50분이었습니다. 대충 준비하고 대회장으로 향했습니다. 10시 반부터 등록이었는데, 한 시간이나 일찍 도착해버렸습니다. 그런데 저보다 일찍 도착하신 분이 계셨습니다. toycartoon 님은 등록 시작 3시간 전인 7시 30분에 도착을 하셨다고 합니다.
대체 왜요
대회 시작까지는 아직 한참 남아서 문 앞에서 노가리를 까면서 기다리고 있으니 점점 사람들이 많아졌습니다. 뭔가... 다들 PS를 하게 생기신 분들이셨어요(이게 무슨 소리지).
10시 반에 대회장의 문이 열리고 등록을 시작했습니다. 바로 들어가서 등록을 마치고 많은 양의 기념품을 받고 들어가서 자리에 앉았습니다.
기념품을 엄청 많이 받았습니다. 행사장 한쪽에는 풍선이 있었는데, 이런 PS 대회에서는 문제를 맞힐 때마다 해당하는 색깔의 풍선을 달아주는 문화가 있다고 합니다. 저는 제 자리에 풍선이 하나도 달리지 않는 사태가 생길까봐 살짝 걱정했습니다.
비추어라, 그러면 보일 것이다
함께 퍼즐을 풀어봅시다!
12시 30분까지 퍼즐 헌트 이벤트를 하고 있었습니다. 페이지에 들어가면 열 개의 문제가 있는데, 뭔가 엄청 어려워 보였습니다. 등록을 하고 입장할 때 투명한 카드 같은 걸 줬는데, 같은 팀원들이 받은 것과 조합을 해 보니...
FIND OPERATIONS
글자가 나타났습니다. FIND OPERATIONS 라는 글자가 보였고, 이를 페이지에 입력하니 문제가 풀렸습니다. 뭔가 다른 문제들은 풀 엄두가 나지 않아 밥을 먹던 중, 여덟 번째 문제를 보고 있었습니다.
이게 뭔데요
' 마법, 별빛이 비추는 길을 따라 ' 라고 되어 있었습니다. 그런데 그림이 뭔가...
티켓.
처음 등록할 때 받았던 티켓과 비슷하게 생겼습니다...? 그래서 빛을 비추어 보았습니다.
WELCOME KIT
빛을 비추어야만 보이는 WELCOME KIT 글자가 있었습니다! 그래서 저는 이 문제를 맞히며 팀의 1솔에 기여했습니다[1]처음으로 맞힌 사람이었다고 썼었는데, 다시 살펴보니 아니었네요. 다른 문제하고 헷갈렸어요 :blobsad:.
퍼즐 부스.
진짜 퍼즐을 풀어야 답을 알 수 있는 문제도 있었는데, 저희 팀원이 어떻게 해서 퍼즐을 풀고 답을 맞혀버렸습니다.
이외에도 팀원들이 여러 문제를 맞혀서 6문제를 맞힌 시점에서 이벤트가 끝났습니다. 꽤나 재밌었던 이벤트였습니다.
실버에서 3솔 난다
Div.2에서 제가 유일한 실버였고, 나머지 분들은 모두 골드 이상이었습니다. 실버 대표로 출전한 느낌이었습니다(누가 대표 시켜준대...?). 대회가 시작되자마자 ABCDEFG를 모두 켜 놓고, A부터 문제를 보기 시작했습니다.
무슨 부분수열이 나오고 그럽니다. 저는 수학이 싫어요... 그런데 이거, 뭔가 풀 수 있을 것 같습니다. 문제에 나오는 수열을 한 번만 돌면 답이 나올 것 같습니다. 그리고 그 예상은 적중했습니다. 인접한 두 수를 한 번씩만 비교하면 되는 것이었습니다. 그런데, 뭔가를 잘못 생각했는지 계속 틀렸습니다가 나오는 겁니다. 그래서 일단 포기하고 C번을 풀고 돌아왔는데, 진짜 잘못 생각한 무언가가 있었습니다.
i부터 j까지 연속된 길이 k에 대해서 \frac{k(k+1)}{2}였는데, 이걸 팩토리얼하고 착각을 해서 팩토리얼을 적어버린 겁니다. 난 바보야 그래서 바로 고쳤고, 맞았습니다!!를 받았습니다.
깡!
저희 집에도 로봇 청소기를 하나 들이고 싶은데, 비싸요. 하여튼 이 로봇 청소기는 써 있는 대로 움직이기 때문에, 그대로 구현을 했습니다. 그리고 영역을 나갔는지 확인하는 코드도 넣어주고, 무한 루프의 가능성도 있기 때문에 먼지가 없는 곳을 99999번 청소하면 프로그램이 터지고 원래 나와야 할 값을 던지는 코드도 넣어줬습니다.
그랬더니 한번에 맞았습니다!!를 받았습니다. 나중에 스코어보드를 보니 이 문제를 11번 틀리고 맞히신 분도 계셨고, 28번을 틀리시고 결국 맞히지 못한 분도 계셨네요.
import sys
input = sys.stdin.readline
h, w = map(int, input().strip().split())
r, c, d = map(int, input().strip().split())
a = [list(map(int, list(input().strip()))) for _ in range(h)]
b = [list(map(int, list(input().strip()))) for _ in range(h)]
x = [[0] * w for _ in range(h)]
o = 0
p = 0
k = 0
while True:
if x[r][c] == 0:
x[r][c] = 1
k = 0
d += a[r][c]
else:
p = 2
k += 1
d += b[r][c]
if d > 3:
d = d % 4
if d == 0:
r -= 1
elif d == 1:
c += 1
elif d == 2:
r += 1
else:
c -= 1
o += 1
if r < 0 or r >= h or c < 0 or c >= w:
if k != 0:
o = o - k
break
if k > 99999:
o = o - k
break
print(o)