-
知道创宇诚聘技术牛

我们深信优秀的工程师才是我们成长的源动力,我们渴求真正热爱编程,有强烈进取心、强烈好奇心、超强动手能力的牛人。我们鼓励创新;鼓励使用Linux;鼓励开源精神;我们提倡敏捷;实践敏捷。我们虽然只能为你提供7-15万的年收入,但我们能为你提供一个追求技术与梦想的乐园,这里没有任何官僚气息,这里有弹性工作时间;浓厚的技术氛围;双显示器办公;随时报销计算机图书购买费用;每天的水果与酸奶;业余爱好组(如游戏休闲/人工智能)等等。 Read More »
84 条评论 -
SSH OTP 认证
在前一篇 blog 的最后提到了采用 OTP + 密码作为 SSH 的认证方案以保证安全性,这里就简单描述一下实现方案。我们采用的软件是 Google Authenticator,其客户端实现支持 Android,iOS,BlackBerry 系统。
在服务器上执行下面的操作:
$ git clone https://code.google.com/p/google-authenticator/ $ cd google-authenticator/libpam/ $ make
然后分别拷贝 pam_google_authenticator.so 和 google-authenticator 到 /lib/security/ 和 /usr/bin/ 目录。之后编辑 /etc/pam.d/sshd 文件,在该文件的最前面插入一行:
auth required pam_google_authenticator.so
至此服务端的配置完成。需要注意的是在这个操作之后如果用户没有做公钥认证的配置会导致用户无法登陆系统。解决办法有多种:基于安全起见可以强制用户在管理员的协助下配置公钥认证方式登录系统;或者在上面的配置项后设置 pam_google_authenticator.so 的选项为 nullok,这样用户在没有做 OTP 相关的设置时可以先用密码登录系统来进行相应的操作。
如果 SSH 服务配置了只允许公钥认证,则需要修改 /etc/ssh/sshd_config 文件的配置项为:
ChallengeResponseAuthentication yes UsePAM yes
并重启 SSH 服务以支持 OTP 和密码认证。
客户端需要每个用户登录到系统之后进行相关的配置。用户可以直接输入 google-authenticator 后按提示操作即可,或者直接用下面的命令:
$ google-authenticator -l test@knownsec.com -t -d -r 3 -R 30 -w 3
google-authenticator -h 能看到可用的参数。上面命令用到的参数解释如下:
- -l 设置移动设备上的程序对应的 OTP 码的标签,便于区分不同的应用。
- -t 设置采用基于时间的验证。相应的也可以 -c 参数采用基于计数的验证。
- -d 禁止重用基于时间的验证码
- -r 限制登录频率
- -R 设置登录频率限制的时间间隔
- -w 设置时间窗的大小,主要在移动设备的时间不是准确同步的情况下比较有用
如果系统安装了 qrencode 软件,google-authenticator 可以直接输出一个二维码供移动设备扫描录入(见下图),否则用户需要根据其输出来手工进行相应的设置。
剩下的就是验证测试,祝顺利!
P.S. 由于系统配置以及软件版本等的不同,本文中提到的配置并不能覆盖所有的环境。准确的配置需要参考官方文档并结合实际的系统进行调整。
P.P.S. 显然,本文中提到的 OTP 认证并不局限于 SSH,其他任何支持 PAM 认证方式的软件也都可以使用。
-
SSH 公钥认证
简介
使用 SSH 登录并管理远程服务器是系统运维之中的常见操作。目前常用的认证方式是 用户名 + 密码。使用密码在某些特定的场合下的缺点是显而易见的,如:
- 在需要多人共用一个帐号的场景下需要将密码告诉所有使用人员,使密码泄漏的风险增大,并且修改密码也需要通知所有人,带来一定的维护管理成本。
- 某些情况下需要无密码访问(系统可以配置成允许空密码登录,但相应的安全风险也大增),如 MPI,大批量的服务器维护等。
采用公钥认证则能避免规避单纯使用密码认证带来的这些问题,多人可以通过持有各自的私钥登录到系统的同一个帐号。用户可以在安全保持私钥的前提下安全的执行无需输入密码的登录操作。
公钥认证的基本工作原理可以参考任何一本密码学相关的参考书籍,或者这里。
接下来的内容就是最常见的 SSH 服务端(OpenSSH)和客户端(OpenSSH 和 PuTTY)的配置方法。其他的软件如何配置可以参考其附带的文档,差别应该仅体现在命令行的使用上。
配置
服务端配置
OpenSSH 的服务端配置文件一般为 /etc/ssh/sshd_config,和公钥认证有关的两个配置项是:
#RSAAuthentication yes #PubkeyAuthentication yes
其缺省值一般为 yes。如果希望仅打开公钥认证,禁用其他的认证方式,则可以修改下列配置项:
PasswordAuthentication no ChallengeResponseAuthentication no UsePAM no
上述配置项如果有任何需要修改的地方在修改之后重启ssh服务器让新的设置生效。
密钥生成
在使用公钥认证前需要实现生成相应的公私钥密码对。OpenSSH 下生成密钥对的命令为:
$ ssh-keygen -C "liuzx@test" -t rsa -b 2048 -f test Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in test. Your public key has been saved in test.pub. The key fingerprint is: 2f:2e:86:fc:8f:55:82:d2:dd:18:fa:9a:6e:3a:b1:d9 liuzx@test The key's randomart image is: +[RSA 2048]-------+ | | | | | . | | . + + | | . + S o | | .. . + | | . * + . | | * E* . | | .B*oo | +-----------------+
更多的参数可以参考 ssh-keygen 的手册页。上面用到的参数分别介绍如下:
-C 是对密钥的一个说明,有助于区分不同的密钥用途。
-t 和 -b 分别指定要生成的密钥类型和密钥长度。
-f 指定生成的密钥对文件名。公钥文件名为test.pub,私钥为 test。PuTTY 提供了一个PuTTYgen可以用来实现类似ssh-keygen的功能。相应的截图如下



