Ircu is the open source IRC server used on Undernet and other IRC networks. I (Wouter Coekaerts) discovered multiple vulnerabilities in various versions some time ago, which have all been fixed for some time (since 2.10.12.06) but not yet made public. Now that servers have had enough time to upgrade, I feel it's time to do so. None of these bugs can be abused for arbitrary code execution. Two are about crashing a server, one about exposing IP addresses, and the effect of the others stay within IRC: they allow clients to get more privileges on the IRC network then they are supposed to have. Overview ======== Affecting only 2.10.12.01: 1. Crashing servers with an innocent-looking oper-only command 2. Easy protocol violations (wallop) flooding 3. Crash with oplevels Affecting 2.10.12.02 up to and including 2.10.12.04: 4. DoS on server by creating many zannels Affecting 2.10.12.01 up to and including 2.10.12.04: 5. Gaining ops on channels that get empty on one side of a netsplit 6. Making clients think someone is on a (+D) channel, who isn't Affecting 2.10.12.03 and 2.10.12.04: 7. Netriding with ops, using zannels Affecting very old up to and including 2.10.12.05: 8. Timestamps in bounces ignored Affecting 2.10.12.01 up to and including 2.10.12.05: 9. Any op setting or changing Apass when server restarts Affecting very old up to and including 2.10.12.05: 10. Desync: unkick/deopable ops Affecting very old up to and including 2.10.12.05: 11. Getting hidden IP's of +x users Background info =============== To fully understand these bug descriptions, you'll need some knowledge of IRC and ircu-specific features like how timestamps (TS) work. Some of these vulnerabilities only affect servers with oplevels or zannels enabled, which was the default (but not anymore). Oplevels (A/Upass) is a feature that allows the creator of a new channel to set passwords on it that, when used to join, automatically give ops. Zannels is a feature introduced in 2.10.12.02 that keeps empty channels alive for a while instead of destroying them immediately, to avoid A/U passwords being set on a channel that was only empty for a short time. Zannels was enabled on Undernet on some servers for a short time and then disabled because of the trouble it caused. Oplevels never were enabled. Details ======= 1. Crashing servers with an innocent-looking oper-only command -------------------------------------------------------------- Servers crash when an oper tries to do a remote names -D (/names #foo -D some.server). This is an oper-only command, but still is a security problem because a user could trick an oper into doing it (because the command is supposed to just show info to the oper). 2. Easy protocol violations triggering -------------------------------------- /join #aa...aa and then #aa..aaa (one character longer) will cause a protocol violation. Too long channel names aren't cut off consistently (or at the wrong place). This could be abused to flood wallops. 3. Crash with oplevels ---------------------- When a server receives a "J 0:#channel" (a server message indicating a join with apass), on a channel of which it thinks doesn't have an apass set, it crashes. This can be done for example by making such a join and a mode -A cross. 4. DoS on server by creating many zannels ----------------------------------------- The fact that channels don't die immediately (but become zannels) can be abused to create a lot of channels, probably enough to take any IRC network down with a not unusually big amount of clients. A quick experiment I did shows one client (constantly sending JOIN 0,#a,#b,#c,... different channels all the time, 20 channels per command) can keep between 600 and 1200 channels alive. Besides using quite some memory for 1 client, this also sends bursts of 600 DE (destroy) messages across the network every few minutes. Now if 1000 drones would be doing this, that would mean more than a million channels alive, and bursts of 600.000 DE messages every few minutes. I guess this would probably take down a lot of servers. 5. Gaining ops on channels that get empty on one side of a netsplit ------------------------------------------------------------------- A bug in how channel TS is handled in .12 makes it possible to gain ops on a channel if you're the only one in it, without lowering the TS. This could be abused during a split to takeover a channel. This works with zannels disabled and enabled. Cause: A join (from a server) with an older TS lowers the TS on the channel, but does not remove ops. Exploit: 2 servers, each one client: s1 and s2. c1 on s1, c2 on s2 c1 the only client, not opped, on #chan. * c2 joins #chan, and parts immediately * at the same time (before the join and part arrive on s1), c1 parts and joins => when the join and part of c2 arrive the TS is set back to the original one, but c1 keeps his ops. 6. Making clients think someone is on a (+D) channel, who isn't --------------------------------------------------------------- A bug in when joins to +D channels are sent to clients can be abused to make people think someone is on the channel, who isn't. It requires you to be an op, so it isn't a big risk, but it could be used to confuse other ops, for example, pretending you can make yourself unkickable. Cause: When a zombie gets opped, the mode is sent to clients (although they think the zombie isn't on the channel). That's a bug, but on itself a small one. But when a delay-joined zombie on a +D channel gets kicked, that mode also causes a join to be sent, which is worse. Example: client1 (opped) and ghost (join-delayed) on server1, client2 (opped) on server2 client2 kicks ghost, and at the same time client1 ops ghost. client2 will see ghost join and get kicked, followed by another join and client1 opping ghost. If client2 tries to kick ghost again, he'll get a "They aren't on that channel", although his (and others on his side of the net) client shows ghost as opped on the channel. 7. Netriding with ops, using zannels ------------------------------------ This one allows netriders to set or remove any mode on any channel that gets empty on a split server with zannels enabled, except modes on users (ops, voice). Cause: When joining a zannel you get opped by the server, but that mode doesn't have a timestamp, so other servers accept it even if they have an older version of the channel. Example: Suppose some server split leaving an invite-only channel empty. During the time it is linking again, someone joins the #chan zannel left on that server, and sets a mode +i and then -i. When the burst completes, he'll get netrider kicked, but his modes get accepted at the other side, because he got opped by his server. It may seem hard to time this right, but it's really easy actually, they can constantly join, mode, part, join, mode, part,... Note: The same problem existed also for joining with the A/Upass, which could only be abused on a restarted server (which hasn't linked yet), but allows setting a new Apass, which means a total channel takeover. This was fixed with the same patch. 8. Timestamps in bounces ignored -------------------------------- Of all the bugs I discovered, this is the one that shocked me the most. Timestamps in bounces are just ignored. Causing a bounce while another server is linking which has an older version of the channel, causes the bounce to go from the new into to the old channel. This allows you to take over a channel during a netjoin. 9. Any op setting or changing Apass when server restarts -------------------------------------------------------- Modes set on a newer version of a channel during a netburst usually aren't accepted because the client setting them isn't opped on that side. But they are accepted if he gets opped fast enough. This doesn't matter for most modes, because if you can op him, you can just as well set the mode. But it does matter for +A. So if he has one client on the newly started server, which sets the mode during the burst, and one on the other side, which ops the other client just when he bursts in, before the mode has arrived, it is accepted on that side, setting a (new) Apass, no matter how old the channel is, no matter which oplevel he has. 10. Desync: unkick/deopable ops ------------------------------- If a kick and a kill or a nick collision of the kicker cross, the kick isn't propagated, leaving an unkickable/deopable (except on his own server or his side of the desync) op. It's pretty easy to make this happen. This situation can only be fixed by an op on his server (which he can prevent), or an oper killing him (and all his other desynced clients, good luck finding all those). So this makes an abuser look like he has some service/opmode power, and can make it really hard to get a taken over channel back into order. 11. Getting hidden IP's of +x users ----------------------------------- The ip of an authenticated user with +x mode set is supposed to be hidden. But you can find out that IP with a trick. With /silence you can check if someone matches a certain mask or not: send them a ctcp ping, and see if you get a reply or not. Ircu .12 supports cidr masks in /silence, so it only takes (maximum) 32 pings (there are 32 bits in an ip address). Without cidr, it takes more messages, but still less than 1000 (and if you do it smart, using tld and isp-wide silences for example, maybe even much less), so even then it's realistic. Similar things can be done with bans with people who have autorejoin on kick and autojoin on invite on, but hardy anyone does that. On the contrary almost everyone replies to ctcp pings. Online version: http://wouter.coekaerts.be/site/security/ircu Note: I am affiliated with Undernet, but this report is about my own findings and from me personally, not representing Undernet or the ircu developers.