DouPHP監査レコード
0x01の概要
DouPHP漳州豆の殻ネットワーク技術有限公司は、Smartyテンプレートエンジンを搭載したシステムをLinuxでは、Windowsの、MacOSXは、Solarisおよび他のプラットフォーム上で動作するPHP + MySQLのアーキテクチャに基づいた軽量企業のウェブサイトの管理システムを開発し、このようなモジュールのメンバーなどのカスタム擬似静的、DIV + CSSデザイン、簡潔な背景インターフェイスのデザインを使用してフォアグラウンドテンプレート、シンプルな機能は優れたユーザーエクスペリエンス、安定性、拡張性、およびセキュリティを持っている傾向がある、とバックラインモジュールを介してインストールすることができ、受注モジュールは、中小のサイトのためのサイト構築ソリューションを提供することができます。
単に学習の目的のための監査は、ローカルコンピュータ上でテストを設定します。
0x02のSQLインジェクション
フロントデスクから直接、いくつかのファイルは、監査を開始するように、システムは、アクセスルートを設定しませんので。ここに私たちの注目点の価値が直接記録:
init.php
のindex.phpを開始するには、いくつかの初期設定をした/include/init.php含まれています
init.php、magic_quotes_runtimeをオフにします
新しい67ラインのファイアウォールのクラス、および88ラインコールdou_firewall()。私たちは、操作が行われていたものを見るためにフォローアップしていき
dou_magic_quotesに従ってください()
addslshes_deepに従ってください()
あなたは、最終的な呼び出しがaddslshes_deep(で見ることができます)にかかわらず、$ _GETの、$ _ POST、$ _ COOKIE $ _ REQUESTは、単一の値または配列で渡され、すべての悪は(にaddslashesを通過します)洗礼。そして、データベース接続設定を、コンフィギュレーションを見て符号化することによって、これだけ、我々は唯一のint SQLインジェクションを見ることができるdou_firewall()を呼び出して、UTF-8です。
また、ラップ、およびクエリ内のパラメータの前に配置されていないパラメータの引用符は、通常の試合を行った見つけることができませんでしたが、SQL文の完全なテキストを読んだ後、唯一の[0-9A-ZA-Z_]許可されている、システムということができます非常に標準化開発。そして、私は通常の試合やエスケープのパラメータ値のすべてを発見したすべての可能な二次注入。
0x03の論理的欠陥
何の注入がないので、あなたは抜け穴の他の種類を監査することができます。
地元の環境観測によって設定し、フロントデスクは機能情報、論理的な抜け穴を表示されることがあり、パスワード回復機能の背景のみのログエントリを表示することです。
ポジション:最後の行への管理/ login.php 136、パスワードを取得するためのコードを処理です
elseif ($rec == 'password_reset_post') {
// Action操作项的初始化
$action = $check->is_rec($_POST['action']) ? $_POST['action'] : 'default';
// 验证管理员用户名
if (!$check->is_username(trim($_POST['user_name']))) {
$dou->dou_msg($_LANG['login_password_reset_fail'], ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset', 'out');
} else {
$user_name = trim($_POST['user_name']);
}
// 验证对应的管理员邮箱
if (!$check->is_email(trim($_POST['email']))) {
$dou->dou_msg($_LANG['login_password_reset_fail'], ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset', 'out');
} else {
$email = trim($_POST['email']);
}
// 找回密码提交、重置密码提交
if ($action == 'default') { // 密码找回提交操作
// 根据用户名和邮箱获取对应的用户信息
$user = $dou->get_row('admin', '*', "user_name = '$user_name' AND email = '$email'");
// 对应的用户信息不存在
if (!$user)
$dou->dou_msg($_LANG['login_password_reset_wrong'], ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset', 'out');
// CSRF防御令牌验证
$firewall->check_token($_POST['token'], 'password_reset');
// 生成包含找回密码链接的邮件正文
$time = time();
$code = substr(md5($user['user_name'] . $user['email'] . $user['password'] . $time . $user['last_login'] . DOU_SHELL) , 0 , 16) . $time;
$site_url = rtrim(ROOT_URL, '/');
$body = $user['user_name'] . $_LANG['login_password_reset_body_0'] . ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset' . '&uid=' . $user['user_id'] . '&code=' . $code . $_LANG['login_password_reset_body_1'] . $_CFG['site_name'] . '. ' . $site_url;
// 发送找回密码邮件
if ($dou->send_mail($user['email'], $_LANG['login_password_reset'], $body)) {
$dou->dou_msg($_LANG['login_password_mail_success'] . $user['email'], ROOT_URL . ADMIN_PATH . '/login.php', 'out', '30');
} else {
$dou->dou_msg($_LANG['mail_send_fail'], ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset', 'out', '30');
}
} elseif ($action == 'reset') { // 密码重置操作
// 获取会员ID和安全码
$user_id = $check->is_number($_POST['user_id']) ? $_POST['user_id'] : '';
$code = preg_match("/^[a-zA-Z0-9]+$/", $_POST['code']) ? $_POST['code'] : '';
// 验证密码
if (!$check->is_password($_POST['password'])) {
$dou->dou_msg($_LANG['manager_password_cue'], '', 'out');
} elseif (($_POST['password_confirm'] !== $_POST['password'])) {
$dou->dou_msg($_LANG['manager_password_confirm_cue'], '', 'out');
}
// 找回密码操作
if ($dou->check_password_reset($user_id, $code)) {
// 重置密码
$sql = "UPDATE " . $dou->table('admin') . " SET password = '" . md5($_POST['password']) . "' WHERE user_id = '$user_id'";
$dou->query($sql);
$dou->dou_msg($_LANG['login_password_reset_success'], ROOT_URL . ADMIN_PATH . '/login.php', 'out', '15');
} else {
$dou->dou_msg($_LANG['login_password_reset_fail'], ROOT_URL . ADMIN_PATH . '/login.php', 'out', '15');
}
}
}
?>
限り、我々は、着信REC = password_reset_postコードのこの層に入るためにGETまたはPOSTとして_REQUEST $ [「REC」]、を通じて取得されたREC $でELSEIF
後の後の着信のため、$アクションを得るために、初めに図を参照してくださいユーザ名と電子メールが定期的に試合をして、あなたは、これら2つのパラメータによってアクションがほとんど不可能であるやりたいです。
以下は$ check-> is_usernameと$ check-> is_email処理コードです
function is_username($username) {
if (preg_match("/^[a-zA-Z]{1}([0-9a-zA-Z]|[._]){3,19}$/", $username)) {
return true;
}
}
function is_email($email) {
if (preg_match("/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/", $email)) {
return true;
}
}
そして、$アクション==「デフォルト」の動作を見て
// 找回密码提交、重置密码提交
if ($action == 'default') { // 密码找回提交操作
// 根据用户名和邮箱获取对应的用户信息
$user = $dou->get_row('admin', '*', "user_name = '$user_name' AND email = '$email'");
// 对应的用户信息不存在
if (!$user)
$dou->dou_msg($_LANG['login_password_reset_wrong'], ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset', 'out');
// CSRF防御令牌验证
$firewall->check_token($_POST['token'], 'password_reset');
// 生成包含找回密码链接的邮件正文
$time = time();
$code = substr(md5($user['user_name'] . $user['email'] . $user['password'] . $time . $user['last_login'] . DOU_SHELL) , 0 , 16) . $time;
$site_url = rtrim(ROOT_URL, '/');
$body = $user['user_name'] . $_LANG['login_password_reset_body_0'] . ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset' . '&uid=' . $user['user_id'] . '&code=' . $code . $_LANG['login_password_reset_body_1'] . $_CFG['site_name'] . '. ' . $site_url;
// 发送找回密码邮件
if ($dou->send_mail($user['email'], $_LANG['login_password_reset'], $body)) {
$dou->dou_msg($_LANG['login_password_mail_success'] . $user['email'], ROOT_URL . ADMIN_PATH . '/login.php', 'out', '30');
} else {
$dou->dou_msg($_LANG['mail_send_fail'], ROOT_URL . ADMIN_PATH . '/login.php?rec=password_reset', 'out', '30');
}
データベースクエリと処理を戻す終了していない結果に最初の投稿入ってくるユーザー名とメールボックス。だから、メールボックスがパスワードの目的をリセットするために任意のリンクを受け入れるようにメールボックスに達し変更する方法はありません。
建設後のパスワード回復リンクを開始し、リンクに対応するメールボックスユーザーに送信されます。
パスワードリセットのリンクが$コード(168行)を含め、我々は直接、パスワードリセットのリンクを作成することはできませんので、MD5は、ユーザー情報の複数のステッチして計算しております。図長い列170は、スプライシング$コード$本体の後ろに、実際には、コード$本体ではなく、完全にテーマを生成します。これは、完全なコードを見て、私のリリースパスワード回復機能の上にすることができます。
このように印刷するにはパスワードのリセットリンク
私たちは、コード$ REC ==「password_reset」の中に直接login.phpを見てリンクを分析することにより、$ REC = password_reset知っています
ここでは116 $のUSER_IDと$ dou-> check_passwrod_reset()入れするおよそ$コード、我々は、操作をフォローアップするために行われていたものを見て
、フロント$コードうち96行$コードを再生成するために16ビット線98、101行を見ることができます$コードと$ get_code比較を取ります。我々はので、ここで我々は制限バイパスすることはできません、$コード検証のためにここにいました。
しかし、これは、最終的な契約、次のようにパスワードを変更するには、最終的な場所のパスワードを変更するための場所ではありません。
しかし残念ながら、191行はこの監査にパスワード回復機能も$コード検証だったので、私は抜け穴を見つけることができませんがあります。
0x04のファイルアップロード
この監査は、ファイルに/監査管理者であるので、ファイルのアップロード機能しませんでしたフロントデスクをdouphp
読み取ることで、すべてのファイルアップロード機能を見つけるには、どこ監査にそのうちの一つ、たとえば、Fileクラスを使用して処理されている
管理者/ system.phpの
とき$ときそこREC ==「更新」ファイルのアップロード、ライン103回のコール$ [ファイル] - > [更新()、我々は$ファイルを来るかを見てみましょう。
20行を参照してください、$ファイルは、オブジェクトファイルのクラスのインスタンスであります
__constructは、次の操作を行い確認するために、Fileクラスに従ってください:
その後、戻って再見$ [ファイル] - > [アップロード()
内の$ this - > FILE_TYPEで一致するファイルの拡張子と外観を得るために、ポイントによって配列に分割した後、ここに。あなたはそれをバイパスすることができない、ホワイトリストフィルタリングであるので、ここでは、唯一のいくつかの写真型の接尾辞上記__constructます$ FILE_TYPEから見ることができます。
次の直接スプライシングファイル名、およびファイルのアップロード。穴を掘っていないファイルのアップロード機能はそう。
0x05の他の脆弱性
CSRF
後も背景CSRFがあるかどうかを見て、結果が最初csrftoken検証する操作を実行する前に、バックグラウンド機能です。ここでは、自己構築するかどうか、CSRFを生成する方法を見て。
以下のコードの読み取りは、乱数発生のために見ることができます。
不正アクセス
不正アクセス監査のは非常に失礼である、バック・ページ・ファイルの先頭には、管理者が含まれています/ /含まので、セッション上でチェックを行うinit.php含まれていないファイルがある場合、管理ディレクトリのディレクトリ・ファイルを直接見init.phpことができます。しかし、最終的に、それは手動でいくつかなって、見つけることができませんでした。
0x06の概要
掘り込み複数のストレージXSS背景の合計の監査、監査プロセスに精通より深く理解コード監査、おそらくより大きな収穫。これは、コードだけでなく、いくつかの安全性のスキル開発、アイデアを学びます。自分の欠点を認識しつつ、コードが遅い速度を読んでいます。
私たちは、彼らの戦闘を改善したいと考えてい後半ハハ、それを渡します。