Aplikasi web yang ada sedang berjalan di Tomcat 4.1. Ada masalah XSS dengan halaman, tetapi saya tidak dapat mengubah sumbernya. Saya telah memutuskan untuk menulis filter servlet untuk membersihkan parameter sebelum dilihat oleh halaman.
Saya ingin menulis kelas Filter seperti ini:
import java.io.*;
import javax.servlet.*;
public final class XssFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
String badValue = request.getParameter("dangerousParamName");
String goodValue = sanitize(badValue);
request.setParameter("dangerousParamName", goodValue);
chain.doFilter(request, response);
}
public void destroy() {
}
public void init(FilterConfig filterConfig) {
}
}
Tapi ServletRequest.setParameter
tidak ada.
Bagaimana cara mengubah nilai parameter permintaan sebelum meneruskan permintaan ke rantai?
java
servlet-filters
Jeremy Stein
sumber
sumber
Jawaban:
Seperti yang Anda catat
HttpServletRequest
tidak memiliki metode setParameter. Ini disengaja, karena kelas mewakili permintaan yang berasal dari klien, dan memodifikasi parameter tidak akan mewakili itu.Salah satu solusinya adalah menggunakan
HttpServletRequestWrapper
kelas, yang memungkinkan Anda menggabungkan satu permintaan dengan yang lain. Anda dapat membuat subkelas itu, dan menggantigetParameter
metode untuk mengembalikan nilai bersih Anda. Anda kemudian bisa meneruskan permintaan yang dibungkus itu kechain.doFilter
alih-alih ke permintaan asli.Ini agak jelek, tapi itulah yang menurut API servlet harus Anda lakukan. Jika Anda mencoba meneruskan apa pun ke
doFilter
, beberapa kontainer servlet akan mengeluh bahwa Anda telah melanggar spesifikasi, dan akan menolak untuk menanganinya.Solusi yang lebih elegan adalah lebih banyak pekerjaan - modifikasi servlet / JSP asli yang memproses parameter, sehingga mengharapkan atribut permintaan daripada parameter. Filter memeriksa parameter, membersihkannya, dan menyetel atribut (menggunakan
request.setAttribute
) dengan nilai yang disanitasi. Tanpa subclass, tidak ada spoofing, tetapi mengharuskan Anda untuk memodifikasi bagian lain dari aplikasi Anda.sumber
<property name="username" value="[email protected]" /> //Change email on logging in <property name="password" value="*********" />//Change Password on logging in
Sebagai catatan, inilah kelas yang akhirnya saya tulis:
sumber
Tulis kelas sederhana yang disubkalsikan
HttpServletRequestWrapper
dengan metode getParameter () yang mengembalikan versi masukan yang sudah dibersihkan. Kemudian teruskan instance AndaHttpServletRequestWrapper
keFilter.doChain()
alih-alih objek permintaan secara langsung.sumber
Saya memiliki masalah yang sama (mengubah parameter dari permintaan HTTP di Filter). Saya akhirnya menggunakan file
ThreadLocal<String>
. DiFilter
Saya punya:Dalam pemroses permintaan saya (
HttpServlet
, pengontrol JSF atau pemroses permintaan HTTP lainnya), saya mendapatkan kembali nilai utas saat ini:Keuntungan:
HttpServletRequestWrapper
boilerplaterequest.setAttribute(String,Object)
, yaitu Anda dapat mengakses variabel di penyaringan lain.Kekurangan:
java.util.stream.Stream.parallel
,java.util.concurrent.Future
,java.lang.Thread
.Beberapa catatan tambahan:
Server memiliki kumpulan Thread untuk memproses permintaan HTTP. Karena ini adalah pool:
if (value!=null) { THREAD_VARIABLE.set(value);}
karena Anda akan menggunakan kembali nilainya dari permintaan HTTP sebelumnya ketikavalue
null: efek samping dijamin).HttpSession.setAttribute()
@RequestScoped
internal menggunakan aThreadLocal
, tetapi menggunakan theThreadLocal
lebih serbaguna: Anda dapat menggunakannya dalam wadah non JEE / CDI (misalnya dalam aplikasi JRE multithread)sumber
@RequestScoped
melakukan hal yang sama secara internal). Akankah beberapa permintaan melihat utas yang sama = tidak (atau setidaknya Anda tidak memiliki jaminan). Saya telah mengedit jawabannya dengan tepat poin-poin ini.Inilah yang akhirnya saya lakukan
sumber
Berdasarkan semua komentar Anda, inilah proposal saya yang berhasil untuk saya:
catatan: queryString () perlu memproses SEMUA nilai untuk setiap KEY dan jangan lupa untuk encodeUrl () saat menambahkan nilai param Anda sendiri, jika diperlukan
Sebagai batasan, jika Anda memanggil request.getParameterMap () atau metode apa pun yang akan memanggil request.getReader () dan mulai membaca, Anda akan mencegah panggilan lebih lanjut ke request.setCharacterEncoding (...)
sumber
Anda dapat menggunakan Ekspresi Reguler untuk Sanitasi. Di dalam filter sebelum memanggil metode chain.doFilter (request, response) , panggil kode ini. Ini Contoh Kode:
sumber
Coba
request.setAttribute("param",value);
. Ini bekerja dengan baik untukku.Silakan temukan contoh kode ini:
sumber