Linking

Capturing Life & Tech

  • 主页
  • 随笔
  • 关于我
所有文章 外链

Linking

Capturing Life & Tech

  • 主页
  • 随笔
  • 关于我

APPScan-SQL盲注与xss跨站点脚本编织问题记录

阅读数:次 2020-03-08
字数统计: 2.8k字   |   阅读时长≈ 13分

0.前述

最近项目进行了第三方测试和等保测试。意料之中,问题比较多。

虽然我已经慢慢从项目中退出,但是遇到问题,还死活要帮忙解决下的。

这次采用的IBM APPScan 进行web扫描检测,只需输入一个网址,便自动测试出网站存在的诸多问题。我猜测是根据域名,通过爬虫来爬取网站上的连接,一层层的往下测试。当然,其中的测试过程,测试软件中需预先设定默认输入参数,尽量多的测试可能性。由此保障测试的可信度、完整度。

本次测试也是我做的项目第一次接受第三方检测,原来都是一些管理系统,没必要。这次是面向外部互联网的,以后还是需要多往互联网项目靠。

测试报告用中英文显示了高中低三档的危险漏洞。其中高危主要是两个问题,SQL注入和XSS跨站脚本编写攻击。以下列出这两个问题的简单解决方式。做个记录吧,以后的工程里默认都要加入。

传统项目真的没有搞头。知识面亟待拓宽。

1.SQL 注入

1.1测试报告

  • 严重性: 高

  • CVSS 分数: 9.7

  • URL:: https://domain/path/to/list

  • 实体: id (Parameter)

  • 风险: 可能会查看、修改或删除数据库条目和表

  • 原因: 未对用户输入正确执行危险字符清理

  • 固定值: 查看危险字符注入的可能解决方案

  • 推理: 测试结果似乎指示存在脆弱性,因为响应包含 SQL Server 错误。这表明测试设法通过注入危险字
    符穿透了应用程序并到达 SQL 查询本身

  • 未经处理的测试响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-00911: invalid
character
...
...
### SQL: select count(0) from (SELECT distinct
...
...
like '%'|| ? ||'%'
and g.PARENT_ID = '-1';' and a.ANNO_TYPE =
'2' ) c on c.DEPT_ID = m.SUBS_DEPT_ID ORDER BY ANNO_TIME DESC
nulls last) tmp_count
### Cause: java.sql.SQLSyntaxErrorException: ORA-00911: invalid character
...

  1. 部分sql注入,nosql注入可能是在==发送参数==,后台报错引起的,只要在后台捕获异常,不让它抛出,appscan可能就不会推理这是个漏洞。
  2. 解决办法:通过建立过滤器方法,对所有用户输入信息进行清理过滤。通过清理过滤用户输入所包含的危险字符,便可能防止恶意的用户导致应用程序执行计划外的任务,例如:启动任意 SQL 查询、嵌入将在客户端执行的Javascript代码、运行各种操作系统命令等。
  3. 降低 SQL 注入攻击风险的一般方式,是禁止详细的 SQL 错误消息,攻击者通常便利用这些消息(如上述示例所说明),轻易找出容易遭受“SQL 注入”的脚本。
    这个(以遮盖获取安全)解决方案可以利用称为“盲目 SQL 注入”的技术来略过,黑客不需要依赖返回 SQL 错误消息,便能找出容易遭受“SQL 注入”的脚本。

1.2现象

1.2.1测试单引号

  • 测试单引号链接

出错,页面显示sql语句.

