İstemci-sunucu tabanlı uygulamaları analiz etmek için sık kullanılan yollardan birisi de kişisel vekil* kullanmaktır. Böylece istemci tarafındaki uygulama ile (genellikle bir İnternet tarayıcısı) sunucu tarafındaki uygulama arasında geçen trafiği (HTTP/S) gözlemlemek mümkün olur.
Bu tür analizlerde karşılaşılabilecek bir durum, istemci tarafındaki uygulamanın (mesela bir JNLP uygulaması) sunucu tarafındaki uygulamaya göndermek istediği veriyi önce (tek yönlü olmayan) bir işlemden geçirmesidir. Öyle ki, bu işlem, veri yakalandığında hızlı (on the fly) analiz yapmayı güç hatta imkansız hale getirir. Ağ gidiş geliş hızını (round-trip time) azaltmak için istemcinin ve sunucunun veriyi göndermeden önce sıkıştırması bir örnek olarak verilebilir.
Analiz edenin (denetçi, saldırgan) böyle bir durumda yapması gereken iki şey vardır. İlk yöntem, kişinin yakaladığı veriyi kopyalayıp, üzerine istemci tarafından yapılan veri değişim işleminin tersini (mesela, sıkıştırma ise açma) uygulayıp, elde ettiği veriyi yakaladığı orijinal veri ile değiştirmek olacaktır. Aynı şekilde sunucunun cevabını da bu işlemden geçirmelidir. Diğer bir yöntem ise bunu otomatik olarak yapabileceği bir araç bulmak/yazmaktır.
Bu problem doğrultusunda bu notta bahsedeceğimiz yöntem Webscarab [3] kişisel vekilinde bulunan Bean Shell eklentisini kullanmaktır. Beanshell [1] java ile java için yazılmış hafif sıklet bir betik (script) dilidir. Webscarab'daki Bean Shell eklentisi istek cevapların betiksel olarak değiştirilmesine yarayan bir alt-bileşendir. Basit olarak, eklentinin çalışma prensibi resimde görülebilir.
Problemin bir çözümü, bir Beanshell betiği yazılarak, isteğin yakalanması (yakalanmış isteğin tekrar yakalanması) sonrası istemcinin uyguladığı değişim algoritmasının tersi uygulanarak analiz edene gösterilmesi, son olarak da yapılabilecek muhtemel değişikliklerin sunucuya gönderilmesiyle gerçekleştirilebilir. Bunun için örnek bir Bean Sheel eklenti kodu aşağıda görülebilir.
/* Please read the JavaDoc and/or the source to understand what methods are available */ import org.owasp.webscarab.model.Request; import org.owasp.webscarab.model.Response; import org.owasp.webscarab.httpclient.HTTPClient; import java.io.IOException; // this is possible only with bsh2.01b class Interceptor extends JDialog implements ActionListener { JTextArea inputField; JButton okButton; JButton cancelButton; String value; JScrollPane scrollPane; public Interceptor() { setModal(true); JPanel topPanel = new JPanel(); topPanel.setLayout( new BorderLayout() ); getContentPane().add( topPanel ); inputField = new JTextArea(30,80); inputField.setEditable(true); scrollPane = new JScrollPane(inputField, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); topPanel.add(scrollPane, BorderLayout.CENTER); okButton = new JButton("OK"); okButton.addActionListener(this); cancelButton = new JButton("Cancel"); cancelButton.addActionListener(this); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10)); buttonPanel.add(okButton); buttonPanel.add(cancelButton); getContentPane().add(buttonPanel, BorderLayout.SOUTH); pack(); setLocationRelativeTo(null); } public void actionPerformed(ActionEvent e) { if( e.getSource() == okButton ) { value = inputField.getText(); } dispose(); } public String getValue(String input, String title){ inputField.setText(input); setTitle(title); setVisible(true); return value; } } dlg = new Interceptor(); public byte [] deflate(byte [] src){ return src; } public byte [] inflate(byte [] src){ return src; } public Response fetchResponse(HTTPClient nextPlugin, Request request) throws IOException { byte [] requestContent = null; byte [] responseContent = null; byte [] deflated = null; String inflated = null; if("POST".compareToIgnoreCase(request.getMethod()) == 0){ requestContent = request.getContent() ; inflated = new String(inflate(requestContent), "ISO-8859-9"); manipulated = dlg.getValue(inflated, "request"); // block the traffic, waits for the user input deflated = manipulated.getBytes("ISO-8859-9"); request.setContent(deflated); } response = nextPlugin.fetchResponse(request); if("POST".compareToIgnoreCase(request.getMethod()) == 0){ responseContent = response.getContent(); inflated = new String(deflate(responseContent), "ISO-8859-9"); dlg.getValue(inflated, "response"); // block the traffic, waits for the user to see the response } return response; }
Interceptor sınıfı (class) yakalanan verinin, ters değiştirme işleminden geçirildikten sonra analiz edene gösterilmesini sağlayan arayüzdür. Bu sınıf Java dilinde JDialog sınıfından türetilir. Bunun nedeni Interceptor arayüzü ile gösterilen verinin gönderilmeden önce kullanıcıyı (analiz eden kişiyi) beklemesi gerektiğindendir. Kullanıcının ters işlem uygulanmış veriye değişiklik yaptıktan veya bu veriyi sadece analiz ettikten sonra onaylaması belirtilen problemin amacıdır.
Kodda daha sonra gelen satır;
dlg = new Interceptor();
hem bu sınıfa ait bir obje oluşturur hem de Beanshell'in özelliklerinden birini kullanır. Bu özellik dilde tür zorunluluğunun (explicit type coercion) olmamasıdır.
Daha sonra gelen iki metod uygulanacak ters işlemlerin basit bir iskeletini içerir. Veri üzerinde uygulanacak asıl işlem işte bu metodlar içerisinde bulunacaktır:
public byte [] deflate(byte [] src) ... public byte [] inflate(byte [] src) ...
Son olarak fetchResponse metodu veri yakalanması durumunda Webscarab tarafından çağrılan metoddur. Bu metodu belirtildiği gibi değiştirilerek yukarıda belirtilen işlemler yapılabilir ve arayüz gösterilebilir. Belirtilen implementasyon daha detaylı ve kapsamlı hale getirilebilir. Bu iş için gerekli metodlar [2];
İstek metodları:
Cevap metodları:
Ve istek ve cevap ortak metodları:
Yazılan Beanshell kodu kullanılarak yakalanan bir resim aşağıdadır.
Son olarak, yukarıdaki izlenen yolun dezavantajları listelenip daha modüler bir çözümden bahsedilebilir.
Interceptor sınıfının bean shell ile yazılması, betiğin diğer kısımlarında yapılacak bir değişikliğin Webscarab'a uygulanmasında (COMMIT) hata alınmasına neden olacaktır (Duplicate class exception). Bunu engellemek ve daha modüler bir yapı için Interceptor sınıfı bir jar halinde derlenerek, Webscarab sınıf yoluna (classpath) eklenebilir [Bu konu hakkında yardım için yukarıdaki e-mail adresi yolu ile bana ulaşabilirsiniz]. Daha sonra Bean Shell eklenti kısmında bu kütüphane (library) betiğe dahil edilerek normal bir sınıf şeklinde kullanılabilir;
/* Please read the JavaDoc and/or the source to understand what methods are available */ import org.owasp.webscarab.model.Request; import org.owasp.webscarab.model.Response; import org.owasp.webscarab.httpclient.HTTPClient; import java.io.IOException; import com.urgun.Interceptor; ... public byte [] deflate(byte [] src) ... public byte [] inflate(byte [] src) ... public Response fetchResponse(HTTPClient nextPlugin, Request request) ...
* Bu amaç için kullanılan bir çok araçtan bir kaçı; Paros, Burp Suite, Suru, Fiddler, Firebug, Live HTTP Headers, Achilles, Ethereal (Wireshark) ve Webscarab. Bir çok ticari web açıklık tarayıcısı da bu tür yakala/değiştir alt-bileşenleri içerdiği gibi sadece bu amaca hizmet eden ev yapımı araçlar yazılabilir.
Referanslar: