ื”ืงืฆืื” ืื•ื˜ื•ืžื˜ื™ืช ืฉืœ Yealink T19 + ืคื ืงืก ื›ืชื•ื‘ื•ืช ื“ื™ื ืžื™

ื›ืฉื‘ืืชื™ ืœืขื‘ื•ื“ ื‘ื—ื‘ืจื” ื”ื–ื•, ื›ื‘ืจ ื”ื™ื” ืœื™ ืžืกื“ ื ืชื•ื ื™ื ื›ืœืฉื”ื• ืฉืœ ื”ืชืงื ื™ IP, ืžืกืคืจ ืฉืจืชื™ื ืขื ื›ื•ื›ื‘ื™ืช ื•ืชื™ืงื•ืŸ ื‘ืฆื•ืจืช FreeBPX. ื‘ื ื•ืกืฃ, ืžืจื›ื–ื™ื” ืื ืœื•ื’ื™ืช Samsung IDCS500 ืขื‘ื“ื” ื‘ืžืงื‘ื™ืœ ื•ื‘ืื•ืคืŸ ื›ืœืœื™ ื”ื™ื™ืชื” ืžืขืจื›ืช ื”ืชืงืฉื•ืจืช ื”ืžืจื›ื–ื™ืช ื‘ื—ื‘ืจื”, ื˜ืœืคื•ื ื™ื” IP ืขื‘ื“ื” ืจืง ืขื‘ื•ืจ ืžื—ืœืงืช ื”ืžื›ื™ืจื•ืช. ื•ื”ื›ืœ ื”ื™ื” ืžืžืฉื™ืš ืœื”ืชื‘ืฉืœ ื›ืš, ืื‘ืœ ื‘ื™ื•ื ื‘ื”ื™ืจ ืื—ื“ ื ื™ืชื ื” ืฆื• ืœื”ืขื‘ื™ืจ ืืช ื›ื•ืœื ืœื˜ืœืคื•ื ื™ื” IP, ืกื•ื›ืžื• ืžื•ืขื“ื™ื, ื ืจื›ืฉ ืฆื™ื•ื“ ื•ื”ื—ืœื” ืœื™ื™ืฉื ืืช ื”ืชื•ื›ื ื™ืช ืœื”ืขื‘ืจืช ื”ืžื™ื–ื ืœืžืื” ื”-21.
ื”ื“ื‘ืจ ื”ืจืืฉื•ืŸ ืฉืžืชื—ื™ืœ ืœื“ืื•ื’ ื‘ืžืฆื‘ ื›ื–ื” ื”ื•ื ื”ืžืกืคืจ ื”ื’ื“ืœ ื‘ืžื”ื™ืจื•ืช ืฉืœ ืžื›ืฉื™ืจื™ ื˜ืœืคื•ืŸ ืฉืฆืจื™ืš ืœื ื”ืœ ืื™ื›ืฉื”ื•, ื”ื“ื‘ืจ ื”ืฉื ื™ ืฉื”ื™ื” ืžื“ืื™ื’ ืžืื•ื“ ื”ื™ื” ืกืคืจ ื”ื˜ืœืคื•ื ื™ื. ืื ืžื ื”ืœ ื ืงื•ื“ื•ืช ืงืฆื” ื™ื›ื•ืœ ืœืขื–ื•ืจ ืœื ื• ืขื ื”ืจืืฉื•ืŸ (ืฉืื’ื‘, ื ื—ืชืš ืžื”ื’ืจืกืื•ืช ื”ืื—ืจื•ื ื•ืช ืฉืœ FreePBX), ืื– ืขืœื• ื›ืžื” ืฉืืœื•ืช ืขื ื”ืกืคืจ:

  • ืจืืฉื™ืช, ื›ื™ืฆื“ ืœื”ื‘ื˜ื™ื— ืืช ื”ื“ื™ื•ืง ืฉืœื• ื›ืืฉืจ ื”ืžื™ืงื•ื/ื”ื ื–ื™ืœื•ืช ืฉืœ ื”ืžืฉืชืžืฉื™ื ืžืฉืชื ื” ื›ืœ ื”ื–ืžืŸ?
  • ืฉื ื™ืช, ืื™ืš ืœื‘ื˜ืœ ืœื—ืœื•ื˜ื™ืŸ ื”ืชืืžื” ืื™ืฉื™ืช ืฉืœ ื˜ืœืคื•ื ื™ื. ื•ืœื ืœืžืœื ืืช ืฉื ืื™ืฉ ื”ืงืฉืจ ื‘ื›ืœ ืคืขื?

