Adventures in HTTP (Part 2) — Secrets of Struts

In the first part of my adventure, I arrived at the Nginx building, where I was greeted by the receptionist at station 04, who then directed me to Tomcat. There, I encountered the famous thread 0x6904, who took me to meet the head of the Struts Filter. We then went to the second floor to find LoginAction, and a new adventure began…

Chapter 3: The Alarm

Upon reaching the second floor, I was amazed to see thousands of channels, all named ActionProxy. Where could LoginAction be? 0x6904 said, “Oh, I just woke up from a nap in the thread pool and got a bit confused. To meet LoginAction, we need to go through a specific ActionProxy channel. Wait a moment, I’ll ask the Filter head which channel we should take.” (Note from the coder: For more about thread pools, see ‘I Am a Thread’).

While I waited for 0x6904, I was intrigued to watch everyone entering one end of the channels and exiting from the other. Some were quick, while others were slow. Suddenly, a suspicious character emerged from one channel, and an alarm blared loudly: “Warning, JavaScript attack detected!” A group of guards rushed over and apprehended him. The leading officer opened the suspect’s package and carefully examined the data inside: “Report to Filter head, this return package is supposed to send user input data back to the browser, but it contains code like <javascript>..</javascript>. How should we handle this?”

“Follow the protocol and sanitize it. Escape the characters ‘<‘ and ‘>’ so that when sent to the browser, they will only display and not execute,” the officer instructed. (Note from the coder: Escaping means converting characters like <, >, & into &lt;, &gt;, &amp; respectively.) No wonder the Filter head was so busy, managing such detailed matters!

At that moment, 0x6904 returned, panting: “Quick, let’s go through channel 0xa84d.” I asked, “What was that alarm about? Why do we need to escape <javascript>?”

“Let me put it this way, these JavaScript scripts are not generated by our system; they might be carefully crafted by hackers and sent to us through parameters. If we don’t sanitize them and send them directly to the user’s browser, these scripts could execute and steal the user’s cookies (which contain the session ID). Then the hacker could impersonate the user and commit malicious acts, like transferring your money!”

I was secretly astonished: “That’s quite powerful!”

“Yes, many websites can run into trouble if they don’t sanitize user input and output. This type of hacker attack is called XSS, or Cross-Site Scripting attack,” 0x6904 explained.

Chapter 4: Interceptors

Along the 0xa84d channel, there was a row of counters. The first few counters were labeled “Interceptor,” and there were people sitting at them. In the middle, one counter was labeled LoginAction, which was our destination. The counters behind were also labeled “Interceptor,” but no one was there. What was the purpose of this?

0x6904 and I approached the first counter, where the interceptor said, “I am the Exception Interceptor, but there’s nothing going on right now. See you later.” I thought to myself: Why are you standing here so seriously if there’s nothing to do?

The second counter’s interceptor said, “I am the I18n Interceptor. Where are you from?”

“Beijing, Zhongguancun Software Park,” I replied.

“No need to be so detailed; I just need to remember the country and language. Use zh_CN, see you later,” he said.

The third counter was the FileUpload Interceptor, who glanced at us and let us pass since I had nothing to upload.

At the fourth counter, a guy smiled and said, “I am the Parameter Interceptor. Hand over all the parameters in your package!” I thought: Oh no, not more fees! But 0x6904 was unfazed: “We have user.name and user.password; take them.” The Parameter Interceptor replied, “Okay, I will put them into the ValueStack for LoginAction to use. See you later, folks.” Why does everyone keep saying ‘see you later’?

The next counter was the Validation Interceptor. I was a bit dissatisfied: “The JavaScript validation at the old IE was already done, and this data is definitely fine!” The Validation Interceptor retorted: “Young man, what does JavaScript validation count for? This browser-based check can be easily bypassed. Didn’t you hear the alarm earlier? Hackers can easily send an HTTP POST with data to us without using a browser.” I quickly fell silent.

The check was quick, and he soon let us pass: “This is for everyone’s safety. Alright, you are through, see you later.”

Adventures in HTTP (Part 2) -- Secrets of Struts

(Click the image to enlarge and see many details)

After passing through five interceptors, we finally arrived at LoginAction.

Here, there was a User object with setName() and setPassword() methods, clearly receiving values from my package. LoginAction worked diligently: it called LoginService to execute the login method, checked the database to see if the username and password were correct, and finally told me: “Login successful, remember this return code ‘success’ for the next counter. Also, here is your session ID; make sure to give it to old IE for safekeeping.”

