Lập trình an toàn

Yêu cầu về kiến thức:

–  An ninh mạng

–  Ngôn ngữ lập trình C/C++.

•  Lên lớp đầy đủ

pdf28 trang | Chia sẻ: Mr Hưng | Lượt xem: 748 | Lượt tải: 0download
Bạn đang xem trước 20 trang nội dung tài liệu Lập trình an toàn, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   LẬP  TRÌNH  AN  TOÀN   Secure  Programming   •  Cung  cấp  các  kiến  thức,  kỹ  thuật  cơ  bản  để  xây  dựng  các  ứng  dụng  an  toàn.   Mục  đích   2   •  Yêu  cầu  về  kiến  thức:  –  An  ninh  mạng  –  Ngôn  ngữ  lập  trình  C/C++.  •  Lên  lớp  đầy  đủ   Yêu  cầu   3   •  Thời  lượng:  45  tiết  –  Lý  thuyết:  30  tiết  –  Bài  tập:15  tiết   Thời  lượng  môn  học   4   •  Secure  Program  Cookbook  for  C  and  C++,  Matt  Messier,   John  Viega,  O'Reilly  2003.   Tài  liệu   5   •  Chương  1.  Kiểm  tra  đầu  vào  •  Chương  2.  Kiểm  soát  truy  nhập  •  Chương  3.  Kiểm  soát  xung  đột  •  Chương  4.  Mã  hóa  đối  xứng  •  Chương  5.  Hàm  băm  và  xác  thực  thông  điệp  •  Chương  6.  Mã  hóa  công  khai  •  Chương  7.  Anti-­‐Tampering  •  Chương  8.  Các  vấn  đề  khác   Nội  dung   6   7   •  Bài  tập  lớn:  70%  •  Quá  trình:  30%   Đánh  giá   8   Lương  Ánh  Hoàng   hoangla@soict.hut.edu.vn   Chương  1.  Kiểm  tra  đầu  vào   Input  Validation   1.1  Nguyên  tắc  kiểm  tra.  1.2  Các  hàm  định  dạng  xâu  (string  formatting)  .  1.3  Tràn  bộ  đệm.  1.4  Tràn  số  học.  1.5  Kiểm  tra  tên  }ile  và  đường  dẫn.  1.6  Giải  mã  URL  1.7  Cross-­‐Site  Scripting  1.8  SQL  Injection   Nội  dung   10   •  Luôn  luôn  giả  định  dữ  liệu  đầu  vào  là  không  đáng  tin  cậy  –  Dữ  liệu  từ  mạng  trong  mô  hình  client-­‐server  –  Dữ  liệu  từ  người  dùng  –  Dữ  liệu  từ  tệp  tin  –   •  Ưu  tiên  loại  bỏ  dữ  liệu  hơn  là  cố  gắng  sửa  chữa  dữ  liệu.  •  Thực  hiện  kiểm  tra  đầu  vào  tại  nhiều  cấp,  nhiều  điểm  –  Kiểm  tra  đầu  vào  ở  các  hàm  –  Kiểm  tra  đầu  vào  giữa  các  module.  –   •  Không  tiếp  nhận  lệnh  trực  tiếp  từ  người  dùng  nếu  chưa  qua  kiểm  tra.  •  Kiểm  tra  các  ký  tự  đặc  biệt,  dấu  nháy.  •  Tìm  hiểu  và  sử  dụng  cơ  chế  trích  dẫn  (quoting  mechanism)  nếu  cần.  •  Càng  hiểu  về  dữ  liệu  bao  nhiêu  càng  lọc  được  tốt  bấy  nhiêu.   1.1  Các  nguyên  tắc  kiểm  tra   11   •  Họ  các  hàm  printf()  ,  syslog()    cho  phép  định  dạng  dữ  liệu  rất  mềm  dẻo  và  mạnh  mẽ  tuy  nhiên  cũng  cực  kỳ  nguy  hiểm.  •  Thận  trọng  khi  sử  dụng  “%n”  –  Tham  số  %n  cho  phép  ghi  ra  số  lượng  ký  tự  đã  kết  xuất  được  ra  một  địa  chỉ  bất  kỳ  chỉ  ra  trong  tham  số  tương  ứng.  Nếu  không  tồn  tại  tham  số  nào  thì  printf  sẽ  ghi  đè  lên  một  vùng  nào  đó  thuộc  stack  của  luồng  đang  thực  thi.  –  VD.   int  counter  =  0;   printf(“Hello%n”,&counter);  //  OK,  counter  =  5   printf(“Hello%n”);  //  Nguy  hiểm  !!!    •  Không  sử  dụng  trực  tiếp  xâu  định  dạng  từ  nguồn  bên  ngoài  –  Xâu  định  dạng  có  nguồn  gốc  từ  ngoài  chương  trình  có  thể  có  một  vài  ký  tự  đặc  biệt  mà  chương  trình  chưa  lường  trước  được,  hoặc  không  có  tham  số  thay  thế  tương  ứng.    –  VD.    char  str[1024];    gets(str);    printf(“Xin  chao:”);    printf(str);  //  Nguy  hiểm  !!!    printf(“%s”,str);  //  OK     1.2  Các  hàm  định  dạng  xâu   12   •  Thận  trọng  khi  sử  dụng  sprintf,  vsprintf  với  “%s”  –  Các  hàm  trên  đều  giả  định  kích  thước  bộ  đệm  cho  xâu  đích  là  vô  hạn.  –  Nên  chỉ  rõ  số  lượng  ký  tự  tối  đa  sẽ  sử  dụng  khi  dùng  với  %s.  –  Nên  sử  dụng  snprintf,  vsnprintf  nếu  có  thể.  –  VD   char  str[1024];   char  dst[32];   gets(str);   sprintf(dst,”Xau  vua  nhap  vao  la  %s”,str);  //  Nguy  hiểm   sprintf(dst,”Xau  vua  nhap  vao  la  %.16s”,str);  //  OK   snprintf(dst,32,”Xau  vua  nhap  vao  la  %s”,str);//  OK   1.2  Các  hàm  định  dạng  xâu   13   •  Tràn  bộ  đệm  (Buffer  Over}low):  copy  dữ  liệu  vượt  quá  biên  của  một  bộ  đệm  nào  đó  =>  đè  lên  vùng  nhớ  của  biến  (cấu  trúc)  khác.  •  Phần  lớn  các  hàm  xử  lý  xâu  trong  C  đều  không  thực  hiện  kiểm  tra  biên  của  bộ  đệm:  gets,  strcpy,    •  VD1:  Dữ  liệu  bị  hỏng    int    x  =  0;    char  buff[8];    strcpy(buff,”Hello      AAAAAAAAAAAAAAAAAAAAAAAAAAAAA”);    printf(“%d”,x);   •  VD2:  Stack  bị  hỏng    char  name[8];    gets(name);    printf(name);   1.3  Tràn  bộ  đệm   14   •  VD3:  Không  trở  về  được  từ  chương  trình  con    void  Hello()    {      char  name[8];      printf(“What  is  your  name  ?”);      gets(name);      printf(“Hello  %s  !”,  name);      }      void  main()    {      Hello();      printf(“Bye”);    }   1.3  Tràn  bộ  đệm   15   •  VD4:  Tấn  công  có  chủ  ý  trên  bộ  đệm    void  Bye()    {      printf(“Bye”);    }    void  Hello()    {      void  (*p)()  =  Bye;      char  name[8];      printf(“What  is  your  name  ?”);      gets(name);      printf(“Hello  %s  !”,  name);      p();      }      void  main()    {      Hello();    }   1.3  Tràn  bộ  đệm   16   •  Giải  pháp:    –  Sử  dụng  các  hàm  strncpy,  memcpyvà  những  hàm  có  kiểm  soát  kích  thước  bộ  đệm  một  cách  tường  minh.  –  Sử  dụng  Stack  Guard  trong  các  trình  biên  dịch  hỗ  trợ.    –  Sử  dụng  DEP  (Data  Execution  Preventation)  trên  hệ  điều  hành  hỗ  trợ.  –  Sử  dụng  ASLR  (Address  Space  Layout  Randomization)  trên  trình  biên  dịch  và  hệ  điều  hành  hỗ  trợ.   1.3  Tràn  bộ  đệm   17   •  Dữ  liệu  nhận  về  có  thể  có  sai  sót  trong  trường  liên  quan  đến  kích  thước.  •  Các  thao  tác  liên  quan  đến  số  nguyên  lớn  có  thể  bị  tràn,  lẫn  lộn  giữa  số  nguyên  không  dấu  và  có  dấu  •  VD1:  Tràn  số   unsigned    int  x  =  0xFFFFFFFF;  //  MAX_INT   if  (  x+5  >  5  )  printf  (“X  >  0”  )    else  printf(“X  <  0”);   •  VD2:  Dùng  sai  kiểu  có/không  dấu                  if  (x  <  MAX_SIZE)  {    //  x,  số  byte  cần  cấp  phát  tùy  theo  giải  thuật  tính  được        if  (!(ptr  =  (unsigned  char  *)malloc(x)))  abort(    );    }      else      {          /*  Handle  the  error  condition  ...  */    }       1.4  Tràn  số  học   18   •  Dữ  liệu  nhận  về  có  thể  là  tên  }ile,  ứng  dụng  cần  xác  định  đường  dẫn  tuyệt  đối  nếu  cần  thiết.  •  Dùng  hàm  realpath()  trên  Unix/Linux  và  GetFullPathName  trên  Windows.  •  Sử  dụng  realpath()   §  Nguyên  mẫu:      char  *realpath(const  char  *pathname,  char  resolved_path[MAXPATHLEN]);   §  Thận  trọng:  Có  thể  tràn  resolved_path  và  không  thread-­‐safe.   §  Thư  viện:  stdlih.h   §  VD    char  resolved[1024];    char  *  result  =  realpath("printf.c",resolved);    printf("%s",result);   1.5  Kiểm  tra  tên  qile  và  đường  dẫn   19   •  Sử  dụng  GetFullPathName()   §  Thư  viện:  windows.h   §  Nguyên  mẫu:      DWORD  GetFullPathName(LPCTSTR  lpFileName,  DWORD  nBufferLength,  LPTSTR                              lpBuffer,  LPTSTR  *lpFilePath);   §  VD:    int  nBufferLen  =  0;    LPTSTR  lpBuffer;    nBufferLen  =  GetFullPathName(L"test.c",0,0,0);    if  (nBufferLen>0)    {      lpBuffer  =  new  TCHAR[nBufferLen+1];      GetFullPathName(L"test.c",nBufferLen,lpBuffer,0);      wprintf(L"%s",lpBuffer);    }       1.5  Kiểm  tra  tên  qile  và  đường  dẫn   20   •  RFC  1738  quy  định  cách  mã  hóa  các  ký  tự  không  nhìn  thấy  được  trong  URL  dưới  dạng  “%”.  •  VD:       •  Cách  giải  mã:  duyệt  từ  đầu  đến  cuối  ,  tìm  các  ký  tự  %  và  thay  thế  bằng  mã  ASCII  tương  ứng.   •  Không  sử  dụng  các  hàm  xử  lý  xâu  chuẩn  vì  có  thể  có  ký  tự  NULL  trong  URL.       1.6  Giải  mã  URL   21   •  Cross-­‐Site  Scripting  (XSS)  là  hình  thức  tấn  công  vào  trình  duyệt  người  dùng  bắt  nguồn  từ  việc  kiểm  tra  lỏng  lẻo  từ  server.  •  Có  thể  dẫn  đến  thất  thoát  thông  tin  nhạy  cảm:  mật  khẩu,  session,  cookie  •  Thực  hiện  bằng  cách  chèn  mã  HTML/JAVASCRIPT  vào  dữ  liệu  sẽ  hiển  thị  ra  trình  duyệt  =>  đoạn  mã  sẽ  chạy  trên  trình  duyệt  của  nạn  nhân.  •  VD.  Một  ứng  dụng  web  có  hai  trang  –  Hello.php:  Hiển  thị  form  và  nhận  tên  của  người  dùng.  –  Chao.php:  hiển  thị  tên  nhận  được  lại  cho  người  dùng.       1.7  Cross-­‐Site  Scripting   22   •  File  Hello.php   Xin  chào,  vui  lòng  nhập  tên  bạn   •  File  Chao.php   <?PHP   echo  "Xin  chao  ".$_POST['name'];   ?>   •  Demo   •  Với  tên  là  :  Secure   •  Với  tên  là:  Secure  alert('XSS  was  found  !');     •  Với  tên  là:  Secure  alert(‘Hacked’);   •  Giải  pháp:  Lọc  bỏ  các  thẻ  HTML  khỏi  dữ  liệu  từ  người  dùng.  Mỗi  ngôn  ngữ  lập  trình  có  một  cách  riêng.   1.7  Cross-­‐Site  Scripting   23   •  SQL  Injection:  Tấn  công  vào  CSDL  thông  qua  dữ  liệu  nhập  từ  trình  duyệt.  •  Lợi  dụng  việc  kiểm  tra  lỏng  lẻo  từ  đầu  vào,  chèn  mã  lệnh  SQL  vào  các  truy  vấn  đến  CSDL  của  ứng  dụng  web.    •  Thường  lợi  dụng    dấu  nháy  “  ‘  “  để  kết  thúc  câu  truy  vấn  SQL  hoặc  thêm  các  câu  truy  vấn  khác.  •  VD:  Lệnh  so  sánh  tên  và  mật  khẩu  trong  SQL  –  select  *  from  users  where  username  =  ‘$user’  and  password  =  ‘$pass’    –  Nếu  $user  hoặc  $pass  chứa  dấu  “’”  thì  SQL  sẽ  hiểu  nhầm  nội  dung  truy  vấn  •  Các  kỹ  thuật  khai  thác:  An  ninh  mạng  •  VD:  Một  ứng  dụng  web  muốn  kiểm  tra  tên  và  mật  khẩu  gồm  hai  trang  –  ask.php:  Hiện  form  đăng  nhập  và  thu  nhận  tên,  mật  khẩu  –  login.php:  Kết  nối  đến  CSDL  và  kiểm  tra   1.8  SQL  Injection   24   •  VD  (tiếp  –  File  ask.php       Vui  long  nhap  ten  va  mat  khau   Ten:     Mat  khau:   1.8  SQL  Injection   25   •  VD  (tiếp)  –  File  login.php    <?PHP   $db_server  =  "localhost";   $db_username=  "root";   $db_password=  "123456";   $db  =  "test";   $table  =  "users";   $conn  =  mysql_connect($server,$db_username,$db_password);   if  (!$conn)    {      echo  "Khong  ket  noi  dc  den  CSDL";      return;    }   $ret    =  mysql_select_db($db,$conn);   1.8  SQL  Injection   26    if  (!$ret)  {      echo  "Khong  ton  tai  CSLD  tuong  ung";      return;      }   $user  =  $_GET['name'];   $pass  =  $_GET['pass'];   $sql  =  "select  *  from  $table  where  username='$user'  and  password='$pass'";   echo  $sql;   $ret  =mysql_query($sql,$conn);   if  (mysql_num_rows($ret)>0)      echo  "Dang  nhap  thanh  cong";   else      echo  "Sai  ten  hoac  mat  khau";   ?>   1.8  SQL  Injection   27   •  Tấn  công  –  username  =  a’  or  ‘1’=‘1  –  password  =  b’  or  ‘1’=‘1  –   •  Phòng  chống  –  Loại  bỏ  tất  cả  các  dấu  ‘  và  các  ký  tự  đặc  biệt  nếu  cần.  –  Sử  dụng  escaped  string    •  Với  php/mysql:  mysql_real_escape_string,  hoặc  thêm  ‘\’.  •  Với  SQL  server:  thêm  ký  tự    ‘  trước  ký  tự  đặc  biệt.  •  Với  Oracle  DB:  thêm  ký  tự  ‘\’  trước  ký  tự  đặc  biệt.       1.8  SQL  Injection   28  

Các file đính kèm theo tài liệu này:

  • pdfsecureprogramming_1_1436.pdf