Go Down

Topic: Excellent Arduino Ethernet Shield Web Server Tutorial (Read 209226 times) previous topic - next topic

SurferTim

#15
Aug 22, 2013, 03:03 pm Last Edit: Aug 22, 2013, 03:05 pm by SurferTim Reason: 1
That server code is easy to lock up. I can do that in a few seconds with PuTTY.  :)

Most of zoomkat's code is more difficult than that. I need my Mega2560/ethernet shield to lock up some of his code examples. I'm not running down zoomkat here. He is a good guy and really smart, like I said in another post. His code has a few vulnerabilities if left exposed on the internet.

oric_dan


I use this code.
http://playground.arduino.cc/Code/WebServerST
It will keep port scanners and hackers like me from locking up your sketch. PuTTY is a wonderful tool.  :)


Tim, can you explain what these vulnerabilities are, and how "locking up" the sketch is done, and also what it is about your sketch that avoids such problems?

SurferTim

Hackers are a bit hesitant to show vulnerabilities in code, but I am a good hacker, not a bad one. I try to prevent a hack. This code will lock up every server example I have seen, including zoomkat's. Follow the serial monitor prompts. Do not close anything until you remove the CAT5 from your Arduino. Change the network settings to suit your localnet.
Code: [Select]
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,2,2);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress server(192,168,1,254);
EthernetClient client;

void setup() {
  Serial.begin(9600);

  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  delay(2000);
  Serial.println("Ready. Enter l to lock");
}

void loop() {
  if(Serial.available()) {

    if(Serial.read() == 'l')     
    {
      if(!getPage(server)) Serial.print("Fail ");
      else Serial.print("Pass ");
    }
  }   
}

byte getPage(IPAddress ipBuf)
{
  Serial.print("connecting...");

  if(client.connect(ipBuf,80))
  {
    Serial.print("connected");

    // send request with no \r\n
    client.print("GET / HTTP/1.1");
  }
  else
  {
    Serial.println("failed");
    return 0;
  }

  Serial.println(" & locked. Remove CAT5 from the shield.");
 
  return 1;
}


oric_dan


Hello all Arduino users.

I have found an excellent resource for making a web server using the Arduino Ethernet shield:
http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/


When that tutorial gets to the point of doing something useful in part 5,
http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/web-server-LED-control/

I believe the following lines have an error, he left out the self-closing tags, or else </input>, on the <input> elements.
Code: [Select]
   if (LED_status) {    // switch LED on
       digitalWrite(2, HIGH);
       // checkbox is checked
       cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \
       onclick=\"submit();\" checked>LED2");
   }
   else {              // switch LED off
       digitalWrite(2, LOW);
       // checkbox is unchecked
       cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \
       onclick=\"submit();\">LED2");
   }

The code will work ok for a single input-control, but hoses for multiple controls. This problem burned me for a couple of days, until I learned what the heck " />" was.

oric_dan


Hackers are a bit hesitant to show vulnerabilities in code, but I am a good hacker, not a bad one. I try to prevent a hack. This code will lock up every server example I have seen, including zoomkat's. Follow the serial monitor prompts. Do not close anything until you remove the CAT5 from your Arduino. Change the network settings to suit your localnet.
Code: [Select]
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,2,2);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress server(192,168,1,254);
EthernetClient client;

void setup() {
  Serial.begin(9600);

  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  delay(2000);
  Serial.println("Ready. Enter l to lock");
}

void loop() {
  if(Serial.available()) {

    if(Serial.read() == 'l')     
    {
      if(!getPage(server)) Serial.print("Fail ");
      else Serial.print("Pass ");
    }
  }   
}

byte getPage(IPAddress ipBuf)
{
  Serial.print("connecting...");

  if(client.connect(ipBuf,80))
  {
    Serial.print("connected");

    // send request with no \r\n
    client.print("GET / HTTP/1.1");
  }
  else
  {
    Serial.println("failed");
    return 0;
  }

  Serial.println(" & locked. Remove CAT5 from the shield.");
 
  return 1;
}


Thanks. I got one serial monitor prompt and nothing at all after that. And nothing showed up at either URL on my PC [at 192.168.1.177 (my 'static ip') or 192.168.1.254].

I guess I'm too naive and confused to even understand what you're trying to do here. It seems to me you've established router connection at one IPaddress, but are trying to access the server on another,
Code: [Select]
IPAddress ip(192,168,2,2);

IPAddress server(192,168,1,254);


