Ukunikezwa okuzenzakalelayo kwe-Yealink T19 + ibhuku lamakheli ashukumisayo

Lapho ngifika ngizosebenzela le nkampani, ngase nginedathabhethi ethile yamadivayisi we-IP, amaseva amaningana anenkanyezi kanye nesiqephu esisesimweni se-FreeBPX. Ngaphezu kwalokho, i-analogue PBX Samsung IDCS500 yasebenza ngokufana futhi, ngokuvamile, kwakuyisistimu yokuxhumana eyinhloko enkampanini; I-IP telephony yayisebenzela umnyango wokuthengisa kuphela. Futhi yonke into yayizoqhubeka nokupheka kanje, kodwa ngolunye usuku oluhle kwakhishwa isimemezelo sokudlulisela wonke umuntu ku-IP telephony, kwavunyelwana ngezinsuku zokugcina, imishini yathengwa, futhi uhlelo lokudlulisela ibhizinisi ekhulwini lama-21 laqala ukusetshenziswa.
Into yokuqala eqala ukukhathazeka esimweni esinjalo inani elikhula ngokushesha lamasethi ezingcingo adinga ukulawulwa ngandlela thile, into yesibili eyayikhathaza kakhulu kwakuyincwadi yocingo. Uma uMphathi we-Endpoint engasisiza ngeyokuqala (okuthe, ngendlela, yasikwa ezinguqulweni zakamuva ze-FreePBX), bese kuqubuka imibuzo ethile nencwadi:

  • Okokuqala, ungaqinisekisa kanjani ukunemba kwayo lapho indawo/uketshezi lwabasebenzisi kushintsha njalo?
  • Okwesibili, indlela yokwenza amafoni ahluke ngokuphelele. Futhi ungagcwalisi igama loxhumana naye njalo?

Inkinga yayithakazelisa, isixazululo asithathanga isikhathi eside ukufika. Manje ngizokunikeza uhlu olugcwele, futhi sizobe sesilubheka ngokulandelana.

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')

Uhlelo lusebenza kukhompyutha yomsebenzisi futhi lusebenza ngaphandle kokuthi ikhompuyutha ixhunywe kunethiwekhi ngefoni, njengoba i-Yealink T19 ayikwazi ukusebenza njengesango.

Okokuqala, sidinga ukuqonda ukuthi ixhunyiwe yini? futhi iyiphi i-mac ne-ip ifoni yethu enayo.

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

Lapha sisebenzisa umsebenzi wokuhogela kusukela kuhlaka lwe-scapy, ngosizo lwayo sithola iphakethe le-udp elinqunywe kusengaphambili, silinde imizuzwana engu-70 futhi uma singabambi lutho, siyaphuma.

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

Okulandelayo, siqinisekisa ukuthi idivayisi iyi-Yealink ngempela futhi sibuyisela amanani adingekayo (ip ne-mac).

Ngokusebenzisa isicelo esikhethekile, sithola i-akhawunti yamanje ocingweni. Ukwenza lokhu, ukucushwa kwamanje kulandwa ocingweni futhi kucazululwe.

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

Thola iphasiwedi yale akhawunti. Ukuze senze lokhu, siphendukela kuthebula le-asterisk.sip kanye nenkambu yedatha kuyo.

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

Nokho, esigabeni sokugcina sixhuma ku-ldap AD futhi sisebenzisa i-sAMAccountName etholwe ngomsebenzi getpass.getuser() thatha i-cn yomsebenzisi wamanje (okuvame ukuqukatha igama eliphelele lomsebenzisi).

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

Sixhuma kuthebula elakhiwe ngaphambilini ku-database (ngiyidale lapho) bese sifaka konke esikufundile, okungukuthi: ip, mac, igama lomsebenzisi.

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()

Singama lapha, ngoba sesivele sidale ibhuku lamakheli eliguqukayo, ungase ubuze, kodwa ngiqhubekele phambili futhi ngengeza ukunikezwa okuzenzakalelayo kwamadivayisi lapha.

Ukwenza lokhu, ukucushwa kwesifanekiso kuyalandwa kuseva ye-tftp emiswe ngaphambili, lapho senza khona izinguquko zethu futhi siyilondoloze njenge-mac.cfg. Okusho ukuthi, ku-Yealink kunezinhlobo ezimbili zokucushwa, eyodwa ingeyomhlaba wonke, kanti eyesibili isebenza ocingweni oluthile futhi kufanele ibe yefomu mac_phone.cfg.

Ngemuva kwazo zonke izinguquko efayeleni nokuyigcina ibuyele kuseva ye-tftp, sinikeza umyalo ocingweni ukuthi uhlinzeke futhi uqalise kabusha idivayisi.

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')

Ngemva kokuqalisa kabusha idivayisi, sithola igama lethu eliphelele esikrinini socingo + ibhuku lamakheli elihlale ligcwaliswe kahle ngendlela yesizindalwazi, okusele nje ukwengeza i-XML ne-PHP encane ukuze kuboniswe okuqukethwe ngamandla. Kunezibonelo eziningi ezinjalo, ngisho no-YEALINK uqobo unazo.

I-PS: Ukuze uthole ukulinganisa okukhulu, ungahambisa izilungiselelo eziyinhloko (iziguquguquko) efayeleni elihlukile.

Source: www.habr.com

Engeza amazwana