Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复安全漏洞 #1004

Merged
merged 8 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/seven-glasses-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@scow/gateway": minor
"@scow/cli": minor
"@scow/docs": minor
"@scow/auth": patch
---

修复 scow 存在的 web 安全漏洞
4 changes: 2 additions & 2 deletions apps/auth/views/login.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
{% endif %}

<input type="hidden" name="token" value="{{ token }}" />
<input type="hidden" name="callbackUrl" value="{{ callbackUrl }}" />
<input type="hidden" name="callbackUrl" value="{{ callbackUrl | escape }}" />

{% if err %}
<p class="my-4 text-center text-red-600">{{ authTexts.login.invalidInput }}</p>
Expand All @@ -116,7 +116,7 @@
<button type="submit" name="action" value="bindOtp" class="px text-gray-400">
{{ authTexts.login.bindOtp }}
</button>
<input type="hidden" name="callbackUrl" value="{{ callbackUrl }}" />
<input type="hidden" name="callbackUrl" value="{{ callbackUrl | escape }}" />
</form>
</div>
{% endif %}
Expand Down
6 changes: 3 additions & 3 deletions apps/auth/views/otp/bindOtp.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<button type="submit" name="action" value="backToLoginUI" class="text-x text-gray-500 mr-4">
{{ authTexts.bindOtp.returnLogin }}
</button>
<input type="hidden" name="callbackUrl" value="{{ callbackUrl }}">
<input type="hidden" name="callbackUrl" value="{{ callbackUrl | escape }}">
</form>
</div>
{% unless bindLimitMinutes %}
Expand Down Expand Up @@ -53,7 +53,7 @@
{{ authTexts.bindOtp.confirm }}
</button>
</div>
<input type="hidden" name="callbackUrl" value="{{ callbackUrl }}">
<input type="hidden" name="callbackUrl" value="{{ callbackUrl | escape }}">
</form>

{% else %}
Expand Down Expand Up @@ -113,7 +113,7 @@
</div>
<input type="hidden" name="otpSessionToken" value="{{ otpSessionToken }}" />
<input type="hidden" name="emailAddress" value="{{ emailAddress }}" />
<input type="hidden" name="callbackUrl" value="{{ callbackUrl }}">
<input type="hidden" name="callbackUrl" value="{{ callbackUrl | escape }}">
</form>
{% endunless %}
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/auth/views/otp/qrcode.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
<input
type="hidden"
name="callbackUrl"
value="{{ callbackUrl }}">
value="{{ callbackUrl | escape }}">
</div>
3 changes: 3 additions & 0 deletions apps/cli/assets/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@
# include includes/headers;
# include includes/websocket;
# }
# # 允许访问的域名或 IP,多个域名或 IP 间用空格隔开
# # 默认接受所有域名和 IP,"_" 即表示接受所有域名和 IP
# allowedServerName: "_"

# 插件配置
# plugins:
Expand Down
6 changes: 6 additions & 0 deletions apps/cli/src/compose/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ export const createComposeSpec = (config: InstallConfigSchema) => {
const publicPath = "/__public__/";
const publicDir = "/app/apps/gateway/public/";

const defaultServerBlock = `server {
listen 80 default_server;
return 444;
}`;
// GATEWAY
addService("gateway", {
image: scowImage,
Expand All @@ -126,6 +130,8 @@ export const createComposeSpec = (config: InstallConfigSchema) => {
"PUBLIC_PATH": publicPath,
"PUBLIC_DIR": publicDir,
"EXTRA": config.gateway.extra,
"ALLOWED_SERVER_NAME": config.gateway.allowedServerName,
"DEFAULT_SERVER_BLOCK": config.gateway.allowedServerName === "_" ? "" : defaultServerBlock,
},
ports: { [config.port]: 80 },
volumes: {
Expand Down
5 changes: 5 additions & 0 deletions apps/cli/src/config/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export const InstallConfigSchema = Type.Object({
description: "更多nginx配置,可接受的格式为nginx的server可接受的属性配置,可增加在当前系统nginx端口(默认80)的服务等",
default: "",
}),

allowedServerName: Type.String({
description: "允许访问的域名或 IP",
default: "_",
}),
}, { default: {} }),

portal: Type.Optional(Type.Object({
Expand Down
4 changes: 4 additions & 0 deletions apps/gateway/assets/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
server {

server_name ${ALLOWED_SERVER_NAME};

resolver ${RESOLVER} valid=10s;
resolver_timeout 5s;

Expand Down Expand Up @@ -60,3 +62,5 @@ server {

${EXTRA}
}

${DEFAULT_SERVER_BLOCK}
3 changes: 3 additions & 0 deletions apps/gateway/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,8 @@ export const config = envConfig({

PUBLIC_DIR: str({ desc: "静态文件在文件系统中的路径。以/结尾", default: "/app/apps/gateway/public/" }),
PUBLIC_PATH: str({ desc: "静态文件路径前缀。以/开头,以/结尾", default: "/__public__/" }),

ALLOWED_SERVER_NAME: str({ desc: "允许访问的域名或 IP,多个域名和 IP 间用空格隔开", default: "_" }),
DEFAULT_SERVER_BLOCK: str({ desc: "当配置了ALLOWED_SERVER_NAME为特定IP或域名时,设置默认服务块拒绝其他访问", default: "" }),
});

28 changes: 21 additions & 7 deletions docs/docs/deploy/config/gateway/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,29 @@ title: 配置
```yaml title="install.yml"
# 网关配置
gateway:
# 更多nginx配置
extra: >
location /extra {
proxy_pass http://extra-web:3000;
include includes/headers;
include includes/websocket;
}
# 更多nginx配置
extra: >
location /extra {
proxy_pass http://extra-web:3000;
include includes/headers;
include includes/websocket;
}
```

您增加`extra`配置后,可以在使用`./cli compose up -d`启动scow后,使用 ` ./cli compose exec gateway sh` 进入gateway服务,在 `/etc/nginx/http.d` 目录下的 `default.conf` 文件最下方查看到您添加的配置。
如果gateway服务启动失败,说明您的配置不符合规范,请保证其正确性。

## 域名白名单配置

scow 网关默认不限制 HTTP Host 头

为了防止 host 头攻击的发生,可以通过设置域名白名单来限制 Host 的域名或 IP

```
gateway:
# 同 nginx server_name 配置
allowedServerName: example.com www.example.com
```

多个域名或 IP 间用空格间隔即可。

Loading