Hopelessly lost, so probably best to forget my question, :-(.

SurferTim

#20
Aug 22, 2013, 11:50 pm Last Edit: Aug 23, 2013, 12:19 am by SurferTim Reason: 1
You asked the question. I answered it. I can lock up any server example except mine. Change the server variable to the target ip you want to lock up. Mine was 192.168.1.254. With my code, it doesn't lock up. With any other example...YOU ARE DOOMED!!

edit: The reason is most Arduino server examples wait for a "\r\n" to determine End Of Header. My crash code sends a request with NO "\r\n". All other server code will lock up unless it receives a '\n'. I don't send one with the crash code. All other examples will wait FOREVER for a '\n'.



zoomkat

Just curious, what hang protection does Apache use?
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

SurferTim

#22
Aug 23, 2013, 05:21 am Last Edit: Aug 23, 2013, 05:34 am by SurferTim Reason: 1

Just curious, what hang protection does Apache use?

About the same as mine.
http://playground.arduino.cc/Code/WebServerST

Both IIS and Apache will brush off that lock code without a problem. Only examples here on the Arduino site have problems with that code. Most (except yours zoomkat) can be locked with PuTTY about the same way. Send the GET line and don't send the blank line, then break the connection.


SurferTim

#23
Aug 23, 2013, 06:52 am Last Edit: Aug 23, 2013, 07:19 am by SurferTim Reason: 1

Thanks. I got one serial monitor prompt and nothing at all after that. And nothing showed up at either URL on my PC [at 192.168.1.177 (my 'static ip') or 192.168.1.254].

I guess I'm too naive and confused to even understand what you're trying to do here. It seems to me you've established router connection at one IPaddress, but are trying to access the server on another,
Code: [Select]
IPAddress ip(192,168,2,2);

IPAddress server(192,168,1,254);


Hopelessly lost, so probably best to forget my question, :-(.

The "IPAddress ip" is the ip of my Arduino that will do the lock attack. The "IPAddress server" is the ip of the victim Arduino running the server code. Mine are on different subnets.

When you start the lock sketch, you should get "Ready. Enter l to lock" on the serial monitor. Press 'l' and enter. That is a lower case L. Then disconnect the CAT5 cable from the attacking Arduino when prompted.

If you do not have two Arduinos, you can use PuTTY in your computer as the attacker. Enter the ip of the victim Arduino in the "Connect To:" box and port 80 in the "Port" box and select "Raw" as the connection type. Then click "Open" at the bottom. You should get a prompt with no response. Type "GET / HTTP/1.1" and press the enter key only once, then pull the CAT5 out of the computer's network card or out of the Arduino. Either will break the connection. It will lock at that point and will not respond until you reboot it.

PuTTY does not lock up some of zoomkat's server code. PuTTY sends a newline character when you press the enter key and zoomkat's code waits only for the first newline, not the blank line.

oric_dan

Quote
The "IPAddress ip" is the ip of my Arduino that will do the lock attack. The "IPAddress server" is the ip of the victim Arduino running the server code. Mine are on different subnets.

Well, that explains a lot, LOL - at this point, I'm happy to have anything working at all.

Ok, I added your timeout counter code from the WebServerST example to my AMI-1284 Server from the other thread. However, PUTTY won't crash anything for me.

With PUTTY, I followed your setup procedure. Then, no matter what I send, <cr>, GET, or whatever, my server dumps the web page correctly, PUTTY receives it correctly, and then a window pops up and says "Connection closed by remote host". The page is correct, since I can capture it, stick it in a file with .htm extension using Notepad, and it displays perfectly on the browser.
Quote
GET / HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/html

<html><title>AMI-1284 Server4</title><body>
<TABLE BORDER=0 BGCOLOR="#DDDDDD" cellpadding=6><TR><TD><TABLE BORDER=1 cellpadding=4><TR><TD><B>AMI-1284 Server</B><BR></TD><TD><FORM action="http://192.168.1.177" ><INPUT type="submit" value="Refresh" /> </FORM></TD></TR></TABLE><TABLE BORDER=0 cellpadding=4><TR><TD><TABLE BORDER=1 bgcolor="#44EE44" width=72 cellspacing=0 cellpadding=4><TR><TD align=center><FORM action="http://192.168.1.177/" ><INPUT type="hidden" name="cmd" value="11" /><INPUT type="submit" value=" OFF " /> </FORM><font color="black"><B>LED1<br>(Red)</B></font></TD></TR></TABLE></TD><TD><TABLE BORDER=1 bgcolor="#EE4444" width=72 cellspacing=0 cellpadding=4><TR><TD align=center><FORM action="http://192.168.1.177/" ><INPUT type="hidden" name="cmd" value="12" /><INPUT type="submit" value=" ON  " /> </FORM><font color="black"><B>LED2<br>(Yellow)</B></font></TD></TR></TABLE></TD><TD><TABLE BORDER=1 bgcolor="#EE4444" width=72 cellspacing=0 cellpadding=4><TR><TD align=center><FORM action="http://192.168.1.177/" ><INPUT type="hidden" name="cmd" value="14" /><INPUT type="submit" value=" ON  " /> </FORM><font color="black"><B>LED3<br>(Green)</B></font></TD></TR></TABLE></TD><TD><TABLE BORDER=1 bgcolor="#66BBFF" width=72 cellspacing=0 cellpadding=4><TR><TD align=center><FORM action="http://192.168.1.177/" ><INPUT type="hidden" name="cmd" value="16" /><INPUT type="submit" value="TRIG" /> </FORM><font color="black"><B>Beep<br>Piezo</B></font></TD></TR></TABLE></TD><TD><TABLE BORDER=1 bgcolor="#44EE44" width=72 cellspacing=0 cellpadding=4><TR><TD align=center><FORM action="http://192.168.1.177/" ><INPUT type="hidden" name="cmd" value="19" /><INPUT type="submit" value=" OFF " /> </FORM><font color="black"><B>Night<br>Light</B></font></TD></TR></TABLE></TD><TD><TABLE BORDER=1 bgcolor="#44EE44" width=72 cellspacing=0 cellpadding=4><TR><TD align=center><FORM action="http://192.168.1.177/" ><INPUT type="hidden" name="cmd" value="21" /><INPUT type="submit" value=" OFF " /> </FORM><font color="black"><B>Fan<br>Ceiling</B></font></TD></TR></TABLE></TD><TD></TD></TR></TABLE><BR>
Vin = 7.61V
<BR>
<table border=1 bgcolor="#AAFFDD" cellspacing=0 cellpadding=4><tr><td rowspan=2 align=center><B>Digital<br>Pins</B><BR></td><td align=center>D31..D24</td><td align=center>D23..D16</td><td align=center>D15..D8</td><td align=center>D7..D0</td></tr><tr><td><font size=+1 color="#AA0000"><B>0</B></font>0001101</td><td>aaa00000</td><td>00001110</td><td>00110011</td></tr></table>
<BR>
<table border=1 bgcolor="#AAFFDD" cellspacing=0 cellpadding=4><tr><td rowspan=2 align=center><B>Analog<br>Pins</B></td><td align=center>A5 (D21)</td><td align=center>A6 (D22)</td><td align=center>A7 (D23)</td></tr><tr><td align=right>293</td>
<td align=right>0</td>
<td align=right>1023</td>
</table>
</TD></TR></TABLE></body></html>


This all happens instantly, so there is no hang at the server, no 10-sec timeout in the server-client loop, and no time to worry about pulling the CAT5 plug. I looked in all the configuration screens of PUTTY, but couldn't see anything obvious to change. "Implicit LF in every CR", and the converse, are not checked.

I'm using my adaptation of zoomkat's logical scheme from the other thread [ie wait for '\n' to dump the page], rather than your WebServerST logical scheme [ie, basically same as original WebServer, except with the timeout added]. The timeout code is in my sketch, in any case.

Thanks, between you and z-k, I seem to be making some progress, :-). I think I can live with what I have.

SurferTim

#25
Aug 23, 2013, 09:03 am Last Edit: Aug 23, 2013, 09:19 am by SurferTim Reason: 1
If you use my timeout code with your Arduino server, you can't crash it with the lockup script or PuTTY. PuTTY won't crash zoomkat's code either. Which code are you using?


oric_dan

I'm using z-k's version with your timeout. I'll experiment some more tomorrow with WebServer style code and no timeout, and z-k's with no timeout. Computer is off, heading for bed now.

SurferTim

#27
Aug 23, 2013, 09:19 am Last Edit: Aug 23, 2013, 09:49 am by SurferTim Reason: 1
This is the part that causes the lockup in most examples. This requires two newlines in a row. You can crash this with PuTTY.
Code: [Select]
if (c == '\n' && currentLineIsBlank) {

This is what zoomkat uses. PuTTY sends that newline immediately with the request. I could not find a way to stop PuTTY from sending the newline with the GET, so I couldn't crash this with PuTTY.
Code: [Select]
if (c == '\n') {

edit: You must use the Arduino sketch code above to crash zoomkat's code. It never sends a newline with the GET. Here is the send with no newline from that code. Note it uses client.print() instead of client.println().
Code: [Select]
 if(client.connect(ipBuf,80))
 {
   Serial.print("connected");

   // send request with no \r\n
   client.print("GET / HTTP/1.1");
 }


oric_dan


SurferTim

The only disadvantage to zoomkat's code is it does not read the entire request header, only the first line with the GET or POST. Since it doesn't read the rest of the header or the body of the request, you can't use a POST request with zoomkat's code.

Go Up