Page MenuHomekolab.org

Apostrophe in employee name causes LDAP crash
Open, Needs TriagePublic

Description

Running pykolab-0.8.10-1.9.el7.kolab_16.noarch

Had a new employee with the surname O'Brien join recently, and I noticed logs growing; on further inspection and installing on a fresh install on the test server there are repeated entries with the following logs below. It seems like something somewhere needs to be escaped, but I'm not sure where to begin with this best. Users with no apostrophes do not experience this.

A simple solution is outlined at http://lists.kolab.org/pipermail/users/2013-March/014584.html and suggests just taking the apostrophe out, but that seems unsatisfactory, plus it seems like it could possibly be the root of a security vulnerability if exploited correctly and there is indeed a function which is not properly parsed.

Expected behaviour is for minimal errors to be printed to logs.
Observed behaviour is users with apostrophes spam continuous ERROR entries in logs when interacting with email.

kolab/pykolab.log:
2019-04-04 03:47:51,212 pykolab.plugins.recipientpolicy ERROR [5349] Policy for secondary email address failed: SyntaxError('invalid syntax', ('<string>', 1, 66, "retval = '{0}.{1}@{2}'.format('James'[0:1].capitalize(), 'O'Brien', 'domain.com')\n"))
2019-04-04 03:47:51,212 pykolab.plugins.recipientpolicy ERROR [5349] Policy for secondary email address failed: SyntaxError('invalid syntax', ('<string>', 1, 66, "retval = '{0}.{1}@{2}'.format('James'[0:1].capitalize(), 'O'Brien', 'domain.com')\n"))

