index.html (15721B)
1<!doctype html> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> 6 <title>STLDoctor</title> 7 <style type="text/css"> 8 body { 9 font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 10 color: #222; 11 font-size: 100%; 12} 13 14.slide { 15 position: absolute; 16 top: 0; bottom: 0; 17 left: 0; right: 0; 18 background-color: #f7f7f7; 19} 20 21.slide-content { 22 width: 800px; 23 height: 600px; 24 overflow: hidden; 25 margin: 80px auto 0 auto; 26 padding: 30px; 27 28 font-weight: 200; 29 font-size: 200%; 30 line-height: 1.375; 31} 32 33.controls { 34 position: absolute; 35 bottom: 20px; 36 left: 20px; 37} 38 39.arrow { 40 width: 0; height: 0; 41 border: 30px solid #333; 42 float: left; 43 margin-right: 30px; 44 45 -webkit-touch-callout: none; 46 -webkit-user-select: none; 47 -khtml-user-select: none; 48 -moz-user-select: none; 49 -ms-user-select: none; 50 user-select: none; 51} 52 53.prev { 54 border-top-color: transparent; 55 border-bottom-color: transparent; 56 border-left-color: transparent; 57 58 border-left-width: 0; 59 border-right-width: 50px; 60} 61 62.next { 63 border-top-color: transparent; 64 border-bottom-color: transparent; 65 border-right-color: transparent; 66 67 border-left-width: 50px; 68 border-right-width: 0; 69} 70 71.prev:hover { 72 border-right-color: #888; 73 cursor: pointer; 74} 75 76.next:hover { 77 border-left-color: #888; 78 cursor: pointer; 79} 80 81h1 { 82 font-size: 300%; 83 line-height: 1.2; 84 text-align: center; 85 margin: 170px 0 0; 86} 87 88h2 { 89 font-size: 100%; 90 line-height: 1.2; 91 margin: 5px 0; 92 text-align: center; 93 font-weight: 200; 94} 95 96h3 { 97 font-size: 140%; 98 line-height: 1.2; 99 border-bottom: 1px solid #aaa; 100 margin: 0; 101 padding-bottom: 15px; 102} 103 104ul { 105 padding: 20px 0 0 60px; 106 font-weight: 200; 107 line-height: 1.375; 108} 109 110.author h1 { 111 font-size: 170%; 112 font-weight: 200; 113 text-align: center; 114 margin-bottom: 30px; 115} 116 117.author h3 { 118 font-weight: 100; 119 text-align: center; 120 font-size: 95%; 121 border: none; 122} 123 124a { 125 text-decoration: none; 126 color: #44a4dd; 127} 128 129a:hover { 130 color: #66b5ff; 131} 132 133pre { 134 font-size: 60%; 135 line-height: 1.3; 136} 137 138.progress { 139 position: fixed; 140 top: 0; left: 0; right: 0; 141 height: 3px; 142 z-index: 1; 143} 144 145.progress-bar { 146 width: 0%; 147 height: 3px; 148 background-color: #b4b4b4; 149 150 -webkit-transition: width 0.05s ease-out; 151 -moz-transition: width 0.05s ease-out; 152 -o-transition: width 0.05s ease-out; 153 transition: width 0.05s ease-out; 154} 155 156.hidden { 157 display: none; 158} 159 160@media (max-width: 850px) { 161 162 body { 163 font-size: 70%; 164 } 165 166 .slide-content { 167 width: auto; 168 } 169 170 img { 171 width: 100%; 172 } 173 174 h1 { 175 margin-top: 120px; 176 } 177 178 .prev, .prev:hover { 179 border-right-color: rgba(135, 135, 135, 0.5); 180 } 181 182 .next, .next:hover { 183 border-left-color: rgba(135, 135, 135, 0.5); 184 } 185} 186 187@media (max-width: 480px) { 188 body { 189 font-size: 50%; 190 overflow: hidden; 191 } 192 193 .slide-content { 194 padding: 10px; 195 margin-top: 10px; 196 height: 340px; 197 } 198 199 h1 { 200 margin-top: 50px; 201 } 202 203 ul { 204 padding-left: 25px; 205 } 206} 207 208@media print { 209 * { 210 -webkit-print-color-adjust: exact; 211 } 212 213 @page { 214 size: letter; 215 } 216 217 .hidden { 218 display: inline; 219 } 220 221 html { 222 width: 100%; 223 height: 100%; 224 overflow: visible; 225 } 226 227 body { 228 margin: 0 auto !important; 229 border: 0; 230 padding: 0; 231 float: none !important; 232 overflow: visible; 233 background: none !important; 234 font-size: 52%; 235 } 236 237 .progress, .controls { 238 display: none; 239 } 240 241 .slide { 242 position: static; 243 } 244 245 .slide-content { 246 border: 1px solid #222; 247 margin-top: 0; 248 margin-bottom: 40px; 249 height: 3.5in; 250 overflow: visible; 251 } 252 253 .slide:nth-child(even) { 254 /* 2 slides per page */ 255 page-break-before: always; 256 } 257} 258 259/* 260 261github.com style (c) Vasily Polovnyov <vast@whiteants.net> 262 263*/ 264 265.hljs { 266 display: block; 267 overflow-x: auto; 268 padding: 0.5em; 269 color: #333; 270 background: #f8f8f8; 271} 272 273.hljs-comment, 274.hljs-quote { 275 color: #998; 276 font-style: italic; 277} 278 279.hljs-keyword, 280.hljs-selector-tag, 281.hljs-subst { 282 color: #333; 283 font-weight: bold; 284} 285 286.hljs-number, 287.hljs-literal, 288.hljs-variable, 289.hljs-template-variable, 290.hljs-tag .hljs-attr { 291 color: #008080; 292} 293 294.hljs-string, 295.hljs-doctag { 296 color: #d14; 297} 298 299.hljs-title, 300.hljs-section, 301.hljs-selector-id { 302 color: #900; 303 font-weight: bold; 304} 305 306.hljs-subst { 307 font-weight: normal; 308} 309 310.hljs-type, 311.hljs-class .hljs-title { 312 color: #458; 313 font-weight: bold; 314} 315 316.hljs-tag, 317.hljs-name, 318.hljs-attribute { 319 color: #000080; 320 font-weight: normal; 321} 322 323.hljs-regexp, 324.hljs-link { 325 color: #009926; 326} 327 328.hljs-symbol, 329.hljs-bullet { 330 color: #990073; 331} 332 333.hljs-built_in, 334.hljs-builtin-name { 335 color: #0086b3; 336} 337 338.hljs-meta { 339 color: #999; 340 font-weight: bold; 341} 342 343.hljs-deletion { 344 background: #fdd; 345} 346 347.hljs-addition { 348 background: #dfd; 349} 350 351.hljs-emphasis { 352 font-style: italic; 353} 354 355.hljs-strong { 356 font-weight: bold; 357} 358 359 360 </style> 361 <script async src="http://localhost:35729/livereload.js"></script> 362</head> 363<body> 364 <div class="progress"> 365 <div class="progress-bar"></div> 366 </div> 367 368 <div class="slide" id="slide-1"> 369 <section class="slide-content"><style> 370 371.footnote { 372 font-size: 16pt; 373 position: absolute; 374 color: gray; 375 bottom: 0px; 376 right: 0px; 377} 378 379.slide-content { 380 position: relative; 381} 382 383.slide-content > ul >li { 384 padding: 7px 0px; 385} 386 387.slide-content > p > img { 388 width: 100%; 389} 390 391</style></section> 392 </div> 393 <div class="slide hidden" id="slide-2"> 394 <section class="slide-content"><h1 id="stldoctor-">STLDoctor 💉</h1> 395</section> 396 </div> 397 <div class="slide hidden" id="slide-3"> 398 <section class="slide-content"><h3 id="the-plan-">The Plan 💡</h3> 399<!-- Familiar with C and wondered about non-standard 400 buffer-/integer overflow C bugs --> 401<!-- Plaintext file inspection service --> 402<!-- Interesting and realisitic bugs --> 403<!-- Written in C --> 404<!-- Have to combine 'gadgets' for exploit, but 405 as a logic bug, not RCE --> 406<ul> 407<li>Plaintext service</li> 408<li>Interesting C bugs</li> 409<li>Exploit logic bugs, not RCE</li> 410<li>Learn about the STL format</li> 411</ul> 412<p><img style="width: 240px !important; transform: rotate(90deg); height: 240px; position:absolute; top:150px; right:70px;" src="https://upload.wikimedia.org/wikipedia/commons/9/9b/STL_sample_2.png"></p> 413</section> 414 </div> 415 <div class="slide hidden" id="slide-4"> 416 <section class="slide-content"><h3 id="setup-">Setup 🔧</h3> 417<ul> 418<li>C binary that communicates via <code>stdin</code> and <code>stdout</code></li> 419<li>Networking abstracted through hosting with <code>socat</code></li> 420<li>File system backend with periodic clean up</li> 421</ul> 422<p><img src="media/socat.gif" alt="socat"></p> 423</section> 424 </div> 425 <div class="slide hidden" id="slide-5"> 426 <section class="slide-content"><h3 id="functionality-">Functionality 🎮</h3> 427<!-- file system backend separates user accounts and stl files location for non-guests --> 428<!-- guest account files can be downloaded by knowing their modelname, 429 premium account files can only be downloaded by authenticated users --> 430<ul> 431<li>Users can upload and search for files</li> 432<li>Register to upload private files</li> 433<li>Uploaded files are analyzed and information is returned to the user</li> 434</ul> 435</section> 436 </div> 437 <div class="slide hidden -" id="slide-6"> 438 <section class="slide-content"><!-- Sample interaction demonstrating how you would retrieve a file you uploaded --> 439<p><img src="media/search.gif" alt="FileSearch"></p> 440</section> 441 </div> 442 <div class="slide hidden" id="slide-7"> 443 <section class="slide-content"><h3 id="1-vuln-">1. Vuln 💉</h3> 444<ul> 445<li>Flags are stored in the solidname of the STL</li> 446<li>Bug in upload info file parsing allows attacker to retrieve any public file</li> 447</ul> 448</section> 449 </div> 450 <div class="slide hidden" id="slide-8"> 451 <section class="slide-content"><h3 id="2-vuln-">2. Vuln 💉</h3> 452<ul> 453<li>Flags are stored in the solidname of a private file</li> 454<li>Buffer overflow in hash function allows enumeration of private user hashes</li> 455<li>Generate preimages of weak hash function to login as users</li> 456</ul> 457</section> 458 </div> 459 <div class="slide hidden" id="slide-9"> 460 <section class="slide-content"><h3 id="goals-met-">Goals Met 🎉</h3> 461<!-- dont need to be an expert at fancy exploitation to exploit, 462 just basic knowledge of C and testing code snippets to see 463 if they do what you expect them to in different cases --> 464<p>⭐ Plaintext file inspection service <br> 465⭐ Interesting and realisitic bugs <br> 466⭐ Combine different gadgets for exploit <br> 467⭐ Don't need to be an expert at fancy ROP <br> 468⭐ No SLA lost in TestCTF <br> 469⭐ Written in C</p> 470</section> 471 </div> 472 <div class="slide hidden" id="slide-10"> 473 <section class="slide-content"><h3 id="issues-">Issues 📉</h3> 474<!-- Currently, the exploits dont require you to understand the 475 STL file format, however, to make sure that the service 476 is working correctly, you need to inspect the code --> 477<!-- Still considering encoding of flags as STL, but want to 478 avoid --> 479<p>💥 Exploits not directly related to STL format <br> 480💥 (Eno)checker has memory leaks</p> 481</section> 482 </div> 483 <div class="slide hidden" id="slide-11"> 484 <section class="slide-content"><h3 id="lesssons-learned">Lesssons Learned</h3> 485<!-- from the feedback I gathered, that not a lot of people write C code 486 often, but this also means it is a great opportunity for learning 487 something new. --> 488<ul> 489<li>Many exploits are not suited for A/D ctfs</li> 490<li>How to write a FSM format parser</li> 491<li>Be careful with casts in C</li> 492<li>People just <em>love</em> C services 🤡</li> 493</ul> 494</section> 495 </div> 496 <div class="slide hidden" id="slide-12"> 497 <section class="slide-content"></section> 498 </div> 499 <div class="slide hidden" id="slide-13"> 500 <section class="slide-content"></section> 501 </div> 502 <div class="slide hidden" id="slide-14"> 503 <section class="slide-content"><h1 id="exploit-1">Exploit 1</h1> 504</section> 505 </div> 506 <div class="slide hidden" id="slide-15"> 507 <section class="slide-content"><p><img src="media/exploit-1-1.png" alt="exploit-1-1"></p> 508</section> 509 </div> 510 <div class="slide hidden" id="slide-16"> 511 <section class="slide-content"><p><img src="media/exploit-1-2.png" alt="exploit-1-2"></p> 512</section> 513 </div> 514 <div class="slide hidden" id="slide-17"> 515 <section class="slide-content"><p><img src="media/exploit-1-3.png" alt="exploit-1-3"></p> 516</section> 517 </div> 518 <div class="slide hidden" id="slide-18"> 519 <section class="slide-content"><p><img src="media/exploit-1-4.png" alt="exploit-1-4"></p> 520</section> 521 </div> 522 <div class="slide hidden" id="slide-19"> 523 <section class="slide-content"><p><img src="media/exploit-1-5.png" alt="exploit-1-5"></p> 524</section> 525 </div> 526 <div class="slide hidden" id="slide-20"> 527 <section class="slide-content"><h1 id="exploit-2">Exploit 2</h1> 528</section> 529 </div> 530 <div class="slide hidden" id="slide-21"> 531 <section class="slide-content"><p><img src="media/exploit-2-1.png" alt="exploit-2-1"></p> 532<script> 533 // var slide_headers = document.querySelectorAll(".slide-content > h3"); 534 // for (var i = 0; i < slide_headers.length; i++) { 535 // var img = document.createElement('img') 536 // img.src = "logo.png"; 537 // img.style = "height: 2.4ex; padding-right: 10px; float:right"; 538 // slide_headers[i].append(img); 539 // } 540</script></section> 541 </div> 542 543 544 545 <script type="text/javascript"> 546 /** 547 * Returns the current page number of the presentation. 548 */ 549function currentPosition() { 550 return parseInt(document.querySelector('.slide:not(.hidden)').id.slice(6)); 551} 552 553 554/** 555 * Navigates forward n pages 556 * If n is negative, we will navigate in reverse 557 */ 558function navigate(n) { 559 var position = currentPosition(); 560 var numSlides = document.getElementsByClassName('slide').length; 561 562 /* Positions are 1-indexed, so we need to add and subtract 1 */ 563 var nextPosition = (position - 1 + n) % numSlides + 1; 564 565 /* Normalize nextPosition in-case of a negative modulo result */ 566 nextPosition = (nextPosition - 1 + numSlides) % numSlides + 1; 567 568 document.getElementById('slide-' + position).classList.add('hidden'); 569 document.getElementById('slide-' + nextPosition).classList.remove('hidden'); 570 571 updateProgress(); 572 updateURL(); 573 updateTabIndex(); 574} 575 576 577/** 578 * Updates the current URL to include a hashtag of the current page number. 579 */ 580function updateURL() { 581 try { 582 window.history.replaceState({} , null, '#' + currentPosition()); 583 } catch (e) { 584 window.location.hash = currentPosition(); 585 } 586} 587 588 589/** 590 * Sets the progress indicator. 591 */ 592function updateProgress() { 593 var progressBar = document.querySelector('.progress-bar'); 594 595 if (progressBar !== null) { 596 var numSlides = document.getElementsByClassName('slide').length; 597 var position = currentPosition() - 1; 598 var percent = (numSlides === 1) ? 100 : 100 * position / (numSlides - 1); 599 progressBar.style.width = percent.toString() + '%'; 600 } 601} 602 603 604/** 605 * Removes tabindex property from all links on the current slide, sets 606 * tabindex = -1 for all links on other slides. Prevents slides from appearing 607 * out of control. 608 */ 609function updateTabIndex() { 610 var allLinks = document.querySelectorAll('.slide a'); 611 var position = currentPosition(); 612 var currentPageLinks = document.getElementById('slide-' + position).querySelectorAll('a'); 613 var i; 614 615 for (i = 0; i < allLinks.length; i++) { 616 allLinks[i].setAttribute('tabindex', -1); 617 } 618 619 for (i = 0; i < currentPageLinks.length; i++) { 620 currentPageLinks[i].removeAttribute('tabindex'); 621 } 622} 623 624/** 625 * Determines whether or not we are currently in full screen mode 626 */ 627function isFullScreen() { 628 return document.fullscreenElement || 629 document.mozFullScreenElement || 630 document.webkitFullscreenElement || 631 document.msFullscreenElement; 632} 633 634/** 635 * Toggle fullScreen mode on document element. 636 * Works on chrome (>= 15), firefox (>= 9), ie (>= 11), opera(>= 12.1), safari (>= 5). 637 */ 638function toggleFullScreen() { 639 /* Convenient renames */ 640 var docElem = document.documentElement; 641 var doc = document; 642 643 docElem.requestFullscreen = 644 docElem.requestFullscreen || 645 docElem.msRequestFullscreen || 646 docElem.mozRequestFullScreen || 647 docElem.webkitRequestFullscreen.bind(docElem, Element.ALLOW_KEYBOARD_INPUT); 648 649 doc.exitFullscreen = 650 doc.exitFullscreen || 651 doc.msExitFullscreen || 652 doc.mozCancelFullScreen || 653 doc.webkitExitFullscreen; 654 655 isFullScreen() ? doc.exitFullscreen() : docElem.requestFullscreen(); 656} 657 658document.addEventListener('DOMContentLoaded', function () { 659 // Update the tabindex to prevent weird slide transitioning 660 updateTabIndex(); 661 662 // If the location hash specifies a page number, go to it. 663 var page = window.location.hash.slice(1); 664 if (page) { 665 navigate(parseInt(page) - 1); 666 } 667 668 document.onkeydown = function (e) { 669 var kc = e.keyCode; 670 671 // left, down, H, J, backspace, PgUp - BACK 672 // up, right, K, L, space, PgDn - FORWARD 673 // enter - FULLSCREEN 674 if (kc === 37 || kc === 40 || kc === 8 || kc === 72 || kc === 74 || kc === 33) { 675 navigate(-1); 676 } else if (kc === 38 || kc === 39 || kc === 32 || kc === 75 || kc === 76 || kc === 34) { 677 navigate(1); 678 } else if (kc === 13) { 679 toggleFullScreen(); 680 } 681 }; 682 683 if (document.querySelector('.next') && document.querySelector('.prev')) { 684 document.querySelector('.next').onclick = function (e) { 685 e.preventDefault(); 686 navigate(1); 687 }; 688 689 document.querySelector('.prev').onclick = function (e) { 690 e.preventDefault(); 691 navigate(-1); 692 }; 693 } 694}); 695 696 697 </script> 698</body> 699</html>