apt-sec.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  1. #!/usr/bin/python3
  2. ## Based on the perl code of Trustminer by CASED
  3. ## Nikos
  4. import sys
  5. import os
  6. from pymongo import MongoClient
  7. #mongodb assumes database at default path
  8. import logging, sys
  9. import configparser
  10. import json
  11. import csv
  12. import urllib.request
  13. import datetime
  14. import debian_advisory as da
  15. import timeseries as ts
  16. import cveparse as cv
  17. import matplotlib.pyplot as plt
  18. import numpy as np
  19. from dateutil import parser
  20. import plotly.plotly as py
  21. import plotly.graph_objs as go
  22. import machine_learning as ml
  23. import lstm_reg as lstm
  24. import metadata as meta
  25. import deps
  26. import psycopg2
  27. logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
  28. ## Increase the recursion limit by much to allow bs to parse large files
  29. ## This is not good practise
  30. sys.setrecursionlimit(6000)
  31. #load config file as library
  32. config = configparser.ConfigParser()
  33. config.read('config_test')
  34. if config.sections == []:
  35. print('configuration file not found\n')
  36. sys.exit(1)
  37. #global variables
  38. secperday = 60*60*24
  39. now = datetime.datetime.now()
  40. verbosity = 1
  41. ###############################################################################
  42. ## logging
  43. # 1 fatal errors
  44. # 2 errors
  45. # 3 note
  46. # 4 trace
  47. # 5 debug
  48. def msg(lvl,msg):
  49. if lvl <= int(config['LOG']['loglevel']):
  50. print(msg)
  51. def debug(msg):
  52. msg(5, msg)
  53. # Need to see if this is necessary
  54. ## load state, different from DBs in that we always need it
  55. def load_state():
  56. cache = config['DIR']['cache_dir'] + 'state'
  57. err = 0
  58. state = dict()
  59. try:
  60. with open(cache) as json_data:
  61. state = json.load(json_data)
  62. except FileNotFoundError:
  63. # Load default state - start from the beginning
  64. state['cache_dir'] = cache
  65. state['next_adv'] = 0
  66. state['next_fsa'] = 0
  67. state['Packages'] = ''
  68. state['Sources'] = ''
  69. state['Sha1Sums'] = ''
  70. err += 1
  71. return (state, err)
  72. ###############################################################################
  73. ## save state, different from DBs in that we always need it
  74. def save_state(state):
  75. cache = config['DIR']['cache_dir'] + 'state'
  76. try:
  77. with open(cache, 'w') as fp:
  78. json.dump(state, fp)
  79. except IOError:
  80. print('write cache state failed!! Fatal error')
  81. sys.exit(1)
  82. ###############################################################################
  83. ## load sha lists :TODO later
  84. def load_sha1lists():
  85. cache = config['DIR']['cache_dir'] + 'state'
  86. ###############################################################################
  87. ## save sha lists :TODO later
  88. def save_sha1lists():
  89. pass
  90. ###############################################################################
  91. ## load from files
  92. def load_DBs():
  93. dsatable = dict()
  94. src2dsa = dict()
  95. dsa2cve = dict()
  96. cvetable = dict()
  97. src2month = dict()
  98. src2sloccount = dict()
  99. src2pop = dict()
  100. src2deps = dict()
  101. cache = config['DIR']['cache_dir']
  102. cache_dsatable = cache + 'dsatable'
  103. try:
  104. with open(cache_dsatable) as fp:
  105. dsatable = json.load(fp)
  106. except (IOError, ValueError):
  107. print('read cache dsatable failed!! Maybe first run of the system?')
  108. cache_src2dsa = cache + 'src2dsa'
  109. try:
  110. with open(cache_src2dsa) as fp:
  111. src2dsa = json.load(fp)
  112. except (IOError, ValueError):
  113. print('read cache src2dsa failed!! Maybe first run of the system?')
  114. cache_dsa2cve = cache + 'dsa2cve'
  115. try:
  116. with open(cache_dsa2cve) as fp:
  117. dsa2cve = json.load(fp)
  118. except (IOError, ValueError):
  119. print('read cache dsa2cve failed!! Maybe first run of the system?')
  120. cache_cvetable = cache + 'cvetable'
  121. try:
  122. with open(cache_cvetable) as fp:
  123. cvetable = json.load(fp)
  124. except (IOError, ValueError):
  125. print('read cache cvetable failed!! Maybe first run of the system?')
  126. cache_src2deps = cache + 'src2deps'
  127. try:
  128. with open(cache_src2deps) as fp:
  129. src2deps = json.load(fp)
  130. except (IOError, ValueError):
  131. print('read cache src2deps failed!! Maybe first run of the system?')
  132. cache_src2month = cache + 'src2month'
  133. try:
  134. with open(cache_src2month) as fp:
  135. src2month = json.load(fp)
  136. except (IOError, ValueError):
  137. print('read cache src2month failed!! Maybe first run of the system?')
  138. cache_src2sloccount = cache + 'src2sloccount'
  139. try:
  140. with open(cache_src2sloccount) as fp:
  141. src2sloccount = json.load(fp)
  142. except (IOError, ValueError):
  143. print('read cache src2sloccount failed!! Maybe first run of the system?')
  144. cache_src2pop = cache + 'src2pop'
  145. try:
  146. with open(cache_src2pop) as fp:
  147. src2pop = json.load(fp)
  148. except (IOError, ValueError):
  149. print('read cache src2pop failed!! Maybe first run of the system?')
  150. return(dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps)
  151. ###############################################################################
  152. ## help for save_DBs
  153. def myconverter(o):
  154. if isinstance(o, datetime.datetime) or isinstance(o, datetime.timedelta):
  155. return str(o)
  156. if isinstance(o, np.float):
  157. return o.astype(int)
  158. ###############################################################################
  159. ## save to files
  160. def save_DBs(dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps):
  161. cache = config['DIR']['cache_dir']
  162. cache_dsatable = cache + 'dsatable'
  163. try:
  164. with open(cache_dsatable, 'w') as fp:
  165. json.dump(dsatable, fp, default = myconverter)
  166. except IOError:
  167. print('write cache dsatable failed!! Fatal error')
  168. sys.exit(1)
  169. cache_src2dsa = cache + 'src2dsa'
  170. try:
  171. with open(cache_src2dsa, 'w') as fp:
  172. json.dump(src2dsa, fp)
  173. except IOError:
  174. print('write cache src2dsa failed!! Fatal error')
  175. sys.exit(1)
  176. cache_dsa2cve = cache + 'dsa2cve'
  177. try:
  178. with open(cache_dsa2cve, 'w') as fp:
  179. json.dump(dsa2cve, fp)
  180. except IOError:
  181. print('write cache dsa2cve failed!! Fatal error')
  182. sys.exit(1)
  183. cache_cvetable = cache + 'cvetable'
  184. try:
  185. with open(cache_cvetable, 'w') as fp:
  186. json.dump(cvetable, fp, default = myconverter)
  187. except IOError:
  188. print('write cache cvetable failed!! Fatal error')
  189. sys.exit(1)
  190. cache_src2sloccount = cache + 'src2sloccount'
  191. try:
  192. with open(cache_src2sloccount, 'w') as fp:
  193. json.dump(src2sloccount, fp, default = myconverter)
  194. except IOError:
  195. print('write cache src2sloccount failed!! Fatal error')
  196. sys.exit(1)
  197. cache_src2pop = cache + 'src2pop'
  198. try:
  199. with open(cache_src2pop, 'w') as fp:
  200. json.dump(src2pop, fp, default = myconverter)
  201. except IOError:
  202. print('write cache src2pop failed!! Fatal error')
  203. sys.exit(1)
  204. cache_src2deps = cache + 'src2deps'
  205. try:
  206. with open(cache_src2deps, 'w') as fp:
  207. json.dump(src2deps, fp, default = myconverter)
  208. except IOError:
  209. print('write cache src2deps failed!! Fatal error')
  210. sys.exit(1)
  211. cache_src2month = cache + 'src2month'
  212. int_list = dict()
  213. for element in src2month:
  214. for i in range(len(src2month[element])):
  215. if element in int_list:
  216. int_list[element].append(int(src2month[element][i]))
  217. else:
  218. int_list[element] = []
  219. int_list[element].append(int(src2month[element][i]))
  220. try:
  221. with open(cache_src2month, 'w') as fp:
  222. json.dump(int_list, fp, default = myconverter)
  223. except IOError:
  224. print('write cache src2month failed!! Fatal error')
  225. sys.exit(1)
  226. ###############################################################################
  227. ## Fetch current Packages, Sources and sha1sums files
  228. ## These are needed to find CVE stats by sha1sums/pkg-names
  229. ## Only Sha1Sums is custom generated, others are from Debian.
  230. ## FIXME: Server might do on-the-fly gzip (but should not for bzip2)
  231. ## Return: 1 on success, to signal that new parsing is needed.
  232. def fetchMeta(filename):
  233. urlbase = config['URL']['pkg_base_url']
  234. mydir = config['DIR']['cache_dir']
  235. bzFile = filename + '.bz2'
  236. url = urlbase + bzFile
  237. logging.info('Checking meta file from ' + url + '\n')
  238. # Download file
  239. urllib.request.urlretrieve(url, mydir + bzfile)
  240. # TODO catch exceptions like file not found
  241. # TODO check if file has changed, if it is new unpack
  242. ###############################################################################
  243. # Sources and Packages are not completely consistent, esp for debian-multimedia
  244. # He we store manual mappings for these..
  245. def addOrphanPkgs(pkg2src):
  246. pkg2src['liblame-dev'] = "lame";
  247. pkg2src['lame-extras'] = "lame";
  248. pkg2src['moonlight'] = "moon";
  249. pkg2src['libmoon0'] = "moon";
  250. pkg2src['xmms-mp4'] = "xmms2";
  251. pkg2src['xmms-mp4'] = "xmms2";
  252. pkg2src['lazarus-src-0.9.30'] = "lazarus";
  253. pkg2src['lazarus-ide-0.9.30'] = "lazarus";
  254. pkg2src['lcl-qt4-0.9.30'] = "lazarus";
  255. pkg2src['lazarus-ide-qt4-0.9.30'] = "lazarus";
  256. pkg2src['lcl-gtk2-0.9.30'] = "lazarus";
  257. pkg2src['lazarus-ide-gtk2-0.9.30'] = "lazarus";
  258. pkg2src['lcl-units-0.9.30'] = "lazarus";
  259. pkg2src['lazarus-0.9.30'] = "lazarus";
  260. pkg2src['lazarus-doc-0.9.30'] = "lazarus";
  261. pkg2src['lcl-0.9.30'] = "lazarus";
  262. pkg2src['lcl-utils-0.9.30'] = "lazarus";
  263. pkg2src['lcl-nogui-0.9.30'] = "lazarus";
  264. pkg2src['libx264-65'] = "x264";
  265. pkg2src['libx264-114'] = "x264";
  266. pkg2src['libx264-60'] = "x264";
  267. # pkg2src['libmlt3']
  268. # pkg2src['libgmerlin-avdec0']
  269. # pkg2src['libxul-dev']
  270. # pkg2src['libmyth-0.23.1-0']
  271. # pkg2src['libmpeg3hv']
  272. # pkg2src['libquicktimehv']
  273. # pkg2src['libxul0d']
  274. # pkg2src['acroread-fonts-kor']
  275. ###############################################################################
  276. ## Parse dpkg Packages file, create map deb-name->pkg-name
  277. def parsePackages(pkgfile):
  278. mydir = cache = config['DIR']['cache_dir']
  279. deb2pkg = dict()
  280. pkg2virt = dict()
  281. virt2pkg = ()
  282. logging.info('Parsing Packages file...\n')
  283. pkgfile = mydir + pkgfile
  284. #TODO open and parse pkg file
  285. ###############################################################################
  286. ## Parse dpkg Sources file, create map pkg-name->src-name
  287. def parseSources(srcfile):
  288. mydir = cache = config['DIR']['cache_dir']
  289. checklinecont = 0
  290. pkg2src = dict()
  291. logging.info('Parsing Sources file...\n')
  292. srcfile = mydir + srcfile
  293. #TODO open and parse sources file
  294. ###############################################################################
  295. def getSHA1(myhash, collection):
  296. return collection.find({"hash": myhash})
  297. ###############################################################################
  298. def addSHA1(myhash, deb, src):
  299. dic = getSHA1(myhash)
  300. thash = dic["hash"]
  301. tdeb = dic["deb"]
  302. tsrc = dic["src"]
  303. #TODO insert SHA to database
  304. ###############################################################################
  305. ## Parse Sha1Sums file. Format: "sha1sum::deb-name::unix-file-path"
  306. ## Create 2 maps: sha1sum->file, file->deb-name
  307. def parseSha1Sums(sha1file):
  308. pass
  309. ###############################################################################
  310. ## Parse local dpkg status, return list of debs
  311. def parseStatus(stsfile):
  312. pass
  313. ###############################################################################
  314. ## Parse Advisory (only Debian supported atm
  315. def parseAdvisory(adv):
  316. if state['vendor'] == 'debian':
  317. return da.parseDSAhtml(adv)
  318. else:
  319. print('Unsupported distribution. We only support Debian at the moment')
  320. system.exit(1)
  321. ###############################################################################
  322. ## Manually fix problems with Advisory entries
  323. def fixAdvisoryQuirks(arg, state, dsastats):
  324. if state['vendor'] == 'debian':
  325. return da.fixDSAquirks(arg, dsastats)
  326. else:
  327. print('Unsupported distribution. We only support Debian at the moment')
  328. system.exit(1)
  329. ###############################################################################
  330. ## Extract CVE ids from new advisories and print URL for mirror script
  331. def printCVEs(myid,adv, state):
  332. logging.info('Looking for CVEs in advisory...\n')
  333. dsastats = parseAdvisory(adv)
  334. if dsastats == []:
  335. return
  336. ## fix DSAs that don't contain correct CVE refs
  337. dsastats = fixAdvisoryQuirks(myid, state, dsastats);
  338. #TODO Fix this part
  339. ##for cve_id in dsastats
  340. ###############################################################################
  341. ## Update internal vuln. DB with new Advisory info
  342. ## Creates CVEtable for MTBF computation:
  343. ## ( cve-id => (date, delay, score1, score2, score3))
  344. def updateCVETables(myid, dsatable, state, src2dsa, dsa2cve, cvetable, client):
  345. logging.info('Updating vulnerability database with advisory ' + state['vendor'] + str(myid) + ' \n')
  346. adv = dsatable[myid]
  347. dsastats = parseAdvisory(adv)
  348. if dsastats == []:
  349. return
  350. dsastats = fixAdvisoryQuirks(myid, state, dsastats)
  351. for srcpkg in dsastats[0]:
  352. if srcpkg in src2dsa:
  353. src2dsa[srcpkg].append(myid)
  354. else:
  355. src2dsa[srcpkg] = []
  356. src2dsa[srcpkg].append(myid)
  357. dsa2cve[str(myid)] = dsastats[2]
  358. for cve_id in dsastats[2]:
  359. # No fetch CVE We use mongodb and cve-search
  360. cve = cv.fetchCVE(cve_id, client)
  361. cvestats = cv.parseCVE(cve_id, cve)
  362. # print(cvestats)
  363. # print(dsastats)
  364. finaldate = cvestats[0]
  365. if cvestats[0] > dsastats[1] or cvestats[0] == 0:
  366. finaldate = dsastats[1]
  367. cvedata = (finaldate, dsastats[1]-finaldate, cvestats[1], cvestats[2], cvestats[3])
  368. ## print(cvedata)
  369. cvetable[cve_id] = cvedata
  370. return cvetable
  371. ###############################################################################
  372. ## Check for updates on Package information
  373. def aptsec_update(state, config, dsatable, client, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss):
  374. args = sys.argv
  375. # if not('--offline' in args):
  376. # fetchMeta('Packages')
  377. # fetchMeta('Sources')
  378. # fetchMeta('Sha1Sums')
  379. now = datetime.datetime.now()
  380. if not('--cves' in args):
  381. parsePackages('Packages')
  382. parseSources('Sources')
  383. # if not('--nosha1' in args):
  384. # parseSha1sums('Sha1Sums')
  385. if state['vendor'] == 'debian':
  386. newAdv = da.checkDSAs(state, config)
  387. else:
  388. print('Unsupported distribution. We only support Debian at the moment')
  389. system.exit(1)
  390. for myid in newAdv:
  391. if myid in dsatable:
  392. logging.info(state['vendor'] + ' advisory ' + myid + ' already known.\n')
  393. elif '--cves' in args:
  394. ## scan for CVE urls only?
  395. printCVEs(myid, newAdv[myid])
  396. else:
  397. ## store advisory and parse it
  398. dsatable[myid] = newAdv[myid]
  399. updateCVETables(myid, dsatable, state, src2dsa, dsa2cve, cvetable, client)
  400. # recompute all pkg statistics
  401. for srcpkg in src2dsa:
  402. processCVEs(srcpkg, now, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss, config)
  403. return 0
  404. ###############################################################################
  405. ## find list of src pkgs from bin pkgs based on pkg2src
  406. def resolvePkg2Src(pkglist, pkg2src):
  407. srclist = []
  408. for pkg in pkglist:
  409. if pkg in pkg2src:
  410. srcpkg = pkg2src[pkg]
  411. srclist.append(srcpkg)
  412. else:
  413. logging.info('Could not find source package for: ' + pkg + ' .\n')
  414. return srclist
  415. ###############################################################################
  416. ## compute and store MTBF, MTBR and Scores of each src pkg
  417. ## output: %src2mtbf:
  418. ## (srcpkg=> ())
  419. def processCVEs(pkg, now, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss, config):
  420. stats = [now, 0, 0, 0, 0, 0, 0]
  421. mylambda = config['TRUST']['lambda']
  422. cvestats = dict()
  423. logging.info('Processing package: ' + pkg + '.\n')
  424. ## keep track of the number of low-medium-high severity vulnerabilities
  425. ## TODO see how cvss affects vulnerability prediction - if some packages show patterns
  426. temp_cvss = 0.0
  427. with_cvss = dict()
  428. ## cvestats = (date: number)
  429. for dsa_id in src2dsa[pkg]:
  430. for cve_id in dsa2cve[str(dsa_id)]:
  431. tt = cvetable[cve_id][0]
  432. if tt in cvestats:
  433. cvestats[tt] += 1
  434. else:
  435. cvestats[tt] = 1
  436. stats[1] += 1
  437. ## with_cvss = (date: number low, number med, number high)
  438. for dsa_id in src2dsa[pkg]:
  439. for cve_id in dsa2cve[str(dsa_id)]:
  440. tt = cvetable[cve_id][0]
  441. temp_cvss = float(cvetable[cve_id][2])
  442. if tt in with_cvss:
  443. if (temp_cvss<4.0):
  444. with_cvss[tt][0] += 1
  445. elif (temp_cvss<7.0):
  446. with_cvss[tt][1] += 1
  447. else:
  448. with_cvss[tt][2] += 1
  449. else:
  450. with_cvss[tt] = [0, 0, 0]
  451. if (temp_cvss<4.0):
  452. with_cvss[tt][0] += 1
  453. elif (temp_cvss<7.0):
  454. with_cvss[tt][1] += 1
  455. else:
  456. with_cvss[tt][2] += 1
  457. # Ignore pkgs with less than one incident, should not happen..
  458. if stats[1] < 1:
  459. return
  460. prev_date = 0
  461. weight = 0
  462. dates = sorted(cvestats, key = cvestats.get)
  463. stats[0] = dates[0]
  464. count = sum(cvestats.values())
  465. print(pkg + ' ' + str(count))
  466. # pkg_with_cvss[pkg] = with_cvss
  467. format_data(pkg, with_cvss, pkg_with_cvss, True)
  468. format_data(pkg, cvestats, src2month, False)
  469. ###############################################################################
  470. ## format vulnerability data into monthly intervals, suitable for tensorflow
  471. def format_data(pkg, cvestats, src2month, cvss):
  472. x = []
  473. y = []
  474. monthyear = []
  475. year = []
  476. temp_items=list(cvestats.items())
  477. items = []
  478. for data_dict in temp_items:
  479. if isinstance(data_dict[0], str):
  480. tmpx = (parser.parse(data_dict[0]))
  481. else:
  482. tmpx = data_dict[0]
  483. x.append(tmpx)
  484. try:
  485. tmpy = int(data_dict[1])
  486. except TypeError:
  487. tmpy = data_dict[1]
  488. y.append(tmpy)
  489. items.append((tmpx, tmpy))
  490. items.sort(key=lambda tup: tup[0])
  491. for i in range(2000, 2018):
  492. temp = []
  493. for j in range(12):
  494. if cvss:
  495. temp.append([0, 0, 0])
  496. else:
  497. temp.append(0)
  498. monthyear.append(temp)
  499. for i in range(len(x)):
  500. if cvss:
  501. tmp0 = y[i][0]
  502. tmp1 = y[i][1]
  503. tmp2 = y[i][2]
  504. monthyear[x[i].year-2000][x[i].month-1][0] += tmp0
  505. monthyear[x[i].year-2000][x[i].month-1][1] += tmp1
  506. monthyear[x[i].year-2000][x[i].month-1][2] += tmp2
  507. else:
  508. monthyear[x[i].year-2000][x[i].month-1] += y[i]
  509. months_list = [item for sublist in monthyear for item in sublist]
  510. if not cvss:
  511. temp_months = np.zeros(len(months_list))
  512. i = 0
  513. for element in months_list:
  514. temp_months[i] = np.float32(element)
  515. i += 1
  516. src2month[pkg] = temp_months
  517. else:
  518. src2month[pkg] = months_list
  519. return
  520. ###############################################################################
  521. ## plot vulnerability time distribution for a single package
  522. def pkg_plot(pkg, cvestats):
  523. colors = list("rgbcmyk")
  524. items = list(cvestats.items())
  525. #print(items)
  526. items.sort(key=lambda tup: tup[0])
  527. x = []
  528. y = []
  529. for data_dict in items:
  530. x.append(parser.parse(data_dict[0]))
  531. y.append(data_dict[1])
  532. monthyear = []
  533. year = []
  534. # initialize list
  535. for i in range(2000,2017):
  536. temp = []
  537. for j in range(12):
  538. temp.append(0)
  539. monthyear.append(temp)
  540. for i in range(len(x)):
  541. # print(str(x[i].year) + str(x[i].month))
  542. monthyear[x[i].year-2000][x[i].month-1] += y[i]
  543. newx = []
  544. yearsx = []
  545. year = []
  546. monthlabel = []
  547. month = []
  548. m1 = 0
  549. m2 = 0
  550. k = 0
  551. label_months = []
  552. months_list = [item for sublist in monthyear for item in sublist]
  553. for i in range(len(months_list)):
  554. label_months.append(i)
  555. plt.bar(label_months, months_list)
  556. for i in range(len(monthyear)):
  557. year.append(0)
  558. cc = 0
  559. for j in range(len(monthyear[i])):
  560. cc += monthyear[i][j]
  561. if j == 5:
  562. m1 = cc
  563. month.append(m1)
  564. if j == 11:
  565. month.append(cc - m1)
  566. k += 1
  567. year[i] = cc
  568. for i in range(len(year)):
  569. yearsx.append(i + 2000)
  570. k = 2000
  571. datapoints = []
  572. for i in range(len(month)):
  573. datapoints.append(i+1)
  574. if i%2 == 0:
  575. monthlabel.append(str(k) + '-1')
  576. else:
  577. monthlabel.append('-2')
  578. k += 1
  579. # plt.xticks(datapoints, monthlabel)
  580. # print(year)
  581. # plt.plot.hist(yearsx,year)
  582. # plt.bar(yearsx, year, 1, color='blue')
  583. # plt.bar(datapoints, month, 1, color='blue')
  584. # ts.predict(month)
  585. plt.legend([pkg], loc='upper left')
  586. plt.show()
  587. return 0
  588. ###############################################################################
  589. ## populate src2sloccount dictionary with number of source lines of code in
  590. ## format (total, [ansic, cpp, asm, java, python, perl, sh])
  591. def getslocs(src2dsa, src2sloccount):
  592. try:
  593. conn = psycopg2.connect("dbname = 'debsources' user = 'postgres' host = 'localhost' password = 'nik'")
  594. except:
  595. print('I am unable to connect to the database')
  596. cur = conn.cursor()
  597. for pkg in src2dsa:
  598. if pkg not in src2sloccount:
  599. print(pkg)
  600. src2sloccount[pkg] = meta.getsloccount(cur, pkg)
  601. return
  602. ###############################################################################
  603. ## get popularity contest data in format src_pkg -> (installed, vote, old, recent)
  604. def getpop(src2dsa, src2pop):
  605. with open('Debian_pop.csv', newline = '') as csvfile:
  606. reader = csv.reader(csvfile, delimiter = ',', quotechar = '|')
  607. for row in reader:
  608. try:
  609. if row[1] in src2dsa and not (row[1] in src2pop):
  610. src2pop[row[1]] = row[2:6]
  611. except IndexError:
  612. print(row)
  613. continue
  614. return
  615. ###############################################################################
  616. ## get dependencies of a given source
  617. def getdeps(src2dsa, src2deps):
  618. for srcpkg in src2dsa:
  619. deps.getdeps(srcpkg, src2deps)
  620. ###############################################################################
  621. ## print some meta-info on internal data
  622. def aptsec_about(dsatable, cvetable, pkg2src, src2dsa):
  623. num_dsa = len(dsatable)
  624. num_cve = len(cvetable)
  625. num_pkg = len(pkg2src)
  626. num_src = len(src2dsa)
  627. print('\nThe current database records %d binary packages and %d DSAs.\n', num_pkg, num_src)
  628. print('%d CVEs are associated with %d source packages.\n', num_cve, num_src)
  629. return
  630. ###############################################################################
  631. ## use scores to suggest alternative packages
  632. def aptsec_alternatives(pkg):
  633. pass
  634. ###############################################################################
  635. ## print overview for pkg high scores
  636. def aptsec_hitlist():
  637. pass
  638. ###############################################################################
  639. ## evaluation helper
  640. ## compute stats until date given in $2, then compute stats
  641. ## for the next year to check accuracy of the prediction.
  642. ## @cvestats = (date base-score impact-score exploit-score)
  643. def simulate_stats(pkg, year):
  644. pass
  645. ###############################################################################
  646. ##TODO Printing functions
  647. ###############################################################################
  648. ## show info on a single src pkg, resolv to src if needed
  649. def aptsec_show(pkg, state, pkg2src, src2dsa, src2mtbf, cvetable):
  650. if state['vendor'] == 'debian':
  651. ADV = 'DSA-'
  652. else:
  653. print('Unsupported distribution. We only support Debian at the moment')
  654. system.exit(1)
  655. if (not(pkg in src2dsa)) and (pkg in pkg2src):
  656. print('\nResolving ' + pkg + ' to ' + pkg2src[pkg] + '\n')
  657. pkg = pkg2src[pkg]
  658. print('\nThe following binary packages are created from ' + pkg + ' :\n\n')
  659. lines = 0
  660. for i in pkg2src:
  661. if pkg2src[i] == pkg:
  662. print(i + '\n')
  663. lines += 1
  664. if lines < 1:
  665. print('-\n')
  666. if not (pkg in src2dsa and pkg in src2mtbf):
  667. print('\nNo vulnerabilities recorded for source package ' + pkg + '.\n')
  668. return
  669. print('\nAdvisories on package ' + pkg + ':\n\n')
  670. for dsa_id in sorted(src2dsa[pkg], key = src2dsa[pkg].get):
  671. print(ADV + dsa_id + '\n')
  672. for cve_id in dsa2cve[dsa_id]:
  673. (sec, minut, hrs, day, mon, yr) = gmtime(cvetable[cve_id][0])
  674. print('%s: Base Score: %04.1f, %02d.%02d.%04d\n', cve_id, cvetable[cve_id][2], day, mon+1, yr+1900)
  675. stats = src2mtbf[pkg]
  676. (sec, minut, hrs, day, mon, yr) = gmtime(stats[0])
  677. print('Now we print various iformation \n')
  678. ###############################################################################
  679. ## print help text
  680. def aptsec_help():
  681. print('See manual for correct usage\n')
  682. ###############################################################################
  683. ## Print system status report from component(files) measurements (sha1sums)
  684. ## Expected input format is Linux IMA. We assume input was validated.
  685. ##
  686. ## Note: aptsec_status(), considers *reportedly installed* packages, while this
  687. ## one looks at *actually loaded* software that influenced the CPU since bootup.
  688. def aptsec_attest(sha1file):
  689. pass
  690. ## Main Program starts here!!
  691. try:
  692. action = sys.argv[1]
  693. except IndexError:
  694. # print('No argument given')
  695. # aptsec_help()
  696. # sys.exit(0)
  697. action = ''
  698. client = MongoClient()
  699. dsatable = dict()
  700. cve_db = client.cvedb
  701. src2dsa = dict()
  702. dsa2cve = dict()
  703. cvetable = dict()
  704. src2month = dict()
  705. src2deps = dict()
  706. pkg_with_cvss = dict()
  707. src2sloccount = dict()
  708. src2pop = dict()
  709. (state, err) = load_state()
  710. state['vendor'] = 'debian'
  711. #detect_distribution()
  712. #d = state['cache_dir']
  713. #if not os.path.exists(d):
  714. # os.makedirs(d)
  715. if action == 'update':
  716. (dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps) = load_DBs()
  717. # loadsha1lists()
  718. # aptsec_update(state,config, dsatable, client, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss)
  719. # save_sha1lists()
  720. # getslocs(src2dsa, src2sloccount)
  721. # getpop(src2dsa, src2pop)
  722. # getdeps(src2dsa, src2deps)
  723. save_DBs(dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps)
  724. save_state(state)
  725. lstm.predict(src2month)
  726. # print(pkg_with_cvss['linux'])
  727. low = []
  728. med = []
  729. high = []
  730. for item in pkg_with_cvss['firefox']:
  731. low.append(item[0])
  732. med.append(item[1])
  733. high.append(item[2])
  734. # plt.plot(low, color = 'green')
  735. # plt.plot(med, color = 'orange')
  736. # plt.plot(high, color = 'red')
  737. # plt.show()
  738. elif action == 'status':
  739. load_DBs or exit(1)
  740. #handle errors more gracefully
  741. aptsec_status(sys.argv[2])
  742. elif action == 'show':
  743. load_DBs or exit(1)
  744. #handle errors more gracefully
  745. aptsec_show(sys.argv[2])
  746. else:
  747. aptsec_help()
  748. #print(state)
  749. save_state(state)
  750. #cve_db = client.cvedb
  751. #collection = db.cves
  752. #testcvss = collection.find_one({"cvss": 9.3})
  753. #print(testcvssi