dirsrv/slapd-mail/access
[04/Apr/2019:04:08:02.642739566 +0000] conn=4 op=526 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=2 filter="(objectClass=kolabinetorgperson)" attrs=ALL
[04/Apr/2019:04:08:02.643012195 +0000] conn=4 op=526 RESULT err=0 tag=101 nentries=1 etime=0.0000311716
[04/Apr/2019:04:08:02.645905431 +0000] conn=4 op=527 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=2 filter="(objectClass=kolabinetorgperson)" attrs=ALL
[04/Apr/2019:04:08:02.646154736 +0000] conn=4 op=527 RESULT err=0 tag=101 nentries=1 etime=0.0003106545
[04/Apr/2019:04:08:02.651035525 +0000] conn=238 op=2 UNBIND
[04/Apr/2019:04:08:02.651049067 +0000] conn=238 op=2 fd=65 closed - U1
[04/Apr/2019:04:08:02.657448221 +0000] conn=4 op=528 SRCH base="dc=domain,dc=com" scope=2 filter="(&(|(mail=james.o'brien@domain.com)(alias=james.o'brien@domain.com)(nsUniqueId=james.o'brien@domain.com))(!(nsUniqueId=058c4601-568c11e9-a18c855e-3bd2aeb5)))" attrs="mail alias nsUniqueId"
[04/Apr/2019:04:08:02.657744709 +0000] conn=4 op=528 RESULT err=0 tag=101 nentries=0 etime=0.0011554739 notes=U
[04/Apr/2019:04:08:02.683915797 +0000] conn=4 op=529 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=0 filter="(objectClass=*)" attrs="distinguishedName mailQuota"
[04/Apr/2019:04:08:02.684103590 +0000] conn=4 op=529 RESULT err=0 tag=101 nentries=1 etime=0.0025389474
[04/Apr/2019:04:08:55.893372900 +0000] conn=239 fd=65 slot=65 connection from 127.0.0.1 to 127.0.0.1
[04/Apr/2019:04:08:55.893464115 +0000] conn=239 op=0 BIND dn="uid=kolab-service,ou=Special Users,dc=domain,dc=com" method=128 version=3
[04/Apr/2019:04:08:55.893873831 +0000] conn=239 op=0 RESULT err=0 tag=97 nentries=0 etime=0.0000466691 dn="uid=kolab-service,ou=special users,dc=domain,dc=com"
[04/Apr/2019:04:08:55.898841175 +0000] conn=239 op=1 BIND dn="uid=obrien,ou=People,dc=domain,dc=com" method=128 version=3
[04/Apr/2019:04:08:55.899123517 +0000] conn=239 op=1 RESULT err=0 tag=97 nentries=0 etime=0.0000314178 dn="uid=obrien,ou=people,dc=domain,dc=com"
[04/Apr/2019:04:08:55.902738767 +0000] conn=4 op=531 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=2 filter="(objectClass=kolabinetorgperson)" attrs=ALL
[04/Apr/2019:04:08:55.903029464 +0000] conn=4 op=531 RESULT err=0 tag=101 nentries=1 etime=0.0000329622
[04/Apr/2019:04:08:55.905869887 +0000] conn=4 op=532 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=2 filter="(objectClass=kolabinetorgperson)" attrs=ALL
[04/Apr/2019:04:08:55.906117000 +0000] conn=4 op=532 RESULT err=0 tag=101 nentries=1 etime=0.0003051524
[04/Apr/2019:04:08:55.911186564 +0000] conn=239 op=2 UNBIND
[04/Apr/2019:04:08:55.911200081 +0000] conn=239 op=2 fd=65 closed - U1
[04/Apr/2019:04:08:55.913678952 +0000] conn=4 op=533 SRCH base="dc=domain,dc=com" scope=2 filter="(&(|(mail=james.o'brien@domain.com)(alias=james.o'brien@domain.com)(nsUniqueId=james.o'brien@domain.com))(!(nsUniqueId=058c4601-568c11e9-a18c855e-3bd2aeb5)))" attrs="mail alias nsUniqueId"
[04/Apr/2019:04:08:55.914002883 +0000] conn=4 op=533 RESULT err=0 tag=101 nentries=0 etime=0.0007850861 notes=U
[04/Apr/2019:04:08:55.940965105 +0000] conn=4 op=534 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=0 filter="(objectClass=*)" attrs="distinguishedName mailQuota"
[04/Apr/2019:04:08:55.941171432 +0000] conn=4 op=534 RESULT err=0 tag=101 nentries=1 etime=0.0022477489
[04/Apr/2019:04:09:02.825278092 +0000] conn=240 fd=65 slot=65 connection from 127.0.0.1 to 127.0.0.1
[04/Apr/2019:04:09:02.825352874 +0000] conn=240 op=0 BIND dn="uid=kolab-service,ou=Special Users,dc=domain,dc=com" method=128 version=3
[04/Apr/2019:04:09:02.825715575 +0000] conn=240 op=0 RESULT err=0 tag=97 nentries=0 etime=0.0000403121 dn="uid=kolab-service,ou=special users,dc=domain,dc=com"
[04/Apr/2019:04:09:02.830557736 +0000] conn=240 op=1 BIND dn="uid=obrien,ou=People,dc=domain,dc=com" method=128 version=3
[04/Apr/2019:04:09:02.830875483 +0000] conn=240 op=1 RESULT err=0 tag=97 nentries=0 etime=0.0000350367 dn="uid=obrien,ou=people,dc=domain,dc=com"
[04/Apr/2019:04:09:02.834741034 +0000] conn=4 op=536 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=2 filter="(objectClass=kolabinetorgperson)" attrs=ALL
[04/Apr/2019:04:09:02.835016552 +0000] conn=4 op=536 RESULT err=0 tag=101 nentries=1 etime=0.0000324573
[04/Apr/2019:04:09:02.837912298 +0000] conn=4 op=537 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=2 filter="(objectClass=kolabinetorgperson)" attrs=ALL
[04/Apr/2019:04:09:02.838152817 +0000] conn=4 op=537 RESULT err=0 tag=101 nentries=1 etime=0.0003096284
[04/Apr/2019:04:09:02.843147061 +0000] conn=240 op=2 UNBIND
[04/Apr/2019:04:09:02.843160294 +0000] conn=240 op=2 fd=65 closed - U1
[04/Apr/2019:04:09:02.845374727 +0000] conn=4 op=538 SRCH base="dc=domain,dc=com" scope=2 filter="(&(|(mail=james.o'brien@domain.com)(alias=james.o'brien@domain.com)(nsUniqueId=james.o'brien@domain.com))(!(nsUniqueId=058c4601-568c11e9-a18c855e-3bd2aeb5)))" attrs="mail alias nsUniqueId"
[04/Apr/2019:04:09:02.845634269 +0000] conn=4 op=538 RESULT err=0 tag=101 nentries=0 etime=0.0007446365 notes=U
[04/Apr/2019:04:09:02.873749816 +0000] conn=4 op=539 SRCH base="uid=obrien,ou=People,dc=domain,dc=com" scope=0 filter="(objectClass=*)" attrs="distinguishedName mailQuota"
[04/Apr/2019:04:09:02.873909494 +0000] conn=4 op=539 RESULT err=0 tag=101 nentries=1 etime=0.0025146948

