This commit is contained in:
JyuHsin
2026-05-22 14:16:41 +08:00
parent c1cb08cee3
commit ab29205a32
6 changed files with 74 additions and 87 deletions
@@ -83,6 +83,7 @@ public class SysLoginController {
@Ok("re")
@Filters
public String login(HttpServletRequest req, HttpSession session) {
// return "";
return "beetl:/platform/sys/login.html";
}
@@ -68,11 +68,11 @@ public class NutShiroProcessor extends AbstractProcessor {
//不需要认证授权的url
String[] authIgnoreUrlArr = Lang.array("/",
"/sso/login",
"/platform/login",
// "/platform/login",
"/platform/login(/doLogin|/logout|/captcha)",
"/platform/qywechat/.*",
"/platform/home/(500|403|404|UnknownAccountError|LockedAccountError)",
"/mobile/login",
// "/mobile/login",
"/mobile/login/doLogin",
"/platform/jsz/login",
"/platform/activity/basic/scope/getScopeUser",
@@ -19,10 +19,11 @@ import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
/**
* SQL XSS拦截
* Created by wizzer on 2016/7/1.
* SQL XSS拦截 终极最终版(强制拦截ORDER BY注入 *号)
* 拦截所有3个PDF漏洞:time注入、pageOrderName注入、applyTime*注入
*/
public class XssSqlFilterProcessor extends AbstractProcessor {
@@ -31,16 +32,21 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
private PropertiesProxy conf;
private List<String> ignoreList;
private final static String regxpForHtml = "<([^>]*)>"; // 过滤所有以<开头以>结尾的标签
// ====================== 终极正则:强制拦截 * 号 ======================
private static final Pattern SQL_PATTERN = Pattern.compile(
"([\\'\\\"\\;\\*\\\\]+)|(--+)|(\\b(and|or|union|select|delete|insert|exec|execute|drop|count)\\b)|(&&)|(\\|\\|)",
Pattern.CASE_INSENSITIVE
);
private final static String regxpForImgTag = "<\\s*img\\s+([^>]*)\\s*>"; // 找出IMG标签
private final static String regxpForImaTagSrcAttrib = "src=\"([^\"]+)\""; // 找出IMG标签的SRC属性
private static final Pattern XSS_PATTERN = Pattern.compile(
"(<script|<iframe|img\\s*src|javascript:|onload|onerror|onclick)",
Pattern.CASE_INSENSITIVE
);
@Override
public void init(NutConfig config, ActionInfo ai) throws Throwable {
try {
conf = config.getIoc().get(org.nutz.ioc.impl.PropertiesProxy.class, "conf");
conf = config.getIoc().get(PropertiesProxy.class, "conf");
ignoreList = Arrays.asList(Strings.splitIgnoreBlank(conf.get("xsssql.ignore.urls", "")));
} catch (Exception e) {
}
@@ -66,86 +72,49 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
protected boolean checkParams(ActionContext ac) {
HttpServletRequest req = ac.getRequest();
Iterator<String[]> values = req.getParameterMap().values().iterator();// 获取所有的表单参数
Iterator<String[]> values2 = req.getParameterMap().values().iterator();// 因为是游标所以要重新获取
boolean isError = false;
//use remove -|,
String regEx_sql = """
and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|
char|declare|sitename|net user|xp_cmdshell|or|+|like'|and|exec|execute|insert|create|drop|
table|from|grant|group_concat|column_name|
information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|
chr|mid|master|truncate|char|declare|or|--|+|like|//|/|%|#
""";
regEx_sql = "select|update|and|or|delete|insert|trancate|char|chr|into|substr|ascii|declare|exec|count|master|drop|execute";
Iterator<String[]> values = req.getParameterMap().values().iterator();
String regEx_xss = "script|iframe|img";
//SQL过滤
while (values.hasNext()) {
String[] valueArray = (String[]) values.next();
for (int i = 0; i < valueArray.length; i++) {
String value = valueArray[i].toLowerCase();
while (values.hasNext() && !isError) {
String[] valueArray = values.next();
for (String value : valueArray) {
if (Strings.isBlank(value)) continue;
if (value.startsWith("data:image/")) continue;
if (value.startsWith("{") || value.startsWith("[")) continue;
if (value.matches(".*\\.(png|jpg|jpeg|gif|bmp|svg|ico|pdf|xls|xlsx|doc|docx)$")) continue;
// 普通日期:2026-02-21 / 2026/02/21 / 2026-02-21 05:59:43
if (value.matches("\\d{4}(-|\\/)\\d{1,2}(-|\\/)\\d{1,2}(\\s\\d{1,2}:\\d{1,2}:\\d{1,2})?")) continue;
//排除掉base64
if (value.startsWith("data:image/png;base64,")) {
// ISO时间:2026-02-21T05:59:43.167Z
if (value.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?Z?")) continue;
if (value.startsWith("#")) continue;
if (value.matches("-?\\d+")) continue;
if (value.startsWith("ST-")) continue;
// ====================== 强制拦截 * 号 ======================
if (value.contains("*")) {
log.errorf("[SQL拦截*号] %s %s 参数=%s", req.getMethod(), req.getRequestURI(), value);
isError = true;
break;
}
Pattern SQL_PATTERN2 = Pattern.compile(
"([\\'\\\"\\;\\*\\\\]+)|(--+)|(\\b(and|or|union|select|delete|insert|exec|execute|drop|count)\\b)|(&&)|(\\|\\|)",
Pattern.CASE_INSENSITIVE
);
if (SQL_PATTERN2.matcher(value).find()) {
log.errorf("[SQL拦截] %s %s 参数=%s", req.getMethod(), req.getRequestURI(), value);
isError = true;
break;
}
//分拆关键字
String[] inj_stra = StringUtils.split(regEx_sql, "\\|");
for (int j = 0; j < inj_stra.length; j++) {
// 判断如果路径参数值中含有关键字则返回true,并且结束循环
if (value.contains(inj_stra[j] + " ") || value.contains(" " + inj_stra[j] + " ") || value.contains(" " + inj_stra[j])) {
// if (value.contains(inj_stra[j])) {
isError = true;
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL关键字过滤:" + value);
break;
}
}
if (isError) {
break;
}
}
if (isError) {
break;
}
}
if (!isError) {
// XSS漏洞过滤
while (values2.hasNext()) {
String[] valueArray = (String[]) values2.next();
for (int i = 0; i < valueArray.length; i++) {
String value = valueArray[i].toLowerCase();
value = HtmlUtil.escape(value);
if (value.trim().startsWith("<") || value.trim().endsWith(">") ||
value.trim().endsWith("/")) {
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "XSS关键字过滤(已被我转义):" + value);
}
// 分拆关键字
String[] inj_stra = StringUtils.split(regEx_xss, "|");
for (int j = 0; j < inj_stra.length; j++) {
// 判断如果路径参数值中含有关键字则返回true,并且结束循环
if (value.contains("<" + inj_stra[j] + ">")
|| value.contains("<" + inj_stra[j])
|| value.contains(inj_stra[j] + ">")) {
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "XSS关键字过滤:" + value);
isError = true;
break;
}
}
if (isError) {
break;
}
}
if (isError) {
if (XSS_PATTERN.matcher(value).find()) {
log.errorf("[XSS拦截] %s %s 参数=%s", req.getMethod(), req.getRequestURI(), value);
isError = true;
break;
}
}
}
return isError;
}
}
}
@@ -31,11 +31,11 @@ public class mobileLoginController {
/**
* 登录页
*/
@At("")
@Ok("beetl:/mobile/login.html")
public void index() {
}
// @At("")
// @Ok("beetl:/mobile/login.html")
// public void index() {
//
// }
/**
* 首页
+12 -3
View File
@@ -201,6 +201,10 @@ layout("/mobile/platform.html"){
<img :src="CREATE_PREVIEW_URL(item.icon)" alt="" class="menu_item_img">
<span class="menu_item_name">{{item.moduleName}}</span>
</div>
<div @click="ydClick" class="menu_item">
<img src="/assets/mobile/img/home/222.png" alt="" class="menu_item_img">
<span class="menu_item_name">阅读打卡</span>
</div>
</div>
</van-row>
@@ -224,10 +228,12 @@ layout("/mobile/platform.html"){
<van-loading size="13" type="spinner"/>
</template>
<template slot="error">
<van-image src="/assets/mobile/img/commonActivity.png" class="middle_item_img"></van-image>
<van-image src="/assets/mobile/img/commonActivity.png"
class="middle_item_img"></van-image>
</template>
</van-image>
<van-image src="/assets/mobile/img/commonActivity.png" class="middle_item_img" v-else></van-image>
<van-image src="/assets/mobile/img/commonActivity.png" class="middle_item_img"
v-else></van-image>
</div>
<div class="middle_item_text">
@@ -583,9 +589,12 @@ layout("/mobile/platform.html"){
pjaxReplace(menu)
}
},
ydClick() {
window.location.href = "https://api.hd.chaoxing.com/activity/4204275/preview"
},
tabbrChange(o) {
console.log(o)
sessionStorage.setItem("zhgh-mobile-home-active",o)
sessionStorage.setItem("zhgh-mobile-home-active", o)
this.needItems = []
this.initData()
},
@@ -4,6 +4,14 @@ const quickEntry = {
<el-card shadow="never">
<div class="card-title" slot="header">快速入口</div>
<div class="quickEntries">
<div @click="window.open('https://api.hd.chaoxing.com/activity/4204275/preview')" class="quickEntryItem">
<el-image src="/assets/mobile/img/home/222.png" alt="">
<div class="image-slot" slot="error">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<span>阅读打卡</span>
</div>
<div v-for="item in quickEntries" :key="item.id" @click="menuClick(item)" class="quickEntryItem">
<el-image :src="CREATE_PREVIEW_URL(item.iconClass)" alt="">
<div class="image-slot" slot="error">