PuTTYgen 生成的私钥文件一般 save 后的后缀为 .ppk,在这个程序的菜单栏 Conversions 里可以执行和 OpenSSH 的私钥格式之间的相互转换。
客户端配置
在完成密钥对的生成后,需要将对应的公钥文件拷贝到服务器上需要登录的用户的home目录下的
.ssh/authorized_keys文件中:$ cat test.pub >> ~test/.ssh/authorized_keys
对 PuTTYgen 生成的密钥将上图蓝色框内的文本拷贝粘贴到 authorized_keys 文件中即可。从上面的重定向用的 >> 就可看出我们可以附加任意多个公钥到这个文件之中(每个公钥占一行)。这样就实现多人以同一个用户的身份登录系统的功能。如果需要取消某个人的访问权限,只需要删除其对应的公钥即可。
事实上 authorized_keys 文件的准确名字是由 sshd_config 中的 AuthorizedKeysFile 配置指定给定的。同样,man sshd_config 获取详细的说明信息。注意: authorized_keys 文件及其所在的目录以及父目录(一直上溯到该用户的HOME目录为止)的权限必须设置为不能被组和其他人写(可以通过 chmod og-w 确认),否则其他人只需要修改这个文件即可以以该身份登录到系统上。
authorized_keys 的格式可以参考 man sshd,AUTHORIZED_KEYS FILE FORMAT 这一节。简单点说,通过配置 authorized_keys 的每一行,可以对不同的用户进行不同的细粒度的控制。如控制不同用户可以执行的命令,设置环境变量,设置允许登录的主机或 IP 地址等。典型的一个例子就是 git 的管理软件 gitolite。
在authorized_keys文件设置好之后,即可以使用公钥认证的方式来登录远程服务器了。
对 OpenSSH 客户端,可以通过 ssh -i test test@remote.host 快速测试是否工作。更一般的方法是将私钥文件 test 拷贝为 .ssh/id_xxx (xxx 由密钥类型决定,如rsa,dsa,ecdsa)。如果不能正常工作,可以 ssh 加上 -v 参数以及查看服务端的日志来排查可能的原因。注意私钥的权限要求必须只能自己具有读写权限(通过 chmod og-rwx 确认),否则ssh客户端会拒绝使用该私钥。在有多个密钥对的情况下,可以通过设置 .ssh/config 对不同的主机和用户使用不同的私钥文件。如下例:
Host * IdentityFile ~/.ssh/%r@%h同样的,更多的细节参考 man ssh_config。
对 PuTTY 客户端,见下图,在执行 session 时选择相应的私钥文件即可。

