fidius-cvedb 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/Gemfile +7 -0
  2. data/LICENSE +57 -0
  3. data/README.md +106 -0
  4. data/Rakefile +15 -0
  5. data/bin/fidius-cvedb +64 -0
  6. data/fidius-cvedb.gemspec +22 -0
  7. data/lib/cveparser/main.rb +31 -0
  8. data/lib/cveparser/ms_parser.rb +65 -0
  9. data/lib/cveparser/parser.rb +138 -0
  10. data/lib/cveparser/parser_model.rb +72 -0
  11. data/lib/cveparser/rails_store.rb +266 -0
  12. data/lib/db/migrate/20101122144313_create_impacts.rb +14 -0
  13. data/lib/db/migrate/20101122145008_create_default_impacts.rb +19 -0
  14. data/lib/db/migrate/20101122153216_create_cvsses.rb +19 -0
  15. data/lib/db/migrate/20101122174719_create_products.rb +19 -0
  16. data/lib/db/migrate/20101122175021_create_vulnerable_softwares.rb +16 -0
  17. data/lib/db/migrate/20101122175244_create_vulnerable_configurations.rb +14 -0
  18. data/lib/db/migrate/20101122175402_create_nvd_entries.rb +18 -0
  19. data/lib/db/migrate/20101125140254_create_vulnerability_references.rb +16 -0
  20. data/lib/db/migrate/20101202100411_create_xmls.rb +14 -0
  21. data/lib/db/migrate/20101210141850_create_mscves.rb +14 -0
  22. data/lib/db/migrate/20110118124541_change_impacts_structure.rb +13 -0
  23. data/lib/db/migrate/20110118131643_destroy_vulnerable_configurations.rb +13 -0
  24. data/lib/fidius-cvedb.rb +17 -0
  25. data/lib/fidius-cvedb/railtie.rb +14 -0
  26. data/lib/fidius-cvedb/version.rb +5 -0
  27. data/lib/models/fidius/cve_db/cve_connection.rb +7 -0
  28. data/lib/models/fidius/cve_db/cvss.rb +5 -0
  29. data/lib/models/fidius/cve_db/impact.rb +2 -0
  30. data/lib/models/fidius/cve_db/mscve.rb +3 -0
  31. data/lib/models/fidius/cve_db/nvd_entry.rb +23 -0
  32. data/lib/models/fidius/cve_db/product.rb +6 -0
  33. data/lib/models/fidius/cve_db/vulnerability_reference.rb +3 -0
  34. data/lib/models/fidius/cve_db/vulnerable_configuration.rb +6 -0
  35. data/lib/models/fidius/cve_db/vulnerable_software.rb +6 -0
  36. data/lib/models/fidius/cve_db/xml.rb +2 -0
  37. data/lib/tasks/db_backup.rake +30 -0
  38. data/lib/tasks/nvd_migrate.rake +25 -0
  39. data/lib/tasks/parse_cves.rake +146 -0
  40. data/test/cve_parser_test.rb +25 -0
  41. data/test/test_references.xml +9 -0
  42. data/test/test_v2.xml +3 -0
  43. metadata +120 -0
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "nokogiri"
4
+ gem "mysql2"
5
+
6
+ # Specify your gem's dependencies in fidius-cvedb.gemspec
7
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,57 @@
1
+ The Simplified BSD License
2
+
3
+ Copyright (C) 2010-2011 FIDIUS Intrusion Detection with Intelligent
4
+ User Support (FIDIUS). All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are
8
+ met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY FIDIUS ``AS IS'' AND ANY EXPRESS OR
18
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ DISCLAIMED. IN NO EVENT SHALL FIDIUS OR CONTRIBUTORS BE LIABLE FOR ANY
21
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ The views and conclusions contained in the software and documentation
30
+ are those of the authors and should not be interpreted as representing
31
+ official policies, either expressed or implied, of FIDIUS.
32
+
33
+
34
+ *OR*
35
+
36
+ GNU GENERAL PUBLIC LICENSE
37
+ Version 2, June 1991
38
+
39
+ Copyright (C) 2010-2011 FIDIUS Intrusion Detection with Intelligent
40
+ User Suppport.
41
+
42
+ This program is free software; you can redistribute it and/or modify
43
+ it under the terms of the GNU General Public License as published by
44
+ the Free Software Foundation; either version 2 of the License, or
45
+ (at your option) any later version.
46
+
47
+ This program is distributed in the hope that it will be useful,
48
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
49
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50
+ GNU General Public License for more details.
51
+
52
+ You should have received a copy of the GNU General Public License along
53
+ with this program; if not, write to the Free Software Foundation, Inc.,
54
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
55
+
56
+ A digital copy is also available for download here:
57
+ http://www.gnu.org/licenses/gpl-2.0.txt.
@@ -0,0 +1,106 @@
1
+ # FIDIUS fidius-cvedb
2
+
3
+ The FIDIUS CVE-DB Gem is used to create and run your own vulnerability database,
4
+ or as an addition to the FIDIUS Command&Control Server to receive vulnerability
5
+ information about target hosts. It uses the National Vulnerability Database
6
+ (NVD [nvd.nist.gov](http://nvd.nist.gov/)) to gather vulnerability entries
7
+ which are based on the Common Vulnerabilities and Exposures (CVE) identifiers.
8
+
9
+ Therefore it includes rake tasks to download and parse XML files provided by the
10
+ NVD, to store and update them in your personal database. Furthermore it includes
11
+ ActiveRecord models, migrations and example database configuration to store
12
+ Vulnerabilities easily.
13
+
14
+ This gem is developed in the context of the students project "FIDIUS" at the
15
+ University of Bremen, for more information about FIDIUS visit
16
+ [fidius.me](http://fidius.me/en).
17
+
18
+ ## Installation
19
+
20
+ Simply install this package with Rubygems:
21
+
22
+ $ gem install fidius-cvedb
23
+
24
+ Then add it to your gemfile (Rails 3)
25
+
26
+ gem 'fidius-cvedb'
27
+ gem 'mysql2' # only required when you use mysql db like in the example below
28
+
29
+ or environment.rb (prior Rails 3)
30
+
31
+ require 'rubygems'
32
+ require 'active_record'
33
+ require 'fidius-cvedb'
34
+
35
+ Please note: The CVE-DB Gem has only been tested with Linux systems and might
36
+ not work with Windows.
37
+
38
+ ## Configuration
39
+
40
+ The setup depends on the context you want to use the gem. It can be used in the
41
+ context of the FIDIUS Command&Control Server, or in your own Rails-app. It might
42
+ access an already existing database or migrate a new one.
43
+
44
+ 0. Go to your Rails-app folder and run `fidius-cvedb --standalone` or
45
+ `fidius-cvedb --fidius`, depending on the context you are using it. For Rails
46
+ versions prior 3 this will create symlinks for the Rake tasks.
47
+ 1. Set up a new CVE Database if you need to or configure an existing one, add
48
+ the CVE Database to your database.yml accordingly. Note that it must be named
49
+ "cve_db":
50
+
51
+ cve_db:
52
+ adapter: mysql2
53
+ encoding: utf8
54
+ database: my_cve_database
55
+ pool: 5
56
+ username: my_username
57
+ password: my_password
58
+ host: localhost
59
+
60
+ 2. When you created a new database, run `rake nvd:migrate` to create the tables
61
+ needed.
62
+ 3. When you set up your own database initialize it (note that it needs to be
63
+ migrated before). Go to your Rails-app folder and run
64
+ `rake nvd:initialize`. This will download all available informations from the
65
+ NVD, parse and store it in your database. This takes about 3 hours, depending
66
+ on your machine. To keep your database up-to-date run `rake nvd:update`
67
+ regularly, e.g. as daily cronjob.
68
+ 4. Now you should be able to use the NVD Entries, to test this go to your
69
+ console (`rails console` | `ruby script/console`) and get an Entry:
70
+
71
+ $ FIDIUS::CveDb::NvdEntry.first
72
+
73
+
74
+ ## Synopsis
75
+
76
+ This package comes with an executable script. You may invoke it as
77
+
78
+ $ fidius-cvedb <option>
79
+
80
+ where _option_ may be:
81
+
82
+ * `-f` | `--fidius` Initialize CVE-DB for Usage in FIDIUS C&C-Server
83
+ * `-s` | `--standalone` Initialize CVE-DB standalone version
84
+ * `-h` | `--help` Show help message
85
+ * `-v` | `--version` Shows the gem version
86
+
87
+
88
+ ## Authors and Contact
89
+
90
+ fidius-cvedb was written by
91
+
92
+ * FIDIUS Intrusion Detection with Intelligent User Support
93
+ <grp-fidius@tzi.de>, <http://fidius.me>
94
+ * in particular:
95
+ * Andreas Bender <bender+fidius-cvedb@tzi.de>
96
+ * Jens Färber <jfaerber+fidius-cvedb@tzi.de>
97
+
98
+ If you have any questions, remarks, suggestion, improvements,
99
+ etc. feel free to drop a line at the addresses given above.
100
+ You might also join `#fidius` on Freenode or use the contact
101
+ form on our [website](http://fidius.me/en/contact).
102
+
103
+
104
+ ## License
105
+
106
+ Simplified BSD License and GNU GPLv2. See also the file LICENSE.
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ require 'rake/clean'
3
+ require 'rubygems'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ CLOBBER.include 'pkg'
8
+
9
+
10
+ namespace :nvd do
11
+
12
+ desc 'Test parsing functionality of the gem.'
13
+ task :test do
14
+ end
15
+ end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'fidius-cvedb/version'
4
+ require 'fileutils'
5
+
6
+ GEM_BASE = File.join(ENV['GEM_HOME'], 'gems',
7
+ "fidius-cvedb-#{FIDIUS::CveDb::VERSION}", 'lib')
8
+
9
+ options = {}
10
+
11
+ optparse = OptionParser.new do|opts|
12
+
13
+ opts.banner = "Usage: fidius-cvedb-runner [options]"
14
+
15
+ opts.on_tail("-f", "--fidius", "Initialize CVE-DB for Usage in FIDIUS C&C-Server") do
16
+ if rails_root?
17
+ rake_tasks
18
+ end
19
+ exit
20
+ end
21
+
22
+ opts.on_tail("-s", "--standalone", "Initialize CVE-DB standalone version") do
23
+ if rails_root?
24
+ rake_tasks
25
+ end
26
+ exit
27
+ end
28
+
29
+ opts.on_tail("-h", "--help", "Show this message") do
30
+ puts opts
31
+ exit
32
+ end
33
+
34
+ opts.on_tail("-v", "--version", "Show version") do
35
+ puts "FIDIUS CVE-DB, Version #{FIDIUS::Cvedb::VERSION}"
36
+ exit
37
+ end
38
+ end
39
+
40
+ def rake_tasks
41
+ if rails_3?
42
+ puts "It seems like you are using Rails 3. Rake tasks are included via "+
43
+ "Railties and don't need to be symlinked."
44
+ else
45
+ symlink_rake_tasks
46
+ end
47
+ end
48
+
49
+ def symlink_rake_tasks
50
+ Dir.glob(File.join GEM_BASE, 'tasks', '*.rake') do |rake|
51
+ dest = File.join 'lib', 'tasks', File.basename(rake)
52
+ FileUtils.ln_s(rake, dest)
53
+ end
54
+ end
55
+
56
+ def rails_root?
57
+ (File.exists?('config/environment.rb') && File.exists?('app/models'))
58
+ end
59
+
60
+ def rails_3?
61
+ File.exists? 'Gemfile'
62
+ end
63
+
64
+ optparse.parse!
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "fidius-cvedb/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "fidius-cvedb"
7
+ s.version = FIDIUS::CveDb::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.add_dependency('nokogiri')
10
+ s.authors = ["Andreas Bender", "Jens Färber"]
11
+ s.email = ["bender@tzi.de", "jfaerber@tzi.de"]
12
+ s.homepage = "http://fidius.me"
13
+ s.summary = %q{Provides a parser and ActiveRecord models for the Common Vulnerability and Exposures (CVE) entries offered by the National Vulnerability Database (http://nvd.nist.gov/). }
14
+ s.description = %q{This gem provides an opportunity to run a vulnerability database in your own environt. Therefore it comes with a parser for the National Vulnerability Database and ActiveRecord models for storing the entries in a local database and accessing Entries comfortable with Rails. }
15
+
16
+ s.rubyforge_project = ""
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
@@ -0,0 +1,31 @@
1
+ require "#{FIDIUS::CveDb::GEM_BASE}/cveparser/parser"
2
+ require "#{FIDIUS::CveDb::GEM_BASE}/cveparser/rails_store"
3
+ require "#{FIDIUS::CveDb::GEM_BASE}/cveparser/ms_parser"
4
+
5
+ include FIDIUS::CveDb
6
+
7
+ PARAMS = {
8
+ '-p' => 'Parse new XML file passed as 2nd param.',
9
+ '-f' => 'Fix duplicate products.',
10
+ '-u' => 'Updates CVE-Entries, needs modified.xml or recent.xml by nvd.nist.gov as 2nd argument.',
11
+ '-m' => 'Creates the mapping between CVEs and Microsoft Security Bulletin Notation entries in the database.'
12
+ }
13
+
14
+ case ARGV[0]
15
+ when '-p'
16
+ entries = FIDIUS::NVDParser.parse_cve_file ARGV[1]
17
+ RailsStore.create_new_entries(ARGV[1].split("/").last, entries)
18
+ when '-f'
19
+ RailsStore.fix_product_duplicates
20
+ when '-u'
21
+ entries = FIDIUS::NVDParser.parse_cve_file ARGV[1]
22
+ RailsStore.update_cves(entries)
23
+ when '-m'
24
+ FIDIUS::MSParser.parse_ms_cve
25
+ else
26
+ puts "ERROR: You've passed none or an unknown parameter, available "+
27
+ "parameters are:"
28
+ PARAMS.each_key do |param|
29
+ puts "#{param}\t#{PARAMS[param]}"
30
+ end
31
+ end
@@ -0,0 +1,65 @@
1
+ # Author:: FIDIUS (mailto:grp-fidius@tzi.de)
2
+ # License:: Distributes under the same terms as fidius-cvedb Gem
3
+
4
+ require 'open-uri'
5
+ require 'nokogiri'
6
+
7
+ # This module provides a parser for the mapping between CVE-Number
8
+ # and Microsoft Security Bulletin Number. It also stores the
9
+ # relationships in the database, so you need the models to store
10
+ # them.
11
+
12
+ module FIDIUS
13
+ module MSParser
14
+
15
+ BASE_URL = "http://cve.mitre.org/data/refs/refmap/source-MS.html"
16
+
17
+ # Calls 'parse' and stores the mapping in the database
18
+ def self.parse_ms_cve
19
+ entries = parse
20
+ counter = 0
21
+ entries.each_pair do |ms,cves|
22
+ cves.each do |cve|
23
+ existing_cve = NvdEntry.find_by_cve(cve.strip)
24
+ if existing_cve
25
+ Mscve.find_or_create_by_nvd_entry_id_and_name(existing_cve.id, ms)
26
+ puts "Found: #{existing_cve.cve}."
27
+ counter += 1
28
+ end
29
+ end
30
+ end
31
+ puts "Added #{counter} items to database."
32
+ end
33
+
34
+ # Print all MS-Notation numbers mapped to CVE-Entries
35
+ def self.print_map
36
+ entries = parse
37
+ entries.each_pair do |ms,cves|
38
+ puts "#{ms}"
39
+ cves.each {|cve| puts "----#{cve}"}
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ # Parses the page given by BASE_URL and returns
46
+ # all entries
47
+ def self.parse
48
+ doc = Nokogiri::HTML(open(BASE_URL))
49
+ entries = Hash.new("")
50
+ current_ms_entry = ""
51
+ doc.css('table[border="2"] > tr').each do |entry|
52
+ entry.css("td").each do |td|
53
+ if td.content =~ /CVE-\d{4}-\d{4}/
54
+ entries[current_ms_entry] = td.content.split("\n")
55
+ else
56
+ current_ms_entry = td.content.split(":").last
57
+ entries[current_ms_entry]
58
+ end
59
+ end
60
+ end
61
+ puts "Parsed #{entries.size} entries."
62
+ entries
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,138 @@
1
+ # Author:: FIDIUS (mailto:grp-fidius@tzi.de)
2
+ # License:: Distributes under the same terms as fidius-cvedb Gem
3
+
4
+ require "#{FIDIUS::CveDb::GEM_BASE}/cveparser/parser_model"
5
+ require 'rubygems'
6
+ require 'nokogiri'
7
+
8
+ # This module provides a parser for the National Vulnerability Database
9
+ # (nvd.nist.gov). The parser can handle XML files provided by the NVD in
10
+ # Version 2.0 and stores all entries from the parsed file in objects
11
+ # from the module 'FIDIUS::NVDParserModel'.
12
+
13
+ module FIDIUS
14
+ module NVDParser
15
+
16
+ include NVDParserModel
17
+
18
+ # Parse Version 2.0 XML-File from nvd.nist.gov.
19
+ def self.parse_cve_file file
20
+
21
+ doc = Nokogiri::XML(File.open(file))
22
+ doc.css("nvd").each do |nvd|
23
+ version = nvd.attributes['nvd_xml_version'].value
24
+ if version != "2.0"
25
+ puts "Your XML has the wrong version (#{version}). " +
26
+ "The CVE-Parser can only handle XML-Feeds in Version 2.0."
27
+ raise 'Invalid XML Version'
28
+ end
29
+ end
30
+
31
+ start_time = Time.now
32
+ puts "[*] Start parsing \"#{file}\""
33
+
34
+ entries = []
35
+ entry_count = 0
36
+ doc.css('nvd > entry').each do |entry|
37
+ entries << single_entry(entry)
38
+ entry_count += 1
39
+ if entry_count % 100 == 0 and entry_count > 0
40
+ puts "Parsed #{entry_count} CVE Entries."
41
+ end
42
+ end
43
+ end_time = Time.now
44
+ puts "[*] Finished parsing, parsed #{entries.size} entries in " +
45
+ "#{(end_time-start_time).round} seconds."
46
+ entries
47
+ end
48
+
49
+ private
50
+
51
+ # Parse single NVD-Entry and store it in an NVDEntry Object
52
+ def self.single_entry entry
53
+ params = {}
54
+ params[:cve] = entry.attributes['id'].value
55
+ params[:vulnerable_configurations] = vulnerable_configurations(entry)
56
+ params[:cvss] = cvss(entry)
57
+ params[:vulnerable_software] = vulnerable_software(entry)
58
+ params[:published_datetime] = child_value(entry, 'vuln|published-datetime')
59
+ params[:last_modified_datetime] = child_value(entry, 'vuln|last-modified-datetime')
60
+ params[:cwe] = cwe(entry)
61
+ params[:summary] = child_value(entry, 'vuln|summary')
62
+ params[:references] = references(entry)
63
+
64
+ NVDParserModel::NVDEntry.new(params)
65
+ end
66
+
67
+ # Return CWE number for given CVE-Entry
68
+ def self.cwe entry
69
+ cwe = entry.at_css('vuln|cwe')
70
+ cwe.attributes['id'].value if cwe
71
+ end
72
+
73
+ # Returns an array of all references which belong to the given CVE-Entry
74
+ def self.references entry
75
+ ref_array = []
76
+ entry.css('vuln|references').each do |references|
77
+ ref_params = {}
78
+ ref_params[:source] = child_value(references, 'vuln|source')
79
+ ref = references.at_css('vuln|reference')
80
+ ref_params[:link] = ref.attributes['href'].value if ref
81
+ ref_params[:name] = child_value(references, 'vuln|reference')
82
+ ref_array << NVDParserModel::Reference.new(ref_params)
83
+ end
84
+ ref_array
85
+ end
86
+
87
+ # Returns an array of all vulnerable products which belong to the given CVE-Entry
88
+ def self.vulnerable_software entry
89
+ vuln_products = []
90
+ entry.css('vuln|vulnerable-software-list > vuln|product').each do |product|
91
+ vuln_products << product.children.to_s if product
92
+ end
93
+ vuln_products
94
+ end
95
+
96
+ # Returns the CVSS-Data from the given CVE-Entry
97
+ def self.cvss entry
98
+
99
+ metrics = entry.css('vuln|cvss > cvss|base_metrics')
100
+ unless metrics.empty?
101
+ cvss_params = {}
102
+ {
103
+ :score => 'score',
104
+ :source => 'source',
105
+ :access_vector => 'access-vector',
106
+ :authentication => 'authentication',
107
+ :access_complexity => 'access-complexity',
108
+ :confidentiality_impact => 'confidentiality-impact',
109
+ :integrity_impact => 'integrity-impact',
110
+ :availability_impact => 'availability-impact',
111
+ :generated_on_datetime => 'generated-on-datetime'
112
+
113
+ }.each_pair do |hash_key, xml_name|
114
+ elem = metrics.at_css("cvss|#{xml_name}")
115
+ value = elem ? elem.children.to_s : nil
116
+ cvss_params[hash_key] = value
117
+ end
118
+ NVDParserModel::Cvss_.new(cvss_params)
119
+ end
120
+ end
121
+
122
+ # Returns an array of all vulnerable configurations which belong to the given CVE-Entry
123
+ def self.vulnerable_configurations entry
124
+ v_confs = []
125
+ entry.css('vuln|vulnerable-configuration > cpe-lang|logical-test'+
126
+ ' > cpe-lang|fact-ref').each do |conf|
127
+ v_confs << conf.attributes['name'].value
128
+ end
129
+ v_confs
130
+ end
131
+
132
+ # Helper method to retrieve the value of a child node in a XML file
133
+ def self.child_value(node, xml)
134
+ val = node.at_css(xml)
135
+ val.children.to_s if val
136
+ end
137
+ end
138
+ end