אופס, צריכים עזרה?


    התקשרו עכשיו:
    050-992-1014
    כתובת דוא''ל ראשית: razwebs@gmail.com
    ימים ושעות פעילות:
    א-ה בין השעות 09:00-19:00,
    ימי שישי וחג 09:00-14:00


אבטחת אתרים ב-PHP

ניווט קלראשימאמרים מקצועייםאבטחת אתרים ב-PHP


אבטחת אתרים ב-PHP

האקרים עלולים לפרוץ את האתר שלכם אם לא תמגנו אותו בצורה הראויה.
מידע חשוב, זמן יקר ולעתים סחיטות כספים הם הראשונים להיפגע במקרה שכזה.
במדריך הבא אסביר דרכים לאבטח את הקוד באתר שלכם.

* הערה: המדריך הינו בגדר המלצה של הכותב והוא נכתב לטובת הכלל ולהשערת הידע בנושא.
במידה ואתם רוצים לאבטח מערכת או למגן את האתר שלכם בצורה חזקה יותר, אנחנו תמיד נמליץ ונעדיף להשתמש בחברת 
בניית אתרים או גורם מוסמך מקצועי אחר.

* הפקודות הרשומות במדריך אינן מפורטות על עצם השימוש בהן וכל זה, אני בטוח שתחפשו בגוגל תמצאו את כל מה שצריך כבר.

 

תחילה נגע בסוגיות אבטחה בקוד PHP

  1. אימות והגנה בשדות (inputs)
  2. אבטחה נגד התקפות XSS
  3. אבטחה נגד התקפות CSRF
  4. מניעת הזרקת SQL
  5. יצירת מערכות העלאת קבצים מאובטחות
  6. עבודה נכונה עם סשנים ומערכות התחברות ואבטחת סיסמאות
  7. תצוגת שגיאות נכונה
  8. מדיניות אבטחה והתנהלות נכונה
  9. העמסה על השרת וספאם

אימות שדות באתר

כשאנחנו בונים אתר אנחנו בדרך כלל מתייחסים לכך שהמשתמשים שלנו הם משתמשים טובים שאינם עושים בעיות,
לפיכך אנחנו מקצים להם את השדות הנדרשים כמו למשל לבחור שם משתמש, סיסמה וכדומה.
אך חשיבה זו אינה נכונה. עלינו לעבוד עם כלל ברזל - לא לסמוך על הלקוח המשתמש במערכת שלנו.

לפיכך עלינו לאמת את הנתונים שהלקוח הזין באמצעות PHP באופן קבוע. זאת מכיוון שניתן לחסום JS בדפדפן ובכך לדלג על אימות שאנחנו עושים עוד בצד הלקוח. בנוסף תמיד רצוי להשתמש בפקודות כמו
htmlspecialchars ו-mysqli_real_escape_string שבהן נגע בהמשך המאמר.


כלומר, אם למשל ביקשתם מהמשתמש להזין כתובת דוא׳׳ל והוא ביטל את ה-JS בדפדפן שלו, אז הוא יכול בקלות לכתוב מייל שגוי כמו למשל sakljasklj!@#13kasl;dk וזה עלול לדפוק לנו את המערכת, לפיכך תמיד חובה לבדוק שדות רגישים גם באמצעות PHP שכן שם הוא אינו בעל גישה לערוך או לשנות כלום.

זכרו קוד ה-PHP שלכם לא נגיש ללקוח בשום צורה שהיא והיא הדרך האולטימטיבית למגן מפני דברים מהסוג הזה.


עוד מומלץ, שבמקום להעביר לעמוד PHP שעושה את העבודה אחרי ש-JS בדק שהכל תקין, אלא באמצעות ה-JS עצמו להפעיל עמוד PHP ובכך אם הוא חסם את ה-JS העמוד PHP לא יופעל כלל ואז מה שהוא מנסה פשוט לא יעבוד וכמובן לא ידפוק משתמשים אחרים או את מסד הנתונים שבאתר שלנו.


אבטחה נגד XSS

פגיעות מסוג זה, שניתנות להיעשות בין אתרים שונים בצד הלקוח כמו למשל הזנת JS לא תקין וכדומה עובדות בצורה הבאה: לקוח עלול לכתוב פקודה כמו alert ב-JS בתוך הטקסט של התגובה שלו ואת זה המערכת תכניס למסד נתונים ואז תציג בפני שאר המשתמשים. ואז כמו שאתם יכולים לנחש, שאר המשתמשים יקבלו הודעה שגיאה אותה הוא כתב.
ובכן, כדי למנוע דבר שכזה שוב, השתמשו בפקודה htmlspecialchars.

