SQL注入
SQL注入,就是利用现有Web应用程序,构建特殊的参数输入,将(恶意的)SQL语句注入到后台数据库引擎,最终达到欺骗服务器执行恶意SQL语句的目的。
分类:
根据注入点位置的不同,可分为列注入、表注入、order注入、limit注入、group by注入等。
根据注入形式的不同,可分为数字型注入、字符型注入、搜索型注入。
根据请求方式的不同,可分为GET型注入、POST型注入、HEADER型注入。
危害:脱库,导致敏感数据泄漏; getshell,获取服务器权限。
防御:对用户输入的参数作好预编译处理,不能预编译的,可采取安全过滤,类型判断,映射等方式进行处理。
备注
- 纯盲注
- order注入
- limit注入
- 宽字节注入
- 二次注入
- 简单注入绕过
- 注入拿shell
常用函数
substring() substr() mid()
ascii() if() case when()
sleep()
updatexml() extractvalue() floor()
concat() concat_ws()
user() database()
procedure analyse()
SQL注入自动化利用工具
- sqlmap 下载地址:https://github.com/sqlmapproject/sqlmap 使用教程:https://www.tr0y.wang/2018/03/21/sqlmap-guide/
参考资料
- https://octobug.gitbooks.io/sqlmap-wiki-zhcn/content/
- https://github.com/wizardforcel/mst-sec-lecture-notes/blob/master/%E6%BC%8F%E6%B4%9E%E7%AF%87%20SQL%E6%B3%A8%E5%85%A5.md
- https://b1ngz.github.io/java-sql-injection-note/
- http://sqlwiki.radare.cn/
python安全开发
时间函数安全使用
astime
asctime()函数是将一个tuple或者是struct_time表示的时间形式转换成类似于Sun Jun 20 23:21:05 1993的形式,对time.struct_time(tm_year=2015, tm_mon=11, tm_mday=7, tm_hour=20, tm_min=58, tm_sec=57, tm_wday=5, tm_yday=311, tm_isdst=0)中每一个键值设置invalid_time可造成溢出错误。
在Python 2.6.x中报错为
OverflowError: long int too large to convert to int
在Python 2.7.x中报错为
OverflowError: Python int too large to convert to C long
OverflowError: signed integer is greater than maximum
因此开发过程中需要考虑时间日期的格式,防止溢出导致信息泄露!
gmtime
time.gmtime()为将秒数转化为struct_time格式,它会基于time_t平台进行检验,如上代码中将秒数扩大进行测试时会产生报错ValueError: timestamp out of range for platform time_t
。如果数值在-2^63到-2^56之间或者2^55到2^62之间又会引发另一种报错ValueError: (84, 'Value too large to be stored in data type')
。
Utime
os.utime(path, times)是设置对应文件的access和modified时间,时间以(atime, mtime)元组的形式传入,代码中将modified time设置过大也会产生报错。
在Python 2.6.x中报错为
OverflowError: long int too large to convert to int
在Python 2.7.x, Python 3.1中报错为
OverflowError: Python int too large to convert to C long
如果我们将其中的modified time设置为2^55,ls后会有:
$ ls -la temp.bin
-rw-r--r-- 1 user01 user01 5 13 Jun 1141709097 temp.bin $ stat temp.bin
A:"Oct 10 16:31:45 2015"
M:"Jun 13 01:26:08 1141709097"
C: ”Oct 10 16:31:42 2015"
在某些操作系统上如果我们将值设为2^56,将会有以下输出(也有造成系统崩溃和数据丢失的风险):
$ ls -la temp.bin
Segmentation fault: 11
$ stat temp.bin
A:"Oct 10 16:32:50 2015"
M:"Dec 31 19:00:00 1969"
C:"Oct 10 16:32:50 2015
Modules通常没有对无效输入进行检查或者测试。例如,对于64位的操作系统,最大数可以达到2^63-1,但是在不同的情况下使用数值会造成不同的错误,任何超出有效边界的数字都会造成溢出,所以要对有效的数据进行检验。
计数函数安全
ctypes
问题在于:ctypes对内存大小没有限制,也没有对溢出进行检查.
所以,在32位和64位操作系统上都可以造成溢出,解决方案就是也要对数据的有效性和溢出进行检查。
xrange
xrange使用Plain Integer Objects而无法接受任意长度的对象。解决方法就是使用Python的long integer object,这样就可以使用任意长度的数字了,限制条件则变为操作系统内存的大小了。
len
因为len()函数没有对对象的长度进行检查,也没有使用python int objects(使用了就会没有限制),当对象可能包含一个“.length”属性的时候,就有可能造成溢出错误。解决办法同样也是使用python int objects。
Decimal
将Decimal实例和浮点值进行比较,在不同Python版本中如果无法比较则用except捕获异常,输出情况为:
在Python 2.6.5, 2.7.4, 2.7.10中输出ERROR: FLOAT seems comparable with DECIMAL (WRONG)
在Python 3.1.2中输出OK: FLOAT is NOT comparable with DECIMAL (CORRECT)
Type Comparsion
将字符串和浮点值进行比较,在不同Python版本中如果无法比较则用except捕获异常,输出情况为:
在Python 2.6.5, 2.7.4, 2.7.10中输出ERROR: FLOAT seems comparable with STRING (WRONG)
在Python 3.1.2中输出OK: FLOAT is NOT comparable with STRING (CORRECT)
在使用同一种类型的对象进行比较之后,Python内置的比较函数就不会进行检验。但在以上两个代码例子当中Python并不知道该如何把STRING和FLOAT进行比较,就会直接返回一个FALSE而不是产生一个Error。同样的问题也发生于在将DECIMAL和FLOATS时。解决方案就是使用强类型(strong type)检测和数据验证。
字符串函数安全
eval
使用__import__导入os,
再结合eval()就可以执行命令了。只要用户加载了解释器就可以没有限制地执行任何命令。
codecs
以上的代码将x41xF5x42x43xF4以二进制的形式写入文件,再分别用codecs和io模块进行读取,编码形式为utf-8,对xF5和xF4不能编码的设置errors='replace',编码成为\ufffd,最后结果如下:
Correct-String —> "u'A\ufffdBC\ufffd'"
CODECS-String —> "u'A\ufffdBC'" (WRONG)
IO-String —> "u'A\ufffdBC\ufffd'" (OK)
当codecs在读取x41xF5x42x43xF4这个字符串的时候,它期望接收到包含4个字节的序列,而且因为在读入xF4的时候它还会再等待其他3个字节,而没有进行编码,结果就是得到的字符串有一段被删除了。更好且安全的方法就是使用os模块,读取整个数据流,然后进行解码处理。解决方案就是使用io模块或者对字符串进行识别和确认来检测畸形字符。
os
在不同的平台上,环境变量名的名称和语法都是基于不同的规则。但Python并不遵守同样的逻辑,它尽量使用一种普遍的接口来兼容大多数的操作系统。这种重视兼容性大于安全的选择,使得用于环境变量的逻辑存在缺陷。
解决方案是对基础设施和操作系统进行检测,检测和环境变量相关的键值对,阻止一些对操作系统为空或者无效键值对的使用。
文件函数安全
pickle
构造恶意序列化字符串,以二进制的形式写入文件中,使用pickle.load()函数加载进行反序列化,还原出原始python对象,从而使用os的system()函数来执行命令"ls -la /"。由于pickle这样不安全的设计,就可以借此来执行命令了。
cPickle
根据使用的Python版本不同,pickle或cPickle要么保存截断的数据而没有错误要么就会保存限制为32bit的部分。而且根据Python在操作系统上安装时编译的情况,它会返回在请求随机数据大小上的错误,或者是报告无效参数的OS错误
解决方案就是执行强大的数据检测来确保不会执行危险行为,还有即使在64位的操作系统上也要限制数据到32位大小。
File Open
在Python2中没有包含原子操作,核心库是在使用缓存进行读写。所以应该尽量去使用io模块。
协议函数安全
httplib
构造了一个HTTP服务端,如果一个客户端连接进来,再去关闭服务端,Python将不会释放资源,操作系统也不会释放socket,引发报错为socket.error: [Errno 48] Address already in use!
解决方案就是每一个协议库都应该由这样的库封装:为每一个OS和协议都适当地建立和撤销通信,并释放资源
poplib
以上代码当中,首先开启一个虚拟的服务端,使用客户端去连接服务端,然后服务端开始发送空字符,客户端持续性接收空字符,最后到客户端内存填满,系统崩溃,解决方案就是如果无法控制检查数据的类型和大小,就使用Python > 2.7.9'或者'Python > 3.3'的版本
urllib
urllib2并没有合适的逻辑来处理数据流而且每次都会失败,将上次代码运行三次都会得到错误的文件大小的输出
不安全的库
ast
bastion
commands
cookie
cpickle/pickle
eval
marshal
mktemp
multiprocessing
os.exec
os.popen
os.spawn
os.system
parser
pipes
pty
rexec
shelve
subprocess
tarfile
urllib2
urlparse
yaml
zipfile
API安全设计指南:http://blog.nsfocus.net/rest-api-design-safety/
nodejs
1、sql注入
sql注入产生的原因是开发人员在进行数据库操作是,未针对用户的输入进行过滤和预编译处理,从而导致攻击者可以控制数据库查询语言而进行非法操作,如下所示:
var query = "SELECT name FROM Users WHERE login='" + req.body.login + "'"; db.sequelize.query(query,{ model: db.User }).then(user => { if(user.length){
修复方案,针对参数进行预编译处理
if (vh.vCode(req.body.login)){ db.User.find({where:{'login':req.body.login}}).then(user => { if (user) {
2、命令注入
命令注入产生的原因是开发人员在调用系统命令是,采用危险的系统命令执行函数,并且过于信任系统命令传递的参数,导致攻击者可以通过管道命令拼接的方式去执行任意系统命令,如下所示:
const exec = require('child\_process').exec; ... exec('ping -c 2 '+ req.body.address, function(err,stdout,stderr){ console.log(err) output = stdout + stderr
修复方案,采用安全的系统命令调用函数,并且针对用户输入进行严格的校验
const execFile = require('child\_process').execFile; ... if (vh.vIP(req.body.address)){ execFile('ping', \['-c', '2', req.body.address\] , function(err,stdout,stderr){ output = stdout + stderr
3、暴力破解
暴力破解攻击主要发生在登陆业务模块中,由于系统针对用户登陆失效性缺乏校验,导致攻击者可以通过自动的方式破解系统的口令,从而获取系统敏感数据 修复建议:针对用户登陆接口增加防止暴力破解的方式,如生物识别、并增加账号或者IP锁定机制
4、敏感信息泄露
敏感信息泄露在使用NodeJS开发中一般存在于无认证访问接口、日志记录的业务场景里面,如下所示:
db.User.findAll({}).then(users => { res.status(200).json({ success: true, users: users })
修复建议:针对用户敏感数据进行脱敏处理,或者禁止接口返回记录用户敏感数据信息
db.User.findAll({attributes: \[ 'id' ,'name', 'email'\]},).then(users => { res.status(200).json({ success: true, users: users })
5、XML实体注入
xml实体注入主要存在于使用xml实体解析的业务功能接口时,未对实体解析的内容进行过滤和校验,导致攻击者可以在xml实体中主任恶意的命令,从而获取系统的敏感数据或者权限,如下所示:
module.exports.bulkProducts = function(req, res) { if (req.files.products & req.files.products.mimetype=='text/xml'){ var products = libxmljs.parseXmlString(req.files.products.data.toString('utf8'), {noent:true,noblanks:true})
修复方案,非业务必须建议禁用xml实体解析功能
module.exports.bulkProducts = function(req, res) { if (req.files.products & req.files.products.mimetype=='text/xml'){ var products = libxmljs.parseXmlString(req.files.products.data.toString('utf8'), {noent:false,noblanks:true})
6、xss注入
xss注入主要的产生的原因是由于开发人员针对用户输入过于信任,导致用户可以任意写入js语言输出到页面上,从而导致js代码执行,获取用户敏感的cookie数据信息。
<%- output.products[i].id %>
<%- output.products[i].name %>
<%- output.products[i].code %>
<%- output.products[i].tags %>
修复方案:xss修复方案的八字原则,输入过滤、输出编码
<%= output.products[i].id %>
<%= output.products[i].name %>
<%= output.products[i].code %>
<%= output.products[i].tags %>
7、不安全的反序列化
在使用NodeJS开发的场景中,如果在序列化和发序列化操作的过程中,未对反序列话生成的对象进行校验,会导致远程命令执行 如下所示:
module.exports.bulkProductsLegacy = function (req,res){ // TODO: Deprecate this soon if(req.files.products){ var products = serialize.unserialize(req.files.products.data.toString('utf8'))
修复方案: 针对反序列化产生的对象进行严格的校验,防止恶意的代码生产
module.exports.bulkProductsLegacy = function (req,res){ // TODO: Deprecate this soon if(req.files.products){ var products = JSON.parse(req.files.products.data.toString('utf8'))
8、不安全的访问控制
不安全的访问控制一般存在于应用接口的未授权访问导致泄露系统敏感信息,如swagger-ui, spring-acutotar等业务场景,在使用Nodejs开发的应用系统中,同样需要注意使用安全的访问控制,防止信息泄露,如下所示
... router.get('/admin',authHandler.isAuthenticated,function(req,res){ res.render('app/admin',{admin: (req.user.role=='admin')}) })
router.get('/admin/api/users',authHandler.isAuthenticated, appHandler.listUsersAPI) ...
修复方案: 针对对外开发的接口增加强身份验证机制,防止未授权访问导致的信息泄露
... var isAdmin = false; if(!isAdmin){ var div = document.getElementById('admin-body'); div.style.display = "none"; }else{ var div = document.getElementById('non-admin-body'); div.style.display = "none";
} ...
9、使用不安全的第三方库
软件过程中通常会使用开发第三方组件来提升编码效率,减少重复造轮子,但是随着不安全的第三方组件引入会对应用系统带来新的安全威胁,因此在NodeJS开发过程中,使用的第三方组件需要进行严格的安全审核和扫描,防止引入存在安全风险的组件库 如mathjs
修复建议: 1、使用安全的组件库替换 2、针对用户的输入进行合法性校验
10、安全配置缺失
在使用NodejS开发应用过程中,为了方便定位问题,存在生产环境中开启debug模式的业务场景,在该模式下,会存在信息泄露的安全风险,导致攻击者可以很轻易的获取系统的敏感信息,如下所示:
... if(req.body.eqn){ req.flash('result',mathjs.eval(req.body.eqn)) res.render('app/calc') ... 修复方案: 生产环境禁止开启debug模式,同时针对应用系统接口的报错信息统一处理 try{ result = mathjs.eval(req.body.eqn) }catch (err){ result = 'Invalid Equation' }
环境说明
DVNA是一个采用纯NodeJS编写的web应用靶场,针对owasp top10类型的漏洞都有相关的漏洞测试验证,学员可以通过靶场的实践操作,真正意义上的理解和掌握NodeJS安全开发规范;
参考材料
1、https://github.com/appsecco/dvna 2、NodeJS安全开发规范:参考附件 3、NodeJS开发文档:http://nodejs.cn/api/
iOS安全开发
APP开发时需要注意,用户的敏感信息一般原则是尽量加密保存在服务器上,特别是密码需要使用Hash加salt的方法,并且传输的时候需要使用HTTPS加密传输,业务所需,实在要保存在本地的敏感信息,需要加密保存在本地,另外保存在Keychain中的数据也需要加密;
加密算法需要使用安全的加密算法:安全的对称加密算法包括:AES128、AES192、AES256以及国密SM1;安全的非对称加密算法包括:RAS2048、ECC256、SM2(特别注意位数一定要够,RSA至少是2048位);安全的Hash包括SHA2(SHA224、SHA256等)、SHA3、SM3。不安全的加密算法禁止使用包括:不安全的对称加密算法:DES、3DES;不安全Hash函数:MD5、SHA1。
上线的APP要关闭日志;对于金融类APP来说,最好自定义键盘;当在有敏感信息的页面进入后台后,需要模糊化页面处理;对于企业内部使用的APP,如果需要许禁止复制和粘贴应用内的数据到外部。
Keychain的安全属性kSecAttrAccessibleAlways、kSecAttrAccessibleAlwaysThisDeviceOnly不建议使用,建议使用kSecAttrAccessibleWhenUnlockedThisSDeviceOnly。
代码中禁止硬编码用户密码等敏感信息以及硬编码用户的密钥信息。
URL Scheme和WebView安全
由于UIWebView默认开启WebKitAllowFileAccessFromURLs等,存在File跨越漏洞,禁止使用UIWebView, 推荐使用WKWebView。
当使用URL Scheme唤起应用时,只允许白名单内的APP通过URL Scheme唤起应用。
iOS加固安全
iOS APP上线前可以进行加固处理,可以使用商业工具,也可以自己进行处理,包括对字符串混淆、类名方法混淆、程序代码逻辑混淆和加入安全的SDK用于越狱检测、调试检测、注入检测。
Xcode和第三方库安全
使用的Xcode和第三方库,最好到官网下载,使用前需要查询是否有cve漏洞。
参考文献
- 《iOS Hacking Guide》
- 《黑客攻防技术宝典:iOS实战篇》
- http://damnvulnerableiosapp.com
web
ssrf
- SSRF(Server-Side Request Forgery),服务器请求伪造,是指利用可以发起网络请求的外部应用和服务当作跳板来攻击内部其他应用和服务的一种攻击方式。
- 该漏洞为服务器发起网络请求从远程获取资源,请求的目标地址和协议用户可控并且服务端并未做研究校验导致,常见于社交分享、图片下载等功能。
- 常见的可能触发该漏洞的函数包括PHP中的file_get_content、fsockopen、curl_exec等。
- 通常可以通过SSRF探测内网应用,读取文件,甚至是作为跳板攻击内网应用,如使用gopher协议利用内网redis写入文件getshell。
- 一般通过校验参数url等方式进行防御,但是不充分的校验可以通过巧妙地构造url等方式绕过。
xss
类型 | 存储区域 | 插入点 |
---|---|---|
反射型 | URL | HTML |
存储型 | 后端数据库 | HTML |
DOM型 | 数据库/前端存储/URL | 前端Javascript |
常见输入点
- 输出到HTML标签中
- 输出到HTML标签属性值中
- 生产HTML标签事件
- 输出到DOM中
- 其他
留意: 1、外部元素(svg, math)标签中能进行html解码 2、RCDATA元素标签(textarea, title)下不能创建新标签,不能执行脚本
关于编码解码
- HTML实体编码:10进制/16进制 在html解析时能被解码使用 实体名称: < > 实体编号(10进制): < > 实体编号(16进制):< >
- Javascript编码:javascript8进制编码,16进制编码,Jsunicode编码 在javascript中能被解码使用 10进制:\74\76 16进制: \x3c\x3e
- Unicode: \u003c \u003e URL编码:使用javascript伪协议的标签属性下,可使用base64编码 在URL中能被解码使用 【协议://】这些不能编码
- 防护绕过的一般方法: 详见ppt
防护建议:
- 利用模板引擎 模板引擎一般自带转义,需尽量保持最新,避免低版本漏洞
- 避免内联事件 尽量不要用onLoad=“onload(‘{{data}}’)” onClick=“go(‘{{action}}’)” 这种写法
- 避免拼接 HTML 使用成熟的渲染框架,并保持新版本+后端过滤,如vue,angular等 使用成熟的过滤器,并保持新版本,如ESAPI,Dompurify等
- 增加攻击难度,降低攻击后果 严格白名单、规范的CSP、限制长度、http-only等
csrf
所谓CSRF漏洞,就是通过浏览器的cookie机制,通过诱骗用户点击包含恶意Javascript代码的HTML页面,在用户不知情的情况下,触发对关键接口的调用。
CSRF漏洞的利用前提是:
- 用户已登录网站
- 网站的关键API接口没有对CSRF做防御
- 用户点击访问了攻击者的网页
CSRF漏洞的利用方式是:
- GET请求:img标签src=属性;
- POST请求:form表单,配合Javascript代码自动提交表单
CSRF漏洞的检测方式是:
- 检查请求中是否包含随机token内容
- 修改token,检查接口的返回结果
- 修改HTTP头中的Referer字段,检查接口的返回结果
CSRF漏洞的防御手段有:
- 基于白名单,检查Referer的内容
- 添加CSRF token(建议)
- 图形/短信验证码
xxe
XXE漏洞原理
XML指可扩展标记语言(Extensible Markup Language),主要用来传输 数据。 XML从1995年开始有其雏形,在 1998 年 2 月 10 日成为W3C的标 准(XML1.0)。
DTD(Document Type Definition):文档类型定义,用于定义XML文档的合 法构建模块,使用一系列合法的元素来定义文档的结构,对XML文档元素进 行约束和验证。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
XXE漏洞正是借助DTD实施攻击。XXE漏洞的根本原因是对非安全的外部实体数据进行解析处理导致的安全问题。 常见编程语言如PHP、JAVA、Python、.NET等使用不当均可能存在XXE漏洞。 2. XXE漏洞利用
XXE漏洞的危害
远程文件读取
命令执行(PHP expect)
内网端口扫描
攻击内网网站
dos攻击
XXE漏洞的防御
禁用外部实体
参考文献
http://oxmlxxe.github.io/
https://github.com/JoyChou93/...
https://github.com/swisskyrep... Injection
JAVA
数据校验
避免直接使用不可信数据来拼接SQL语句
避免直接使用不可信数据来拼接XML
避免直接使用不可信数据来记录日志
避免向Runtimeexec() 方法传递不可信、未净化的数据
防止用户输入未经过验证直接输出到html界面
I/O操作
及时删除使用完毕的临时文件
在多用户系统中创建文件时指定合适的访问许可
限定上传文件的格式和大小
序列化和反序列化
敏感数据的加密和签名
禁止序列化未加密的敏感数据
防止序列化和反序列化被利用来绕过安全管理
运行环境
将所有安全敏感代码都放在一个jar包中,签名再加密
生产代码避免包含任何调试入口点
其他
禁止在日志中保存敏感数据
安全加密算法
添加盐值(salt)
禁止硬编码敏感信息
使用强随机数
fastjson
2017年3月15日,FastJson官方发布安全公告表示fastjson在1.2.24及之前版本存在远程代码执行高危安全漏洞。漏洞产生的原因是由于fastjson反序列化Json字符串为Java对象时autoType没有做正确的检测处理,支持使用autoType来实例化任意类。
参考资料
- Fred Long, Dhruv Mohindra, Robert C. Seacord, Dean F. Sutherland, David Svoboda. The CERT Oracle Secure Coding Standard for Java. Addison-Wesley Professional, 2011
- Secure Coding Guidelines for the Java Programming Language. http://www.oracle.com/technet...
- CWE&SANS TOP 25, http://www.sans.org/top25-sof...
- OWASP Guide Project, https://www.owasp.org/index.p...
文件上传
- js检查
- 上传特殊后缀
- .htaccess绕过
- Windows特性(点号、空格、::$DATA)
- 后缀大小写绕过
- 双后缀绕过
- 解析漏洞
- MIME绕过
- 截断绕过
- 文件头检查
- Getimagesize绕过
- exif_imagetype绕过
- 图片二次渲染绕过
- 条件竞争、数组绕过
- apache解析漏洞
- IIS解析漏洞
- PUt方法
- 绕过waf等等
Android
https://repo.xposed.info/module/mobi.acpm.sslunpinning
Android整体加固主要是将apk中的dex进行加密保存,同时将原App的入口改成壳程序;由壳程序对加密dex的解密, 并且实现自定义的DexClassLoader对解密后dex的加载,和运行环境的调整修改,之后进入原dex的代码流程; 由于在dex的加载过程中会调用到dexopt进行dex的优化,从而对dvmDexFileOpenPartial、dexFileParse等进行下断点 即可dump出解密后的dex,实现脱壳;
IDA 调试 Android 方法及简单的脱壳实现