XSS案例分析和规避

1. 什么是XSS

跨站脚本(XSS)是一种安全漏洞,允许攻击者向网站注入恶意客户端代码。该代码由受害者执行从而让攻击者绕过访问控制并冒充用户。XSS可能导致cookie、token等用户敏感信息被窃取,或者HTML被重写。
下面是一个极简易的新闻发布功能的案例,前端获取用户输入的标题和新闻内容,服务端接收并保存。用户点击新闻标题列表时将id传给服务端,服务端根据id找到标题和内容,再拼接成html格式的内容发给前端,前端直接输出到页面。
2. 案例代码

前端代码,从input获取新闻标题和内容通过ajax发给服务端

<head>
    <meta charset="UTF-8">
    <title>发布新闻</title>
    <script>
        function add() {
            var title = document.getElementById("txtTitle").value;
            var content = document.getElementById("txtContent").value;
            var httpRequest = new XMLHttpRequest()
            httpRequest.onreadystatechange = function () {
                if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                    document.getElementById("txtTitle").value = ''
                    document.getElementById("txtContent").value = ''
                    alert('添加成功')
                }
            }
            httpRequest.open('POST', 'http://localhost:8093/news', true)
            httpRequest.setRequestHeader(
                'Content-type',
                'application/x-www-form-urlencoded'
            )
            var str = `title=${title}&content=${content}`
            httpRequest.send(str)
        }
</script>
</head>
<body>
<div>
    标题:<input style="width: 280px;" type="text" name="title" id="txtTitle"> <br>
    内容:<textarea name="content" id="txtContent" cols="40" rows="6"></textarea><br>
    <input type="button" onclick="add()" value="新增">
</div>
View Code

 

服务端保存(java),问题点1:保存没有检查数据格式

@PostMapping
public int add(News news) {
    int num = jdbcTemplate.update("insert into tb_news(id,title,content) values(?,?,?)", new Object[]{UUID.randomUUID().toString(), news.getTitle(), news.getContent()});
    return num;
}
View Code

 

服务端生成html返回

@GetMapping("/{id}")
public String getNews(@PathVariable String id) {
    News news = jdbcTemplate.queryForObject("select * from tb_news where id = ?", new BeanPropertyRowMapper<>(News.class), id);
    String html = getTemplate();
    html = html.replace("@title", news.getTitle());
    html = html.replace("@content", news.getContent());
    return html;
}
private String getTemplate() {
    String template = "<html>\n" + "<head>\n" + "    <title>news</title>\n" + "    <meta charset=\"utf-8\">\n" + "</head>\n" + "<body>\n" + "<div style=\"margin: 100px 100px 100px 100px\">\n" + "    <h2 style=\"text-align: center;\">@title</h2>\n" + "    <p>@content</p>\n" + "</div>\n" + "</body>\n" + "</html>";
    return template;
}
View Code

前端展示新闻列表

window.onload = function () {
    var httpRequest = new XMLHttpRequest()
    httpRequest.onreadystatechange = function () {
        if (httpRequest.readyState == 4 && httpRequest.status == 200) {
            var news = JSON.parse(httpRequest.responseText)
            for (var i = 0; i < news.length; i++) {
                showNews(news[i])
            }
        }
    }
    httpRequest.open('GET', 'http://localhost:8093/news', true)
    httpRequest.send()
}
//新闻列表
function showNews(news) {
    var li = document.createElement("li");
    li.innerHTML = `<a href="javascript:view('${news.id}')">${news.title}</a>`;
    document.getElementById("news").append(li);
}
View Code

前端展示新闻详情,问题点2:用document.write输出

//从服务端获取新闻内容展示到页面
function view(id) {
    var httpRequest = new XMLHttpRequest()
    httpRequest.onreadystatechange = function () {
        if (httpRequest.readyState == 4 && httpRequest.status == 200) {
            //演示xss
            document.write(httpRequest.responseText)
    }
    httpRequest.open('GET', `http://localhost:8093/news/${id}`, true)
    httpRequest.send()
}
View Code

演示弹出alter消息

 

 

演示效跳转网站

 

 

posted @ 2024-10-29 22:13  chyun2011  阅读(30)  评论(0编辑  收藏  举报