עוד סוג של פריצה מהסוג הזה היא כשרושמים מחרוזת ארוכה מדי, למשל בלהבלהבלה....בלהבלה ברצף, ללא הפרדות וללא שום דבר. אם המערכת שלכם לא תדע להפריד את המחרוזות הארוכות בהתאם לגודל המקום שבו אתם הולכים לשתול אותם זה עשוי ליצור גלילה רוחבית ולקלקל משמעותית את חוויית המשתמש של הלקוח. נמנע את זה באמצעות הפקודה: wordwrap.

בעצם פריצות מסוג זה הן פריצות הנעשות בצד הלקוח.

 
 

אבטחה נגד התקפות CSRF

מהן התקפות מהסוג הזה? אני אסביר. אלו הן פריצות שמשתמשים עושים בין משתמשים ושפוגעים בצורה לוגית במערכת.
כלומר, במקרים שכאלו הלקוח לא פוגע במערכת עצמה אלא מפעיל גורמים חיצוניים ועקיפין לפגיעה ישירה במערכת.
כך למשל, נניח יש לנו עמוד באתר שמעביר כספים בין משתמשים.
והעמוד הזה פועל באמצעות GET וכל מה שצריך כדי להעביר כסף הוא להפעיל עמוד מסויים עם הפרמטרים הנכונים,
כמו למשל העמוד הזה:
somepage.php?action=transfer&to=kobi&amount=1000
כשנפעיל את העמוד שכתבתי כאן למעלה אנחנו נפעיל פקודה שמעבירה לחשבון של קובי 1000 ש׳ח או דולר או מה שזה לא יהיה. כל מה שקובי צריך לעשות זה לשלוח קישור לשרה למשל, במייל או אפילו בווצאפ וברגע ששרה תפעיל את זה היא תעביר כסף לקובי בלי שהיא ידעה בכלל. אז קובי לוקח את הכסף סוגר את החשבון ונעלם.

כיצד מונעים? מאוד פשוט. קודם כל אנחנו צריכים להתחיל לדעת לעבוד עם טוקנים. אנחנו יוצרים טוקן (אסימון) זמני לכל פעולה ושומרים אותו במסד נתונים. בלי האסימון הזה לא ניתן להפעיל את הפקודה והיא לא תעבוד.
כך אנחנו מאמתים עוד מראש שהקישור הגיע ממקור רלוונטי כמו מהאתר שלנו.
את האסימון אנחנו יוצרים ב-PHP רגע לפני הפנייה וכל דרך אחרת חוסמת את האסימון.

אם כמובן אנחנו יכולים להרשות לעצמנו לעבוד עם POST זה כבר יהיה אפילו עוד יותר קל שכן ללקוח אין גישה ל-POST באמצעות לינק שהוא שולח במייל או בווצאפ.

 


כיצד מונעים הזרקת SQL? 

קודם כל מזה אומר בכלל? שוב, זוכרים את המשתמש שמכניס תכנים זדוניים בשדות תמימים שהקצבנו לו באתר?
אז בדומה לזה גם כאן, רק שהפעם הלקוח מכניס דברים שעשויים לשבש באמת את תהליכי העבודה של האתר שלנו באמצעות החדרה תוכן זדוני למסד נתונים.
למשל, חשבו על מערכת התחברות שבה הלקוח מזין שם משתמש וסיסמה.
המערכת משווה את השם משתמש והסיסמה למה שיש כרגע במסד נתונים ובמידה וזה נכון היא מוסיפה לו סשן או קוקי כדי שהוא יוכל להתחבר ולהמשיך לעבוד באתר.
אבל מה קורה אם הלקוח משחק עם התוכן שהוא מכניס ובמקום להכניס שם משתמש רגיל הוא כותב פקודת SQL תוך איפה שהיה צריך לכתוב שם משתמש? אז אני אגלה לכם סוד. אם לא מיגנתם את זה, בעצם כל מה שהוא כתב זה חלק מהפקודה SQL ומשם הוא יכול לעשות מה שבא לו, כולל למחוק את הטבלה כולל לעדכן, כולל ליצור טבלה חדשה, להשיג את הסיסמה וכדומה!!

אז איך ממגנים? זה הכי פשוט בעולם. קודם כל מומלץ לעבוד עם PHP7 שזו הגרסה הכי מעודכנת שיש כיום. במידה ויצאה גרסה מעודכנת יותר אז תמיד עדיף לעדכן. דבר שני, זוכרים את הפקודה htmlspecialchars?
ובכן זו פקודה מפתח כי היא בעצם מסירה את כל ה= ״ ו ה- ׳ וכל שאר הסימנים איתם אנחנו עובדים על שאילתת ה-SQL שלנו. בעצם היא לא מסירה אלא מתעלמת ואז מה שהוא מכניס הוא תמיד יהיה מוגדר כטקסט רגיל ולא כפקודת SQL זדונית.


 

