1#!/usr/local/bin/bash 2# 3# ratproxy - report generator 4# --------------------------- 5# 6# This is essentially a prettyprinter for ratproxy logs. It removes 7# dupes, sorts entries within groups, then sorts groups base don highest 8# priority within the group, and produces some nice HTML with form replay 9# capabilities. 10# 11# TODO: Use standalone stylesheets to conserve bytes. 12# 13# Author: Michal Zalewski <lcamtuf@google.com> 14# 15# Copyright 2007, 2008 by Google Inc. All Rights Reserved. 16# 17# Licensed under the Apache License, Version 2.0 (the "License"); 18# you may not use this file except in compliance with the License. 19# You may obtain a copy of the License at 20# 21# http://www.apache.org/licenses/LICENSE-2.0 22# 23# Unless required by applicable law or agreed to in writing, software 24# distributed under the License is distributed on an "AS IS" BASIS, 25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26# See the License for the specific language governing permissions and 27# limitations under the License. 28# 29 30if [ "$1" = "" ]; then 31 echo "Usage: $0 ratproxy.log" 1>&2 32 exit 1 33fi 34 35if [ ! -f "$1" ]; then 36 echo "Input file not found." 1>&2 37 exit 1 38fi 39 40test "$RAT_URLPREFIX" = "" || RAT_URLPREFIX="/$RAT_URLPREFIX/" 41 42# Output prologue... 43 44cat <<_EOF_ 45<html> 46 47<head> 48<meta http-equiv="Content-Type" content="text/plain; charset=iso-8859-1"> 49<title>ratproxy - security testing proxy</title> 50<style> 51a:link, a:visited { text-decoration: none; color: green } 52a:hover { text-decoration: underline; color: red } 53body { background-color: white; background-image: url('ratproxy-back.png'); background-repeat: no-repeat; } 54</style> 55</head> 56 57<body> 58 59<div style="width: 60%"> 60<span style="float: left; height: 190px; width: 350px"></span> 61 62<font face="arial,helvetica" size=+0> 63<b>Ratproxy audit report</b> 64<p> 65<font size=-1> 66Generated on: <b>`date +'%Y/%m/%d %H:%M'`</b><br> 67Input file: <b>$1</b> 68</font> 69<p> 70<font color="crimson" size=-1>NOTE: Not all of the issues reported necessarily 71correspond to actual security flaws. Findings should be validated 72by manual testing and analysis where appropriate. When in doubt, 73<a href="mailto:lcamtuf@google.com">contact the author</a>.</font> 74<br clear=all> 75 76<hr size=1 color=black> 77<p> 78<font size=-1> 79<div style="border: 1px solid teal; background-color: white"> 80<b>Report risk and risk modifier designations:</b> 81<table border=0> 82<tr> 83<td width=25%> 84<font face="Bitstream Vera Sans Mono,Andale Mono,lucida console" size=-2> 85<span style="border: solid black 1px; background-color: blue; color: white; padding: 0.1em 0.4em 0.1em 0.4em"><b>LOW</b></span> 86to 87<span style="border: solid black 1px; background-color: crimson; color: white; padding: 0.1em 0.4em 0.1em 0.4em"><b>HIGH</b></span> 88</td> 89<td><font size=-1>Issue urgency classification (composite of impact and identification accuracy)</font></td> 90</tr> 91<tr> 92<td width=25%> 93<font face="Bitstream Vera Sans Mono,Andale Mono,lucida console" size=-2> 94<span style="border: solid black 1px; background-color: gray; color: white; padding: 0.1em 0.4em 0.1em 0.4em"><b>INFO</b></span> 95</td> 96<td><font size=-1>Non-discriminatory entry for further analysis</font></td> 97</tr> 98<tr> 99<td width=25%> 100<font face="Bitstream Vera Sans Mono,Andale Mono,lucida console" size=-2> 101<span style="border: solid gray 1px; background-color: #fffece; color: #800000; padding: 0.1em 0.4em 0.1em 0.4em">ECHO</span> 102/ 103<span style="border: solid gray 1px; background-color: #fffece; color: #A0A080; padding: 0.1em 0.4em 0.1em 0.4em">echo</span> 104</font> 105</td> 106<td><font size=-1>Query parameters echoed back / not echoed in HTTP response, respectively</font></td> 107</tr> 108<tr> 109<td width=25%> 110<font face="Bitstream Vera Sans Mono,Andale Mono,lucida console" size=-2> 111<span style="border: solid gray 1px; background-color: #fffece; color: #800000; padding: 0.1em 0.4em 0.1em 0.4em">PRED</span> 112/ 113<span style="border: solid gray 1px; background-color: #fffece; color: #A0A080; padding: 0.1em 0.4em 0.1em 0.4em">pred</span> 114</font> 115</td> 116<td><font size=-1>Request URL or query data likely is / is not predictable to third parties, respectively</font></td> 117</tr> 118<tr> 119<td> 120<font face="Bitstream Vera Sans Mono,Andale Mono,lucida console" size=-2> 121<span style="border: solid gray 1px; background-color: #fffece; color: #800000; padding: 0.1em 0.4em 0.1em 0.4em">AUTH</span> 122/ 123<span style="border: solid gray 1px; background-color: #fffece; color: #A0A080; padding: 0.1em 0.4em 0.1em 0.4em">auth</span> 124</font> 125</td> 126<td><font size=-1>Request requires / does not require cookie authentication, respectively</font></td> 127</tr> 128</table> 129</div> 130</font> 131<p> 132<hr size=1 color=black> 133 134<script> 135function toggle(id) { 136 var i = document.getElementById(id); 137 if (i.style.display == 'none') i.style.display = 'inline'; else i.style.display = 'none'; 138 i = document.getElementById('hid_' + id); 139 if (i.style.display == 'none') i.style.display = 'inline'; else i.style.display = 'none'; 140} 141</script> 142 143<font face="arial,helvetica" size=-1> 144<ul> 145_EOF_ 146 147if [ ! -s "$1" ]; then 148 echo "<b>No activity to report on found in log file." 149 exit 1 150fi 151 152PREVDESC=X 153CNT=0 154SCNT=0 155 156# So this is some nearly incomprehensible logic to sort entries by priorities, 157# sort groups based on highest priority within a group, and then remove any 158# duplicates (paying no attention to some fields, such as trace file location), 159# group "offending value" fields, and more. At some point - too late in the 160# game - it became painfully obvious that this should not be a shell script ;-) 161 162( sort -t '|' -k 1,9 -k 11,100 -ru <"$1" | grep '^[0123]|' | sort -t '|' -k 3,3 -s | \ 163 awk -F'|' '{if ($3!=PF) { npri=$1;PF=$3; }; printf "%s-%s|%s\n", npri, $3, $0}' | \ 164 sort -r -k 1,1 -s | sed 's/|!All /|All /'; echo "Dummy EOF" ) | \ 165 awk -F'|' '{ 166 167 PTRM=TRM; PFR=FR; PTA=TA; 168 FR=""; TA=""; TRM=""; GOTVAL=""; 169 170 for (a=1;a<=NF;a++) { 171 if (a < 5) { 172 TRM=TRM "|" $a; 173 FR=FR $a "|"; 174 } else if (a > 5) { 175 TRM=TRM "|" $a; 176 TA=TA "|" $a; 177 } else GOTVAL=$a; 178 179 } 180 181 if (PTRM == TRM) { 182 if (GOTVAL != "-") { 183 if (LIST == "-") LIST="<span style=\"background-color: #FFFFB0\">" GOTVAL "</span>"; 184 else LIST=LIST ", <span style=\"background-color: #FFFFB0\">" GOTVAL "</span>"; 185 } 186 } else { 187 if (PTRM != "") print PFR LIST PTA; 188 if (GOTVAL == "-") LIST="-"; 189 else LIST="<span style=\"background-color: #FFFFB0\">" GOTVAL "</span>"; 190 } 191 192 }' | \ 193 while IFS="|" read -r skip severity modifier desc offend code len mime sniff cset trace method url cookies payload response; do 194 195 # If issue name changed, output a new header, complete with fold / unfold controls. 196 # Default groups with 'info' items only to folded state. 197 198 if [ ! "$PREVDESC" = "$desc" ]; then 199 200 SCNT=$[SCNT+1] 201 202 if [ ! "$severity" = "0" ]; then 203 204 echo "</ul></span><font size=+1><u>$desc</u></font> <font size=-2 color=gray>[<a href=\"javascript:void(0)\" onclick=\"toggle('list$SCNT')\">toggle</a>]</font>" 205 echo "<span id=hid_list$SCNT style=\"display:none\"><br><br><font color=gray><i>Section hidden</i></font><p></p></span>" 206 echo "<span id=list$SCNT style=\"display:inline\"><ul style=\"margin-top: 0px\"><font size=-2>" 207 208 else 209 210 echo "</ul></span><font size=+1><u>$desc</u></font> <font size=-2 color=gray>[<a href=\"javascript:void(0)\" onclick=\"toggle('list$SCNT')\">toggle</a>]</font>" 211 echo "<span id=hid_list$SCNT style=\"display:inline\"><br><br><font color=gray><i>Section hidden</i></font><p></p></span>" 212 echo "<span id=list$SCNT style=\"display:none\"><ul style=\"margin-top: 0px\"><font size=-2>" 213 214 fi 215 216 echo "<font color=darkslateblue>" 217 grep -F "~$desc~" messages.list | cut -d'~' -f3 218 echo "</font></font><p>" 219 220 PREVDESC="$desc" 221 222 fi 223 224 # Output severity data. 225 226 echo -n "<li><font face=\"Bitstream Vera Sans Mono,Andale Mono,Lucida Console\" size=-2>" 227 228 if [ "$severity" = "3" ]; then 229 echo -n "<span style=\"border: solid black 1px; background-color: crimson; color: white; padding: 0.1em 0.4em 0.1em 0.4em\"><b>HIGH</b></span>" 230 elif [ "$severity" = "2" ]; then 231 echo -n "<span style=\"border: solid black 1px; background-color: darkmagenta; color: white; padding: 0.1em 0.4em 0.1em 0.4em\"><b>MEDIUM</b></span>" 232 elif [ "$severity" = "1" ]; then 233 echo -n "<span style=\"border: solid black 1px; background-color: blue; color: white; padding: 0.1em 0.4em 0.1em 0.4em\"><b>LOW</b></span>" 234 else 235 echo -n "<span style=\"border: solid black 1px; background-color: gray; color: white; padding: 0.1em 0.4em 0.1em 0.4em\"><b>INFO</b></span>" 236 fi 237 238 # Provide additional flags on all but 'All visited URLs' sections. 239 240 if [ ! "$desc" = "All visited URLs" ]; then 241 242 echo -n "<span style=\"border: solid gray; border-width: 1px 1px 1px 0px; background-color: #fffece; color: #A0A040; padding: 0.1em 0.4em 0.1em 0.4em\">" 243 244 if [ "$[modifier & 4]" = "0" ]; then 245 echo -n "echo " 246 else 247 echo -n "<font color=\"#800000\">ECHO</font> " 248 fi 249 250 if [ "$[modifier & 1]" = "0" ]; then 251 echo -n "pred " 252 else 253 echo -n "<font color=\"#800000\">PRED</font> " 254 fi 255 256 if [ "$[modifier & 2]" = "0" ]; then 257 echo -n "auth" 258 else 259 echo -n "<font color=\"#800000\">AUTH</font>" 260 fi 261 262 echo -n "</span> " 263 264 else 265 266 echo -n " " 267 268 fi 269 270 # Prepare trace / decompile links, if available. 271 272 if [ "$trace" = "-" ]; then 273 TLINK="" 274 else 275 276 if [ -s "$trace.flr" ]; then 277 TLINK=" <font size=-2>[<a href=\"$RAT_URLPREFIX$trace.flr\">decompile</a>] [<a href=\"$RAT_URLPREFIX$trace\">view trace</a>]</font>" 278 else 279 TLINK=" <font size=-2>[<a href=\"$RAT_URLPREFIX$trace\">view trace</a>]</font>" 280 fi 281 282 fi 283 284 # Output URL, query, and response data. 285 286 test "$method" = "-" && method="[Referer]" 287 288 if [ "$payload" = "-" ]; then 289 290 echo "<font color=\"teal\">$method</font> <a href=\"$url\">$url</a> ⇒ $code$TLINK<br>" 291 292 if [ ! "$response" = "-" ]; then 293 echo "<font size=-3 color=gray>Response ($len): $response</font><br>" 294 fi 295 296 if [ ! "$cookies" = "-" ]; then 297 echo "<font size=-3 color=royalblue>Cookies set: $cookies</font><br>" 298 fi 299 300 if [ ! "$offend" = "-" ]; then 301 echo "<font size=-3 color=darkred>Offending value: $offend</font><br>" 302 fi 303 304 if [ "$method" = "[Referer]" ]; then 305 echo "<font size=-3 color=black>Target resource: <a href=\"$sniff\">$sniff</a></font>" 306 else 307 echo "<font size=-3 color=black>MIME type: <font color=teal>$mime</font>, detected: <font color=teal>$sniff</font>, charset: <font color=teal>$cset</font></font>" 308 fi 309 310 else 311 312 isfile="" 313 314 if echo "$payload" | grep -qF "=FILE["; then 315 isfile="(FILE) " 316 fi 317 318 echo "<font color=\"crimson\">$isfile$method</font> <a href=\"javascript:void(0)\" onclick=\"document.getElementById('form$CNT').submit();return false;\">$url</a> ⇒ $code$TLINK<br>" 319 echo "<font size=-3 color=teal>Payload: $payload</font><br>" 320 321 if [ ! "$response" = "-" ]; then 322 echo "<font size=-3 color=gray>Response ($len): $response</font><br>" 323 fi 324 325 if [ ! "$cookies" = "-" ]; then 326 echo "<font size=-3 color=royalblue>Cookies set: $cookies</font><br>" 327 fi 328 329 if [ ! "$offend" = "-" ]; then 330 echo "<font size=-3 color=darkred>Offending value: $offend</font><br>" 331 fi 332 333 echo "<font size=-3 color=black>MIME type: <font color=teal>$mime</font>, detected: <font color=teal>$sniff</font>, charset: <font color=teal>$cset</font></font><br>" 334 335 if ! echo "$payload" | grep -q '^GWT_RPC\['; then 336 337 echo "<input type=submit value=\"edit values\" onclick=\"document.getElementById('form$CNT').style.display='inline';return false;\" style=\"border-width: 1px; background-color: #FFFFC0; font-size: 0.9em; display: inline\">" 338 echo "<form action=\"$url\" method=\"POST\" id=\"form$CNT\" style=\"display: none\">" 339 echo "$payload" | sed 's/\&#x\(..\);/%\1/g' | sed 's/&/\ 340/g' | sed 's/%26/\&/g;s/%3B/;/g' | sed 's/\%\(..\)/\&#x\1;/g' | \ 341 while IFS='=' read -r param val; do 342 echo "<INPUT TYPE=text STYLE=\"border-width: 1px; background-color: #FFC0A0; font-size: 0.9em\" NAME=\"$param\" VALUE=\"$val\">" 343 done 344 echo "</form>" 345 346 fi 347 348 fi 349 350 echo "</font><p></li>" 351 352 CNT=$[CNT+1] 353 354 done 355 356echo "</ul></div></body></html>" 357