[Secure-testing-team] Re: ekg: CAN-2005-1916 Bug#317027 and #318059
FIXED
Marcin Owsiany
porridge at debian.org
Fri Jul 15 16:04:59 UTC 2005
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
All previous versions are vulnerable (except for some very old ones,
which do not contain the scripts).
Woody does not contain ekg package.
ekg2 (in experimental) does not contain the vulnerable scripts.
please issue a DSA
Marcin
--
Marcin Owsiany <porridge at debian.org> http://marcin.owsiany.pl/
GnuPG: 1024D/60F41216 FE67 DA2D 0ACA FC5E 3F75 D6F6 3A0D 8AA0 60F4 1216
-------------- next part --------------
interdiff debian/ekg_1.5+20050411-4.diff.0 debian/ekg_1.5+20050411-4.diff
diff -u ekg-1.5+20050411/debian/changelog ekg-1.5+20050411/debian/changelog
--- ekg-1.5+20050411/debian/changelog 2005-05-24 19:14:30.000000000 +0200
+++ ekg-1.5+20050411/debian/changelog 2005-07-13 21:30:21.829781920 +0300
@@ -1,3 +1,12 @@
+ekg (1:1.5+20050411-4) stable-security; urgency=medium
+
+ * Security upload
+ * Fixes symlink creation and potential shell injection vulnerabilities in
+ user-contributed example scripts. (CAN-2005-1916) (CAN-2005-XXXX -
+ optionally if we decide to get new one). Closes: #318059
+
+ -- Marcin Owsiany <porridge at kufelek> 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 2002-10-30 01:00:00.000000000 +0200
+++ ekg-1.5+20050411/contrib/ekgh 2005-07-13 21:33:26.810660552 +0300
@@ -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 2002-03-30 01:00:00.000000000 +0200
+++ ekg-1.5+20050411/contrib/ekgnv.sh 2005-07-13 21:33:26.847654928 +0300
@@ -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 2002-05-29 01:00:00.000000000 +0300
+++ ekg-1.5+20050411/contrib/getekg.sh 2005-07-13 21:33:26.848654776 +0300
@@ -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 2003-06-29 21:19:00.000000000 +0300
+++ ekg-1.5+20050411/contrib/scripts/ekgbot-pre1.py 2005-07-13 21:33:26.888648696 +0300
@@ -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
@@ -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
@@ -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)
@@ -307,17 +313,15 @@
try:
ekg.command("add %d %s" % (int(duin), nazwa))
ekg.command("msg %d Doda?em %s (%s) do listy kontakt?w." % (uin, duin, nazwa))
- except: ekg.command("msg %d Pierwszy parametro to UIN, a drugi NAZWA." % uin)
+ except: ekg.command("msg %d Pierwszy parametr to UIN, a drugi NAZWA." % uin)
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 +336,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 +354,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 +397,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 +411,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 +495,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 +523,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 +557,27 @@
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 2003-06-29 23:29:58.000000000 +0300
+++ ekg-1.5+20050411/contrib/scripts/linki.py 2005-07-13 21:33:26.926642920 +0300
@@ -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,9 +122,9 @@
return 0
def wielejest (buff):
- file=open('/tmp/rmrmg_ekg_url' , 'w')
+ file=open(linkfile , 'w')
#buff= file.readlines()
#file.truncate()
#file.writelines
file.writelines('\n'.join (buff[1:]))
- file.close()
\ Brak znaku nowej linii na ko?cu pliku
+ file.close()
#-diff -u debian/ekg_1.5+20050411-4.diff.0 debian/ekg_1.5+20050411-4.diff
More information about the Secure-testing-team
mailing list