1
2
3
4
5
6
7
8
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-01756: quoted string not properly terminated 
### The error may exist in file [/usr/tomcat/path/to/xxx.xml]
### The error may involve com.package.name.projectName.getlist
### The error occurred while setting parameters
...
...
STATUS = ? and a.ANNO_DEL_STATUS = ? and a.ANNO_RECEIVE_CLIENT like '%'|| ? ||'%' and g.PARENT_ID = '''-1'' ) c on c.DEPT_ID = m.SUBS_DEPT_ID ORDER BY ANNO_TIME DESC nulls last) tmp_count
### Cause: java.sql.SQLSyntaxErrorException: ORA-01756: quoted string not properly terminated

1.2.2其他符号 ^&$之类,400

  • 测试链接

有的页面显示400

1
2
This page isn’t workingIf the problem continues, contact the site owner.
HTTP ERROR 400

1.3修改

1.3.1过滤特殊字符

  • 前端: 虽然意义不大
  • 后端: 过滤特殊字符
1
2
3
4
5
6
7
8
9
/**
* 处理前端参数输入,替换以下特殊字符为空,以防SQL注入
*/
public static String filterParameter(String source) {

if (StringUtils.isEmpty(source)) return "";

return source.replaceAll("[|@$%^&()\'\"<>,;+]|(CR)|(LF)", "");
}

1.3.2使用预编译,不要拼接sql

1.3.3对sql执行部分异常进行捕获,不要抛出不同的异常,以免被推测有漏洞

尤其是 SQL 错误信息,不要在前端显示具体的信息,留给黑客猜测的空间

1
2
3
4
//原输出信息
view.addObject("exMsg", e.getMessage());
//修改后输出方式
view.addObject("exMsg", "出错了");

1.3.4同时处理sql注入和xss跨站脚本编制攻击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 将容易引起xss & sql漏洞的半角字符直接替换成全角字符
*/
private static String xssEncode(String s) {
if (s == null || s.isEmpty()) {
return s;
} else {
s = stripXSSAndSql(s);
}
StringBuilder sb = new StringBuilder(s.length() + 16);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '>':
sb.append(">");// 转义大于号
break;
case '<':
sb.append("<");// 转义小于号
break;
case '\'':
sb.append("'");// 转义单引号
break;
case '\"':
sb.append(""");// 转义双引号
break;
case '&':
sb.append("&");// 转义&
break;
case '#':
sb.append("#");// 转义#
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}

1.3.4可能appscan误报

1.3.5误报解决

(1)、把错误的页面单独反复测试
(2)、把AppScan扫描的线程数改成1(默认10)

1.4参考

  • Web系统常见安全漏洞及解决方案-SQL盲注
  • appScan常见高危漏洞,走过的坑啊

2.XSS 跨站脚本编制

2.1测试报告

  • 严重性: 高
  • CVSS 分数: 7.5
  • URL:: https://domain/path/to/list
  • 实体: list (Page)
  • 风险: 可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查
    看或变更用户记录以及执行事务
  • 原因: 未对用户输入正确执行危险字符清理
  • 固定值: 查看危险字符注入的可能解决方案
  • 推理: 测试结果似乎指示存在脆弱性,因为 Appscan 在响应中成功嵌入了脚本,在用户浏览器中装入页
    面时将执行该脚本。
  • 测试响应: alert 弹框

情况:

  • sql查询的参数插入js脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
script%3E&pageCount=%3E%22%27%3E%3Cscript%3Ealert%281304%29%3C%2Fscript%3E&pageNum=%3E%22%27%3E%3
Cscript%3Ealert%281304%29%3C%2Fscript%3E&keyWord=%3E%22%27%3E%3Cscript%3Ealert%281304%29%3C%2Fscr
ipt%3E
HTTP/1.1 200 OK
x-ua-compatible: ie=edge
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx/1.15.9
Content-Language: en-US
Date: Thu, 27 Feb 2020 09:27:33 GMT
Content-Type: text/html;charset=UTF-8
...
...
... '%'|| ? ||'%' and g.PARENT_ID = '>"'>
<script>alert(1304)</script>' and
a.ANNO_TYPE = '>"'><script>aler...
...

? AND a.ANNO_DEL_STATUS = ? AND a.ANNO_RECEIVE_CLIENT LIKE '%' || ? || '%' AND a.ANNO_TYPE =
'<script>alert(3033)</script>') c ON c.DEPT_ID = m.SUBS_DEPT_ID) table_count
### Cause: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number
  • input 输入框
1
2
3
4
5
6
7
8
9
<input type="text" name="keyWord" id="keyWord" class="input-search"
value=""/><iframe src=javascript:alert(2976) "
placeholder="搜索"
autocomplete="off"
onkeyup="if(event.keyCode!=38 &&event.keyCode!=40)
{searchRelative(this)};"
onfocus="if(this.value==''){this.value='';};searchRelative(this)"
onblur="if(this.value==''){this.value=''};setTimeout(hiddenhot,200)"
/>

2.2现象

  • 测试链接

点击链接,查询参数带了脚本,会弹出alert信息,页面同时报sql错误.

  • input 搜索框输入带js脚本的信息,同样弹框,报错,页面格式错误
1
/><iframe src=javascript:alert(2976) 

2.3修改

后端Java代码加入XssFilter过滤掉非法脚本.见参考链接.

2.4参考

  • https://blog.csdn.net/weixin_43881309/article/details/84862452
  • github - tools
  • 解决AppScan扫描的问题SQL注入/XSS攻击

3.最终解决代码

同时过滤 sql注入和XSS脚本编制

3.1XssAndSqlFilter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.package.name.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class XssAndSqlFilter implements Filter {

@Override
public void destroy() {
System.out.println("[XssAndSqlFilter] destroy success!");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
XssAndSqlHttpServletRequestWrapper xssRequest = new XssAndSqlHttpServletRequestWrapper(
(HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}

@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("[XssAndSqlFilter] init success!");
}

}

3.2XssAndSqlHttpServletRequestWrapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package com.package.name.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Pattern;

/**
* request装饰类,防止Xss/csrf/注入钓鱼网站/SQL等的攻击.
*/
public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest orgRequest;

XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
orgRequest = request;
}

/**
* 覆盖getParameter方法,将参数名和参数值都做xss & sql过滤。<br/>
* 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
* getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
*/
@Override
public String getParameter(String name) {
String value = super.getParameter(xssEncode(name));
if (value != null) {
value = xssEncode(value);
}
return value;
}

/**
* 覆盖getHeader方法,将参数名和参数值都做xss & sql过滤。<br/>
* 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
* getHeaderNames 也可能需要覆盖
*/
@Override
public String getHeader(String name) {
String value = super.getHeader(xssEncode(name));
if (value != null) {
value = xssEncode(value);
}
return value;
}

/**
* 将容易引起xss & sql漏洞的半角字符直接替换成全角字符
*/
private static String xssEncode(String s) {
if (s == null || s.isEmpty()) {
return s;
} else {
s = stripXSSAndSql(s);
}
StringBuilder sb = new StringBuilder(s.length() + 16);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '>':
sb.append(">");// 转义大于号
break;
case '<':
sb.append("<");// 转义小于号
break;
case '\'':
sb.append("'");// 转义单引号
break;
case '\"':
sb.append(""");// 转义双引号
break;
case '&':
sb.append("&");// 转义&
break;
case '#':
sb.append("#");// 转义#
break;
default:
sb.append(c);
break;
}
}
return sb.toString();
}

/**
* 获取最原始的request
*/
private HttpServletRequest getOrgRequest() {
return orgRequest;
}

/**
* 获取最原始的request的静态方法
*/
public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
if (req instanceof XssAndSqlHttpServletRequestWrapper) {
return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();
}
return req;
}

/**
* 防止xss跨脚本攻击(替换,根据实际情况调整)
*/
private static String stripXSSAndSql(String value) {
if (value != null) {
Pattern scriptPattern = Pattern.compile(
"<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
| Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
| Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
| Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
| Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}
}

3.3web.xml

1
2
3
4
5
6
7
8
9
<!--sql注入&xss脚本编制攻击过滤-->
<filter>
<filter-name>xssFilter</filter-name>
<filter-class>com.package.name.filter.XssAndSqlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>xssFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
  • 本文作者: Linking
  • 本文链接: https://linking.fun/2020/03/08/APPScan-SQL盲注与xss跨站点脚本编织问题记录/
  • 版权声明: 版权所有,转载请注明出处!
  • APPScan
  • SQl盲注
  • xss
  • CS

扫一扫,分享到微信

docker安装运行并连接Oracle
redis.conf-readthrough
  1. 1. 0.前述
  2. 2. 1.SQL 注入
    1. 2.1. 1.1测试报告
    2. 2.2. 1.2现象
      1. 2.2.1. 1.2.1测试单引号
      2. 2.2.2. 1.2.2其他符号 ^&$之类,400
    3. 2.3. 1.3修改
      1. 2.3.1. 1.3.1过滤特殊字符
      2. 2.3.2. 1.3.2使用预编译,不要拼接sql
      3. 2.3.3. 1.3.3对sql执行部分异常进行捕获,不要抛出不同的异常,以免被推测有漏洞
      4. 2.3.4. 1.3.4同时处理sql注入和xss跨站脚本编制攻击
      5. 2.3.5. 1.3.4可能appscan误报
      6. 2.3.6. 1.3.5误报解决
    4. 2.4. 1.4参考
  3. 3. 2.XSS 跨站脚本编制
    1. 3.1. 2.1测试报告
    2. 3.2. 2.2现象
    3. 3.3. 2.3修改
    4. 3.4. 2.4参考
  4. 4. 3.最终解决代码
    1. 4.1. 3.1XssAndSqlFilter.java
    2. 4.2. 3.2XssAndSqlHttpServletRequestWrapper.java
    3. 4.3. 3.3web.xml
© 2015-2026 Linking
GitHub:hexo-theme-yilia-plus by Litten
本站总访问量次 | 本站访客数人
  • 所有文章
  • 外链

tag:

  • weather
  • 需求
  • essay
  • basketball
  • olympic
  • nginx
  • APPScan
  • SQl盲注
  • xss
  • Ajax
  • ajax
  • ai
  • agent
  • openclaw
  • ccf
  • Nginx
  • HTML5
  • html5
  • hmtl5
  • sse
  • JavaScriptCore
  • Oracle
  • operation
  • Linux
  • deploy
  • Mac Office
  • markdown
  • ListView
  • GridView
  • MySQL
  • 慢查询
  • mongodb
  • 转置
  • thought
  • network
  • ubuntu
  • NetworkManager
  • RFKill
  • Netplan
  • avatar
  • cocoa
  • blog
  • Gitalk
  • container
  • macvlan
  • docker
  • oracle
  • cookie
  • patch
  • gitea
  • git
  • iOS
  • https
  • 多线程
  • bundle
  • 兼容性
  • HTTP
  • 绘图
  • cs
  • java
  • 效率
  • 快捷键
  • route
  • nodejs
  • pip
  • arcgis
  • arcgis 建模
  • 标识
  • redis
  • read
  • bookList
  • running
  • showdoc
  • disk
  • unit-test
  • D.Wade
  • thoughts
  • duoduo
  • Python
  • python
  • tomcat
  • 读书节
  • session
  • jdk
  • war
  • 加班
  • Android onclick事件监听
  • 正则
  • 手机品牌匹配
  • ntp
  • OpenLayers
  • Geoserver
  • wechat
  • 微信公众号
  • 爬虫
  • WeChat
  • 张靓颖
  • 动漫
  • vpn
  • PPT
  • MarkDown
  • plan
  • 朱赟
  • 极客时间专栏
  • 极客邦
  • 模块化
  • MVC
  • excel
  • NBA
  • kobe
  • team
  • crawler
  • 进度条
  • ssl
  • book
  • anti-stealing-link
  • Agentic Engineering
  • Vibe Coding
  • Software 3.0
  • Andrej Karpathy
  • LLM
  • Programming

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia-plus根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • GitHub Trending
  • OpenAI ChatGPT
  • Gitee码云
  • 简书
  • CSDN