
diff --git a/api.php b/api.php
index cec20df..98dfa52 100644
--- a/api.php
+++ b/api.php
@@ -9,15 +9,17 @@ if(isset($_GET['cmd']))
{
switch($_GET['cmd'])
{
+ //所有记录包括详细信息
case 'list':
echo json_encode(dirList());
break;
-
+
+ //只列出时间戳(索引id)
case 'simplelist':
-
echo json_encode(dirSimpleList());
break;
-
+
+ //根据时间戳(索引id)获得单条信息
case 'get':
if(isset($_GET['id'])&&preg_match('/^[0-9]{10}$/',$_GET['id']))
echo json_encode(loadInfo($_GET['id']));
@@ -25,6 +27,7 @@ if(isset($_GET['cmd']))
echo json_encode(false);
break;
+ //根据时间戳(索引id)删除单条信息
case 'del':
if(isset($_GET['id'])&&preg_match('/^[0-9]{10}$/',$_GET['id']))
echo json_encode(delInfo($_GET['id']));
@@ -32,11 +35,18 @@ if(isset($_GET['cmd']))
echo json_encode(false);
break;
+ //清空记录
case 'clear':
echo json_encode(clearInfo());
- break;
+ break;
+
+ default:
+ echo json_encode(false);
}
}
+else
+ echo json_encode(false);
+
function dirSimpleList() {
$files = glob(DATA_PATH . '/*.php');
foreach ($files as &$file){
@@ -44,17 +54,17 @@ function dirSimpleList() {
}
return $files;
}
-function dirList() {
+function dirList() {
$list=array();
$files = glob(DATA_PATH . '/*.php');
arsort($files);
foreach ($files as $file) {
- $listinfo=array();
$filename=basename($file,".php");
$info=loadInfo($filename);
$isChange=false;
+ //如果没有设置location,就查询qqwry.dat判断location
if(!isset($info['location']))
{
$info['location']=convertip($info['user_IP'],IPDATA_PATH);
@@ -63,10 +73,8 @@ function dirList() {
if($isChange)
saveInfo(json_encode($info),$filename);
-
$list[]= $info;
- }
-
+ }
return $list;
-}
+}
?>
\ No newline at end of file
diff --git a/auth.php b/auth.php
index 763e4ee..e57d073 100644
--- a/auth.php
+++ b/auth.php
@@ -2,9 +2,12 @@
if(!defined('IN_XSS_PLATFORM')) {
exit('Access Denied');
}
+
+//设置httponly
ini_set("session.cookie_httponly", 1);
session_start();
+//判断登陆情况,ip和useragent是否改变,改变则强制退出
if(!(isset($_SESSION['isLogin']) && $_SESSION['isLogin']===true && isset($_SESSION['user_IP']) &&$_SESSION['user_IP']!="" &&$_SESSION['user_IP']=== $_SERVER['REMOTE_ADDR'] &&isset($_SESSION['user_agent']) &&$_SESSION['user_agent']!="" &&$_SESSION['user_agent']=== $_SERVER['HTTP_USER_AGENT'] ))
{
$_SESSION['isLogin']=false;
@@ -16,9 +19,8 @@ if(!(isset($_SESSION['isLogin']) && $_SESSION['isLogin']===true && isset($_SESSI
exit();
}
+//开启CSP
header("Content-Security-Policy: default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; frame-src 'none'");
header("X-Content-Security-Policy: default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; frame-src 'none'");
header("X-WebKit-CSP: default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; frame-src 'none'");
-
-
?>
\ No newline at end of file
diff --git a/config.php b/config.php
index 78a25f7..b8e00fe 100644
--- a/config.php
+++ b/config.php
@@ -2,11 +2,16 @@
if(!defined('IN_XSS_PLATFORM')) {
exit('Access Denied');
}
-
-define('PASS', '2a05218c7aa0a6dbd370985d984627b8');//bluelotus
+//默认密码bluelotus
+define('PASS', '2a05218c7aa0a6dbd370985d984627b8');
+//记录,封禁ip列表存放位置
define('DATA_PATH', 'data');
+//开启对记录,封禁ip列表的AES加密
define('ENABLE_ENCRYPT', true);
+//加密密码
define('ENCRYPT_PASS', "bluelotus");
+//是否启用KEEP_SESSION功能,需要外部定时访问keepsession.php
define('KEEP_SESSION', true);
+//ip数据库地址
define('IPDATA_PATH', "qqwry.dat");
?>
\ No newline at end of file
diff --git a/dio.php b/dio.php
index f6edd43..9dd4e71 100644
--- a/dio.php
+++ b/dio.php
@@ -5,6 +5,7 @@ if(!defined('IN_XSS_PLATFORM')) {
require_once("config.php");
require_once("functions.php");
+//对记录的读写操作,无数据库,采用读写文件的方式,文件名即请求时的时间戳,同时也是记录的id
function saveInfo($info,$filename)
{
$logFile = dirname( __FILE__ ).'/'.DATA_PATH.'/'.$filename.'.php';
diff --git a/functions.php b/functions.php
index b6659d8..d78da81 100644
--- a/functions.php
+++ b/functions.php
@@ -4,6 +4,7 @@ if(!defined('IN_XSS_PLATFORM')) {
}
require_once("aes.php");
+//nginx无getallheaders函数
if (!function_exists('getallheaders')) {
function getallheaders() {
foreach ($_SERVER as $name => $value) {
@@ -15,7 +16,7 @@ if (!function_exists('getallheaders')) {
}
}
-
+//判断该记录是否
function isKeepSession($info){
$keepsession=false;
foreach($info['cookie_data'] as $k => $v) {
@@ -33,8 +34,7 @@ function isKeepSession($info){
return $keepsession;
}
-
-
+//xss过滤
function stripStr($str){
if(get_magic_quotes_gpc())
$str=stripslashes($str);
@@ -49,6 +49,7 @@ function stripArr($arr){
return $new_arr;
}
+//尝试base64解码
function tryBase64Decode($arr)
{
if(isset($arr)&&count($arr)>0)
@@ -74,6 +75,7 @@ function tryBase64Decode($arr)
return false;
}
+//判断string是否为base64编码(判断方法:解码后为可见字符串)
function isBase64Formatted($str)
{
if(preg_match('/^[A-Za-z0-9+\/=]+$/',$str))
@@ -93,6 +95,7 @@ function decrypt($info,$encryptPass)
return AESDecryptCtr($info,$encryptPass);
}
+//基于Discuz X3.1 function_misc.php
function convertip($ip, $ipdatafile) {
$ipaddr = '未知';
if(preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
diff --git a/guide/mainpanel.png b/guide/mainpanel.png
index 63e3bd2..b10639a 100644
Binary files a/guide/mainpanel.png and b/guide/mainpanel.png differ
diff --git a/index.php b/index.php
index 7dfa85a..5c17f47 100644
--- a/index.php
+++ b/index.php
@@ -19,6 +19,7 @@ $request_time = isset($_SERVER['REQUEST_TIME'])?$_SERVER['REQUEST_TIME']:time();
$headers_data =getallheaders();
+//如果提交的数据有base64编码的就解码
$get_data=$_GET;
$decoded_get_data=tryBase64Decode($_GET);
$post_data=$_POST;
@@ -26,6 +27,7 @@ $decoded_post_data=tryBase64Decode($_POST);
$cookie_data=$_COOKIE;
$decoded_cookie_data=tryBase64Decode($_COOKIE);
+//防xss过滤,对array要同时处理key与value
$info['user_IP'] = stripStr($user_IP);
$info['user_port'] = stripStr($user_port);
$info['protocol'] = stripStr($protocol);
@@ -46,6 +48,7 @@ $info['cookie_data'] = stripArr($cookie_data);
if($decoded_cookie_data)
$info['decoded_cookie_data'] = stripArr($decoded_cookie_data);
+//判断是否keepsession(判断标准:get或者post或者cookie包含keepsession=1)
$info['keepsession']=isKeepSession($info)?true:false;
saveInfo(json_encode($info),$request_time);
diff --git a/login.php b/login.php
index 8877e1e..e74c3ea 100644
--- a/login.php
+++ b/login.php
@@ -5,18 +5,20 @@ header("Content-Security-Policy: default-src 'self'; object-src 'none'; frame-sr
header("X-Content-Security-Policy: default-src 'self'; object-src 'none'; frame-src 'none'");
header("X-WebKit-CSP: default-src 'self'; object-src 'none'; frame-src 'none'");
+//设置httponly
ini_set("session.cookie_httponly", 1);
session_start();
require_once("config.php");
require_once("functions.php");
-
+//判断是否登陆
if(isset($_SESSION['isLogin']) && $_SESSION['isLogin']===true)
{
header("Location: admin.php");
exit();
}
+//判断ip是否在封禁列表中
$forbiddenIPList=loadForbiddenIPList();
$ip=$_SERVER['REMOTE_ADDR'];
if(!isset($forbiddenIPList[$ip]) || $forbiddenIPList[$ip]<3)
@@ -53,7 +55,8 @@ function loadForbiddenIPList()
$logfile = DATA_PATH . '/forbiddenIPList.dat';
!file_exists( $logfile ) && @touch( $logfile );
$str = file_get_contents( $logfile );
- $str =decrypt($str,ENCRYPT_PASS);
+ if(ENABLE_ENCRYPT)
+ $str =decrypt($str,ENCRYPT_PASS);
if($str!='')
{
$result=json_decode($str,true);
@@ -70,7 +73,10 @@ function saveForbiddenIPList($forbiddenIPList)
{
$logfile = DATA_PATH . '/forbiddenIPList.dat';
!file_exists( $logfile ) && @touch( $logfile );
- @file_put_contents($logfile, encrypt(json_encode($forbiddenIPList),ENCRYPT_PASS));
+ $str=json_encode($forbiddenIPList);
+ if(ENABLE_ENCRYPT)
+ $str = encrypt($str,ENCRYPT_PASS);
+ @file_put_contents($logfile, $str);
}
/*
@@ -81,6 +87,7 @@ function checkPassword($p)
{
if(isset($_SESSION['firesunCheck'])&&isset($_POST['firesunCheck'])&&$_SESSION['firesunCheck']!=""&&$_POST['firesunCheck']===$_SESSION['firesunCheck'])
{
+ //改了这个盐记得改login.js里的,两个要一致
$salt="!KTMdg#^^I6Z!deIVR#SgpAI6qTN7oVl";
$key=PASS;
$key=md5($salt.$key.$_SESSION['firesunCheck'].$salt);
@@ -92,6 +99,7 @@ function checkPassword($p)
return false;
}
+//生成挑战应答的随机值
function generate_password( $length = 32 ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$password = "";
diff --git a/logout.php b/logout.php
new file mode 100644
index 0000000..617b5fd
--- /dev/null
+++ b/logout.php
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/static/css/Fonts/icomoon.eot b/static/css/Fonts/icomoon.eot
deleted file mode 100644
index 87a0ec5..0000000
Binary files a/static/css/Fonts/icomoon.eot and /dev/null differ
diff --git a/static/css/Fonts/icomoon.svg b/static/css/Fonts/icomoon.svg
deleted file mode 100644
index bf28776..0000000
--- a/static/css/Fonts/icomoon.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/static/css/Fonts/icomoon.ttf b/static/css/Fonts/icomoon.ttf
deleted file mode 100644
index 01872ef..0000000
Binary files a/static/css/Fonts/icomoon.ttf and /dev/null differ
diff --git a/static/css/Fonts/icomoon.woff b/static/css/Fonts/icomoon.woff
deleted file mode 100644
index 1570088..0000000
Binary files a/static/css/Fonts/icomoon.woff and /dev/null differ
diff --git a/static/css/Site.css b/static/css/Site.css
index 2c8fe5e..db59383 100644
--- a/static/css/Site.css
+++ b/static/css/Site.css
@@ -37,11 +37,11 @@ body,
/* font */
@font-face {
font-family: 'icomoon';
- src:url('Fonts/icomoon.eot?c8m22a');
- src:url('Fonts/icomoon.eot?#iefixc8m22a') format('embedded-opentype'),
- url('Fonts/icomoon.woff?c8m22a') format('woff'),
- url('Fonts/icomoon.ttf?c8m22a') format('truetype'),
- url('Fonts/icomoon.svg?c8m22a#icomoon') format('svg');
+ src:url('../fonts/icomoon.eot?c8m22a');
+ src:url('../fonts/icomoon.eot?#iefixc8m22a') format('embedded-opentype'),
+ url('../fonts/icomoon.woff?c8m22a') format('woff'),
+ url('../fonts/icomoon.ttf?c8m22a') format('truetype'),
+ url('../fonts/icomoon.svg?c8m22a#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -60,20 +60,20 @@ body,
-moz-osx-font-smoothing: grayscale;
}
+.icon-logout:before {
+ content: "\e900";
+}
.icon-info:before {
- content: "\e600";
+ content: "\e904";
}
-.icon-faves:before {
- content: "\e601";
+.icon-template:before {
+ content: "\e901";
}
-.icon-star-empty:before {
- content: "\e602";
+.icon-my-js:before {
+ content: "\e903";
}
-.icon-chart-column:before {
- content: "\e603";
-}
-.icon-mobile:before {
- content: "\e604";
+.icon-panel:before {
+ content: "\e902";
}
.icon {
@@ -146,12 +146,16 @@ body,
}
#rights {
+ width:100%;
color: #848690;
- font-size: 10px;
+ font-size: 12px;
position: absolute;
bottom: 10px;
+ text-align: center;
+ line-height: 120%;
}
+
/* Toggle button */
#toggle-button {
margin-top: 27px;
@@ -197,4 +201,5 @@ body,
-webkit-box-shadow: 1px 0 4px #ededee;
box-shadow: 1px 0 4px #ededee;
background-color: #fff;
-}
\ No newline at end of file
+}
+
diff --git a/static/fonts/icomoon.eot b/static/fonts/icomoon.eot
new file mode 100644
index 0000000..4528d43
Binary files /dev/null and b/static/fonts/icomoon.eot differ
diff --git a/static/fonts/icomoon.svg b/static/fonts/icomoon.svg
new file mode 100644
index 0000000..7f8ccf2
--- /dev/null
+++ b/static/fonts/icomoon.svg
@@ -0,0 +1,15 @@
+
+
+
\ No newline at end of file
diff --git a/static/fonts/icomoon.ttf b/static/fonts/icomoon.ttf
new file mode 100644
index 0000000..fcfe0c1
Binary files /dev/null and b/static/fonts/icomoon.ttf differ
diff --git a/static/fonts/icomoon.woff b/static/fonts/icomoon.woff
new file mode 100644
index 0000000..2387aa0
Binary files /dev/null and b/static/fonts/icomoon.woff differ
diff --git a/static/js/loadgrid.js b/static/js/loadgrid.js
index 21d29ad..fbd9278 100644
--- a/static/js/loadgrid.js
+++ b/static/js/loadgrid.js
@@ -7,6 +7,7 @@ var interval = 1000; //向服务器获取记录的时间间隔,同时也是aja
$(document).ready(function() {
var self = this;
+ //数据源与datafields
var source = {
datatype: "json",
datafields: [{
@@ -76,6 +77,7 @@ $(document).ready(function() {
root: 'data',
};
+ //从接口获得数据后的处理,格式化时间与根据useragent判断客户端
var dataAdapter = new $.jqx.dataAdapter(source, {
downloadComplete: function(data, status, xhr) {
if (status == "success") {
@@ -104,6 +106,7 @@ $(document).ready(function() {
},
});
+ //每行detail信息初始化
var initrowdetails = function(index, parentElement, gridElement, datarecord) {
var tabsdiv = null;
var information = null;
@@ -119,7 +122,8 @@ $(document).ready(function() {
post_grid = tabsdiv.find('.post_grid');
cookie_grid = tabsdiv.find('.cookie_grid');
headers_grid = tabsdiv.find('.headers_grid');
- //datarecord.client=datarecord.headers_data["User-Agent"]?get_client_info(datarecord.headers_data["User-Agent"]):"未知";
+
+ //GET表
var get_data = new Array();
for (key in datarecord.get_data) {
var get_data_item = new Array();
@@ -193,6 +197,7 @@ $(document).ready(function() {
]
});
+ //POST表
var post_data = new Array();
for (key in datarecord.post_data) {
var post_data_item = new Array();
@@ -269,6 +274,7 @@ $(document).ready(function() {
]
});
+ //COOKIE表
var cookie_data = new Array();
for (key in datarecord.cookie_data) {
var cookie_data_item = new Array();
@@ -341,6 +347,7 @@ $(document).ready(function() {
]
});
+ //HTTP Headers表
var headers_data = new Array();
for (key in datarecord.headers_data) {
var headers_data_item = new Array();
@@ -392,6 +399,8 @@ $(document).ready(function() {
},
]
});
+
+ //其他信息
var container = $('
');
container.appendTo($(information));
var leftcolumn = $('
');
@@ -419,6 +428,7 @@ $(document).ready(function() {
$(rightcolumn).append(uri_item);
$(rightcolumn).append(client_item);
+ //tab大小调整
$(tabsdiv).jqxTabs({
width: '95%',
height: '100%'
@@ -426,16 +436,18 @@ $(document).ready(function() {
}
}
+ //主面板初始化
$("#panelGrid").jqxGrid({
pageable: true,
+ //如果需要autoresizecolumn,可以在这开启
ready: function() {
//$('#panelGrid').jqxGrid('autoresizecolumn', 'request_date_and_time_string');
//$('#panelGrid').jqxGrid('autoresizecolumn', 'data_type');
//$('#panelGrid').jqxGrid('autoresizecolumn', 'user_IP');
},
+ //最底下的状态栏初始化
pagerrenderer: function() {
-
var container = $("
");
var deleteButton = $("
删除");
var clearButton = $("
清空");
@@ -468,20 +480,15 @@ $(document).ready(function() {
});
- // reload grid data.
clearButton.click(function(event) {
$('#clearConfirmWindow').jqxWindow('open');
$("#clearConfirmWindow").addClass('animated');
- //$("#panelGrid").jqxGrid({
- // source: getAdapter()
- //});
});
+
// search for a record.
searchButton.click(function(event) {
- //var offset = $("#panelGrid").offset();
$("#searchWindow").jqxWindow('open');
$("#searchWindow").addClass('animated');
- //$("#jqxwindow").jqxWindow('move', offset.left + 30, offset.top + 30);
});
var pageElementsContainer = $("
");
@@ -524,8 +531,6 @@ $(document).ready(function() {
});
return container;
},
-
- //selectionmode: 'multiplerowsextended',
scrollmode: 'logical',
sortable: true,
pagesize: 25,
@@ -677,6 +682,32 @@ $(document).ready(function() {
}
});
+ //注销确认窗口
+ $('#logoutConfirmWindow').jqxWindow({
+ height: 100,
+ width: 270,
+ resizable: false,
+ okButton: $('#logoutConfirm_ok'),
+ cancelButton: $('#logoutConfirm_cancel'),
+ autoOpen: false,
+ });
+
+ $('#logoutConfirm_ok').jqxButton({
+ width: '65px'
+ });
+ $('#logoutConfirm_cancel').jqxButton({
+ width: '65px'
+ });
+
+ $('#logoutConfirmWindow').on('close',
+ function(event) {
+ if (event.args.dialogResult.OK) {
+ window.location.href = "logout.php";
+ }
+ });
+
+
+
$('#failedWindow').jqxWindow({
height: 100,
width: 270,
@@ -697,6 +728,7 @@ $(document).ready(function() {
width: 210,
height: 180
});
+
// create find and clear buttons.
$("#findButton").jqxButton({
width: 70
@@ -704,6 +736,7 @@ $(document).ready(function() {
$("#clearButton").jqxButton({
width: 70
});
+
// find records that match a criteria.
$("#dropdownlist").jqxDropDownList({
autoDropDownHeight: true,
@@ -768,6 +801,12 @@ $(document).ready(function() {
//$('#panelGrid').jqxGrid('autoresizecolumn', 'user_IP');
});
+ $("#logout").click(function() {
+ $('#logoutConfirmWindow').jqxWindow('open');
+ $("#logoutConfirmWindow").addClass('animated');
+
+ });
+
//定时判断是否有新的记录
checkNewMessages();
setIntervalID = setInterval(checkNewMessages, interval);