mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-08-26 19:42:02 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| efbadde4ed |
@@ -382,9 +382,10 @@ public abstract class PanBase implements IPanTool, Closeable {
|
|||||||
log.error("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
log.error("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
||||||
fail("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
fail("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
||||||
} else {
|
} else {
|
||||||
|
// 上游响应体可能来自内网探测目标,仅写日志,避免经 HTTP 500 回传给调用方
|
||||||
String bodyPreview = responseBodyPreview(res);
|
String bodyPreview = responseBodyPreview(res);
|
||||||
log.error("解析失败: json格式异常: {}", bodyPreview);
|
log.error("解析失败: json格式异常: {}", bodyPreview);
|
||||||
fail("解析失败: json格式异常: {}", bodyPreview);
|
fail("解析失败: json格式异常");
|
||||||
}
|
}
|
||||||
return JsonObject.of();
|
return JsonObject.of();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ public class Ce4Tool extends PanBase {
|
|||||||
private void requestShareDetail(String baseUrl, String key, String pwd, String path) {
|
private void requestShareDetail(String baseUrl, String key, String pwd, String path) {
|
||||||
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
|
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
|
||||||
|
|
||||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
// 禁止跟随重定向:防止公网 host 302 到内网/元数据绕过 assertPublicHost
|
||||||
|
HttpRequest<Buffer> httpRequest = clientNoRedirects.getAbs(shareApiUrl);
|
||||||
if (pwd != null && !pwd.isEmpty()) {
|
if (pwd != null && !pwd.isEmpty()) {
|
||||||
httpRequest.addQueryParam("password", pwd);
|
httpRequest.addQueryParam("password", pwd);
|
||||||
}
|
}
|
||||||
@@ -232,7 +233,7 @@ public class Ce4Tool extends PanBase {
|
|||||||
.put("uris", new JsonArray().add(filePath))
|
.put("uris", new JsonArray().add(filePath))
|
||||||
.put("download", true);
|
.put("download", true);
|
||||||
|
|
||||||
clientSession.postAbs(fileUrlApi)
|
clientNoRedirects.postAbs(fileUrlApi)
|
||||||
.putHeader("Content-Type", "application/json")
|
.putHeader("Content-Type", "application/json")
|
||||||
.sendJsonObject(requestBody)
|
.sendJsonObject(requestBody)
|
||||||
.onSuccess(res -> {
|
.onSuccess(res -> {
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ public class CeTool extends PanBase {
|
|||||||
private void tryV4Ping(String baseUrl, String key, String pwd) {
|
private void tryV4Ping(String baseUrl, String key, String pwd) {
|
||||||
String pingUrlV4 = baseUrl + PING_API_V4_PATH;
|
String pingUrlV4 = baseUrl + PING_API_V4_PATH;
|
||||||
|
|
||||||
clientSession.getAbs(pingUrlV4).send().onSuccess(res -> {
|
// 禁止跟随重定向:assertPublicHost 只校验初始 host,自动 30x 会绕过 SSRF 防护
|
||||||
|
clientNoRedirects.getAbs(pingUrlV4).send().onSuccess(res -> {
|
||||||
if (res.statusCode() == 200) {
|
if (res.statusCode() == 200) {
|
||||||
try {
|
try {
|
||||||
JsonObject json = asJson(res);
|
JsonObject json = asJson(res);
|
||||||
@@ -108,7 +109,7 @@ public class CeTool extends PanBase {
|
|||||||
private void tryV3Ping(String baseUrl, String key, String pwd) {
|
private void tryV3Ping(String baseUrl, String key, String pwd) {
|
||||||
String pingUrlV3 = baseUrl + PING_API_V3_PATH;
|
String pingUrlV3 = baseUrl + PING_API_V3_PATH;
|
||||||
|
|
||||||
clientSession.getAbs(pingUrlV3).send().onSuccess(res -> {
|
clientNoRedirects.getAbs(pingUrlV3).send().onSuccess(res -> {
|
||||||
if (res.statusCode() == 200) {
|
if (res.statusCode() == 200) {
|
||||||
try {
|
try {
|
||||||
JsonObject json = asJson(res);
|
JsonObject json = asJson(res);
|
||||||
@@ -139,7 +140,7 @@ public class CeTool extends PanBase {
|
|||||||
*/
|
*/
|
||||||
private void verifyV3AndParse(String baseUrl, String key, String pwd) {
|
private void verifyV3AndParse(String baseUrl, String key, String pwd) {
|
||||||
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
|
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
|
||||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
HttpRequest<Buffer> httpRequest = clientNoRedirects.getAbs(shareApiUrl);
|
||||||
if (pwd != null && !pwd.isEmpty()) {
|
if (pwd != null && !pwd.isEmpty()) {
|
||||||
httpRequest.addQueryParam("password", pwd);
|
httpRequest.addQueryParam("password", pwd);
|
||||||
}
|
}
|
||||||
@@ -175,7 +176,7 @@ public class CeTool extends PanBase {
|
|||||||
*/
|
*/
|
||||||
private void tryV4ShareApi(String baseUrl, String key, String pwd) {
|
private void tryV4ShareApi(String baseUrl, String key, String pwd) {
|
||||||
String shareApiUrl = baseUrl + "/api/v4/share/info/" + key;
|
String shareApiUrl = baseUrl + "/api/v4/share/info/" + key;
|
||||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
HttpRequest<Buffer> httpRequest = clientNoRedirects.getAbs(shareApiUrl);
|
||||||
if (pwd != null && !pwd.isEmpty()) {
|
if (pwd != null && !pwd.isEmpty()) {
|
||||||
httpRequest.addQueryParam("password", pwd);
|
httpRequest.addQueryParam("password", pwd);
|
||||||
}
|
}
|
||||||
@@ -291,7 +292,8 @@ public class CeTool extends PanBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void getDownURL(String shareApiUrl) {
|
private void getDownURL(String shareApiUrl) {
|
||||||
clientSession.putAbs(shareApiUrl)
|
// PUT 默认不跟随重定向,但仍统一使用 no-redirect 客户端避免配置漂移
|
||||||
|
clientNoRedirects.putAbs(shareApiUrl)
|
||||||
.putHeader("Referer", shareLinkInfo.getShareUrl())
|
.putHeader("Referer", shareLinkInfo.getShareUrl())
|
||||||
.send().onSuccess(res -> {
|
.send().onSuccess(res -> {
|
||||||
JsonObject jsonObject = asJson(res);
|
JsonObject jsonObject = asJson(res);
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package cn.qaiu.parser;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GHSA-997r-7xx2-p9x6 regression: Cloudreve generic parser must reject
|
||||||
|
* hosts that resolve to loopback / private / link-local / metadata ranges
|
||||||
|
* before any outbound request.
|
||||||
|
*/
|
||||||
|
public class AssertPublicHostTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rejectsLoopbackAndPrivateHosts() throws Exception {
|
||||||
|
String[] blocked = {
|
||||||
|
"http://127.0.0.1.nip.io/s/poc",
|
||||||
|
"http://localhost/s/poc",
|
||||||
|
"http://10.0.0.1/s/poc",
|
||||||
|
"http://192.168.1.1/s/poc",
|
||||||
|
"http://172.16.0.1/s/poc",
|
||||||
|
"http://169.254.169.254/s/poc",
|
||||||
|
"http://[::1]/s/poc"
|
||||||
|
};
|
||||||
|
for (String raw : blocked) {
|
||||||
|
try {
|
||||||
|
PanBase.assertPublicHost(new URL(raw));
|
||||||
|
fail("expected block for " + raw);
|
||||||
|
} catch (IOException expected) {
|
||||||
|
assertTrue(expected.getMessage().contains("不允许访问")
|
||||||
|
|| expected.getMessage().contains("无法解析"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allowsPublicHost() throws Exception {
|
||||||
|
PanBase.assertPublicHost(new URL("https://example.com/s/demo"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user