关于密钥的更多说明
一般来说生成密钥对时选择 RSA 2048 的强度足够安全了。此外还有dsa 和 ecdsa。根据 PuTTY 的用户手册,推荐使用 RSA,不建议用 DSA, PuTTY 不支持 ECDSA。
由于在配置了公钥认证的情况下,为方便起见,一般都不设置私钥密码,即只要持有私钥就可登录系统。因此私钥文件泄漏带来的风险就非常大了。因此,对私钥文件应仅在可信的环境下才能以无密码的方式存储,其他情况下应该以强密码保护。如果最初生成密钥是没有设置密码,可以通过 ssh-keygen -p -f test 重新设置密码。对 PuTTY 只需在 Load 私钥后输入密码然后重新保存即可。
幸好,SSH 对这种情况已经有所考虑,并提供了相应的辅助程序做认证代理。OpenSSH 的程序名为 ssh-agent,PuTTY 的程序名为 pageant。其基本思想是预先加载私钥在内存之中,在记载的过程之中如果私钥有密码,会请求用户输入密码。这样以后的 SSH 连接就不需要频繁的输入私钥的密码。
OpenSSH 下的响应操作如下:
$ eval $(ssh-agent –t 1800) $ ssh-add .ssh/id_rsa Enter passphrase for ./ssh/id_rsa: $ ssh-add -l 2048 f3:65:34:01:24:61:56:94:5d:54:63:44:1e:1a:18:6a .ssh/id_rsa (RSA)
PuTTY 下的操作如图:

