检查你的工具
有一个单行密码喷洒脚本被广泛用于检测域内用户是否使用弱密码(如LetMeIn!或Winter2015)。该脚本从文件中读取用户列表和密码列表(如果担心账户锁定,也可以只使用一个密码),并尝试连接到域控制器的IPC共享。
像大多数单行脚本一样,在替换客户特定部分时很容易破坏整个脚本。因此,在针对整个域运行之前,最好先在自己的用户账户上测试。如果脚本找到了你提供的密码,说明语法正确,也能找到其他密码。
在最近的一次任务中,情况并非如此。完整性检查未能找到测试账户的密码,尽管该密码确实在尝试文件中。接下来的过程是一个关于注意细节、理解工作原理和手动阅读的教训。
故障排除的第一步是清晰描述问题,然后将测试案例缩小到最少的变量。
问题:使用有效凭据时测试失败
完整命令如下:
|
|
这个命令很复杂,像大多数单行脚本一样,失败点不明显。为了更易读:
|
|
即:
- 对password.txt中的每一行,设置变量%p
- 对每个%p变量,从users.txt的下一行设置变量%n
- 尝试连接到域控制器的IPC$共享,并忽略输出
- 如果连接成功,将用户名和密码写入stdout
- 然后断开连接
现在问题清楚了,需要缩小范围。从基础开始:尝试从测试文件读取一行并写入stdout,以确保正确读取文件。可能是行尾序列、字符编码问题,或者命令行文件名传递方式有误。
发现问题
很快发现问题是只读取了行的第一个单词,而不是整行。本以为按行读取,但实际是"将其分解为单独的文本行,然后将每行解析为零个或多个令牌"。
制表符和空格是默认分隔符,但可以指定其他分隔符。需要选择密码中不包含的字符:
|
|
这样可行。但能确保密码中永远不会包含加号吗?空字符呢?
不行。
空字符串呢?
成功!
现在知道是空格导致的问题,下一个问题是:必须在命令行中引用包含空格的内容。这就是为什么像我这样的懒黑客仍尽量避免在文件名中使用空格,省去繁琐的引用。那么,在脚本中作为输出使用时是否需要引用%p?测试发现:需要引用。
解决方案
引用后工作正常,不引用则失败。因此从现在开始将使用引用。
新的、更健壮的密码喷洒单行脚本如下:
|
|
应该把这个保存在能找到的地方。