Details

Ticket Type
Task

Related Objects

Mentioned Here
U1 selinux

Event Timeline

smiler2505 raised the priority of this task from Needs Triage to Unbreak Now!.EditedApr 4 2019, 2:08 PM

Ignore this post, I am keeping it here as it was a clue to the final solution:

As it may assist others, the error string appears in /lib/python2.7/site-packages/pykolab/plugins/recipientpolicy/__init__.py

I attempted a replacement of line 136
< exec("retval = '%s'.%s" % (routine,alternative_mail_routines[number][routine] % user_attrs))
with the following and so far it seems to work:

exec("retval = \"%s\".%s" % (routine,alternative_mail_routines[number][routine] % user_attrs))

However I don't think the bug should be closed. It should be better to escape the values using something like json.dump() (to safely catch all weirdness from unicode beyond backslashes) passed to the exec() function since a name containing '"' would make this fix fail instead (although it could be caught in other routines, it shouldn't be since '"' is a valid e-mail character too conforming to the relevant RFCs when contained in a form "this"@test.com). It doesn't look like it can be exploited here but it should be investigated whether this bug is repeated elsewhere and can have worse effects.

I don't know what effect that escaping may have throughout although my feeling is it would be minimal since retval only appears to be used on line 139:
alternative_mail.append(retval)

Line 151 should also be edited:
< exec("retval = '%s'.%s" % (routine,alternative_mail_routines[number][routine] % user_attrs))

exec("retval = \"%s\".%s" % (routine,alternative_mail_routines[number][routine] % user_attrs))

smiler2505 renamed this task from Apostrophe in employee name causes fail in slapd to Apostrophe in employee name causes LDAP crash.Apr 4 2019, 2:08 PM
smiler2505 lowered the priority of this task from Unbreak Now! to Needs Triage.EditedApr 4 2019, 2:46 PM

Moving priority back to needs triage, I had caused a second fault during my investigation with a stray vim command. The above code alters the message to:

2019-04-04 12:53:12,651 pykolab.plugins.recipientpolicy ERROR [5380] Policy for secondary email address failed: SyntaxError('invalid syntax', ('<string>', 1, 66, 'retval = "{0}.{1}@{2}".format(\'James\'[0:1].capitalize(), \'O\'Brien\', \'domain.com\')\n'))

smiler2505 updated the task description. (Show Details)Apr 4 2019, 3:01 PM

Apologies that this has taken some time to post, I found the solution earlier today but was investigating other issues too. The patch is to add, on line 133:

user_attrs['surname'] = user_attrs['surname'].replace(r"'", r"\'")

Lines should also be inserted for:

user_attrs['givenname'] = user_attrs['surname'].replace(r"'", r"\'")
user_attrs['domain'] = user_attrs['surname'].replace(r"'", r"\'")

Error is due to the second part of line 137, which attempts to format the string but inserts the user_attrs without escaping them. The string can be manipulated further by inserting a name like 'O','Brien, which ends up then with 4 values for the format. Since this is called as a valid routine, there should be some extra logic inserted to make sure the string is properly escaped, although I'm not knowledgeable enough on the codebase as to where that can best be done.

I am unconvinced this is the best escaping function in python (a Mr. O\'Brien could cause an error again if the backslash isn't escaped earlier) but it fixed the issue.

smiler2505 updated the task description. (Show Details)Apr 4 2019, 6:19 PM