Además, es importante mencionar que permitir a las personas inyectar HTML o JavaScript en su página (y no en su fuente de datos) no conlleva ningún riesgo de seguridad inherente. Ya existen extensiones de navegador que le permiten modificar el DOM y las secuencias de comandos en las páginas web, pero dado que solo están en el lado del cliente, son las únicas que sabrán.
Dónde XSS se convierte en un problema es cuando las personas a) lo utilizan para eludir la validación del lado del cliente o el filtrado de entrada o b) cuando las personas lo utilizan para manipular los campos de entrada (por ejemplo, cambiando los valores de etiquetas de opción en una ACL a otórgales permisos que no deberían tener). La ÚNICA forma de prevenir estos ataques es desinfectar y validar las entradas del lado del servidor en lugar de, o además de, la validación del lado del cliente.
Para desinfectar HTML de entrada, htmlspecialchars es perfectamente adecuado a menos que QUIERA permitir ciertas etiquetas, en cuyo caso puede usar una biblioteca como HTMLPurifier. Si está colocando la entrada del usuario en HREF, ONCLICK o cualquier atributo que permita la creación de scripts, solo está buscando problemas.
EDIT: mirando su código, parece que no está citando sus atributos! Eso es bastante tonto. Si alguien puso su nombre de usuario como:
john onclick="alert('hacking your megabits!1')"
A continuación, la secuencia de comandos podría analizar como:
<input type=text name=username value=john onclick="alert('hacking your megabits!1')">
SIEMPRE use comillas alrededor de los atributos. Incluso si no son ingresados por el usuario, es un buen hábito entrar.
<input type="text" name="username" value="<?php echo htmlspecialchars($_POST['username']); ?>">
Excelente pregunta, porque Confío en htmlspecialchars() para la seguridad, como lo estoy, estoy seguro, mucha gente. Me hace preguntarme si se puede deslizar una evaluación() o algo así ... especialmente porque creo que el navegador se deshabilita antes de aprobar valores para el intérprete js. Creo que sería más explotable si está insertando datos de usuario en un clic en un clic o href u otro atributo ejecutable; explotar un atributo de valor parece ser más difícil. –
@Frank: si está poniendo datos maliciosos en Javascript, también necesitas codificarlo con Javascript. – SLaks