[LWN Logo]
[Timeline]
Date:         Mon, 15 Jan 2001 09:40:45 -0800
From: nealk <nealk@VERINET.COM>
Subject:      Flash plugin write-overflow
To: BUGTRAQ@SECURITYFOCUS.COM

Hello all,

I'm learning more and more about plugins.
I have recreated the write-overflow I found 6 months ago.

The affected plugins:
There are two primary sources for Flash plugins.
- Macromedia provides the official version.  They are NOT affected by this
  latest defect.
- Olivier Debon provides an unofficial version that has been ported to all
  operating systems not supported by Macromedia (and some that are
  supported by Macromedia).
  Systems affected include: Linux (those viewing Flash without the
  Macromedia plugin), FreeBSD, HP-UX, BeOS, Amiga, Solaris 2.5-2.8.
  The port to Windows CE by Conduit Technologies is not affected.

To determine which one you are using, use the URL "about:plugins" under Netscape.
If you see Olivier Debon's name, then you are vulnerable.
Even if you compiled it with the "NOSOUND" flag, you are still vulnerable.

Location of the defect:
DefineSound.
The format of this tag:
  tag_14  length_of_tag  sound_id flags samples data

Sound_id is two bytes giving the sound object a reference ID.
Flags is one byte that determine things like sampling rate and stereo.
"Samples" are four bytes telling the number of samples in the recording.
(ID + Flags + Samples = 5 bytes.)
The remaining data contains the actual sound.
(Flags + Samples + Data = length of tag)

The defect:
File "script.cc", in function "ParseDefineSound()".

void CInputScript::ParseDefineSound()
{
  Sound     *sound;
  U32 tagid = (U32) GetWord();
  long       nbSamples;
  long       flags;
  char      *buffer;

  sound = new Sound(tagid);

  flags = GetByte();
  sound->setSoundFlags(flags);

  addCharacter(sound);

  nbSamples = GetDWord();
  buffer = sound->setNbSamples(nbSamples);

  if (flags & soundIsADPCMCompressed) {
    Adpcm           *adpcm;
    adpcm = new Adpcm( &m_fileBuf[m_filePos] , flags & soundIsStereo );
    adpcm->Decompress((short *)buffer, nbSamples);
    delete adpcm;
  } else {
          memcpy(buffer, &m_fileBuf[m_filePos], m_tagLen-5);
  }
}

The last memcpy/Decompress call causes a write-overflow when the
number of samples is less than the remaining amount of data in the file.

"buffer" is allocated in sound.cc:
char *  Sound::setNbSamples(long n) {
        long size;
        nbSamples = n;
        size = nbSamples * (stereo ? 2 : 1) * sampleSize;
        samples = new char[ size ];
        memset((char *)samples,0, size);
        return samples;
}

The "sampleSize" is either 1 or 2 (depends on the flags used).
The size of "buffer" is allocated to be "number of samples * sampleSize *
1 or 2 for stereo".
The memcpy in ParseDefineSound() copies all of the data into the allocated
buffer.

So the defect:
I can define nbSamples (number of samples).
I define it to be much less than the number of data bytes.
  Should be:  ID + Flags + Samples = length of tag - Data.
  Overflow when:  ID + Flags + Samples < length of tag - Data

This is a write-overflow.  This is capable of running arbitrary code.
I believe this may be what I saw 6 months ago.

I have an example posted at:
  http://www.verinet.com/~nealk/Flash_and_Crash/

Reporting history:
- Reported to Macromedia on Jan. 13, 2001.  A day later they identified
  it as Olivier's code and pointed out that they were not vulnerable.
  (They may read-overflow, crash the browser, or pin the CPU, but they are
  immune to this one.)  This is also how I learned that there were multiple
  sources.
- My email to Olivier Debon on Jan. 14, 2001 bounced as undeliverable.
  Decided to post.
  (In addition, I know of literally dozens of people who are right now
  looking very closely at the Flash plugins.  It's best to post sooner
  than later.)

					-Neal