Boom!-爆破专场

源码

  • 两道题分别泄露.index.php.swpwww.zip

.index.php.swp

<?php
$flag = $_GET['flag'];
if ($flag != '15562') {
	if (strstr($flag, 'zctf')) {
		if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)) {
			die('ZCTF{#########}');
		}
	}
}
die('ha?')
?>

www.zip中admin.php (解密:混淆phpjm, 3元)


<?php
require_once("db.php");
$auth = 0;
if (isset($_COOKIE["auth"])) {
    $auth = $_COOKIE["auth"];
    $hsh = $_COOKIE["hsh"];
    if ($auth == $hsh) {
        $auth = 0;
    } else if (sha1((string)$hsh) == md5((string)$auth)) {
        $auth = 1;
    } else {
        $auth = 0;
    }
} else {
    $auth = 0;
    $s = $auth;
    setcookie("auth", $s);
    setcookie("hsh", sha1((string)$s));
}
if ($auth) {
    if (isset($_GET['query'])) {
        $db = new SQLite3($SQL_DATABASE, SQLITE3_OPEN_READONLY);
        $qstr = SQLITE3::escapeString($_GET['query']);
        $query = "SELECT amount FROM my_wallets WHERE id=$qstr";
        $result = $db->querySingle($query);
        if (!$result === NULL) {
            echo "Error - invalid query";
        } else {
            echo "Wallet contains: $result";
        }
    } else {
        echo "<html><head><title>Admin Page</title></head><body>Welcome to the admin panel!<br /><br /><form name='input' action='admin.php' method='get'>Wallet ID: <input type='text' name='query'><input type='submit' value='Submit Query'></form></body></html>";
    }
} else echo "Sorry, not authorized.";

分析

关键部分1

if (strstr($flag, 'zctf')) {
	if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)) {
		die('ZCTF{#########}');
	}
}

  • 分析可知由于==为php弱类型相等,flag的MD5的8-16位为开头0e的全数字,且flag中包含zctf子串

关键部分2

else if (sha1((string)$hsh) == md5((string)$auth)) {
        $auth = 1;
  • 分析可知由于==为php弱类型相等,$hsh的sha1值为0e开头的全数字,并且$auth的MD5值也为0e开头的全数字

爆破

  • 爆破脚本的构造方式有如下分类思路
    • 出口判断
      • 0e数字
      • 题设相等
    • payload设置
      • 数值递增
      • 字符递归

第一题的题设相等,数值递增的PHP脚本

<?php
for ($a = 1; $a <= 999999; $a++) {
    $flag = "zctf".$a;
        if (substr(md5($flag),8,16) == substr(md5('15562'),8,16)){
            echo $flag.":";
            echo substr(md5($flag),8,16)."\n";
        }
}
echo $flag;
?>

第一题的0e数字,数值递增的Python脚本

import hashlib
for i in range(10000000):
	s = 'zctf' + str(i)
	md5 = hashlib.md5(s).hexdigest()
	h = md5[8:24]
	flag = 1
	if md5[8:10] == '0e':
		for j in md5[10:24]:
			if j.isalpha():
				flag = 0
				break
		if flag == 1:
			print s
			break


第二题的0e数字,字符递归的php爆破脚本,其中sha1(40位)和MD5(32位)函数可互相更改

<?php
function find($a)
{
	$s='asdfghjklpoiuytrewqzxcvbnm1234567890ZXCVBNMLKJHGFDSAQWERTYUIOP{}._';
	$ss=substr(sha1($a), 0,2);
	if($ss=='0e') //判断前两位是否为0e
	{
		$flag = 0;
		for($i=2;$i<40;$i++)  // 40为摘要位数
		{
			if(sha1($a)[$i]>'9') //判断后38位是否为数字
			{
				$flag=1;
				break;
			}
		}
		if($flag==0)
		{
			echo $a."的sha1:".sha1($a)."\n";
		}

	}
	if(strlen($a)>7)  //递归字符串长度
		return;
	else
	{
		for($j=0;$j<strlen($s);$j++)
		{
			find($a.$s[$j]);  // 递归调用
		}
	}
}

$p='';
find($p);
?>

知识小结

  • 花式源码泄露
  • php弱类型相等
  • 密码爆破脚本的构造