Django的两则url跳转漏洞:CVE-2017-7233和CVE-2017-7234分析

Django官方News&Event在4月4日发布了一个安全更新,修复了两个URL跳转的漏洞,一个是urlparse的锅,另一个来自国内的安全研究员 phithon@长亭,都非常漂亮。因为有复现Django漏洞的习惯,晚上抽了点时间复现了一下。有趣的点还挺多。把两个漏洞的分析整合在一起,凑了篇文章。(还是研究漏洞有趣啊,泪流满面QAQ)

CVE-2017-7233分析

国外安全研究员roks0n提供给Django官方的一个漏洞。

n0js case1 writeup

跟着蘑菇老师学前端安全第一弹[二哈]

地址:

http://server.n0tr00t.com/n0js/case1.html

主要代码:

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
function test(a1, a2, a3) {
console.log(`${a1}`);
eval(`${a2}`);
console.warn(`${a3}`)
};
var x = location.hash;
l1 = escape(x.split('#')[1]);
l2 = x.split('#')[2];
l3 = x.split('#')[3];
if (l1 === 'undefined' || l1.length >= 30) {
a1
};
if (l2 === 'undefined' || l2.length >= 35) {
a2
};
var v = ['1', l2, '3'];
if (l1.indexOf(';') >= 0 || l2.indexOf('(') >= 0) {
a3
};
if (l2.indexOf('/') >= 0) {
b1
};
if (l3.indexOf(']') >= 0 || l3.length >= 2) {
c3
}; {
d = l1 + 'v' + l3.trim();
eval('test(' + d + ')')
};

记一下PythonWeb代码审计应该注意的地方

《Code Review For Python-Based Web Apps》(《PythonWebApp代码审计》)做的笔记,正好自己也在写相关的文章:讨论PythonWeb开发中可能会遇到的安全问题,所以就翻译了一下作者原文,省去一些不必要的口水,并添加了一些自己的想法。

SQL注入

安全的做法:

1
2
stmt = "SELECT * FROM table WHERE id=?"
connection.execute(stmt, (value,))

不安全的做法:

1
2
3
"SELECT * FROM table WHERE id=" + value
"SELECT * FROM table WHERE id=%s" % value
"SELECT * FROM table WHERE id={0}".format(value)

大部分Python操作数据库的第三方模块,如pymysql、sqlite3等,执行sql语句的函数,都支持参数化查询,如上安全的做法所示,可以给sql语句传递参数,这个参数经过过滤。而下面的字符串拼接是不经过过滤。所以会出现sql注入。

使用PyQt4.QtWebKit降低自动化XSS检测的误报

一直以来的一个想法,现在有新的思路的就写出来看看。

自动化Web漏洞扫描器是渗透测试亘古不变的话题。把当前一直重复的手工劳动和新的思路转化为自动化工具,利用技术和程序实现为自己节省时间是一件非常有趣的事情。然而,自动化的路坑却不少。其中误报就是一件比较蛋疼的事情,XSS的误报尤其蛋疼。当前众多扫描器的XSS插件都存在误报的情况,我们来看一下大部分扫描器的XSS检测思路,我写了一个简单的Python函数来描述它,当然实际的通用XSS检测插件肯定会比这个要复杂的多,我只截取了一部分来说明思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
headers={}

def xss_detect(method='GET', querylist=[], url=''):
params = {}
resp = None
# 这里有更多的payload,如onfocus=alert(2333)
payload = '-->\'"><script>alert(1);</script>'
if method == 'GET':
for query in querylist:
# url = '{url}?{query}={payload}'.format(url=url,query=query,payload=payload)
params[query] = payload
resp = requests.get(url, params=params, headers=headers)
# 此处省略POST
if resp:
# 这里有更多的正则匹配规则
if '<script>alert(1);</script>' in resp.content:
return True
else:
return False