I asked 0x6904: “I think I have a session ID in my package; why give me another one?”

“For security reasons, after a successful login, a new session ID must be generated, and the old session ID must be invalidated. Think about XSS attacks and why this is necessary,” he explained.

I thought for a moment: XSS attacks mainly steal user sessions. If a hacker constructs an XSS attack on the page before login, and someone views that page, even without logging in, the session ID could be stolen. Then the hacker could keep trying those stolen session IDs to access pages that require login. If the session ID corresponds to a user who is logged into the site, the hacker could also log in because the session ID hasn’t changed.

I said: “I didn’t realize the online world was so scary; thankfully, your defenses are so tight here!”

The next counter indeed asked for the return code “success,” then found the configuration for LoginAction from struts.xml, located the corresponding JSP: /WEB-INF/home.jsp, and generated the HTML to hand over to me.

<action name="login" class="example.LoginAction">            <result name="success">/WEB-INF/home.jsp</result></action>

To my surprise, the next counter was filled with people I had just seen. No wonder they all said ‘see you later.’

Only the order was different from when we entered: first was Validation, then Parameter, FileUpload, I18n, Exception, completely reversed from when we came in!

Adventures in HTTP (Part 2) -- Secrets of Struts

(Click the image to enlarge and see many details)

I began to understand; these guys were just intercepting us before executing LoginAction and then intercepting us again afterward.

Like this: Exception: intercept before executing login; I18n: intercept before executing login; FileUpload: intercept before executing login; Parameter: intercept before executing login; Validation: intercept before executing login; execute LoginAction to generate results; Validation: intercept after login; Parameter: intercept after login; FileUpload: intercept after login; I18n: intercept after login; Exception: intercept after login. Validation, Parameter, FileUpload, and I18n just smiled at us and let us pass; we had already completed our execution, and they indeed had nothing to intercept.

When we reached the Exception Interceptor again, he asked us: “Is there any exception?” I thought for a moment; there were indeed no exceptions throughout the process: “Everything went smoothly.” The Exception Interceptor replied: “Good, then I don’t need to do anything else; you can leave this channel now.” (Note from the coder: The actual Struts interceptors are more than those listed here.)

Finally, we emerged, and I remarked to 0x6904: “This ActionProxy channel is quite troublesome!” 0x6904 replied: “Actually, this channel is designed quite elegantly. You see, just by going through it once, things like parameter handling, form validation, and internationalization are all taken care of.”

I asked him: “Does every Action have so many interceptors?”

“Not necessarily; this can be customized. Each Action can have different interceptors,” he explained.

“So after we leave, will this channel be available for others?”

“Absolutely not; it’s one per person. Once used, it is destroyed and garbage collected,” he assured me.

I was a bit surprised, but upon reflection, it made sense; this channel actually stored my information, and others indeed could not use it.

Conclusion

Just as I was talking to 0x6904, a loudspeaker blared: “0x6904, what are you dawdling about? Customers are lining up, and we don’t have enough staff. Hurry back!” 0x6904 immediately looked tense and pointed to a channel: “You can return to the Nginx building from here. I need to hurry and attend to others. Goodbye!” Upon returning to the Nginx building, compared to Tomcat, it felt like a different world, bustling with activity. The receptionist at station 04 was as busy as ever. Seeing me back, he asked: “How was it at Tomcat?” I sighed: “It was much more complicated than here.” The receptionist helped me store the returned package in a small safe and told me: “Alright, I’ve finished my work here. Soon you can take a ride back to old IE.” Yes, I had been out for quite a while and was indeed missing old IE. The long journey was about to begin again, carrying the safe, crossing mountains and rivers, using various modes of transportation. Although tiring, it was quite interesting. I’ll share more next time.

Special thanks: to the netizen blindingdark for providing the detailed illustrations, which were hand-drawn on paper and then scanned to become images. It was not easy! 🙂

Related readings:

Adventures in HTTP (Part 1) I Am a Thread Why IE Injured Chrome and Firefox The Second Interview with Browser Village

Node.js: I Just Need a Waiter

JavaScript: A Loser’s Comeback

Adventures in HTTP (Part 2) -- Secrets of Struts

Public account: Coder Reversal “Coder Reversal” is a public account created by a former IBM architect with 15 years of experience, sharing programming and career lessons.

Leave a Comment