יצירת מערכות העלאת קבצים מאובטחות

בוא נגיד שלא מיגנתם בכלל את מערכת העלאת הקבצים שלכם ונתתם ללקוח שלכם להעלות מה שהוא רוצה. במקום להעלות תמונה שלו לפרופיל למשל הוא יעלה קובץ ששוקל 300 מגה שיתקע את טעינת העמוד לכולם, עשוי לתקוע את השרת וכמובן לא יציג שום תמונה. אז האבטחה הבסיסית היא קודם כל לאפשר לו להעלות רק את הקבצים הרצויים, אם זה תמונה למשל אז שיעלה רק JPG או PNG וכדומה ובמשקל הראוי והמתאים.

עוד בצד הלקוח ניתן למנוע ממנו לעשות זאת (להכניס תכנים זדוניים) באמצעות JS.
אנחנו יכולים לדעת את מידת הקובץ וסוגו עוד לפני שהעלה אותו לשרת ואז במקום לאמת אותו רק באמצעות PHP אנחנו יכולים לאמת אותו כבר ב-JS עוד לפני שהטריח את השרת להעלות קובץ ששוקל 300 מגה סתם.

שוב זכרו, צריך למגן את זה באמצעות JS וגם באמצעות PHP גם יחד שכן המשתמש עשוי לחסום את ה-JS שלו בכוונה.

 

 

עבודה נכונה עם סשנים ומערכות התחברות

זה אחד הדברים הכי חשובים. נתחיל קודם כל עם משפט ברזל:
בחיים אבל בחיים אל תשמרו נתונים סודיים של הלקוח שלכם במסד נתונים, כמו למשל סיסמאות. במקום זה אתם צריכים לשמור את ה-hash של הסיסמה שלהם.

ה-hash של הסיסמה שלהם הוא בעצם צופן חד צדדי שניתן להשיג באמצעות פקודת php עם SALT. את ה-hash עצמו אנחנו שותלים במסד נתונים וגם בקוקי של הלקוח ואז משווים אם הם נכונים בכל פעם שהוא נכנס ובכך אנחנו שומרים אותו מחובר גם באופן עתידי. בכל פעם שהוא מזין את הסיסמה כדי להתחבר מה שאנחנו עושים זה משתמשים בפקודה password_verify שהיא בעצם היחידה שיודעת להפוך את הסיסמה שהוא הזין לאותו hash בדיוק ששמרנו במסד נתונים, במידה וזה נכון אנחנו יודעים שהסיסמה שלו נכונה. זכרו אנחנו לא אמורים לדעת ולשמור את הסיסמה שלו.
ובחיים לא לשמור פרטים סודיים על הקוקי שלו גם.

קוד לדוגמה של פעולה זו:

 

function generateHash($password) {
    if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
        $salt = '$2y$11$' . substr(md5(uniqid(rand(), true)), 0, 22);
        return crypt($password, $salt);
    }
}

$generate = htmlspecialchars($_GET['generate'], ENT_QUOTES);

