electron 可能有什么目录逃逸的漏洞。
首先选择 electron-quick-start 仓库作为模板
主进程代码几乎不变,摘抄相关代码如下:
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
}
在渲染进程中,使用 fetch()
接口逃出应用目录并访问相同文件系统任意文件
window.addEventListener('load', () => {
let output = document.getElementById('output')
fetch('../../../../../../../../../../../../../opensource/freebsd-src/sys/sys/systm.h')
.then(async (res) => {
output.textContent = await res.text()
})
})
我还没有想到有没有办法枚举出文件名,另外写这个的时候正在用 electron-forge 打包,打包器在下载 electron,淘宝镜像好像该位置了,electron mirror 要怎么设置啊?
另外访问的那个文件是 freebsd 系统的源码,放在 盘符:/opensource/freebsd-src
Electron + Vite + Vue 大杂烩,解决 Electron 关于 ESM 的支持:
主进程的代码:
const { app, protocol, BrowserWindow, ipcMain } = require('electron/main')
const path = require('path')
// 一上来就要运行这个代码
// 给 app:// 授权
protocol.registerSchemesAsPrivileged([{
scheme: 'app',
privileges: {
secure: true, // 安全 (这个就能支持 esm)
standard: true, // URL 标准化有关(为了好解析)
supportFetchAPI: true, // 开启 fetch()
allowServiceWorkers: true, // 允许 Service Worker
}
}])
// 注册 app://
function registerProtocol()
{
protocol.registerFileProtocol('app', (request, callback) => {
// console.log(`app-protocol: ${request.url}`);
let requrl = new URL(request.url)
let reqpath = requrl .pathname
let boundary = path.join('/', reqpath) // used for prevent ../.. attack
callback({ path: path.join(app.getAppPath(), 'dist/renderer', boundary) })
})
}
// 创建窗口
function createWindow()
{
const mainWindow = new BrowserWindow({
width: 1360,
height: 768,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
let loadurl = (process.env.NODE_ENV === 'development') ?
'http://localhost:3000' : // development
'app://renderer/index.html' // builded
mainWindow.loadURL(loadurl)
// Open the DevTools
// mainWindow.webContents.openDevTools({mode: 'bottom'})
}
app.whenReady().then(() => {
registerProtocol()
createWindow()
app.on('activate', function() {
// macOS
if (BrowserWindow.getAllWindows.length === 0) createWindow()
})
})
registerProtocol
中的 boundry
是我想的一个对付 ../../..
的方法,也不知道能不能行。原因是,其实不需要注册新的协议,只需要使用 protocol.registerSchemesAsPrivileged
给 file
协议声明 secure: true
即可,但是经过我测试,使用 fetch('../../../..')
就可以直接逃出应用目录。。。所以我打算使用本办法。另外可以使用 protocol
的某个方法来换掉已有的协议,比如 http
(还没有试过)。
arpa/inet.h
网络操作定义htons
htonl
ntohs
ntohl
inet_addr()
字符串转 in_addr
inet_ntoa()
in_addr
转字符串inet_ntop()
inet_pton()
字符串和 sockaddr_in
互转netinet/in.h
网络格式家族in_addr_t
地址类型in_port_t
端口类型sockaddr_in
网络地址INADDR_ANY
通配地址宏INADDR_BROADCAST
广播地址宏sys/socket.h
主要 socket 头文件sockaddr
网络地址msghdr
给 sendmsg()
recvmsg()
用的消息成员socket(域, 类型, 协议)
创建 socket 通信端点socketpair(域, 类型, 协议, int sv[2])
创建一堆连接的 socketshutdown(套接字, 如何半关闭)
半关闭bind(套接字, 地址, 地址长度)
绑定本地地址listen(套接字, backlog)
监听accept(套接字, 客户端地址, 地址长度)
接受连接connect(套接字, 地址, 地址长度)
连接send(套接字, 消息, 长度, 标志)
发送recv(套接字, 缓存, 长度, 标志)
接收getsockopt()
获取 socket 选项setsockopt()
设置 socket 选项凭记忆瞎写的
POSIX 网络库
sys/socket.h - socket 接口
arpa/忘了 - 字节序
inet/in.h - 网络地址
socket() 返回套接字,是一种特殊的文件描述符
发送接收使用 sendto() recv() 或者 read() write()
另外有一次调用多次收发的接口(忘了)
setsockopt 用来设置套接字
然后后面是 linger 之类的看不懂不知道是啥的东西
写了个归档的脚本,将一个目录的文件归档进去,使用相对路径,解压的时候一定要带上 -C
,或者提前 cd
进空目录
#!/usr/bin/env bash
# mktar.sh
# make tar archive && make literal happy
#
# usage:
# mktar <filename> <rootdir>
#
# extract (you must use `-C` option):
# $ tar xf <filename> -C <directory>
#
# prototype:
# LANG=C bsdtar -cf root.tar -C "${rootdir}" $(ls -A ${rootdir})
if [ ! "$#" = "2" ]; then
echo "usage: mktar <filename> <rootdir>"
exit 1
fi
if [[ -e "$1" && ! -f "$1" ]]; then
echo "'$1' exists but not regular file"
exit 1
fi
if [ ! -d "$2" ]; then
echo "'$2' not a directory"
exit 1
fi
if [ -n "${VERBOSE}" ]; then
VERBOSE="v"
fi
LANG=C \
bsdtar \
-ca${VERBOSE}f "$1" \
-C "$2" \
$(ls -A "$2")
莉特雅 literal
写代码业余爱好者 amateur coder