Yealink T19 + Buugga ciwaanka firfircoon ee otomaatiga ah

Markii aan u imid inaan u shaqeeyo shirkaddan, waxaan horey u haystay xoogaa xog ah oo ku saabsan aaladaha IP, dhowr server oo leh calaamado iyo balastar qaab FreeBPX ah. Intaa waxaa dheer, analooga PBX Samsung IDCS500 ayaa si barbar socda u shaqeeyay, guud ahaan, wuxuu ahaa nidaamka isgaarsiinta ugu weyn ee shirkadda; Telefoonka IP wuxuu u shaqeeyay kaliya waaxda iibka. Wax walbana sidaan oo kale ayay ku sii ahaan lahaayeen, laakiin maalin maalmaha ka mid ah ayaa waxaa la soo saaray wareegto qof walba loogu wareejinayo teleefanka IP-ga, waxaana la isku afgartay waqti kama dambays ah, waxaana la soo iibiyay qalab, waxaana la billaabay in la hirgeliyo qorshihii ganacsiga lagu wareejin lahaa qarniga 21-aad.
Waxa ugu horreeya ee bilaaba walwalka xaaladdan oo kale waa tirada xawliga ah ee tirada taleefannada ee u baahan in si uun loo maareeyo, tan labaad ee aadka u welwelka badnayd waxay ahayd buugga talefannada. Haddii Maamulaha Endpoint uu naga caawin karo kan ugu horreeya (kaas oo, jidka laga gooyay noocyadii ugu dambeeyay ee FreePBX), dabadeed su'aalaha qaarkood ayaa ka soo baxay buugga:

  • Marka hore, sida loo hubiyo saxnimadeeda marka goobta / dareeraha isticmaalayaashu ay si joogto ah isu bedelayaan?
  • Marka labaad, sida gebi ahaanba laga dhigo telefoonnada shakhsi ahaaneed. Oo ha buuxin magaca xiriirka mar kasta?

Dhibaatadu waxay ahayd mid xiiso leh, xalku ma qaadan waqti dheer in la yimaado. Hadda waxaan siin doonaa liiska buuxa, ka dibna waxaan u eegi doonaa sida ay u kala horreeyaan.

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

Barnaamijku wuxuu ku shaqeeyaa kombuyuutarka isticmaalaha wuxuuna ku shaqeeyaa waa haddii kombuyuutarku ku xiran yahay shabakadda telefoonka, maadaama Yealink T19 uusan u shaqeyn karin albaab ahaan.

Marka hore, waxaan u baahanahay inaan fahamno inay ku xiran tahay? iyo mac iyo ip talefankeenu leeyahay.

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

Halkan waxaan ku isticmaalnaa shaqada urin ee qaabka qashinka leh, iyada oo caawinteeda aan helno xirmo udp ah oo horay loo sii go'aamiyay, sug 70 ilbiriqsi iyo haddii aynaan waxba qaban, waan ka baxnaa.

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

Marka xigta, waxaan hubineynaa in qalabku runtii yahay Yealink oo aan soo celinno qiyamka lagama maarmaanka ah (ip iyo mac).

Isticmaalka codsi gaar ah, waxaan ku ogaanay xisaabta hadda ee telefoonka. Si tan loo sameeyo, qaabka hadda jira ayaa laga soo dejisan karaa taleefanka oo la kala saarayaa.

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

Soo ogow erayga sirta ah ee akoonkan Si tan loo sameeyo, waxaan u leexanaynaa miiska asterisk.sip iyo goobta xogta ku jirta.

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

Hagaag, marxaladda ugu dambeysa waxaan ku xireynaa ldap AD anagoo adeegsanayna sAMAccountName oo laga helay shaqada getpass.getuser() Qaado cn ee isticmaalaha hadda (oo inta badan ka kooban magaca isticmaalaha oo buuxa).

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

Waxaan ku xireynaa miis horay loo sameeyay oo ku jira keydka xogta (halkaas ayaan ku abuuray) oo geli wax kasta oo aan baranay, kuwaas oo kala ah: 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()

Waxaan ku joojin karnaa halkan, sababtoo ah waxaan horeyba u abuurnay buug ciwaanka firfircoon, waxaad waydiin kartaa, laakiin waan sii dheeraaday oo waxaan ku daray si toos ah qalabka halkan.

Si tan loo sameeyo, qaabeynta template ayaa laga soo dejiyey tftp server horay loo habeeyay, kaas oo aan ku samaynayno isbeddeladayada oo aan u xafidno mac.cfg ahaan. Taasi waa, Yealink waxaa jira laba nooc oo qaabeyn ah, mid waa caalami, kan labaadna wuxuu quseeyaa taleefan gaar ah waana inuu noqdaa foomka mac_phone.cfg

Ka dib dhammaan isbeddellada ku jira faylka oo dib loogu keydiyo tftp server-ka, waxaan ku siineynaa amarka taleefanka si uu u bixiyo oo dib u bilaabo qalabka.

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

Ka dib dib-u-kicinta aaladda, waxaan helnaa magacayaga oo buuxa shaashadda taleefanka + buug had iyo jeer si sax ah loo buuxiyey oo ah qaab database, ka dib waxa hadhay oo dhan waa in lagu daro XML iyo PHP yar si ay si firfircoon u muujiyaan waxa ku jira. Waxaa jira tusaalooyin badan oo noocaas ah, xitaa YEALINK lafteeda ayaa leh.

PS: Si aad u miisaan weyn u yeelato, waxaad u wareejin kartaa goobaha muhiimka ah (kala duwanaanshaha) fayl gaar ah.

Source: www.habr.com

Add a comment