/
10.0.1.2.html.erb
164 lines (145 loc) · 10.4 KB
/
10.0.1.2.html.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<% content_for :title do %>
Clock Description for 10.0.1.14
<% end %>
<% content_for :tags do %>
<% # TODO: add in textual listing of new tags that this view creates -%>
<% end %>
<% content_for :data do %>
<%
$slice = [72, 170, 178]
$delta = 30*60
$base = @data[0].observed_at.to_f
def num_clock_ticks(i)
(@data[$slice[i-1]+1].observed_at.to_f-@data[$slice[i-1]].observed_at.to_f)/$delta
end
def slice_number(p)
if p <= $slice[0]
0
elsif (p > $slice[0] and p <= $slice[1])
1
elsif (p > $slice[1] and p <= $slice[2])
2
elsif p > $slice[2]
3
end
end
def tick_count(p)
if p == 0
0
else
n = slice_number(p)
tick_count(p-1) + ((n > 0 and p == $slice[n-1]+1) ? num_clock_ticks(n) : 1)
end
end
def map_to_hash(data)
data.map_with_index { |d, i| { :id => d.id, :position => i, :t_host => d.observed_at.to_f, :t_ref => tick_count(i-1)*$delta+$base } }
end
-%>
<script>
var raw_data = <%=raw (map_to_hash @data).to_json %>;
</script>
<% end %>
<% content_for :note do %>
<p>
In this research note we use the clock description models of <%= link_to "An Improved Clock Model for Translating Timestamps", "http://www.infosec.jmu.edu/reports/jmu-infosec-tr-2007-001.php" %> (by Florian Bucholz) to build up a common time reference model.
</p>
<p>
We have from the analysis of our <%= link_to "ip addresses", "/research/ip_address" %> that 10.0.1.2 and 10.0.1.14 (the IP address of our web server) are on the same subnet. The network proximity of these two IP addresses suggests that they are under the same administrative jurisdiction and so, should the need arise, we can perform additional information gathering from 10.0.1.2.
</p>
<p>
From 10.0.1.2's <%= link_to "RSS accesses", "/research/web_server/rss/10.0.1.2" %>, we have that 10.0.1.2 regularly (ie. once every 27.5 minutes [±5%]) sends newsfeed requests to 10.0.1.14. The regularity of these events offers us the hope that we should be able to use them to build up a clock description for 10.0.1.2. By relating that clock description to the clock source on 10.0.1.14, we should then be able to calculate a trusted reference time model for 10.0.1.14's log events.
</p>
<p>
We have from 10.0.1.2's <%= link_to "user agent string", "/research/by?ip_address=10.0.1.2" %> (we have here used <%= link_to "user-agent-string.info", "http://user-agent-string.info" %> to interpret browser agent strings) that 10.0.1.2 is running OS X 10.6.2 along with the following browsers:
<ul>
<li>Firefox 3.6.3</li>
<li>Safari 4.0.5.</li>
</ul>
By default on OS X (these conclusions have been determined by inspecting vanilla copies of Mail.app, Firefox and Safari - the most common RSS clients within OS X):
<ul>
<li>Firefox fetches live bookmarks (ie. RSS newsfeeds) ever 60 minutes</li>
<li>Mail.app (a common RSS client on OS X) defaults to updating every 30 minutes</li>
<li>and Safari defaults to every 30 minutes.</li>
</ul>
Given that our RSS requests are estimated as being generated every 27.5 minutes [±5%], then RSS newsfeed clients are probably scheduled to be updated every 30 minutes.
</p>
<p>
Regardless of RSS client, newsfeed HTTP requests are here generated using Apple's PubSub agent. This agent is ran regularly via launchd (a cron-like replacement). Thus, by performing additional experiments on 10.0.1.2 (see below), we may then generate an estimate for the accuracy of using launchd as a model of clock ticks.
</p>
<p>
The 10.0.1.14 log event timestamp is generated by 10.0.1.14's system clock when the log event is received (according to <%= link_to "Capturing Timestamp Precision for Digital Forensics", "http://www.infosec.jmu.edu/reports/jmu-infosec-tr-2009-002.php" %> by Eugene Antsilevich, this is achieved via a call to <code>gettimeofday()</code>). This timestamp represents the time at which 10.0.1.14 received the RSS request from 10.0.1.2. The accuracy of this timestamp (relative to real time) is related to:
<ul>
<li>accuracy of launchd in triggering RSS HTTP update events</li>
<li>and network latency.</li>
</ul>
The network proximity of 10.0.1.2 and 10.0.1.14 suggests that network latency should essentially be a constant. Thus, our timestamp accuracy should boil down to the timing accuracy of launchd.
</p>
<div class="note">
<h3>launchd Experimental Note:</h3>
In order to estimate the accuracy of launchd as a timing mechanism, we set up a launchd job (within a vanilla install of OS X 10.6) to regularly (ie. once every 5 minutes) issue a HTTP request (via <code>curl -I</code>) to a web server on a local network. By measuring the time difference between the Date HTTP header in each response (over a 7 day period), we can now estimate launchd's timing accuracy. In performing this experiment, we estimate that launchd maintains time to an accuracy of ±0.1% and so can be considered as a suitably accurate timing reference.
</div>
<p>
For each RSS request (say request number n ≥ 0), let t<sub>ref</sub>(n) be the time determined using 10.0.1.2's clock. Due to the periodicity of 10.0.1.2's newsfeed requests we can represent this time via the equation:
<center>
t<sub>ref</sub>(n) = t<sub>offset</sub> + δ × n
</center>
where δ is the periodicity with which these RSS requests are generated (using the analysis above, we shall take this value to be 30 minutes) and t<sub>offset</sub> is a starting, base or offset time value. In addition, we have that this time is equivalent to the newsfeed's recorded timestamp t<sub>host</sub>(n).
</p>
<p>
In the absence of any further clock data for 10.0.1.2, we choose to fix t<sub>offset</sub> to be t<sub>host</sub>(0). We may now build a clock reference model for 10.0.1.14 by estimating its clock ticks as follows:
<ul>
<li>over the observed time period, we have that t<sub>ref</sub>'s clock ticks correspond precisely with the order of 10.0.1.2 RSS logging events</li>
<li>by trusting 10.0.1.14 to accurately measure time duration and assuming that 10.0.1.2 generates an RSS request every 30 minutes (an inspection of 10.0.1.2 should allow one to provide an accurate alternative here), we can estimate how many clock ticks have occurred during each of our RSS refresh gaps.</li>
</ul>
As a result of these considerations, we may now implement a function that calculates how many 10.0.1.2 clock ticks have occurred since t<sub>host</sub>(0). Using this function, we can now plot the following graph:
</p>
<h3>Clock Description: t<sub>ref</sub> vs t<sub>host</sub></h3>
<script type="text/javascript+protovis">
var data = raw_data.map(function(d) { h = {}; h['position'] = d.position; h['t_host'] = d.t_host; h['x'] = d.t_ref; h['y'] = d.t_host; return h; });
<%= render :partial => '/graph/area.js' %>
xlabel.text(function(d) pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d*1000)));
ylabel.text(function(d) pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d*1000)));
area.title(function(d) "{ position: "+d.position+", t_ref: "+pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d.x*1000))+", t_host: "+pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d.y*1000))+" }");
vis.add(pv.Line)
.data([{ x:data.first().x, y:data.first().x }, { x:data.last().x, y:data.last().x }])
.bottom(function(d) y(d.y))
.left(function(d) x(d.x))
.lineWidth(1)
.strokeStyle("#FF2D26");
vis.render();
</script>
<p>
<b>Note:</b> the <font color="#ff2d26">red</font> line in the above graph represents the equation y=x and describes the curve that should be followed in the case where 10.0.1.14 has its clock precisely synchronised with the reference clock on 10.0.1.2.
</p>
<p>
Using this graph we can see that 10.0.1.14 (ie. t<sub>host</sub>) has its clock set behind our reference clock on 10.0.1.2 (ie. t<sub>ref</sub>). By measuring the rate of change of the difference in times (between 10.0.1.2 and 10.0.1.14), we may estimate 10.0.1.14's clock skew (see graph below).
</p>
<p>
Looking at the graph above, we can also see that every day, 10.0.1.2's clock drifts from our reference model (ie. t<sub>ref</sub>) by approximately 1 hour. Thus we see that, for the data we are examining, clock skew is significant!
</p>
<h3>Clock Skew: t<sub>ref</sub> vs (t<sub>host</sub>-t<sub>ref</sub>)</h3>
<script type="text/javascript+protovis">
var data = raw_data.map(function(d) { h = {}; h['position'] = d.position; h['t_host'] = d.t_host; h['x'] = d.t_ref; h['y'] = d.t_host-d.t_ref; return h; });
<%= render :partial => '/graph/area.js' %>
xlabel.text(function(d) pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d*1000)));
ylabel.text(function(d) (d)+" s");
area.title(function(d) "{ position: "+d.position+", t_ref: "+pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d['x']*1000))+", t_host: "+pv.Format.date("%d/%b/%y %H:%M:%S")(new Date(d['t_host']*1000))+", t_host-t_ref: "+d['y']+"s }");
vis.add(pv.Line)
.data([{ x:data.first().x, y:305.4984 }, { x:data[72].x, y: -5176.986 }, { x:data[73].x, y: -5176.986 }, { x:data[170].x, y: -12563.11 }, { x:data[171].x, y: -12563.11 }, { x:data[178].x, y: -13096.13 }, { x:data[179].x, y: -13096.13 }, { x:data.last().x, y:-17512.58 }])
.bottom(function(d) y(d.y))
.left(function(d) x(d.x))
.lineWidth(1)
.strokeStyle("#FF2D26");
vis.render();
</script>
<p>
From <%= link_to "An Improved Clock Model for Translating Timestamps", "http://www.infosec.jmu.edu/reports/jmu-infosec-tr-2007-001.php" %> (by Florian Bucholz), we have that clock skews are generally linear. As a result, we use a least squares approximation (see below) to build a linear model describing 10.0.1.14's clock. The result of this analysis has been drawn in <font color="#ff2d26">red</font> on the graph above.
</p>
<div class="note">
<h3>Linear Regression Note:</h3>
In order to estimate a clock description for 10.0.1.2 we need to first perform a linear transformation on the x-coordinates of our data to ensure that our RSS refresh gaps are eliminated. Once this has been done, we may then build a linear model via least squares approximation (here we use <%= link_to "R", "http://www.r-project.org/" %> to perform this step). By applying a reverse linear transformation to our data x-coordinates, we obtain the graph description (in <font color="#ff2d26">red</font>) given above.
</div>
<p>
Based upon this linear regression model, we can now estimate 10.0.1.14's clock skew as being -0.04230 [±0.3%]. We additionally offer to explain 10.0.1.2's RSS refresh gaps as being due to downtime.
</p>
<% end %>