Let $a < x < y < b$. We will prove $f(y)=f(x)$ by proving $|f(y)-f(x)| < \epsilon(y-x)$ for every $\epsilon>0$. So fix $\epsilon > 0$. By the hypothesis on vanishing of derivatives, for every $t \in [x,y]$ there is $\delta_t > 0$ such that for $|z-t|<\delta_t$, $|f(z)-f(t)|<\epsilon|z-t|$.
Now here is a minor little trick: The intervals $(t-\delta_t/2,t+\delta_t/2)$ (of radius $\delta_t/2$, rather than $\delta_t$) cover $[x,y]$. For now say an interval of the form $(t-\delta_t/2,t+\delta_t/2)$ is a narrow interval and one of the form $(t-\delta_t,t+\delta_t)$ is a wide interval. By compactness there is a finite subcover by narrow intervals, centered at say $t_1,\dotsc,t_s$, with $x \leq t_1 < t_2 < \dotsc < t_s \leq y$. We can reduce to an irredundant cover, i.e., so that no narrow interval centered at $t_i$ is contained in the narrow interval centered at $t_j$ for $j \neq i$. This implies that for each $i$, the narrow intervals centered at $t_i$ and $t_{i+1}$ overlap: otherwise, at least one point in the gap between them must be covered by the interval centered at some $t_j$ with $j<i$ or $j>i+1$; and either $t_i$ is redundant, or $t_{i+1}$ is redundant. Next, this implies that for each $i$, $|t_{i+1}-t_i| < \max(\delta_{t_{i+1}},\delta_{t_i})$. Indeed, if a point $u$, $t_i < u < t_{i+1}$, lies in the intersection of the narrow intervals, then
$$
t_{i+1}-t_i = t_{i+1}-u+u-t_i < \delta_{t_{i+1}}/2 + \delta_{t_i}/2 \leq 2 \max(\delta_{t_{i+1}}/2,\delta_{t_i}/2).
$$
It follows that for each $i$, $t_{i+1}$ lies in the wide interval centered at $t_i$ or $t_i$ lies in the wide interval centered at $t_{i+1}$ (or both). In particular, for each $i$, $|f(t_{i+1})-f(t_i)| < \epsilon |t_{i+1}-t_i|$.
We claim that the same relation holds between $x$ and $t_1$, and between $y$ and $t_s$. Indeed, $x$ lies in the narrow interval centered at $t_1$, hence also in the wide interval. So $|f(t_1)-f(x)| < \epsilon |t_1-x|$. Similarly for $y$ and $t_s$.
Putting it all together, we have:
$$
\begin{split}
|f(y)-f(x)| &\leq |f(y)-f(t_s)| + |f(t_s)-f(t_{s-1})| + \dotsb + |f(t_1)-f(x)| \\
&< \epsilon|y-t_s| + \epsilon|t_s-t_{s-1}| + \dotsb + \epsilon|t_1-x| \\
&= \epsilon(y-t_s) + \epsilon(t_s-t_{s-1}) + \dotsb + \epsilon(t_1-x) \\
&= \epsilon(y-x),
\end{split}
$$
as claimed.
Notes: (1) Thanks for several very helpful comments about simplifications, gaps in the proof, etc! (2) I wonder if an application of Cousin's theorem might simplify the argument.