Marcin Owsiany wrote:
> The following vulnerabilities:
> 
> * CAN-2005-1916 (insecure tempfile creation and arbitrary command
>   execution in contrib/scripts/linki.py found by Eric Romang) (local
>   vuln.)
> 
> * other vulnerabilities in user-contributed example scripts:
>  - insecure tempfile creation in contrib/ekgh, contrib/ekgnv.sh,
>    contrib/getekg.sh (local vuln.)
>  - potential shell command injection in contrib/scripts/ekgbot-pre1.py
>    (if indeed exploitable, a remote vuln.)
>  found by Marcin Owsiany and Wojtek Kaniewski
> 
> Are fixed in:
>  - upstream version 1.6rc2
>  - sid package 1:1.5+20050712+1.6rc2-1 (uploaded)
>  - sarge package 1:1.5+20050411-4 (available at
>    deb http://people.debian.org/~porridge/ekg-sarge/ ./
>    interdiff attached

Thanks a lot!

I've adjusted the changelog entry and assigned two more CVE ids:

  * Fixes insecure temporary file creation [contrib/scripts/linki.py,
    CAN-2005-1916, Bug#318059]
  * Fixes insecure temporary file creation [contrib/ekgh,
    contrib/ekgnv.sh, contrib/getekg.sh, CAN-2005-1850]
  * Fixes potential shell command injection
    [contrib/scripts/ekgbot-pre1.py, CAN-2005-1851]

Please mention them in the sid changelog when you're doing the next upload.

Please also forward them upstream.

> @@ -80,7 +83,7 @@
>  
>       if text[0] == "@":
>               if uin != owner:
> -                     ekg.command("msg %d Czy Ty, aby na pewno jeste? 
> w?a?cicielem tego bota?;)" % uin)
> +                     ekg.command("msg %d Czy Ty aby na pewno jeste? 
> w?a?cicielem tego bota?;)" % uin)
>                       return
>               tablica = ownerz
>       elif text[0] == "!": tablica = userz

Such changes should not appear in security updates!

I have removed these documentation changes.

> @@ -99,14 +102,17 @@
>       try: funkcja, ilosc = tablica[kom]
>       except: return
>  
> +     # jesli komenda wymaga argumentow
>       if ilosc > 0:
>               splitarg = arg.split()
>               args = splitarg[:ilosc]
>               if len(splitarg) > ilosc:
>                       args.append(string.join(splitarg[ilosc:]))
> +     # jesli komenda nie wymaga argumentow
>       elif ilosc == 0:
>               if len(arg) > 0: args = [arg]
>               else: args = []
> +     # bledny wpis w liscie komend
>       else: return
>  
>       try: funkcja(uin, *args)

Same goes for these changes.

Attached is the new interdiff.

Regards,

        Joey

-- 
Computers are not intelligent.  They only think they are.

Please always Cc to me when replying to me on the lists.
diff -u ekg-1.5+20050411/debian/changelog ekg-1.5+20050411/debian/changelog
--- ekg-1.5+20050411/debian/changelog
+++ ekg-1.5+20050411/debian/changelog
@@ -1,3 +1,15 @@
+ekg (1:1.5+20050411-4) stable-security; urgency=medium
+
+  * Security upload
+  * Fixes insecure temporary file creation [contrib/scripts/linki.py,
+    CAN-2005-1916, Bug#318059]
+  * Fixes insecure temporary file creation [contrib/ekgh,
+    contrib/ekgnv.sh, contrib/getekg.sh, CAN-2005-1850]
+  * Fixes potential shell command injection
+    [contrib/scripts/ekgbot-pre1.py, CAN-2005-1851]
+
+ -- Marcin Owsiany <[EMAIL PROTECTED]>  Wed, 13 Jul 2005 21:25:04 +0300
+
 ekg (1:1.5+20050411-3) unstable; urgency=high
 
   * Applied patches selected from upstream CVS, to fix the following important
only in patch2:
unchanged:
--- ekg-1.5+20050411.orig/contrib/ekgh
+++ ekg-1.5+20050411/contrib/ekgh
@@ -44,15 +44,8 @@
 
 #¯eby siê cudzys³owy, przecinki, oraz \r \n dobrze wy¶wietla³y...
 
-tail -n $ILELINII $HISTFILE | sed -e 's/\\r/\\\\r/g; s/\\n/\\\\n/g; s/,"/,/; 
s/"$//; s/*/"*"/g' > /usr/tmp/gg_history 
-                                
-                                # czemu * wy¶wietla zaw. katalogu?
-                                # *uj j± tam wie :>
-                                                       
-
-#No to sru
-
-cat /usr/tmp/gg_history | while read linia; do
+tail -n $ILELINII $HISTFILE | sed -e 's/\\r/\\\\r/g; s/\\n/\\\\n/g; s/,"/,/; 
s/"$//; s/*/"*"/g' | \
+while read linia; do
 
 DATA_S=$(echo $linia | cut -d "," -f4 )
 DATA=$(date -d "1970-01-01 `echo $DATA_S` sec UTC" +"%Y-%m-%d %T")
only in patch2:
unchanged:
--- ekg-1.5+20050411.orig/contrib/ekgnv.sh
+++ ekg-1.5+20050411/contrib/ekgnv.sh
@@ -8,7 +8,7 @@
 #
 # Zmienne dla ~/.ekgnv :
 # WGET= ¶cie¿ka do wget'a
-# EKGTMP= gdzie ma wrzucaæ pliki tymaczasowe
+# EKGTMP= gdzie zostanie utworzony podkatalog na pliki tymaczasowe
 # EKGWWW= adres strony ekg.
 # EKGCONF= co ma podawaæ do configure gdy automatycznie budujesz ekg
 # LASTEKG= ostatnia zainstalowana werja ekg
@@ -40,6 +40,15 @@
 # Wczytaj ustawienia.
   . ~/.ekgnv
 
+# wymyslamy bezpieczny podkatalog
+EKGTMPS="$EKGTMP/ekgnv-$$"
+mkdir "$EKGTMPS"
+if [ "$?" != "0" ]; then
+       echo "Proba utworzenia katalogu tymczasowego \"$EKGTMPS\" nie powiodla 
sie." >&2
+       echo "Posprzataj \"$EKGTMP\" i sprobuj ponownie." >&2
+       exit 1
+fi
+
 # Czy w systemie jest wget?
 function check_wget {
  if [ ! -x "$WGET" ]; then \
@@ -52,13 +61,13 @@
 function get_list {
  check_wget
  echo -n "¦ci±gam listê wersji EKG. Poczekaj chwilê. "
-  wget -q -P $EKGTMP $EKGWWW/download.php
+  wget -q -P $EKGTMPS $EKGWWW/download.php
  # to mozna zamienic na odczytywanie pliku ktory bylby automatycznie po
  # twojej stronie generowany, a w ktorym bylby tylko numer najnowszej 
  # werjsji
- LASTES="`grep ekg-20 $EKGTMP/download.php | cut -d\  -f6 | \
+ LASTES="`grep ekg-20 $EKGTMPS/download.php | cut -d\  -f6 | \
           cut -d\\" -f2 | tail -1 | sed -e s/.tar.gz//`"
-  rm -f $EKGTMP/download.php*
+  rm -f $EKGTMPS/download.php*
  echo "Gotowe!"
 }
 
@@ -82,13 +91,13 @@
  check_new
   if [ ! -z "$NEW" ]; then \
    echo -n "¦ci±gam j±, poczekaj chwilê. "
-   wget -q -P $EKGTMP $EKGWWW/$LASTES.tar.gz
+   wget -q -P $EKGTMPS $EKGWWW/$LASTES.tar.gz
    cat ~/.ekgnv | sed -e s/$LASTEKG/$LASTES/ > ~/.ekgtmp
  # lub jak ktos nie ma seda to grep -v "LASTEKG" ~/.ekgnv > ~/.ekgtmp
  # echo "export LASTEKG=$LASTES" >> ~/.ekgtmp
    mv -f ~/.ekgtmp ~/.ekgnv
    echo "Gotowe.
-Plik znajduje siê w $EKGTMP/$LASTES.tar.gz"
+Plik znajduje siê w $EKGTMPS/$LASTES.tar.gz"
   else 
    echo 
   fi
@@ -99,11 +108,11 @@
  get_new
   if [ ! -z "$NEW" ]; then \
    echo -n "Buduje nowe EKG. Poczekaj chwilê. "
-   ( cd $EKGTMP ;
+   ( cd $EKGTMPS ;
    tar -zxf $LASTES.tar.gz ; cd $LASTES ;
      ./configure $EKGCONF > /dev/null ; # tylko b³êdy bêd± na konsoli.
       make ; make install > /dev/null ;
-   rm -rf ../$LASTES* ; )
+      cd .. ; rm -rf $LASTES $LATES.tar.gz ; )
    echo "Skoñczy³em. Masz ju¿ najnowsz± wersjê."
   fi
 }
only in patch2:
unchanged:
--- ekg-1.5+20050411.orig/contrib/getekg.sh
+++ ekg-1.5+20050411/contrib/getekg.sh
@@ -7,8 +7,13 @@
        echo "Podaj zmienne (\"--prefix=/usr\" itp.) dla configure'a!"; 
        exit 1; 
 fi
-echo "Wchodzê do katalogu tymczasowego."
-cd /tmp
+DIR="${TMPDIR:-${TMP:-/tmp}}/getekg-$$"
+if ! mkdir "$DIR"; then
+       echo "Nie udalo sie utworzyc katalogu tymczasowego \"$DIR\"." >&2
+       exit 1
+fi
+echo "Wchodzê do katalogu tymczasowego \"$DIR\"."
+cd "$DIR"
 echo -n "¦ci±gam najnowsz± wersjê."
  if [ ! -x "`which wget`" ]; then \
     if [ ! -x "`which curl`" ]; then \
only in patch2:
unchanged:
--- ekg-1.5+20050411.orig/contrib/scripts/ekgbot-pre1.py
+++ ekg-1.5+20050411/contrib/scripts/ekgbot-pre1.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# -*- coding: ISO-8859-2 -*-
 # ekg-bot 0.1-pre1
 # Copyright (C) 2003 Andrzej Lindna³
 #
@@ -25,6 +26,8 @@
 from urllib import *                                   # Obs³uga www
 from time import *                                     # Operacje czasowe
 from random import Random                              # Random
+from os import *                                       # do implementacji popen
+#import sys                                            # debugowanie 
implementacji popen
 
 # Konfiguracja
 owner = twojnumer                                      # Numer gg ownera
@@ -312,12 +315,10 @@
 def freestats(uin):
        free = os.popen("%s -m" % path_free).read()
        ekg.command("msg %d %s" % (uin, free))
-       os.popen("%s -m" % path_free).close()
 
 def hddstats(uin):
        df = os.popen("%s -h" % path_df).read()
        ekg.command("msg %d %s" % (uin, df))
-       os.popen("%s -h" % path_df).close()
 
 def refstatus(uin):
        status_ref = strftime("%a, %d %b %Y %H:%M:%S %Z")
@@ -332,9 +333,8 @@
        ekg.command("msg %d %s" % (uin, checkurl.info().getheader('Server')))
 
 def ciekhost(uin, host):
-       qmer = os.popen("%s %s" % (path_host, re.escape(host))).read()
+       qmer = safepopen([path_host, host])
        ekg.command("msg %d %s" % (uin, qmer))
-       os.popen("%s %s" % (path_host, re.escape(host))).close()
 
 def fetchmail(uin):
        os.popen("%s" % path_fetchmail)
@@ -351,6 +351,7 @@
                ekg.command("block %d" % ktos)
                ekg.command("msg %d %d zosta³ zablokowany" % (uin, ktos))
        except: ekg.command("msg %d Musisz podaæ parametr jako UIN do 
zablokowania" % uin)
+
 def unblock(uin, numer):
        try:
                numer = int(numer)
@@ -393,16 +394,13 @@
 
 def uname(uin):
        ekg.command("msg %d %s" % (uin, os.popen("%s -mnrs" % 
path_uname).read()))
-       os.popen("%s -mnrs" % path_uname).close()
 
 def krot(uin, ile, tekst):
        ile = int(ile)
        if ile < 2 or ile > 23: ekg.command("msg %d Jako pierwszy parametr 
nale¿y podaæ liczbê z zakresu 2-23." % uin)
        else:
                try:
-                       cmdline = "%s -ear%d %s" % (path_erecoder, ile, 
re.escape(tekst))
-                       ekg.command("msg %d %s" % (uin, 
os.popen(cmdline).read()))
-                       os.popen(cmdline).close()
+                       ekg.command("msg %d %s" % (uin, 
safepopen([path_erecoder, '-ear'+ile, '--', tekst])))
                except: ekg.command("msg %d Jako pierwszy parametr nale¿y podaæ 
liczbê z zakresu 2-23." % uin)
 
 def drot(uin, ile, tekst):
@@ -410,9 +408,7 @@
        if ile < 2 or ile > 23: ekg.command("msg %d Jako pierwszy parametr 
nale¿y podaæ liczbê z zakresu 2 - 23." % uin)
        else:
                try:
-                       cmdline = "%s -dar%d %s" % (path_erecoder, int(ile), 
re.escape(tekst))
-                       ekg.command("msg %d %s" % (uin, 
os.popen(cmdline).read()))
-                       os.popen(cmdline).close()
+                       ekg.command("msg %d %s" % (uin, 
safepopen([path_erecoder, '-dar'+ile, '--', tekst])))
                except: ekg.command("msg %d Jako pierwszy parametr nale¿y podaæ 
liczbê z zakresu 2-23" % uin)
 
 def kbase(uin, tekst):
@@ -496,6 +492,7 @@
                ekg.command("msg %d Wylosowane przez komputer liczby do losowañ 
Zak³adów Specjalnych to: %s" % (uin, lotto(42,5)))
        else:
                ekg.command("msg %d Nieznany parametr! Parametry:\r\nmulti, 
duzy, express, zaklady" % uin)
+
 def sin(uin, liczba):
        try: ekg.command("msg %d %s" % (uin, trygonometria('sin', liczba)))
        except: ekg.command("msg %d B³êdne wywo³anie." % uin)
@@ -523,14 +520,10 @@
                ?polecenie. Na przyk³ad: ?status.\r\nAutorem tego bota jest 
Andrzej Lindna³""" % uin)
 
 def kmorse(uin, tekst):
-       cmdline = "%s -eam -- %s" % (path_erecoder, re.escape(tekst))
-       ekg.command("msg %d %s" % (uin, os.popen(cmdline).read()))
-       os.popen(cmdline).close()
+       ekg.command("msg %d %s" % (uin, safepopen([path_erecoder, '-eam', '--', 
tekst])))
 
 def dmorse(uin, tekst):
-       cmdline = "%s -dam -- %s" % (path_erecoder, re.escape(tekst))
-       ekg.command("msg %d %s" % (uin, os.popen(cmdline).read()))
-       os.popen(cmdline).close()
+       ekg.command("msg %d %s" % (uin, safepopen([path_erecoder, '-dam', '--', 
tekst])))
 
 def bmi(uin, masa, wzrost):
        try:
@@ -561,3 +554,26 @@
 def killme(uin):
        ekg.command("msg %d Wy³±czam EKG. Aby mnie ponownie w³±czyæ, bêdziesz 
musia³ zalogowaæ siê na shella niestety;))" % uin)
        ekg.command("quit")
+
+
+def safepopen(cmd):
+       rfd, wfd = pipe()
+       ret = fork()
+       # child
+       if ret == 0:
+               close(rfd)
+               dup2(wfd, 1)
+               execv(cmd[0], cmd)
+               exit(1)
+       # parent
+       else:
+               close(wfd)
+#              sys.stderr.write('reading..')
+               readstring = read(rfd, 4094)
+#              sys.stderr.write('got it!')
+               while read(rfd, 4096) != '':
+                       pass
+#              sys.stderr.write('EOF')
+               waitpid(ret, 0)
+#              sys.stderr.write('reaped')
+               return readstring
only in patch2:
unchanged:
--- ekg-1.5+20050411.orig/contrib/scripts/linki.py
+++ ekg-1.5+20050411/contrib/scripts/linki.py
@@ -1,14 +1,21 @@
+# -*- coding: ISO-8859-2 -*-
 # Skrypt ten uruchamia siê z poziomu ekg (polecenie python) a zadanie jego to
 # wy³apywanie adresów URL w otzymanych wiadomo¶ciach. Mozna by w tym miejscu 
poopowiadaæ o dzia³aniu skryptu
 # ale my¶le ze skypt jest dosæ rozmowny pozatym by poczytaæ helpa (i nie 
tylko) wystarczy nacisn±æ F8
 # wszelkie pretensje mo¿na kierowaæ na adres: rmrmg(at)wp(dot)pl
+#
+# poprawki bezpieczeñstwa: wojtekka (2005-07-11)
+
 import re
 import ekg
 import string
 import os
 
+browser="firefox"
 link=re.compile(".*http.*")
 linka=re.compile("http.*")
+linkfile=os.path.expanduser("~/.gg/rmrmg_ekg_url")
+
 def init ():
  ekg.printf("generic", "linkownik")
  return 1
@@ -17,6 +24,17 @@
  ekg.printf("generic", "linkownik poszed³")
  return 1 
 
+def launch(url, tab):
+    url = string.replace(string.replace(url, ",", "%2c"), "'", "%27");
+    
+    if tab:
+       command = "%s -remote 'openURL(%s, new-tab)'" % (browser, url)
+    else:
+       command = "%s '%s'" % (browser, url)
+
+    #ekg.printf("generic", "[%s]" % (command))
+    os.system(command)
+
 def handle_msg(uin, name, msgclass, text, time, secure):
     #ekg.printf("generic", "echo dzia³a")
     if link.match(text):
@@ -26,7 +44,7 @@
                ekg.printf("generic", "znaleziono link: %s" %(x)) 
                ekg.printf("generic", "by otworzyæ w: nowym oknie wcisnij F7, 
nowej zak³adce F5, by nie otwierac wci¶nijF6.")
                ekg.printf("generic", "F8 pokazuje liste przechwyconych linków; 
F5-F7 dzia³a na pierwszym linku z listy")
-               os.system("echo \"%s\" >> /tmp/rmrmg_ekg_url" %(x))
+               open(linkfile, 'a').write(x + '\n');
        #ekg.printf("generic","echo tada")
        return 1
     else:
@@ -42,13 +60,13 @@
            dlug=len(nurl)
            if dlug == 1:
                ekg.printf("generic", "otwieram %s w nowej zak³adce" %(nurl[0]))
-               os.system("MozillaFirebird -remote 'openURL(%s, new-tab)'" 
%(nurl[0]))
-               os.system('rm /tmp/rmrmg_ekg_url')
+               launch(nurl[0], True)
+               os.unlink(linkfile)
            else:
                ekg.printf("generic", "linków mam %d" %(dlug))
                wielejest(nurl)
                ekg.printf("generic", "otwieram %s w nowej zak³adce" %(nurl[0]))
-               os.system("MozillaFirebird -remote 'openURL(%s, new-tab)'" 
%(nurl[0]))
+               launch(nurl[0], True)
     elif key == 270:
        ekg.printf("generic", "wcisniêto F6")
        nurl=czyjest()
@@ -58,7 +76,7 @@
            dlug=len(nurl)
            if dlug == 1:
                ekg.printf("generic", "kasuje adres %s" %(nurl[0]))         
-               os.system('rm /tmp/rmrmg_ekg_url')
+               os.unlink(linkfile)
            else:
                ekg.printf("generic", "jest wiele linków")
                wielejest(nurl)
@@ -72,8 +90,8 @@
            dlug=len(nurl)
            if dlug == 1:
                ekg.printf("generic", "otwieram %s w nowym oknie" %(nurl[0]))
-               os.system("MozillaFirebird %s" %(nurl[0]))
-               os.system('rm /tmp/rmrmg_ekg_url')              
+               launch(nurl[0], False)
+               os.unlink(linkfile)
            else:
                ekg.printf("generic", "linków mam %d" %(dlug))
                wielejest(nurl)
@@ -93,8 +111,8 @@
 ###########################################################
 
 def czyjest ():
-    if os.path.exists('/tmp/rmrmg_ekg_url'):
-       wejsc= open ('/tmp/rmrmg_ekg_url')
+    if os.path.exists(linkfile):
+       wejsc= open (linkfile)
        file = wejsc.readlines()
        dlug=len(file)
        wejsc.close()
@@ -104,7 +122,7 @@
        return 0
        
 def wielejest (buff):
-    file=open('/tmp/rmrmg_ekg_url' , 'w')              
+    file=open(linkfile , 'w')          
     #buff= file.readlines()
     #file.truncate()
     #file.writelines

Attachment: signature.asc
Description: Digital signature

_______________________________________________
Secure-testing-team mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/secure-testing-team

Reply via email to