在执行pageant后,在托盘栏会有相应的图标,右键单击即出现上图,点击 Add Key 按提示操作即可。结语
严格说来,在不可信的环境里不管是采用密码还是公钥任何认证方式都是有风险的。我们所能作的就是在风险控制和易用性方便权衡选择。
最后,采用公钥认证由于需要私钥文件才能登录,在特殊的情况下,如果没有私钥会导致无法登陆系统。简单的回到密码认证又规避不了风险。这种情况下,采用 One-time passcodes (OTP ,HOTP 或者 TOTP) 也许是一种选择。Google Authenticator 提供了一个很好的实现方案,包括移动客户端。我会在另一篇 blog 里来简单介绍如何实现。
P.S. 由于系统配置以及软件版本等的不同,本文中提到的配置并不能覆盖所有的环境。准确的配置需要参考官方文档并结合实际的系统进行调整。
-
python的命令注入威胁之eval()
小G@北京 2012/5/15 19:23
eval函数是python最常用于做序列化、反序列化的函数,有些人就会把外部输入的数据,eval一下变成对象,但你不做任何过滤就执行eval的时候可知道,你变成一个很初级的码农了。
命令执行的场景如下:
code ="""__import__('os').system('echo 1')""" eval(code) 1 0很简单,code变量的值可能是外部提交的,一旦被你序列化的时候,里面是可以写python代码并被执行了,而且eval执行的代码是在当前命名空间下的。
eval是可以指定执行时的全局和局部的命令空间的:
安全使用eval
eval接受3个参数: eval(source[, globals[, locals]]) -> value
只要将2个命名空间置空即可隔绝上下文的代码进行安全执行表达式。
eval('{1:2}',{},{})不过! 通过builtins内置的方法仍有可能绕过:import('os').system('dir')、 eval("globals()", {}, {}), 直接秒杀
情况看上去似乎很复杂,不好解决问题啊。
此时只能祭出大招了。。
嗯哼,吭叽吭叽地写出一个安全eval的接口,方便开发的同学不需要再考虑这些产品相关性很低而复杂的问题。safeeval模块因此而诞生,为序列化操作提供安全转换,对eval数据进行词法分析,确保eval的数据中不会包含不合法的TRUE等写法,并且在隔离、安全的环境执行eval。
用法:
myobj = safe_eval(eval_str)源代码已经开源,大家可以到
https://github.com/greysign/pysec/blob/master/safeeval.py
得到全部信息。 -
python的常见命令注入威胁
小G@北京 2012/5/15 18:45
ah!其实没有标题说的那么严重!
不过下面可是我们开发产品初期的一些血淋淋的案例,更多的安全威胁可以看看北北同学的《python hack》PPT,里面提及了不只命令执行的威胁,那些都是我们亲身经历的代码。
千万要记得执行命令的时候,不要信任其他传入数据就行了,既然意识到问题,那么修复方法是多种多样的。
在我们的系统中,多处出现问题然后修修补补是不靠谱的,那么我们需要一个通用的安全执行接口,这个接口过后更新进来。
此外,我们在开发新功能的时候,也要掌握安全编程的规范技巧,这些技巧不局限在命令执行安全。
总结了一下,就是一下几点要素啦:
- 命令执行的字符串不要去拼接输入的参数,非要拼接的话,要对输入参数进行白名单过滤
- 对传入的参数一定要做类型校验,例如知道是数字型的,就int测试一下,会安全许多
- 对于拼接串,也要严格一些,例如int类型参数的拼接,对于参数要用%d,不要%s。
- 使用subprocess来传入多个参数,就可以防止命令行注入
拿我们曾经的代码(当时是最新版=,=时过境迁了)存在的bug来做教程:
示例1(变量没过滤):
a.py
site变量其实是个url格式的串,未经过滤。由于老版本中site格式没有出现问题,新版本支持url格式,就可以传入各种符号了。
cmd = 'python /a.py --task_id=%s --site=%s -b' % (taski, site)
示例2(不牢靠的过滤):
util/update.py
downloadFile函数尽管对fileName使用了过滤,但绕过的方法很多。
linux下面的命令分隔方法非常多,黑名单法是不牢靠的。
fileName = downloadInfo[0] fileName = fileName.replace(';','').replace('&','') #过滤文件名 localMd5 = os.popen('md5sum %s%s' %(path,fileName)).read()修复的方法就是对fileName进行白名单格式检查,比如,只允许出现字符数字以及.。
示例3(不安全的格式化字符串):
b.py
target是个url格式的串,未经过滤。并且还有潜在威胁,deep使用了%s,其实它必须是个int,使用%d才对,假如以后有机会感染deep变量,那就xxoo了。
cmd = 'python b.py --task_id "%s" -s %s --deep %s --check_level %s -b' %(taski,target,deep,check_level)
示例4(无法利用的命令注入):
c.py
site_report函数,tid参数未经格式化,目前无法利用是因为有一个查询数据库的语句: get_object_or_404(Task, get_domain_query(request), id=tid)#这里会让带了特殊符号的tid查不到记录,所以变为404,暂时保护了位于下文的cmd拼接。 一旦该语句变更,就会导致新的命令注入漏洞 cmd = 'sh /opt/report %s >/tmp/export_report.log 2>&1' % tid
-
“知道杯”第二届台球比赛
-
DEDECMS SQL注入0day预警
2012/4/29 凌晨 知道创宇安全研究团队截获到最新DEDECMS SQL注入 0day,官网目前提供下载的最新版5.7也受影响,截止本告警发出时官方尚未给出补丁或解决方案,此漏洞利用简单且dedecms安装之后默认即开启漏洞模块。
知道创宇给出三种临时解决方案:
方案一、临时补丁,需要四步
1. 确保您的magic_quotes_gpc = On
详细开启方式:打开php安装目录中的php.ini(若您使用的是appserv等集成环境,php.ini可能在系统盘符:\windows\php.ini),搜索magic_quotes_gpc,将其设置为On。
2.
/plus/carbuyaction.php 22行附近即
if($cfg_mb_open == 'N') { ShowMsg("系统关闭了会员功能,因此你无法访问此页面!","javascript:;"); exit(); }下面添加一行代码
$rs =array();
3.
在 member/ajax_membergroup.php 33行附近即
if(empty($membergroup)){ echo "您还没有设置分组!"; exit; }下面加入如下代码:
if(strpos($membergroup,"'")){ echo "SQL注入防护临时补丁,知道创宇安全团队提醒您关注官方补丁!"; exit; }4.
原member/ajax_membergroup.php 36 行附近的
$row = $dsql->GetOne("SELECT groupname FROM #@__member_group WHERE mid = {$cfg_ml->M_ID} AND id={$membergroup}");修改为
$row = $dsql->GetOne("SELECT groupname FROM #@__member_group WHERE mid = {$cfg_ml->M_ID} AND id='{$membergroup}'");方案二、以网站管理员身份后台禁用会员功能
系统 -> 系统基本参数 -> 会员设置 -> 是否开启会员功能 改为(否)
方案三、若贵站不需要会员功能,可考虑直接重命名或删除存在漏洞的文件 /member/ajax_membergroup.php,最暴力却最有效的方式。
本文给出的临时补丁仅供临时防御,对系统造成轻微影响尚未进行系统测试,目前我们已经通知织梦CMS官方,具体补丁等请等待官方补丁。
关于我们:
知道创宇拥有一支国际一流的Web安全研究团队,能够实时跟踪最新Web安全技术及趋势。
我们追求卓越的WEB安全技术,致力于为网站提供安全产品、SaaS(安全即服务)服务,让网站更安全,为中国互联网的信息安全贡献我们的一份力量。
更新:
目前织梦CMS已发布安全补丁,请关注官网:http://www.dedecms.com/
-
多线程下pymongo连接数过多的问题处理
背景
项目中有个应用,用到了多线程,线程中会有对MongoDB的操作。一般涉及到这种场景,都会小心MongoDB的连接的数量控制。
实现这个应用的时候必然已经考虑这点了,但实际碰到的情况是:多线程的程序运行起来,MongoDB连接数比预期多。
涉及的环境:
- Linux
- Python 2.6.5
- MongoDB 2.0.0
- MongoDB的驱动是pymongo。本文涉及的版本有4个:1.1.1、2.0.1、2.1.1,以及最新的2.2rc1。
过程
简化的代码
先用一段简化的代码来说明下这个问题。
#-*- encoding:UTF-8 -*- import threading import time import pymongo single_conn = pymongo.Connection('mongodb://127.0.0.1', max_pool_size=1) class SimpleExampleThread(threading.Thread): def run(self): print single_conn['fvck'].damnit.count(), self.getName() time.sleep(10) for i in range(100): SimpleExampleThread().start()代码的大致意思是创建1个MongoDB连接,然后生成100个线程,在线程中会有对MongoDB的操作 Read More »
-
关于 Content-Encoding: gzip
背景
===
如果你的网页抓取程序(例如爬虫)在抓取网页时没有发送 Accept-Encoding: gzip,那么你 out 了:
因为今天超过 99% 的网页抓取程序都会声明支持 gzip (或 deflate) 编码。如果你的程序属于这 99%,那么恭喜,但别高兴的太早。 你的程序是否正确处理了 Content-Encoding: gzip?
问题
===
典型的处理 Content-Encoding: gzip 的代码片段 (python):html_data = GzipFile(fileobj=StringIO(html_data), mode="r").read()
假设 html_data 为 Web 服务器返回的Content-Encoding 为 gzip 的数据。
那么在大多数情况下,上述代码都能正确处理。 但很不幸,你会发现,对有些 url,浏览器可以正常显示内容,
但是你的网页抓取程序会出错!分析
===
不是所有 Web 服务器(或应用)都是遵纪守法的公民。 极少数应用,会在 gzip 压缩后的数据后面,添加一些“尾巴”数据。
一些数据解压模块(如Python 的 GzipFile 模块)在这种情况下会出现处理异常。例外的是浏览器。它们充分体会和考虑到了现实世界的复杂,会自动抛弃多出的“尾巴”,正常解压和处理页面数据。
解决
===
Python GzipFile 模块有个未公开属性: extrabuf, 负责保存已经成功解压的数据。 因此,下面的代码有更好的兼容性:try: gf = GzipFile(fileobj=StringIO(html_data), mode="r") html_data = gf.read() except: html_data = gf.extrabuf -
2011-2012中国互联网网站安全报告
2012年3月26日,北京知道创宇信息技术有限公司“2011-2012中国互联网网站安全报告”发布会在金台饭店举行,100多位行业用户、专家学者及国内知名媒体出席了本次发布会。
知道创宇CEO赵伟代表公司致欢迎辞,感谢大家的光临并和大家分享了公司专注于Web安全以及“更好更安全的互联网”公司愿景。中国信息安全测评中心资深安全顾问蒋鲁宁老师对2011年互联网网络安全行业趋势进行了详细的回顾,并探讨了未来的应对策略;CNCERT/CC运行部副主任王明华通过具体的数据对2011年中国互联网网络安全态势进行了深度的解析,并指出网站安全问题依然是未来的安全热点问题。
知道创宇研究部总监钟晨鸣(网名:余弦)对“2011-2012中国互联网网站安全报告”内容进行了详细解读。知道创宇互联网网站监测中心对2011年的挂马、暗链数据按行业及地区进行了统计分析。监测数据显示,网站挂马事件得到了有效控制,但挂马的方式方法变得复杂和多样化。一些国家重点部门以及重点行业的网站仍旧是挂马攻击的主要目标。在网站挂马得到有效抑制的同时,比网站挂马更为隐蔽、不易察觉的恶意行为——暗链,成为了新的、重要的攻击手段。