ื”ื‘ืขื™ื” ื”ื™ื™ืชื” ืžืขื ื™ื™ื ืช, ื”ืคืชืจื•ืŸ ืœื ืœืงื— ื”ืจื‘ื” ื–ืžืŸ ืœื”ื’ื™ืข. ืขื›ืฉื™ื• ืื ื™ ืืชืŸ ืืช ื”ืจืฉื™ืžื” ื”ืžืœืื”, ื•ืื– ื ืกืชื›ืœ ืขืœ ื–ื” ืœืคื™ ื”ืกื“ืจ.

from scapy.all import sniff
from scapy.layers.inet import IP
import mysql.connector
import ldap
import getpass
import tftpy
import requests
import os
import time
from string import replace

def conn_ldap(login):
    ad = ldap.initialize('ldap://***.local')
    ad.simple_bind_s('voip@***.local', 'password')
    basedn = 'OU=IT,DC=***,DC=LOCAL'
    basedn_user = 'OU=***,OU=***,DC=***,DC=LOCAL'
    scope = ldap.SCOPE_SUBTREE
    filterexp = "(&(sAMAccountName=" + login + ")(ObjectClass=person))"
    filterexp2 = "(&(ObjectClass=organizationUnit))"
    attrlist = ['cn']
    attrlist2 = ['OU']
    search = ad.search_s(basedn, scope, filterexp, attrlist)
    adname = search[0][1]['cn'][0].decode('utf-8')
    if adname == ' ':
        search = ad.search_s(basedn_user, scope, filterexp2, attrlist2)
        for i in range(1, len(search)+1):
            group = search[i][1]['ou'][0]
            basedn_user2 = 'OU='+group+','+basedn_user
            search = ad.search_s(basedn_user2, scope, filterexp, attrlist)
            adname = search[0][1]['cn'][0].decode('utf-8')
            if adname != ' ':
                return adname
        adname = search[0][1]['cn'][0].decode('utf-8')
    ad.unbind_s()
    return adname