if ($generate=="true")
{
  function generateStrongPassword($length = 20, $add_dashes = false, $available_sets = 'luds')
  {
      $sets = array();
      if(strpos($available_sets, 'l') !== false)
          $sets[] = 'abcdefghjkmnpqrstuvwxyz';
      if(strpos($available_sets, 'u') !== false)
          $sets[] = 'ABCDEFGHJKMNPQRSTUVWXYZ';
      if(strpos($available_sets, 'd') !== false)
          $sets[] = '23456789';
      if(strpos($available_sets, 's') !== false)
          $sets[] = '#$%*';
      $all = '';
      $password = '';
      foreach($sets as $set)
      {
          $password .= $set[array_rand(str_split($set))];
          $all .= $set;
      }
      $all = str_split($all);
      for($i = 0; $i < $length - count($sets); $i++)
          $password .= $all[array_rand($all)];
      $password = str_shuffle($password);
      if(!$add_dashes)
          return $password;
      $dash_len = floor(sqrt($length));
      $dash_str = '';
      while(strlen($password) > $dash_len)
      {
          $dash_str .= substr($password, 0, $dash_len) . '-';
          $password = substr($password, $dash_len);
      }
      $dash_str .= $password;
      return $dash_str;
  }
  $new_password = generateStrongPassword();
  $hashed_password = generateHash($new_password);

 

בעצם מה שאנחנו עושים פה זה לוקחים ממציאים סיסמה חזקה מאוד ועלייה עושים hash. את ה-hash צריך לשמור במד נתונים ולשתול בקוקי של הלקוח.
ואז לפעול באותה צורה שכתבתי למעלה. מאוד פשוט.
רצוי גם לעשות שאם הלקוח משנה משהו בקוקי שלו, אז שלא ישמור אותו מחובר אלא יעביר אותו לעמוד התנתקות ויעיף אותו מהאתר.


 

תצוגת שגיאות נכונה

display_error on בקובץ php.ini עשוי להציג למשתמשים שגיאות שאינן הכרחיות ואינן מפריעות לעמוד להיטען, ככה שהכל בסדר אבל הלקוח עשוי לראות שגיאות שהוא אינו אמור. לכן מומלץ להשבית פקודה זו ולדבג טעויות באמצעות הקובץ error שנמצא בתקיית ה-public_html. וכמובן באמצעות פקודות כמו var_dump על סביבת הפיתוח וכדומה.
 

מדיניות אבטחה והתנהלות נכונה

  1. בחיים אל תשמרו את הסיסמאות של הלקוחות שלכם.
  2. בחיים אל תשמרו פרטים חשובים בקוקי של הלקוחות שלכם ועם כן, תדאגו לצרף אסימון (טוקן).
  3. בחיים אל תגבילו לקוחות לכמות תווים מסויימת בסיסמה או משהו כזה, הפוך, תגבילו אותם למינימום של תווים ושיהיו חייבים לשים אות גדולה וקטנה ומספר ותו אחד לפחות.
  4. שנו מדי פעם את הסיסמאות שלכם.
  5. אל תאחסנו את הסיסמאות בתוספים כמו LastPass וכל מיני שטויות שכאלו שעשויים לדפוק לכם הכל או ליפול מתישהו או להיפרץ בעצמם ואכלתם אותה.
  6. תמיד שיהיה לכם גיבוי עדכני אצלכם ביד ולא בשרת ולא בענן ולא שום דבר אחר. גיבוי באמצעות USB או כונן נייד.
  7. אל תשתמשו באותה סיסמה 300 פעם.
  8. אל תשתפו את הסיסמה שלכם עם גורמים אחרים כל עוד היא רגישה. כלומר - שתפו סיסמאות שהן זמניות ואין להן ערך במערכות אחרות שלכם.
  9. עבדו עם SSL - פרוטוקול אבטחה והצפנה HTTPS.
  10. בחרו שרת איכותי שיש לו מערכת אבטחה טובה וזמן העלאה אחרי פריצות מינימלי ככל הניתן.
 

העמסה על שרתים וספאם

תעשו קאפצ׳ה או חסימה של אייפי למי שהתחבר או ניסה להתחבר יותר מ-5 פעמים ברצף (בטווח של כמה דקות) בחייאת. אחרת יבוא מישהו ויציב 500 פניות בדקה על מערכת ההתחברות שלכם עד שהשרת ייפול. מאוד קל למגן את זה.
אבל חשוב גם לא להציק - 3 טעויות לא לחסום ישר, תנו 5 או 6 טעויות בטווח של דקה.
ואז כמובן חסמו אותו. קאפצ׳ה גם יכולה להיות פתרון טוב. הכי טוב זה את שניהם ביחד.

רצוי גם לעשות ככה על כל דבר שהלקוח יכול לעשות באופן קבוע כמו למשל להכניס משתמשים, לכתוב פוסטים, להגיב, לקנות מוצרים וכדומה. תגבילו אותו שלא יעשה 300 פעולות בחצי שנייה וחסמו אותו במידה הצורך.

 

סיכום

מגנו את המערכות שלכם והשאירו האקרים בחוץ. כל מה שכתבתי פה הוא בגדר המלצה וכתוב בחצי שורה בלבד. אני מציע שתחפשו על כל דבר ודבר בגוגל עד שתלמדו למגן את האתרים שלכם על הצד הטוב ביותר.


 

רז בניית אתרים - בית עסק בוטיק המספק פתרונות לבניית אתרים ותכנות, קידום ושיווק באינטרנט ופיתוח אפליקציות. לתיאום פגישת ייעוץ בחינם חייגו 050-992-1014 או צרו קשר דרך האתר



אודותיי

    אני בונה ומפתח אתרי אינטרנט מקצועיים המקודמים במנועי חיפוש ומותאמים לכל הדפדפנים, הסלולריים ואפילו טבלטים. האתרים נבנים עם מערכת ניהול תוכן שפותחה והותאמה אישית לדרישתו של הלקוח ולאתר שהוא רכש.
    אשמח לתת לכם שירות בכל אשר תרצו.