def tftp_file_change(config,place,adname,current_account,current_account_password):

    client = tftpy.TftpClient("192.168.0.3", 69)
    client.download('template.cfg', place)
    fileread = open(place, 'r')
    line = fileread.readlines()
    fileread.close()
    line[5] = (('account.1.label = ').encode('utf-8') + adname.encode('utf-8') + 'n')
    line[2] = (('account.1.auth_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[3] = (('account.1.display_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[6] = (('account.1.password = ').encode('utf-8') + current_account_password[0][0] + 'n')
    filewrite = open(place, 'w')
    for i in line:
      filewrite.write(i)
    filewrite.close()
    print place
    print config
    client.upload(config,place)


def get_phone_inform(ipaddr):
    fileconf = requests.get('http://admin:admin@'+ipaddr+'/servlet?phonecfg=get[&accounts=1]')
    conf = fileconf.text.split('|')
    current_account = conf[2]
    return current_account


def sniff_frame():
    pcapf = sniff(count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060")
    if len(pcapf) == 0:
        exit()
    frame = pcapf[0]
    macaddr = frame.src
    print macaddr[:8]
    if macaddr[:8] != '80:5e:c0':
        exit()
    ipaddr = frame[0][IP].src
    return macaddr, ipaddr


def conn_mysql(query,fquery,macaddr,qwery2):
    connect = mysql.connector.connect(host='192.168.0.3', database='voip', user='voip_wr', password='***')
    cursor = connect.cursor()
    cursor.execute(fquery)
    state = cursor.fetchall()
    state = bool(state[0][0])
    if state == True:
        cursor.execute(qwery2)
        connect.commit()
        connect.close()
    else:
        cursor.execute(query)
        connect.commit()
        connect.close()


def check_account(current_account):
    connect = mysql.connector.connect(host='192.168.0.3', database='asterisk', user='voip_wr', password='***')
    cursor = connect.cursor()
    qwery = 'select data from sip where id=' + current_account + ' and keyword="secret";'
    cursor.execute(qwery)
    password = cursor.fetchall()
    if password == ' ':
        exit()
    else:
        return password


if __name__ == '__main__':
    macaddr, ipaddr = sniff_frame()
    current_account = get_phone_inform(ipaddr)
    current_account_password = check_account(current_account)
    macaddr = macaddr.replace(':', '')
    ipaddr = ipaddr.decode('utf-8')
    adname = conn_ldap(getpass.getuser())
    query = 'INSERT INTO station (mac, ip, name, number) VALUES (' + '"' + macaddr + '",' + '"' + ipaddr + '",' + '"' + adname + '",' + '"' + get_phone_inform(ipaddr) + '"' + ')'
    qwery2 = 'UPDATE station SET ip=' + '"' + ipaddr + '"' + ', name=' + '"' + adname + '"' + ', number=' + '"' + get_phone_inform(ipaddr) + '"' + ' WHERE mac=' + '"' + macaddr + '"'
    fquery = 'SELECT EXISTS(SELECT mac FROM voip.station WHERE mac=' + '"' + macaddr + '")'
    query = query.encode('utf-8')
    fquery = fquery.encode('utf-8')
    config = macaddr + '.cfg'
    place = os.path.expanduser("~") + "" + "AppDataLocal" + config
    conn_mysql(query,fquery,macaddr,qwery2)
    tftp_file_change(config,place,adname,current_account,current_account_password)
    requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=AutoP')
    requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=Reboot')

ื”ืชื•ื›ื ื” ืคื•ืขืœืช ืขืœ ื”ืžื—ืฉื‘ ืฉืœ ื”ืžืฉืชืžืฉ ื•ืคื•ืขืœืช ื‘ืชื ืื™ ืฉื”ืžื—ืฉื‘ ืžื—ื•ื‘ืจ ืœืจืฉืช ื‘ืืžืฆืขื•ืช ื˜ืœืคื•ืŸ, ืฉื›ืŸ Yealink T19 ืœื ื™ื›ื•ืœ ืœืขื‘ื•ื“ ื›ืฉืขืจ.

ืจืืฉื™ืช, ืขืœื™ื ื• ืœื”ื‘ื™ืŸ ื”ืื ื”ื•ื ืžื—ื•ื‘ืจ? ื•ืื™ื–ื” mac ื•-ip ื™ืฉ ืœื˜ืœืคื•ืŸ ืฉืœื ื•.

def sniff_frame():
    pcapf = sniff(count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060")
    if len(pcapf) == 0:
        exit()
    frame = pcapf[0]
    macaddr = frame.src
    print macaddr[:8]
    if macaddr[:8] != '80:5e:c0':
        exit()
    ipaddr = frame[0][IP].src
    return macaddr, ipaddr

ื›ืืŸ ืื ื• ืžืฉืชืžืฉื™ื ื‘ืคื•ื ืงืฆื™ื™ืช sniff ืžื”ืžืกื’ืจืช scapy, ื‘ืขื–ืจืชื” ืžืงื‘ืœื™ื ื—ื‘ื™ืœืช udp ืžื•ื’ื“ืจืช ืžืจืืฉ, ืžืžืชื™ื ื™ื 70 ืฉื ื™ื•ืช ื•ืื ืœื ืงื•ืœื˜ื™ื ื›ืœื•ื, ื™ื•ืฆืื™ื.

count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060"

ืœืื—ืจ ืžื›ืŸ, ืื ื• ืžื•ื•ื“ืื™ื ืฉื”ืžื›ืฉื™ืจ ืื›ืŸ Yealink ื•ืžื—ื–ื™ืจื™ื ืืช ื”ืขืจื›ื™ื ื”ื“ืจื•ืฉื™ื (ip ื•-mac).

ื‘ืืžืฆืขื•ืช ื‘ืงืฉื” ืžื™ื•ื—ื“ืช, ืื ื• ืžื‘ืจืจื™ื ืืช ื”ื—ืฉื‘ื•ืŸ ื”ื ื•ื›ื—ื™ ื‘ื˜ืœืคื•ืŸ. ืœืฉื ื›ืš, ื”ืชืฆื•ืจื” ื”ื ื•ื›ื—ื™ืช ืžื•ืจื™ื“ื” ืžื”ื˜ืœืคื•ืŸ ื•ืžื ืชื—ืช.

def get_phone_inform(ipaddr):
    fileconf = requests.get('http://admin:admin@'+ipaddr+'/servlet?phonecfg=get[&accounts=1]')
    conf = fileconf.text.split('|')
    current_account = conf[2]
    return current_account

ื’ืœื” ืืช ื”ืกื™ืกืžื” ืœื—ืฉื‘ื•ืŸ ื–ื”. ืœืฉื ื›ืš, ืื ื• ืคื•ื ื™ื ืœื˜ื‘ืœืช asterisk.sip ื•ืœืฉื“ื” ื”ื ืชื•ื ื™ื ื‘ื”.

def check_account(current_account):
    connect = mysql.connector.connect(host='192.168.0.3', database='asterisk', user='voip_wr', password='***')
    cursor = connect.cursor()
    qwery = 'select data from sip where id=' + current_account + ' and keyword="secret";'
    cursor.execute(qwery)
    password = cursor.fetchall()
    if password == ' ':
        exit()
    else:
        return password

ื•ื‘ื›ืŸ, ืœืฉืœื‘ ื”ืื—ืจื•ืŸ ืื ื—ื ื• ืžืชื—ื‘ืจื™ื ืœ-ldap AD ื•ืžืฉืชืžืฉื™ื ื‘-sAMAccountName ืฉืžืชืงื‘ืœ ื“ืจืš ื”ืคื•ื ืงืฆื™ื” getpass.getuser() ืงื— ืืช ื”-cn ืฉืœ ื”ืžืฉืชืžืฉ ื”ื ื•ื›ื—ื™ (ืฉืžื›ื™ืœ ื‘ื“ืจืš ื›ืœืœ ืืช ืฉืžื• ื”ืžืœื ืฉืœ ื”ืžืฉืชืžืฉ).

def conn_ldap(login):
    ad = ldap.initialize('ldap://***.local')
    ad.simple_bind_s('voip@***.local', 'password')
    basedn = 'OU=***,DC=***,DC=LOCAL'
    basedn_user = 'OU=***,OU=***,DC=***,DC=LOCAL'
    scope = ldap.SCOPE_SUBTREE
    filterexp = "(&(sAMAccountName=" + login + ")(ObjectClass=person))"
    filterexp2 = "(&(ObjectClass=organizationUnit))"
    attrlist = ['cn']
    attrlist2 = ['OU']
    search = ad.search_s(basedn, scope, filterexp, attrlist)
    adname = search[0][1]['cn'][0].decode('utf-8')
    if adname == ' ':
        search = ad.search_s(basedn_user, scope, filterexp2, attrlist2)
        for i in range(1, len(search)+1):
            group = search[i][1]['ou'][0]
            basedn_user2 = 'OU='+group+','+basedn_user
            search = ad.search_s(basedn_user2, scope, filterexp, attrlist)
            adname = search[0][1]['cn'][0].decode('utf-8')
            if adname != ' ':
                return adname
        adname = search[0][1]['cn'][0].decode('utf-8')
    ad.unbind_s()
    return adname

ืื ื—ื ื• ืžืชื—ื‘ืจื™ื ืœื˜ื‘ืœื” ืฉื ื•ืฆืจื” ืžืจืืฉ ื‘ืžืกื“ ื”ื ืชื•ื ื™ื (ืื ื™ ื™ืฆืจืชื™ ืื•ืชื” ืฉื) ื•ืžื›ื ื™ืกื™ื ืืช ื›ืœ ืžื” ืฉืœืžื“ื ื•, ื›ืœื•ืžืจ: ip, mac, username.

def conn_mysql(query,fquery,macaddr,qwery2):
    connect = mysql.connector.connect(host='192.168.0.3', database='voip', user='voip_wr', password='***')
    cursor = connect.cursor()
    cursor.execute(fquery)
    state = cursor.fetchall()
    state = bool(state[0][0])
    if state == True:
        cursor.execute(qwery2)
        connect.commit()
        connect.close()
    else:
        cursor.execute(query)
        connect.commit()
        connect.close()

ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœืขืฆื•ืจ ื›ืืŸ, ื›ื™ ื›ื‘ืจ ื™ืฆืจื ื• ืคื ืงืก ื›ืชื•ื‘ื•ืช ื“ื™ื ืžื™, ืืชื” ื™ื›ื•ืœ ืœืฉืื•ืœ, ืื‘ืœ ื”ืœื›ืชื™ ืจื—ื•ืง ื™ื•ืชืจ ื•ื”ื•ืกืคืชื™ ื›ืืŸ ื”ืงืฆืื” ืื•ื˜ื•ืžื˜ื™ืช ืฉืœ ืžื›ืฉื™ืจื™ื.

ืœืฉื ื›ืš, ืžื•ืจื™ื“ื™ื ืชืฆื•ืจืช ืชื‘ื ื™ืช ืžืฉืจืช tftp ืžื•ื’ื“ืจ ืžืจืืฉ, ืฉืืœื™ื• ืื ื• ืžื‘ืฆืขื™ื ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื• ื•ืฉื•ืžืจื™ื ืื•ืชื” ื›-mac.cfg. ื›ืœื•ืžืจ, ืขื‘ื•ืจ Yealink ื™ืฉื ื ืฉื ื™ ืกื•ื’ื™ ืชืฆื•ืจื”, ื”ืื—ื“ ื”ื•ื ื’ืœื•ื‘ืœื™, ื•ื”ืฉื ื™ ื—ืœ ืขืœ ื˜ืœืคื•ืŸ ืกืคืฆื™ืคื™ ื•ืฆืจื™ืš ืœื”ื™ื•ืช ื‘ืฆื•ืจื” mac_phone.cfg

ืœืื—ืจ ื›ืœ ื”ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื‘ืฅ ื•ืฉืžื™ืจืชื• ื‘ื—ื–ืจื” ืœืฉืจืช tftp, ืื ื• ื ื•ืชื ื™ื ืืช ื”ืคืงื•ื“ื” ืœื˜ืœืคื•ืŸ ืœื”ืงืฆื•ืช ื•ืœืืชื—ืœ ืืช ื”ืžื›ืฉื™ืจ.

def tftp_file_change(config,place,adname,current_account,current_account_password):

    client = tftpy.TftpClient("192.168.0.3", 69)
    client.download('template.cfg', place)
    fileread = open(place, 'r')
    line = fileread.readlines()
    fileread.close()
    line[5] = (('account.1.label = ').encode('utf-8') + adname.encode('utf-8') + 'n')
    line[2] = (('account.1.auth_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[3] = (('account.1.display_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[6] = (('account.1.password = ').encode('utf-8') + current_account_password[0][0] + 'n')
    filewrite = open(place, 'w')
    for i in line:
      filewrite.write(i)
    filewrite.close()
    print place
    print config
    client.upload(config,place)

requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=AutoP')
requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=Reboot')

ืœืื—ืจ ืืชื—ื•ืœ ื”ืžื›ืฉื™ืจ, ื ืงื‘ืœ ืืช ื”ืฉื ื”ืžืœื ืฉืœื ื• ืขืœ ืžืกืš ื”ื˜ืœืคื•ืŸ + ืคื ืงืก ื›ืชื•ื‘ื•ืช ืžืžื•ืœื ืชืžื™ื“ ื‘ืฆื•ืจื” ืฉืœ ืžืกื“ ื ืชื•ื ื™ื, ื•ืื– ื›ืœ ืžื” ืฉื ื•ืชืจ ื”ื•ื ืœื”ื•ืกื™ืฃ XML ื•ืงืฆืช PHP ื›ื“ื™ ืœื”ืฆื™ื’ ื‘ืื•ืคืŸ ื“ื™ื ืžื™ ืืช ื”ืชื•ื›ืŸ. ื™ืฉ ื”ืจื‘ื” ื“ื•ื’ืžืื•ืช ื›ืืœื”, ืืคื™ืœื• ืœ-YEALINK ืขืฆืžื” ื™ืฉ ืื•ืชืŸ.

ื .ื‘.: ืœืงื‘ืœืช ืžื“ืจื’ื™ื•ืช ืจื‘ื” ื™ื•ืชืจ, ืืชื” ื™ื›ื•ืœ ืœื”ืขื‘ื™ืจ ืืช ื”ื”ื’ื“ืจื•ืช ื”ืจืืฉื™ื•ืช (ื”ืžืฉืชื ื™ื) ืœืงื•ื‘ืฅ ื ืคืจื“.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”